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 {
6475            let mut only_carets = true;
6476            let mut same_text_selected = true;
6477            let mut selected_text = None;
6478
6479            let mut selections_iter = selections.iter().peekable();
6480            while let Some(selection) = selections_iter.next() {
6481                if selection.start != selection.end {
6482                    only_carets = false;
6483                }
6484
6485                if same_text_selected {
6486                    if selected_text.is_none() {
6487                        selected_text =
6488                            Some(buffer.text_for_range(selection.range()).collect::<String>());
6489                    }
6490
6491                    if let Some(next_selection) = selections_iter.peek() {
6492                        if next_selection.range().len() == selection.range().len() {
6493                            let next_selected_text = buffer
6494                                .text_for_range(next_selection.range())
6495                                .collect::<String>();
6496                            if Some(next_selected_text) != selected_text {
6497                                same_text_selected = false;
6498                                selected_text = None;
6499                            }
6500                        } else {
6501                            same_text_selected = false;
6502                            selected_text = None;
6503                        }
6504                    }
6505                }
6506            }
6507
6508            if only_carets {
6509                for selection in &mut selections {
6510                    let word_range = movement::surrounding_word(
6511                        &display_map,
6512                        selection.start.to_display_point(&display_map),
6513                    );
6514                    selection.start = word_range.start.to_offset(&display_map, Bias::Left);
6515                    selection.end = word_range.end.to_offset(&display_map, Bias::Left);
6516                    selection.goal = SelectionGoal::None;
6517                    selection.reversed = false;
6518                    select_next_match_ranges(
6519                        self,
6520                        selection.start..selection.end,
6521                        replace_newest,
6522                        autoscroll,
6523                        cx,
6524                    );
6525                }
6526
6527                if selections.len() == 1 {
6528                    let selection = selections
6529                        .last()
6530                        .expect("ensured that there's only one selection");
6531                    let query = buffer
6532                        .text_for_range(selection.start..selection.end)
6533                        .collect::<String>();
6534                    let is_empty = query.is_empty();
6535                    let select_state = SelectNextState {
6536                        query: AhoCorasick::new(&[query])?,
6537                        wordwise: true,
6538                        done: is_empty,
6539                    };
6540                    self.select_next_state = Some(select_state);
6541                } else {
6542                    self.select_next_state = None;
6543                }
6544            } else if let Some(selected_text) = selected_text {
6545                self.select_next_state = Some(SelectNextState {
6546                    query: AhoCorasick::new(&[selected_text])?,
6547                    wordwise: false,
6548                    done: false,
6549                });
6550                self.select_next_match_internal(display_map, replace_newest, autoscroll, cx)?;
6551            }
6552        }
6553        Ok(())
6554    }
6555
6556    pub fn select_all_matches(
6557        &mut self,
6558        action: &SelectAllMatches,
6559        cx: &mut ViewContext<Self>,
6560    ) -> Result<()> {
6561        self.push_to_selection_history();
6562        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6563
6564        loop {
6565            self.select_next_match_internal(&display_map, action.replace_newest, None, cx)?;
6566
6567            if self
6568                .select_next_state
6569                .as_ref()
6570                .map(|selection_state| selection_state.done)
6571                .unwrap_or(true)
6572            {
6573                break;
6574            }
6575        }
6576
6577        Ok(())
6578    }
6579
6580    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) -> Result<()> {
6581        self.push_to_selection_history();
6582        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6583        self.select_next_match_internal(
6584            &display_map,
6585            action.replace_newest,
6586            Some(Autoscroll::newest()),
6587            cx,
6588        )?;
6589        Ok(())
6590    }
6591
6592    pub fn select_previous(
6593        &mut self,
6594        action: &SelectPrevious,
6595        cx: &mut ViewContext<Self>,
6596    ) -> Result<()> {
6597        self.push_to_selection_history();
6598        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6599        let buffer = &display_map.buffer_snapshot;
6600        let mut selections = self.selections.all::<usize>(cx);
6601        if let Some(mut select_prev_state) = self.select_prev_state.take() {
6602            let query = &select_prev_state.query;
6603            if !select_prev_state.done {
6604                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
6605                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
6606                let mut next_selected_range = None;
6607                // When we're iterating matches backwards, the oldest match will actually be the furthest one in the buffer.
6608                let bytes_before_last_selection =
6609                    buffer.reversed_bytes_in_range(0..last_selection.start);
6610                let bytes_after_first_selection =
6611                    buffer.reversed_bytes_in_range(first_selection.end..buffer.len());
6612                let query_matches = query
6613                    .stream_find_iter(bytes_before_last_selection)
6614                    .map(|result| (last_selection.start, result))
6615                    .chain(
6616                        query
6617                            .stream_find_iter(bytes_after_first_selection)
6618                            .map(|result| (buffer.len(), result)),
6619                    );
6620                for (end_offset, query_match) in query_matches {
6621                    let query_match = query_match.unwrap(); // can only fail due to I/O
6622                    let offset_range =
6623                        end_offset - query_match.end()..end_offset - query_match.start();
6624                    let display_range = offset_range.start.to_display_point(&display_map)
6625                        ..offset_range.end.to_display_point(&display_map);
6626
6627                    if !select_prev_state.wordwise
6628                        || (!movement::is_inside_word(&display_map, display_range.start)
6629                            && !movement::is_inside_word(&display_map, display_range.end))
6630                    {
6631                        next_selected_range = Some(offset_range);
6632                        break;
6633                    }
6634                }
6635
6636                if let Some(next_selected_range) = next_selected_range {
6637                    self.unfold_ranges([next_selected_range.clone()], false, true, cx);
6638                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
6639                        if action.replace_newest {
6640                            s.delete(s.newest_anchor().id);
6641                        }
6642                        s.insert_range(next_selected_range);
6643                    });
6644                } else {
6645                    select_prev_state.done = true;
6646                }
6647            }
6648
6649            self.select_prev_state = Some(select_prev_state);
6650        } else {
6651            let mut only_carets = true;
6652            let mut same_text_selected = true;
6653            let mut selected_text = None;
6654
6655            let mut selections_iter = selections.iter().peekable();
6656            while let Some(selection) = selections_iter.next() {
6657                if selection.start != selection.end {
6658                    only_carets = false;
6659                }
6660
6661                if same_text_selected {
6662                    if selected_text.is_none() {
6663                        selected_text =
6664                            Some(buffer.text_for_range(selection.range()).collect::<String>());
6665                    }
6666
6667                    if let Some(next_selection) = selections_iter.peek() {
6668                        if next_selection.range().len() == selection.range().len() {
6669                            let next_selected_text = buffer
6670                                .text_for_range(next_selection.range())
6671                                .collect::<String>();
6672                            if Some(next_selected_text) != selected_text {
6673                                same_text_selected = false;
6674                                selected_text = None;
6675                            }
6676                        } else {
6677                            same_text_selected = false;
6678                            selected_text = None;
6679                        }
6680                    }
6681                }
6682            }
6683
6684            if only_carets {
6685                for selection in &mut selections {
6686                    let word_range = movement::surrounding_word(
6687                        &display_map,
6688                        selection.start.to_display_point(&display_map),
6689                    );
6690                    selection.start = word_range.start.to_offset(&display_map, Bias::Left);
6691                    selection.end = word_range.end.to_offset(&display_map, Bias::Left);
6692                    selection.goal = SelectionGoal::None;
6693                    selection.reversed = false;
6694                }
6695                if selections.len() == 1 {
6696                    let selection = selections
6697                        .last()
6698                        .expect("ensured that there's only one selection");
6699                    let query = buffer
6700                        .text_for_range(selection.start..selection.end)
6701                        .collect::<String>();
6702                    let is_empty = query.is_empty();
6703                    let select_state = SelectNextState {
6704                        query: AhoCorasick::new(&[query.chars().rev().collect::<String>()])?,
6705                        wordwise: true,
6706                        done: is_empty,
6707                    };
6708                    self.select_prev_state = Some(select_state);
6709                } else {
6710                    self.select_prev_state = None;
6711                }
6712
6713                self.unfold_ranges(
6714                    selections.iter().map(|s| s.range()).collect::<Vec<_>>(),
6715                    false,
6716                    true,
6717                    cx,
6718                );
6719                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
6720                    s.select(selections);
6721                });
6722            } else if let Some(selected_text) = selected_text {
6723                self.select_prev_state = Some(SelectNextState {
6724                    query: AhoCorasick::new(&[selected_text.chars().rev().collect::<String>()])?,
6725                    wordwise: false,
6726                    done: false,
6727                });
6728                self.select_previous(action, cx)?;
6729            }
6730        }
6731        Ok(())
6732    }
6733
6734    pub fn toggle_comments(&mut self, action: &ToggleComments, cx: &mut ViewContext<Self>) {
6735        let text_layout_details = &self.text_layout_details(cx);
6736        self.transact(cx, |this, cx| {
6737            let mut selections = this.selections.all::<Point>(cx);
6738            let mut edits = Vec::new();
6739            let mut selection_edit_ranges = Vec::new();
6740            let mut last_toggled_row = None;
6741            let snapshot = this.buffer.read(cx).read(cx);
6742            let empty_str: Arc<str> = "".into();
6743            let mut suffixes_inserted = Vec::new();
6744
6745            fn comment_prefix_range(
6746                snapshot: &MultiBufferSnapshot,
6747                row: u32,
6748                comment_prefix: &str,
6749                comment_prefix_whitespace: &str,
6750            ) -> Range<Point> {
6751                let start = Point::new(row, snapshot.indent_size_for_line(row).len);
6752
6753                let mut line_bytes = snapshot
6754                    .bytes_in_range(start..snapshot.max_point())
6755                    .flatten()
6756                    .copied();
6757
6758                // If this line currently begins with the line comment prefix, then record
6759                // the range containing the prefix.
6760                if line_bytes
6761                    .by_ref()
6762                    .take(comment_prefix.len())
6763                    .eq(comment_prefix.bytes())
6764                {
6765                    // Include any whitespace that matches the comment prefix.
6766                    let matching_whitespace_len = line_bytes
6767                        .zip(comment_prefix_whitespace.bytes())
6768                        .take_while(|(a, b)| a == b)
6769                        .count() as u32;
6770                    let end = Point::new(
6771                        start.row,
6772                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
6773                    );
6774                    start..end
6775                } else {
6776                    start..start
6777                }
6778            }
6779
6780            fn comment_suffix_range(
6781                snapshot: &MultiBufferSnapshot,
6782                row: u32,
6783                comment_suffix: &str,
6784                comment_suffix_has_leading_space: bool,
6785            ) -> Range<Point> {
6786                let end = Point::new(row, snapshot.line_len(row));
6787                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
6788
6789                let mut line_end_bytes = snapshot
6790                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
6791                    .flatten()
6792                    .copied();
6793
6794                let leading_space_len = if suffix_start_column > 0
6795                    && line_end_bytes.next() == Some(b' ')
6796                    && comment_suffix_has_leading_space
6797                {
6798                    1
6799                } else {
6800                    0
6801                };
6802
6803                // If this line currently begins with the line comment prefix, then record
6804                // the range containing the prefix.
6805                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
6806                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
6807                    start..end
6808                } else {
6809                    end..end
6810                }
6811            }
6812
6813            // TODO: Handle selections that cross excerpts
6814            for selection in &mut selections {
6815                let start_column = snapshot.indent_size_for_line(selection.start.row).len;
6816                let language = if let Some(language) =
6817                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
6818                {
6819                    language
6820                } else {
6821                    continue;
6822                };
6823
6824                selection_edit_ranges.clear();
6825
6826                // If multiple selections contain a given row, avoid processing that
6827                // row more than once.
6828                let mut start_row = selection.start.row;
6829                if last_toggled_row == Some(start_row) {
6830                    start_row += 1;
6831                }
6832                let end_row =
6833                    if selection.end.row > selection.start.row && selection.end.column == 0 {
6834                        selection.end.row - 1
6835                    } else {
6836                        selection.end.row
6837                    };
6838                last_toggled_row = Some(end_row);
6839
6840                if start_row > end_row {
6841                    continue;
6842                }
6843
6844                // If the language has line comments, toggle those.
6845                if let Some(full_comment_prefix) = language.line_comment_prefix() {
6846                    // Split the comment prefix's trailing whitespace into a separate string,
6847                    // as that portion won't be used for detecting if a line is a comment.
6848                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
6849                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
6850                    let mut all_selection_lines_are_comments = true;
6851
6852                    for row in start_row..=end_row {
6853                        if snapshot.is_line_blank(row) && start_row < end_row {
6854                            continue;
6855                        }
6856
6857                        let prefix_range = comment_prefix_range(
6858                            snapshot.deref(),
6859                            row,
6860                            comment_prefix,
6861                            comment_prefix_whitespace,
6862                        );
6863                        if prefix_range.is_empty() {
6864                            all_selection_lines_are_comments = false;
6865                        }
6866                        selection_edit_ranges.push(prefix_range);
6867                    }
6868
6869                    if all_selection_lines_are_comments {
6870                        edits.extend(
6871                            selection_edit_ranges
6872                                .iter()
6873                                .cloned()
6874                                .map(|range| (range, empty_str.clone())),
6875                        );
6876                    } else {
6877                        let min_column = selection_edit_ranges
6878                            .iter()
6879                            .map(|r| r.start.column)
6880                            .min()
6881                            .unwrap_or(0);
6882                        edits.extend(selection_edit_ranges.iter().map(|range| {
6883                            let position = Point::new(range.start.row, min_column);
6884                            (position..position, full_comment_prefix.clone())
6885                        }));
6886                    }
6887                } else if let Some((full_comment_prefix, comment_suffix)) =
6888                    language.block_comment_delimiters()
6889                {
6890                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
6891                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
6892                    let prefix_range = comment_prefix_range(
6893                        snapshot.deref(),
6894                        start_row,
6895                        comment_prefix,
6896                        comment_prefix_whitespace,
6897                    );
6898                    let suffix_range = comment_suffix_range(
6899                        snapshot.deref(),
6900                        end_row,
6901                        comment_suffix.trim_start_matches(' '),
6902                        comment_suffix.starts_with(' '),
6903                    );
6904
6905                    if prefix_range.is_empty() || suffix_range.is_empty() {
6906                        edits.push((
6907                            prefix_range.start..prefix_range.start,
6908                            full_comment_prefix.clone(),
6909                        ));
6910                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
6911                        suffixes_inserted.push((end_row, comment_suffix.len()));
6912                    } else {
6913                        edits.push((prefix_range, empty_str.clone()));
6914                        edits.push((suffix_range, empty_str.clone()));
6915                    }
6916                } else {
6917                    continue;
6918                }
6919            }
6920
6921            drop(snapshot);
6922            this.buffer.update(cx, |buffer, cx| {
6923                buffer.edit(edits, None, cx);
6924            });
6925
6926            // Adjust selections so that they end before any comment suffixes that
6927            // were inserted.
6928            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
6929            let mut selections = this.selections.all::<Point>(cx);
6930            let snapshot = this.buffer.read(cx).read(cx);
6931            for selection in &mut selections {
6932                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
6933                    match row.cmp(&selection.end.row) {
6934                        Ordering::Less => {
6935                            suffixes_inserted.next();
6936                            continue;
6937                        }
6938                        Ordering::Greater => break,
6939                        Ordering::Equal => {
6940                            if selection.end.column == snapshot.line_len(row) {
6941                                if selection.is_empty() {
6942                                    selection.start.column -= suffix_len as u32;
6943                                }
6944                                selection.end.column -= suffix_len as u32;
6945                            }
6946                            break;
6947                        }
6948                    }
6949                }
6950            }
6951
6952            drop(snapshot);
6953            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
6954
6955            let selections = this.selections.all::<Point>(cx);
6956            let selections_on_single_row = selections.windows(2).all(|selections| {
6957                selections[0].start.row == selections[1].start.row
6958                    && selections[0].end.row == selections[1].end.row
6959                    && selections[0].start.row == selections[0].end.row
6960            });
6961            let selections_selecting = selections
6962                .iter()
6963                .any(|selection| selection.start != selection.end);
6964            let advance_downwards = action.advance_downwards
6965                && selections_on_single_row
6966                && !selections_selecting
6967                && this.mode != EditorMode::SingleLine;
6968
6969            if advance_downwards {
6970                let snapshot = this.buffer.read(cx).snapshot(cx);
6971
6972                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
6973                    s.move_cursors_with(|display_snapshot, display_point, _| {
6974                        let mut point = display_point.to_point(display_snapshot);
6975                        point.row += 1;
6976                        point = snapshot.clip_point(point, Bias::Left);
6977                        let display_point = point.to_display_point(display_snapshot);
6978                        let goal = SelectionGoal::HorizontalPosition(
6979                            display_snapshot
6980                                .x_for_display_point(display_point, &text_layout_details)
6981                                .into(),
6982                        );
6983                        (display_point, goal)
6984                    })
6985                });
6986            }
6987        });
6988    }
6989
6990    pub fn select_larger_syntax_node(
6991        &mut self,
6992        _: &SelectLargerSyntaxNode,
6993        cx: &mut ViewContext<Self>,
6994    ) {
6995        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6996        let buffer = self.buffer.read(cx).snapshot(cx);
6997        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
6998
6999        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
7000        let mut selected_larger_node = false;
7001        let new_selections = old_selections
7002            .iter()
7003            .map(|selection| {
7004                let old_range = selection.start..selection.end;
7005                let mut new_range = old_range.clone();
7006                while let Some(containing_range) =
7007                    buffer.range_for_syntax_ancestor(new_range.clone())
7008                {
7009                    new_range = containing_range;
7010                    if !display_map.intersects_fold(new_range.start)
7011                        && !display_map.intersects_fold(new_range.end)
7012                    {
7013                        break;
7014                    }
7015                }
7016
7017                selected_larger_node |= new_range != old_range;
7018                Selection {
7019                    id: selection.id,
7020                    start: new_range.start,
7021                    end: new_range.end,
7022                    goal: SelectionGoal::None,
7023                    reversed: selection.reversed,
7024                }
7025            })
7026            .collect::<Vec<_>>();
7027
7028        if selected_larger_node {
7029            stack.push(old_selections);
7030            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
7031                s.select(new_selections);
7032            });
7033        }
7034        self.select_larger_syntax_node_stack = stack;
7035    }
7036
7037    pub fn select_smaller_syntax_node(
7038        &mut self,
7039        _: &SelectSmallerSyntaxNode,
7040        cx: &mut ViewContext<Self>,
7041    ) {
7042        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
7043        if let Some(selections) = stack.pop() {
7044            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
7045                s.select(selections.to_vec());
7046            });
7047        }
7048        self.select_larger_syntax_node_stack = stack;
7049    }
7050
7051    pub fn move_to_enclosing_bracket(
7052        &mut self,
7053        _: &MoveToEnclosingBracket,
7054        cx: &mut ViewContext<Self>,
7055    ) {
7056        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
7057            s.move_offsets_with(|snapshot, selection| {
7058                let Some(enclosing_bracket_ranges) =
7059                    snapshot.enclosing_bracket_ranges(selection.start..selection.end)
7060                else {
7061                    return;
7062                };
7063
7064                let mut best_length = usize::MAX;
7065                let mut best_inside = false;
7066                let mut best_in_bracket_range = false;
7067                let mut best_destination = None;
7068                for (open, close) in enclosing_bracket_ranges {
7069                    let close = close.to_inclusive();
7070                    let length = close.end() - open.start;
7071                    let inside = selection.start >= open.end && selection.end <= *close.start();
7072                    let in_bracket_range = open.to_inclusive().contains(&selection.head())
7073                        || close.contains(&selection.head());
7074
7075                    // If best is next to a bracket and current isn't, skip
7076                    if !in_bracket_range && best_in_bracket_range {
7077                        continue;
7078                    }
7079
7080                    // Prefer smaller lengths unless best is inside and current isn't
7081                    if length > best_length && (best_inside || !inside) {
7082                        continue;
7083                    }
7084
7085                    best_length = length;
7086                    best_inside = inside;
7087                    best_in_bracket_range = in_bracket_range;
7088                    best_destination = Some(
7089                        if close.contains(&selection.start) && close.contains(&selection.end) {
7090                            if inside {
7091                                open.end
7092                            } else {
7093                                open.start
7094                            }
7095                        } else {
7096                            if inside {
7097                                *close.start()
7098                            } else {
7099                                *close.end()
7100                            }
7101                        },
7102                    );
7103                }
7104
7105                if let Some(destination) = best_destination {
7106                    selection.collapse_to(destination, SelectionGoal::None);
7107                }
7108            })
7109        });
7110    }
7111
7112    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
7113        self.end_selection(cx);
7114        self.selection_history.mode = SelectionHistoryMode::Undoing;
7115        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
7116            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
7117            self.select_next_state = entry.select_next_state;
7118            self.select_prev_state = entry.select_prev_state;
7119            self.add_selections_state = entry.add_selections_state;
7120            self.request_autoscroll(Autoscroll::newest(), cx);
7121        }
7122        self.selection_history.mode = SelectionHistoryMode::Normal;
7123    }
7124
7125    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
7126        self.end_selection(cx);
7127        self.selection_history.mode = SelectionHistoryMode::Redoing;
7128        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
7129            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
7130            self.select_next_state = entry.select_next_state;
7131            self.select_prev_state = entry.select_prev_state;
7132            self.add_selections_state = entry.add_selections_state;
7133            self.request_autoscroll(Autoscroll::newest(), cx);
7134        }
7135        self.selection_history.mode = SelectionHistoryMode::Normal;
7136    }
7137
7138    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
7139        self.go_to_diagnostic_impl(Direction::Next, cx)
7140    }
7141
7142    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
7143        self.go_to_diagnostic_impl(Direction::Prev, cx)
7144    }
7145
7146    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
7147        let buffer = self.buffer.read(cx).snapshot(cx);
7148        let selection = self.selections.newest::<usize>(cx);
7149
7150        // If there is an active Diagnostic Popover jump to its diagnostic instead.
7151        if direction == Direction::Next {
7152            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
7153                let (group_id, jump_to) = popover.activation_info();
7154                if self.activate_diagnostics(group_id, cx) {
7155                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
7156                        let mut new_selection = s.newest_anchor().clone();
7157                        new_selection.collapse_to(jump_to, SelectionGoal::None);
7158                        s.select_anchors(vec![new_selection.clone()]);
7159                    });
7160                }
7161                return;
7162            }
7163        }
7164
7165        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
7166            active_diagnostics
7167                .primary_range
7168                .to_offset(&buffer)
7169                .to_inclusive()
7170        });
7171        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
7172            if active_primary_range.contains(&selection.head()) {
7173                *active_primary_range.end()
7174            } else {
7175                selection.head()
7176            }
7177        } else {
7178            selection.head()
7179        };
7180
7181        loop {
7182            let mut diagnostics = if direction == Direction::Prev {
7183                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
7184            } else {
7185                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
7186            };
7187            let group = diagnostics.find_map(|entry| {
7188                if entry.diagnostic.is_primary
7189                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
7190                    && !entry.range.is_empty()
7191                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
7192                    && !entry.range.contains(&search_start)
7193                {
7194                    Some((entry.range, entry.diagnostic.group_id))
7195                } else {
7196                    None
7197                }
7198            });
7199
7200            if let Some((primary_range, group_id)) = group {
7201                if self.activate_diagnostics(group_id, cx) {
7202                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
7203                        s.select(vec![Selection {
7204                            id: selection.id,
7205                            start: primary_range.start,
7206                            end: primary_range.start,
7207                            reversed: false,
7208                            goal: SelectionGoal::None,
7209                        }]);
7210                    });
7211                }
7212                break;
7213            } else {
7214                // Cycle around to the start of the buffer, potentially moving back to the start of
7215                // the currently active diagnostic.
7216                active_primary_range.take();
7217                if direction == Direction::Prev {
7218                    if search_start == buffer.len() {
7219                        break;
7220                    } else {
7221                        search_start = buffer.len();
7222                    }
7223                } else if search_start == 0 {
7224                    break;
7225                } else {
7226                    search_start = 0;
7227                }
7228            }
7229        }
7230    }
7231
7232    fn go_to_hunk(&mut self, _: &GoToHunk, cx: &mut ViewContext<Self>) {
7233        let snapshot = self
7234            .display_map
7235            .update(cx, |display_map, cx| display_map.snapshot(cx));
7236        let selection = self.selections.newest::<Point>(cx);
7237
7238        if !self.seek_in_direction(
7239            &snapshot,
7240            selection.head(),
7241            false,
7242            snapshot
7243                .buffer_snapshot
7244                .git_diff_hunks_in_range((selection.head().row + 1)..u32::MAX),
7245            cx,
7246        ) {
7247            let wrapped_point = Point::zero();
7248            self.seek_in_direction(
7249                &snapshot,
7250                wrapped_point,
7251                true,
7252                snapshot
7253                    .buffer_snapshot
7254                    .git_diff_hunks_in_range((wrapped_point.row + 1)..u32::MAX),
7255                cx,
7256            );
7257        }
7258    }
7259
7260    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
7261        let snapshot = self
7262            .display_map
7263            .update(cx, |display_map, cx| display_map.snapshot(cx));
7264        let selection = self.selections.newest::<Point>(cx);
7265
7266        if !self.seek_in_direction(
7267            &snapshot,
7268            selection.head(),
7269            false,
7270            snapshot
7271                .buffer_snapshot
7272                .git_diff_hunks_in_range_rev(0..selection.head().row),
7273            cx,
7274        ) {
7275            let wrapped_point = snapshot.buffer_snapshot.max_point();
7276            self.seek_in_direction(
7277                &snapshot,
7278                wrapped_point,
7279                true,
7280                snapshot
7281                    .buffer_snapshot
7282                    .git_diff_hunks_in_range_rev(0..wrapped_point.row),
7283                cx,
7284            );
7285        }
7286    }
7287
7288    fn seek_in_direction(
7289        &mut self,
7290        snapshot: &DisplaySnapshot,
7291        initial_point: Point,
7292        is_wrapped: bool,
7293        hunks: impl Iterator<Item = DiffHunk<u32>>,
7294        cx: &mut ViewContext<Editor>,
7295    ) -> bool {
7296        let display_point = initial_point.to_display_point(snapshot);
7297        let mut hunks = hunks
7298            .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
7299            .filter(|hunk| {
7300                if is_wrapped {
7301                    true
7302                } else {
7303                    !hunk.contains_display_row(display_point.row())
7304                }
7305            })
7306            .dedup();
7307
7308        if let Some(hunk) = hunks.next() {
7309            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
7310                let row = hunk.start_display_row();
7311                let point = DisplayPoint::new(row, 0);
7312                s.select_display_ranges([point..point]);
7313            });
7314
7315            true
7316        } else {
7317            false
7318        }
7319    }
7320
7321    pub fn go_to_definition(&mut self, _: &GoToDefinition, cx: &mut ViewContext<Self>) {
7322        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, false, cx);
7323    }
7324
7325    pub fn go_to_type_definition(&mut self, _: &GoToTypeDefinition, cx: &mut ViewContext<Self>) {
7326        self.go_to_definition_of_kind(GotoDefinitionKind::Type, false, cx);
7327    }
7328
7329    pub fn go_to_definition_split(&mut self, _: &GoToDefinitionSplit, cx: &mut ViewContext<Self>) {
7330        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, true, cx);
7331    }
7332
7333    pub fn go_to_type_definition_split(
7334        &mut self,
7335        _: &GoToTypeDefinitionSplit,
7336        cx: &mut ViewContext<Self>,
7337    ) {
7338        self.go_to_definition_of_kind(GotoDefinitionKind::Type, true, cx);
7339    }
7340
7341    fn go_to_definition_of_kind(
7342        &mut self,
7343        kind: GotoDefinitionKind,
7344        split: bool,
7345        cx: &mut ViewContext<Self>,
7346    ) {
7347        let Some(workspace) = self.workspace() else {
7348            return;
7349        };
7350        let buffer = self.buffer.read(cx);
7351        let head = self.selections.newest::<usize>(cx).head();
7352        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
7353            text_anchor
7354        } else {
7355            return;
7356        };
7357
7358        let project = workspace.read(cx).project().clone();
7359        let definitions = project.update(cx, |project, cx| match kind {
7360            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
7361            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
7362        });
7363
7364        cx.spawn(|editor, mut cx| async move {
7365            let definitions = definitions.await?;
7366            editor.update(&mut cx, |editor, cx| {
7367                editor.navigate_to_definitions(
7368                    definitions
7369                        .into_iter()
7370                        .map(GoToDefinitionLink::Text)
7371                        .collect(),
7372                    split,
7373                    cx,
7374                );
7375            })?;
7376            Ok::<(), anyhow::Error>(())
7377        })
7378        .detach_and_log_err(cx);
7379    }
7380
7381    pub fn navigate_to_definitions(
7382        &mut self,
7383        mut definitions: Vec<GoToDefinitionLink>,
7384        split: bool,
7385        cx: &mut ViewContext<Editor>,
7386    ) {
7387        let Some(workspace) = self.workspace() else {
7388            return;
7389        };
7390        let pane = workspace.read(cx).active_pane().clone();
7391        // If there is one definition, just open it directly
7392        if definitions.len() == 1 {
7393            let definition = definitions.pop().unwrap();
7394            let target_task = match definition {
7395                GoToDefinitionLink::Text(link) => Task::Ready(Some(Ok(Some(link.target)))),
7396                GoToDefinitionLink::InlayHint(lsp_location, server_id) => {
7397                    self.compute_target_location(lsp_location, server_id, cx)
7398                }
7399            };
7400            cx.spawn(|editor, mut cx| async move {
7401                let target = target_task.await.context("target resolution task")?;
7402                if let Some(target) = target {
7403                    editor.update(&mut cx, |editor, cx| {
7404                        let range = target.range.to_offset(target.buffer.read(cx));
7405                        let range = editor.range_for_match(&range);
7406                        if Some(&target.buffer) == editor.buffer.read(cx).as_singleton().as_ref() {
7407                            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
7408                                s.select_ranges([range]);
7409                            });
7410                        } else {
7411                            cx.window_context().defer(move |cx| {
7412                                let target_editor: View<Self> =
7413                                    workspace.update(cx, |workspace, cx| {
7414                                        if split {
7415                                            workspace.split_project_item(target.buffer.clone(), cx)
7416                                        } else {
7417                                            workspace.open_project_item(target.buffer.clone(), cx)
7418                                        }
7419                                    });
7420                                target_editor.update(cx, |target_editor, cx| {
7421                                    // When selecting a definition in a different buffer, disable the nav history
7422                                    // to avoid creating a history entry at the previous cursor location.
7423                                    pane.update(cx, |pane, _| pane.disable_history());
7424                                    target_editor.change_selections(
7425                                        Some(Autoscroll::fit()),
7426                                        cx,
7427                                        |s| {
7428                                            s.select_ranges([range]);
7429                                        },
7430                                    );
7431                                    pane.update(cx, |pane, _| pane.enable_history());
7432                                });
7433                            });
7434                        }
7435                    })
7436                } else {
7437                    Ok(())
7438                }
7439            })
7440            .detach_and_log_err(cx);
7441        } else if !definitions.is_empty() {
7442            let replica_id = self.replica_id(cx);
7443            cx.spawn(|editor, mut cx| async move {
7444                let (title, location_tasks) = editor
7445                    .update(&mut cx, |editor, cx| {
7446                        let title = definitions
7447                            .iter()
7448                            .find_map(|definition| match definition {
7449                                GoToDefinitionLink::Text(link) => {
7450                                    link.origin.as_ref().map(|origin| {
7451                                        let buffer = origin.buffer.read(cx);
7452                                        format!(
7453                                            "Definitions for {}",
7454                                            buffer
7455                                                .text_for_range(origin.range.clone())
7456                                                .collect::<String>()
7457                                        )
7458                                    })
7459                                }
7460                                GoToDefinitionLink::InlayHint(_, _) => None,
7461                            })
7462                            .unwrap_or("Definitions".to_string());
7463                        let location_tasks = definitions
7464                            .into_iter()
7465                            .map(|definition| match definition {
7466                                GoToDefinitionLink::Text(link) => {
7467                                    Task::Ready(Some(Ok(Some(link.target))))
7468                                }
7469                                GoToDefinitionLink::InlayHint(lsp_location, server_id) => {
7470                                    editor.compute_target_location(lsp_location, server_id, cx)
7471                                }
7472                            })
7473                            .collect::<Vec<_>>();
7474                        (title, location_tasks)
7475                    })
7476                    .context("location tasks preparation")?;
7477
7478                let locations = futures::future::join_all(location_tasks)
7479                    .await
7480                    .into_iter()
7481                    .filter_map(|location| location.transpose())
7482                    .collect::<Result<_>>()
7483                    .context("location tasks")?;
7484                workspace
7485                    .update(&mut cx, |workspace, cx| {
7486                        Self::open_locations_in_multibuffer(
7487                            workspace, locations, replica_id, title, split, cx,
7488                        )
7489                    })
7490                    .ok();
7491
7492                anyhow::Ok(())
7493            })
7494            .detach_and_log_err(cx);
7495        }
7496    }
7497
7498    fn compute_target_location(
7499        &self,
7500        lsp_location: lsp::Location,
7501        server_id: LanguageServerId,
7502        cx: &mut ViewContext<Editor>,
7503    ) -> Task<anyhow::Result<Option<Location>>> {
7504        let Some(project) = self.project.clone() else {
7505            return Task::Ready(Some(Ok(None)));
7506        };
7507
7508        cx.spawn(move |editor, mut cx| async move {
7509            let location_task = editor.update(&mut cx, |editor, cx| {
7510                project.update(cx, |project, cx| {
7511                    let language_server_name =
7512                        editor.buffer.read(cx).as_singleton().and_then(|buffer| {
7513                            project
7514                                .language_server_for_buffer(buffer.read(cx), server_id, cx)
7515                                .map(|(_, lsp_adapter)| {
7516                                    LanguageServerName(Arc::from(lsp_adapter.name()))
7517                                })
7518                        });
7519                    language_server_name.map(|language_server_name| {
7520                        project.open_local_buffer_via_lsp(
7521                            lsp_location.uri.clone(),
7522                            server_id,
7523                            language_server_name,
7524                            cx,
7525                        )
7526                    })
7527                })
7528            })?;
7529            let location = match location_task {
7530                Some(task) => Some({
7531                    let target_buffer_handle = task.await.context("open local buffer")?;
7532                    let range = target_buffer_handle.update(&mut cx, |target_buffer, _| {
7533                        let target_start = target_buffer
7534                            .clip_point_utf16(point_from_lsp(lsp_location.range.start), Bias::Left);
7535                        let target_end = target_buffer
7536                            .clip_point_utf16(point_from_lsp(lsp_location.range.end), Bias::Left);
7537                        target_buffer.anchor_after(target_start)
7538                            ..target_buffer.anchor_before(target_end)
7539                    })?;
7540                    Location {
7541                        buffer: target_buffer_handle,
7542                        range,
7543                    }
7544                }),
7545                None => None,
7546            };
7547            Ok(location)
7548        })
7549    }
7550
7551    pub fn find_all_references(
7552        &mut self,
7553        _: &FindAllReferences,
7554        cx: &mut ViewContext<Self>,
7555    ) -> Option<Task<Result<()>>> {
7556        let buffer = self.buffer.read(cx);
7557        let head = self.selections.newest::<usize>(cx).head();
7558        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
7559        let replica_id = self.replica_id(cx);
7560
7561        let workspace = self.workspace()?;
7562        let project = workspace.read(cx).project().clone();
7563        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
7564        Some(cx.spawn(|_, mut cx| async move {
7565            let locations = references.await?;
7566            if locations.is_empty() {
7567                return Ok(());
7568            }
7569
7570            workspace.update(&mut cx, |workspace, cx| {
7571                let title = locations
7572                    .first()
7573                    .as_ref()
7574                    .map(|location| {
7575                        let buffer = location.buffer.read(cx);
7576                        format!(
7577                            "References to `{}`",
7578                            buffer
7579                                .text_for_range(location.range.clone())
7580                                .collect::<String>()
7581                        )
7582                    })
7583                    .unwrap();
7584                Self::open_locations_in_multibuffer(
7585                    workspace, locations, replica_id, title, false, cx,
7586                );
7587            })?;
7588
7589            Ok(())
7590        }))
7591    }
7592
7593    /// Opens a multibuffer with the given project locations in it
7594    pub fn open_locations_in_multibuffer(
7595        workspace: &mut Workspace,
7596        mut locations: Vec<Location>,
7597        replica_id: ReplicaId,
7598        title: String,
7599        split: bool,
7600        cx: &mut ViewContext<Workspace>,
7601    ) {
7602        // If there are multiple definitions, open them in a multibuffer
7603        locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
7604        let mut locations = locations.into_iter().peekable();
7605        let mut ranges_to_highlight = Vec::new();
7606        let capability = workspace.project().read(cx).capability();
7607
7608        let excerpt_buffer = cx.new_model(|cx| {
7609            let mut multibuffer = MultiBuffer::new(replica_id, capability);
7610            while let Some(location) = locations.next() {
7611                let buffer = location.buffer.read(cx);
7612                let mut ranges_for_buffer = Vec::new();
7613                let range = location.range.to_offset(buffer);
7614                ranges_for_buffer.push(range.clone());
7615
7616                while let Some(next_location) = locations.peek() {
7617                    if next_location.buffer == location.buffer {
7618                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
7619                        locations.next();
7620                    } else {
7621                        break;
7622                    }
7623                }
7624
7625                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
7626                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
7627                    location.buffer.clone(),
7628                    ranges_for_buffer,
7629                    1,
7630                    cx,
7631                ))
7632            }
7633
7634            multibuffer.with_title(title)
7635        });
7636
7637        let editor = cx.new_view(|cx| {
7638            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx)
7639        });
7640        editor.update(cx, |editor, cx| {
7641            editor.highlight_background::<Self>(
7642                ranges_to_highlight,
7643                |theme| theme.editor_highlighted_line_background,
7644                cx,
7645            );
7646        });
7647        if split {
7648            workspace.split_item(SplitDirection::Right, Box::new(editor), cx);
7649        } else {
7650            workspace.add_item(Box::new(editor), cx);
7651        }
7652    }
7653
7654    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
7655        use language::ToOffset as _;
7656
7657        let project = self.project.clone()?;
7658        let selection = self.selections.newest_anchor().clone();
7659        let (cursor_buffer, cursor_buffer_position) = self
7660            .buffer
7661            .read(cx)
7662            .text_anchor_for_position(selection.head(), cx)?;
7663        let (tail_buffer, _) = self
7664            .buffer
7665            .read(cx)
7666            .text_anchor_for_position(selection.tail(), cx)?;
7667        if tail_buffer != cursor_buffer {
7668            return None;
7669        }
7670
7671        let snapshot = cursor_buffer.read(cx).snapshot();
7672        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
7673        let prepare_rename = project.update(cx, |project, cx| {
7674            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
7675        });
7676
7677        Some(cx.spawn(|this, mut cx| async move {
7678            let rename_range = if let Some(range) = prepare_rename.await? {
7679                Some(range)
7680            } else {
7681                this.update(&mut cx, |this, cx| {
7682                    let buffer = this.buffer.read(cx).snapshot(cx);
7683                    let mut buffer_highlights = this
7684                        .document_highlights_for_position(selection.head(), &buffer)
7685                        .filter(|highlight| {
7686                            highlight.start.excerpt_id == selection.head().excerpt_id
7687                                && highlight.end.excerpt_id == selection.head().excerpt_id
7688                        });
7689                    buffer_highlights
7690                        .next()
7691                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
7692                })?
7693            };
7694            if let Some(rename_range) = rename_range {
7695                let rename_buffer_range = rename_range.to_offset(&snapshot);
7696                let cursor_offset_in_rename_range =
7697                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
7698
7699                this.update(&mut cx, |this, cx| {
7700                    this.take_rename(false, cx);
7701                    let buffer = this.buffer.read(cx).read(cx);
7702                    let cursor_offset = selection.head().to_offset(&buffer);
7703                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
7704                    let rename_end = rename_start + rename_buffer_range.len();
7705                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
7706                    let mut old_highlight_id = None;
7707                    let old_name: Arc<str> = buffer
7708                        .chunks(rename_start..rename_end, true)
7709                        .map(|chunk| {
7710                            if old_highlight_id.is_none() {
7711                                old_highlight_id = chunk.syntax_highlight_id;
7712                            }
7713                            chunk.text
7714                        })
7715                        .collect::<String>()
7716                        .into();
7717
7718                    drop(buffer);
7719
7720                    // Position the selection in the rename editor so that it matches the current selection.
7721                    this.show_local_selections = false;
7722                    let rename_editor = cx.new_view(|cx| {
7723                        let mut editor = Editor::single_line(cx);
7724                        editor.buffer.update(cx, |buffer, cx| {
7725                            buffer.edit([(0..0, old_name.clone())], None, cx)
7726                        });
7727                        editor.select_all(&SelectAll, cx);
7728                        editor
7729                    });
7730
7731                    let ranges = this
7732                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
7733                        .into_iter()
7734                        .flat_map(|(_, ranges)| ranges.into_iter())
7735                        .chain(
7736                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
7737                                .into_iter()
7738                                .flat_map(|(_, ranges)| ranges.into_iter()),
7739                        )
7740                        .collect();
7741
7742                    this.highlight_text::<Rename>(
7743                        ranges,
7744                        HighlightStyle {
7745                            fade_out: Some(0.6),
7746                            ..Default::default()
7747                        },
7748                        cx,
7749                    );
7750                    let rename_focus_handle = rename_editor.focus_handle(cx);
7751                    cx.focus(&rename_focus_handle);
7752                    let block_id = this.insert_blocks(
7753                        [BlockProperties {
7754                            style: BlockStyle::Flex,
7755                            position: range.start.clone(),
7756                            height: 1,
7757                            render: Arc::new({
7758                                let rename_editor = rename_editor.clone();
7759                                move |cx: &mut BlockContext| {
7760                                    let mut text_style = cx.editor_style.text.clone();
7761                                    if let Some(highlight_style) = old_highlight_id
7762                                        .and_then(|h| h.style(&cx.editor_style.syntax))
7763                                    {
7764                                        text_style = text_style.highlight(highlight_style);
7765                                    }
7766                                    div()
7767                                        .pl(cx.anchor_x)
7768                                        .child(EditorElement::new(
7769                                            &rename_editor,
7770                                            EditorStyle {
7771                                                background: cx.theme().system().transparent,
7772                                                local_player: cx.editor_style.local_player,
7773                                                text: text_style,
7774                                                scrollbar_width: cx.editor_style.scrollbar_width,
7775                                                syntax: cx.editor_style.syntax.clone(),
7776                                                status: cx.editor_style.status.clone(),
7777                                                inlays_style: HighlightStyle {
7778                                                    color: Some(cx.theme().status().hint),
7779                                                    font_weight: Some(FontWeight::BOLD),
7780                                                    ..HighlightStyle::default()
7781                                                },
7782                                                suggestions_style: HighlightStyle {
7783                                                    color: Some(cx.theme().status().predictive),
7784                                                    ..HighlightStyle::default()
7785                                                },
7786                                            },
7787                                        ))
7788                                        .into_any_element()
7789                                }
7790                            }),
7791                            disposition: BlockDisposition::Below,
7792                        }],
7793                        Some(Autoscroll::fit()),
7794                        cx,
7795                    )[0];
7796                    this.pending_rename = Some(RenameState {
7797                        range,
7798                        old_name,
7799                        editor: rename_editor,
7800                        block_id,
7801                    });
7802                })?;
7803            }
7804
7805            Ok(())
7806        }))
7807    }
7808
7809    pub fn confirm_rename(
7810        &mut self,
7811        _: &ConfirmRename,
7812        cx: &mut ViewContext<Self>,
7813    ) -> Option<Task<Result<()>>> {
7814        let rename = self.take_rename(false, cx)?;
7815        let workspace = self.workspace()?;
7816        let (start_buffer, start) = self
7817            .buffer
7818            .read(cx)
7819            .text_anchor_for_position(rename.range.start.clone(), cx)?;
7820        let (end_buffer, end) = self
7821            .buffer
7822            .read(cx)
7823            .text_anchor_for_position(rename.range.end.clone(), cx)?;
7824        if start_buffer != end_buffer {
7825            return None;
7826        }
7827
7828        let buffer = start_buffer;
7829        let range = start..end;
7830        let old_name = rename.old_name;
7831        let new_name = rename.editor.read(cx).text(cx);
7832
7833        let rename = workspace
7834            .read(cx)
7835            .project()
7836            .clone()
7837            .update(cx, |project, cx| {
7838                project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
7839            });
7840        let workspace = workspace.downgrade();
7841
7842        Some(cx.spawn(|editor, mut cx| async move {
7843            let project_transaction = rename.await?;
7844            Self::open_project_transaction(
7845                &editor,
7846                workspace,
7847                project_transaction,
7848                format!("Rename: {}{}", old_name, new_name),
7849                cx.clone(),
7850            )
7851            .await?;
7852
7853            editor.update(&mut cx, |editor, cx| {
7854                editor.refresh_document_highlights(cx);
7855            })?;
7856            Ok(())
7857        }))
7858    }
7859
7860    fn take_rename(
7861        &mut self,
7862        moving_cursor: bool,
7863        cx: &mut ViewContext<Self>,
7864    ) -> Option<RenameState> {
7865        let rename = self.pending_rename.take()?;
7866        if rename.editor.focus_handle(cx).is_focused(cx) {
7867            cx.focus(&self.focus_handle);
7868        }
7869
7870        self.remove_blocks(
7871            [rename.block_id].into_iter().collect(),
7872            Some(Autoscroll::fit()),
7873            cx,
7874        );
7875        self.clear_highlights::<Rename>(cx);
7876        self.show_local_selections = true;
7877
7878        if moving_cursor {
7879            let rename_editor = rename.editor.read(cx);
7880            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
7881
7882            // Update the selection to match the position of the selection inside
7883            // the rename editor.
7884            let snapshot = self.buffer.read(cx).read(cx);
7885            let rename_range = rename.range.to_offset(&snapshot);
7886            let cursor_in_editor = snapshot
7887                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
7888                .min(rename_range.end);
7889            drop(snapshot);
7890
7891            self.change_selections(None, cx, |s| {
7892                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
7893            });
7894        } else {
7895            self.refresh_document_highlights(cx);
7896        }
7897
7898        Some(rename)
7899    }
7900
7901    #[cfg(any(test, feature = "test-support"))]
7902    pub fn pending_rename(&self) -> Option<&RenameState> {
7903        self.pending_rename.as_ref()
7904    }
7905
7906    fn format(&mut self, _: &Format, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
7907        let project = match &self.project {
7908            Some(project) => project.clone(),
7909            None => return None,
7910        };
7911
7912        Some(self.perform_format(project, FormatTrigger::Manual, cx))
7913    }
7914
7915    fn perform_format(
7916        &mut self,
7917        project: Model<Project>,
7918        trigger: FormatTrigger,
7919        cx: &mut ViewContext<Self>,
7920    ) -> Task<Result<()>> {
7921        let buffer = self.buffer().clone();
7922        let buffers = buffer.read(cx).all_buffers();
7923
7924        let mut timeout = cx.background_executor().timer(FORMAT_TIMEOUT).fuse();
7925        let format = project.update(cx, |project, cx| project.format(buffers, true, trigger, cx));
7926
7927        cx.spawn(|_, mut cx| async move {
7928            let transaction = futures::select_biased! {
7929                _ = timeout => {
7930                    log::warn!("timed out waiting for formatting");
7931                    None
7932                }
7933                transaction = format.log_err().fuse() => transaction,
7934            };
7935
7936            buffer
7937                .update(&mut cx, |buffer, cx| {
7938                    if let Some(transaction) = transaction {
7939                        if !buffer.is_singleton() {
7940                            buffer.push_transaction(&transaction.0, cx);
7941                        }
7942                    }
7943
7944                    cx.notify();
7945                })
7946                .ok();
7947
7948            Ok(())
7949        })
7950    }
7951
7952    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
7953        if let Some(project) = self.project.clone() {
7954            self.buffer.update(cx, |multi_buffer, cx| {
7955                project.update(cx, |project, cx| {
7956                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
7957                });
7958            })
7959        }
7960    }
7961
7962    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
7963        cx.show_character_palette();
7964    }
7965
7966    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
7967        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
7968            let buffer = self.buffer.read(cx).snapshot(cx);
7969            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
7970            let is_valid = buffer
7971                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
7972                .any(|entry| {
7973                    entry.diagnostic.is_primary
7974                        && !entry.range.is_empty()
7975                        && entry.range.start == primary_range_start
7976                        && entry.diagnostic.message == active_diagnostics.primary_message
7977                });
7978
7979            if is_valid != active_diagnostics.is_valid {
7980                active_diagnostics.is_valid = is_valid;
7981                let mut new_styles = HashMap::default();
7982                for (block_id, diagnostic) in &active_diagnostics.blocks {
7983                    new_styles.insert(
7984                        *block_id,
7985                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
7986                    );
7987                }
7988                self.display_map
7989                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
7990            }
7991        }
7992    }
7993
7994    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
7995        self.dismiss_diagnostics(cx);
7996        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
7997            let buffer = self.buffer.read(cx).snapshot(cx);
7998
7999            let mut primary_range = None;
8000            let mut primary_message = None;
8001            let mut group_end = Point::zero();
8002            let diagnostic_group = buffer
8003                .diagnostic_group::<Point>(group_id)
8004                .map(|entry| {
8005                    if entry.range.end > group_end {
8006                        group_end = entry.range.end;
8007                    }
8008                    if entry.diagnostic.is_primary {
8009                        primary_range = Some(entry.range.clone());
8010                        primary_message = Some(entry.diagnostic.message.clone());
8011                    }
8012                    entry
8013                })
8014                .collect::<Vec<_>>();
8015            let primary_range = primary_range?;
8016            let primary_message = primary_message?;
8017            let primary_range =
8018                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
8019
8020            let blocks = display_map
8021                .insert_blocks(
8022                    diagnostic_group.iter().map(|entry| {
8023                        let diagnostic = entry.diagnostic.clone();
8024                        let message_height = diagnostic.message.lines().count() as u8;
8025                        BlockProperties {
8026                            style: BlockStyle::Fixed,
8027                            position: buffer.anchor_after(entry.range.start),
8028                            height: message_height,
8029                            render: diagnostic_block_renderer(diagnostic, true),
8030                            disposition: BlockDisposition::Below,
8031                        }
8032                    }),
8033                    cx,
8034                )
8035                .into_iter()
8036                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
8037                .collect();
8038
8039            Some(ActiveDiagnosticGroup {
8040                primary_range,
8041                primary_message,
8042                blocks,
8043                is_valid: true,
8044            })
8045        });
8046        self.active_diagnostics.is_some()
8047    }
8048
8049    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
8050        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
8051            self.display_map.update(cx, |display_map, cx| {
8052                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
8053            });
8054            cx.notify();
8055        }
8056    }
8057
8058    pub fn set_selections_from_remote(
8059        &mut self,
8060        selections: Vec<Selection<Anchor>>,
8061        pending_selection: Option<Selection<Anchor>>,
8062        cx: &mut ViewContext<Self>,
8063    ) {
8064        let old_cursor_position = self.selections.newest_anchor().head();
8065        self.selections.change_with(cx, |s| {
8066            s.select_anchors(selections);
8067            if let Some(pending_selection) = pending_selection {
8068                s.set_pending(pending_selection, SelectMode::Character);
8069            } else {
8070                s.clear_pending();
8071            }
8072        });
8073        self.selections_did_change(false, &old_cursor_position, cx);
8074    }
8075
8076    fn push_to_selection_history(&mut self) {
8077        self.selection_history.push(SelectionHistoryEntry {
8078            selections: self.selections.disjoint_anchors(),
8079            select_next_state: self.select_next_state.clone(),
8080            select_prev_state: self.select_prev_state.clone(),
8081            add_selections_state: self.add_selections_state.clone(),
8082        });
8083    }
8084
8085    pub fn transact(
8086        &mut self,
8087        cx: &mut ViewContext<Self>,
8088        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
8089    ) -> Option<TransactionId> {
8090        self.start_transaction_at(Instant::now(), cx);
8091        update(self, cx);
8092        self.end_transaction_at(Instant::now(), cx)
8093    }
8094
8095    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
8096        self.end_selection(cx);
8097        if let Some(tx_id) = self
8098            .buffer
8099            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
8100        {
8101            self.selection_history
8102                .insert_transaction(tx_id, self.selections.disjoint_anchors());
8103        }
8104    }
8105
8106    fn end_transaction_at(
8107        &mut self,
8108        now: Instant,
8109        cx: &mut ViewContext<Self>,
8110    ) -> Option<TransactionId> {
8111        if let Some(tx_id) = self
8112            .buffer
8113            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
8114        {
8115            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
8116                *end_selections = Some(self.selections.disjoint_anchors());
8117            } else {
8118                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
8119            }
8120
8121            cx.emit(EditorEvent::Edited);
8122            Some(tx_id)
8123        } else {
8124            None
8125        }
8126    }
8127
8128    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
8129        let mut fold_ranges = Vec::new();
8130
8131        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
8132
8133        let selections = self.selections.all_adjusted(cx);
8134        for selection in selections {
8135            let range = selection.range().sorted();
8136            let buffer_start_row = range.start.row;
8137
8138            for row in (0..=range.end.row).rev() {
8139                let fold_range = display_map.foldable_range(row);
8140
8141                if let Some(fold_range) = fold_range {
8142                    if fold_range.end.row >= buffer_start_row {
8143                        fold_ranges.push(fold_range);
8144                        if row <= range.start.row {
8145                            break;
8146                        }
8147                    }
8148                }
8149            }
8150        }
8151
8152        self.fold_ranges(fold_ranges, true, cx);
8153    }
8154
8155    pub fn fold_at(&mut self, fold_at: &FoldAt, cx: &mut ViewContext<Self>) {
8156        let buffer_row = fold_at.buffer_row;
8157        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
8158
8159        if let Some(fold_range) = display_map.foldable_range(buffer_row) {
8160            let autoscroll = self
8161                .selections
8162                .all::<Point>(cx)
8163                .iter()
8164                .any(|selection| fold_range.overlaps(&selection.range()));
8165
8166            self.fold_ranges(std::iter::once(fold_range), autoscroll, cx);
8167        }
8168    }
8169
8170    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
8171        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
8172        let buffer = &display_map.buffer_snapshot;
8173        let selections = self.selections.all::<Point>(cx);
8174        let ranges = selections
8175            .iter()
8176            .map(|s| {
8177                let range = s.display_range(&display_map).sorted();
8178                let mut start = range.start.to_point(&display_map);
8179                let mut end = range.end.to_point(&display_map);
8180                start.column = 0;
8181                end.column = buffer.line_len(end.row);
8182                start..end
8183            })
8184            .collect::<Vec<_>>();
8185
8186        self.unfold_ranges(ranges, true, true, cx);
8187    }
8188
8189    pub fn unfold_at(&mut self, unfold_at: &UnfoldAt, cx: &mut ViewContext<Self>) {
8190        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
8191
8192        let intersection_range = Point::new(unfold_at.buffer_row, 0)
8193            ..Point::new(
8194                unfold_at.buffer_row,
8195                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
8196            );
8197
8198        let autoscroll = self
8199            .selections
8200            .all::<Point>(cx)
8201            .iter()
8202            .any(|selection| selection.range().overlaps(&intersection_range));
8203
8204        self.unfold_ranges(std::iter::once(intersection_range), true, autoscroll, cx)
8205    }
8206
8207    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
8208        let selections = self.selections.all::<Point>(cx);
8209        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
8210        let line_mode = self.selections.line_mode;
8211        let ranges = selections.into_iter().map(|s| {
8212            if line_mode {
8213                let start = Point::new(s.start.row, 0);
8214                let end = Point::new(s.end.row, display_map.buffer_snapshot.line_len(s.end.row));
8215                start..end
8216            } else {
8217                s.start..s.end
8218            }
8219        });
8220        self.fold_ranges(ranges, true, cx);
8221    }
8222
8223    pub fn fold_ranges<T: ToOffset + Clone>(
8224        &mut self,
8225        ranges: impl IntoIterator<Item = Range<T>>,
8226        auto_scroll: bool,
8227        cx: &mut ViewContext<Self>,
8228    ) {
8229        let mut ranges = ranges.into_iter().peekable();
8230        if ranges.peek().is_some() {
8231            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
8232
8233            if auto_scroll {
8234                self.request_autoscroll(Autoscroll::fit(), cx);
8235            }
8236
8237            cx.notify();
8238        }
8239    }
8240
8241    pub fn unfold_ranges<T: ToOffset + Clone>(
8242        &mut self,
8243        ranges: impl IntoIterator<Item = Range<T>>,
8244        inclusive: bool,
8245        auto_scroll: bool,
8246        cx: &mut ViewContext<Self>,
8247    ) {
8248        let mut ranges = ranges.into_iter().peekable();
8249        if ranges.peek().is_some() {
8250            self.display_map
8251                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
8252            if auto_scroll {
8253                self.request_autoscroll(Autoscroll::fit(), cx);
8254            }
8255
8256            cx.notify();
8257        }
8258    }
8259
8260    pub fn set_gutter_hovered(&mut self, hovered: bool, cx: &mut ViewContext<Self>) {
8261        if hovered != self.gutter_hovered {
8262            self.gutter_hovered = hovered;
8263            cx.notify();
8264        }
8265    }
8266
8267    pub fn insert_blocks(
8268        &mut self,
8269        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
8270        autoscroll: Option<Autoscroll>,
8271        cx: &mut ViewContext<Self>,
8272    ) -> Vec<BlockId> {
8273        let blocks = self
8274            .display_map
8275            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
8276        if let Some(autoscroll) = autoscroll {
8277            self.request_autoscroll(autoscroll, cx);
8278        }
8279        blocks
8280    }
8281
8282    pub fn replace_blocks(
8283        &mut self,
8284        blocks: HashMap<BlockId, RenderBlock>,
8285        autoscroll: Option<Autoscroll>,
8286        cx: &mut ViewContext<Self>,
8287    ) {
8288        self.display_map
8289            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
8290        if let Some(autoscroll) = autoscroll {
8291            self.request_autoscroll(autoscroll, cx);
8292        }
8293    }
8294
8295    pub fn remove_blocks(
8296        &mut self,
8297        block_ids: HashSet<BlockId>,
8298        autoscroll: Option<Autoscroll>,
8299        cx: &mut ViewContext<Self>,
8300    ) {
8301        self.display_map.update(cx, |display_map, cx| {
8302            display_map.remove_blocks(block_ids, cx)
8303        });
8304        if let Some(autoscroll) = autoscroll {
8305            self.request_autoscroll(autoscroll, cx);
8306        }
8307    }
8308
8309    pub fn longest_row(&self, cx: &mut AppContext) -> u32 {
8310        self.display_map
8311            .update(cx, |map, cx| map.snapshot(cx))
8312            .longest_row()
8313    }
8314
8315    pub fn max_point(&self, cx: &mut AppContext) -> DisplayPoint {
8316        self.display_map
8317            .update(cx, |map, cx| map.snapshot(cx))
8318            .max_point()
8319    }
8320
8321    pub fn text(&self, cx: &AppContext) -> String {
8322        self.buffer.read(cx).read(cx).text()
8323    }
8324
8325    pub fn text_option(&self, cx: &AppContext) -> Option<String> {
8326        let text = self.text(cx);
8327        let text = text.trim();
8328
8329        if text.is_empty() {
8330            return None;
8331        }
8332
8333        Some(text.to_string())
8334    }
8335
8336    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
8337        self.transact(cx, |this, cx| {
8338            this.buffer
8339                .read(cx)
8340                .as_singleton()
8341                .expect("you can only call set_text on editors for singleton buffers")
8342                .update(cx, |buffer, cx| buffer.set_text(text, cx));
8343        });
8344    }
8345
8346    pub fn display_text(&self, cx: &mut AppContext) -> String {
8347        self.display_map
8348            .update(cx, |map, cx| map.snapshot(cx))
8349            .text()
8350    }
8351
8352    pub fn wrap_guides(&self, cx: &AppContext) -> SmallVec<[(usize, bool); 2]> {
8353        let mut wrap_guides = smallvec::smallvec![];
8354
8355        if self.show_wrap_guides == Some(false) {
8356            return wrap_guides;
8357        }
8358
8359        let settings = self.buffer.read(cx).settings_at(0, cx);
8360        if settings.show_wrap_guides {
8361            if let SoftWrap::Column(soft_wrap) = self.soft_wrap_mode(cx) {
8362                wrap_guides.push((soft_wrap as usize, true));
8363            }
8364            wrap_guides.extend(settings.wrap_guides.iter().map(|guide| (*guide, false)))
8365        }
8366
8367        wrap_guides
8368    }
8369
8370    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
8371        let settings = self.buffer.read(cx).settings_at(0, cx);
8372        let mode = self
8373            .soft_wrap_mode_override
8374            .unwrap_or_else(|| settings.soft_wrap);
8375        match mode {
8376            language_settings::SoftWrap::None => SoftWrap::None,
8377            language_settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
8378            language_settings::SoftWrap::PreferredLineLength => {
8379                SoftWrap::Column(settings.preferred_line_length)
8380            }
8381        }
8382    }
8383
8384    pub fn set_soft_wrap_mode(
8385        &mut self,
8386        mode: language_settings::SoftWrap,
8387        cx: &mut ViewContext<Self>,
8388    ) {
8389        self.soft_wrap_mode_override = Some(mode);
8390        cx.notify();
8391    }
8392
8393    pub fn set_style(&mut self, style: EditorStyle, cx: &mut ViewContext<Self>) {
8394        let rem_size = cx.rem_size();
8395        self.display_map.update(cx, |map, cx| {
8396            map.set_font(
8397                style.text.font(),
8398                style.text.font_size.to_pixels(rem_size),
8399                cx,
8400            )
8401        });
8402        self.style = Some(style);
8403    }
8404
8405    #[cfg(any(test, feature = "test-support"))]
8406    pub fn style(&self) -> Option<&EditorStyle> {
8407        self.style.as_ref()
8408    }
8409
8410    // Called by the element. This method is not designed to be called outside of the editor
8411    // element's layout code because it does not notify when rewrapping is computed synchronously.
8412    pub(crate) fn set_wrap_width(&self, width: Option<Pixels>, cx: &mut AppContext) -> bool {
8413        self.display_map
8414            .update(cx, |map, cx| map.set_wrap_width(width, cx))
8415    }
8416
8417    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
8418        if self.soft_wrap_mode_override.is_some() {
8419            self.soft_wrap_mode_override.take();
8420        } else {
8421            let soft_wrap = match self.soft_wrap_mode(cx) {
8422                SoftWrap::None => language_settings::SoftWrap::EditorWidth,
8423                SoftWrap::EditorWidth | SoftWrap::Column(_) => language_settings::SoftWrap::None,
8424            };
8425            self.soft_wrap_mode_override = Some(soft_wrap);
8426        }
8427        cx.notify();
8428    }
8429
8430    pub fn set_show_gutter(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
8431        self.show_gutter = show_gutter;
8432        cx.notify();
8433    }
8434
8435    pub fn set_show_wrap_guides(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
8436        self.show_wrap_guides = Some(show_gutter);
8437        cx.notify();
8438    }
8439
8440    pub fn reveal_in_finder(&mut self, _: &RevealInFinder, cx: &mut ViewContext<Self>) {
8441        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
8442            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
8443                cx.reveal_path(&file.abs_path(cx));
8444            }
8445        }
8446    }
8447
8448    pub fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
8449        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
8450            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
8451                if let Some(path) = file.abs_path(cx).to_str() {
8452                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
8453                }
8454            }
8455        }
8456    }
8457
8458    pub fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
8459        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
8460            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
8461                if let Some(path) = file.path().to_str() {
8462                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
8463                }
8464            }
8465        }
8466    }
8467
8468    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
8469        self.highlighted_rows = rows;
8470    }
8471
8472    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
8473        self.highlighted_rows.clone()
8474    }
8475
8476    pub fn highlight_background<T: 'static>(
8477        &mut self,
8478        ranges: Vec<Range<Anchor>>,
8479        color_fetcher: fn(&ThemeColors) -> Hsla,
8480        cx: &mut ViewContext<Self>,
8481    ) {
8482        self.background_highlights
8483            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
8484        cx.notify();
8485    }
8486
8487    pub fn highlight_inlay_background<T: 'static>(
8488        &mut self,
8489        ranges: Vec<InlayHighlight>,
8490        color_fetcher: fn(&ThemeColors) -> Hsla,
8491        cx: &mut ViewContext<Self>,
8492    ) {
8493        // TODO: no actual highlights happen for inlays currently, find a way to do that
8494        self.inlay_background_highlights
8495            .insert(Some(TypeId::of::<T>()), (color_fetcher, ranges));
8496        cx.notify();
8497    }
8498
8499    pub fn clear_background_highlights<T: 'static>(
8500        &mut self,
8501        cx: &mut ViewContext<Self>,
8502    ) -> Option<BackgroundHighlight> {
8503        let text_highlights = self.background_highlights.remove(&TypeId::of::<T>());
8504        let inlay_highlights = self
8505            .inlay_background_highlights
8506            .remove(&Some(TypeId::of::<T>()));
8507        if text_highlights.is_some() || inlay_highlights.is_some() {
8508            cx.notify();
8509        }
8510        text_highlights
8511    }
8512
8513    #[cfg(feature = "test-support")]
8514    pub fn all_text_background_highlights(
8515        &mut self,
8516        cx: &mut ViewContext<Self>,
8517    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
8518        let snapshot = self.snapshot(cx);
8519        let buffer = &snapshot.buffer_snapshot;
8520        let start = buffer.anchor_before(0);
8521        let end = buffer.anchor_after(buffer.len());
8522        let theme = cx.theme().colors();
8523        self.background_highlights_in_range(start..end, &snapshot, theme)
8524    }
8525
8526    fn document_highlights_for_position<'a>(
8527        &'a self,
8528        position: Anchor,
8529        buffer: &'a MultiBufferSnapshot,
8530    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
8531        let read_highlights = self
8532            .background_highlights
8533            .get(&TypeId::of::<DocumentHighlightRead>())
8534            .map(|h| &h.1);
8535        let write_highlights = self
8536            .background_highlights
8537            .get(&TypeId::of::<DocumentHighlightWrite>())
8538            .map(|h| &h.1);
8539        let left_position = position.bias_left(buffer);
8540        let right_position = position.bias_right(buffer);
8541        read_highlights
8542            .into_iter()
8543            .chain(write_highlights)
8544            .flat_map(move |ranges| {
8545                let start_ix = match ranges.binary_search_by(|probe| {
8546                    let cmp = probe.end.cmp(&left_position, buffer);
8547                    if cmp.is_ge() {
8548                        Ordering::Greater
8549                    } else {
8550                        Ordering::Less
8551                    }
8552                }) {
8553                    Ok(i) | Err(i) => i,
8554                };
8555
8556                let right_position = right_position.clone();
8557                ranges[start_ix..]
8558                    .iter()
8559                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
8560            })
8561    }
8562
8563    pub fn has_background_highlights<T: 'static>(&self) -> bool {
8564        self.background_highlights
8565            .get(&TypeId::of::<T>())
8566            .map_or(false, |(_, highlights)| !highlights.is_empty())
8567    }
8568
8569    pub fn background_highlights_in_range(
8570        &self,
8571        search_range: Range<Anchor>,
8572        display_snapshot: &DisplaySnapshot,
8573        theme: &ThemeColors,
8574    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
8575        let mut results = Vec::new();
8576        for (color_fetcher, ranges) in self.background_highlights.values() {
8577            let color = color_fetcher(theme);
8578            let start_ix = match ranges.binary_search_by(|probe| {
8579                let cmp = probe
8580                    .end
8581                    .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
8582                if cmp.is_gt() {
8583                    Ordering::Greater
8584                } else {
8585                    Ordering::Less
8586                }
8587            }) {
8588                Ok(i) | Err(i) => i,
8589            };
8590            for range in &ranges[start_ix..] {
8591                if range
8592                    .start
8593                    .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
8594                    .is_ge()
8595                {
8596                    break;
8597                }
8598
8599                let start = range.start.to_display_point(&display_snapshot);
8600                let end = range.end.to_display_point(&display_snapshot);
8601                results.push((start..end, color))
8602            }
8603        }
8604        results
8605    }
8606
8607    pub fn background_highlight_row_ranges<T: 'static>(
8608        &self,
8609        search_range: Range<Anchor>,
8610        display_snapshot: &DisplaySnapshot,
8611        count: usize,
8612    ) -> Vec<RangeInclusive<DisplayPoint>> {
8613        let mut results = Vec::new();
8614        let Some((_, ranges)) = self.background_highlights.get(&TypeId::of::<T>()) else {
8615            return vec![];
8616        };
8617
8618        let start_ix = match ranges.binary_search_by(|probe| {
8619            let cmp = probe
8620                .end
8621                .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
8622            if cmp.is_gt() {
8623                Ordering::Greater
8624            } else {
8625                Ordering::Less
8626            }
8627        }) {
8628            Ok(i) | Err(i) => i,
8629        };
8630        let mut push_region = |start: Option<Point>, end: Option<Point>| {
8631            if let (Some(start_display), Some(end_display)) = (start, end) {
8632                results.push(
8633                    start_display.to_display_point(display_snapshot)
8634                        ..=end_display.to_display_point(display_snapshot),
8635                );
8636            }
8637        };
8638        let mut start_row: Option<Point> = None;
8639        let mut end_row: Option<Point> = None;
8640        if ranges.len() > count {
8641            return Vec::new();
8642        }
8643        for range in &ranges[start_ix..] {
8644            if range
8645                .start
8646                .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
8647                .is_ge()
8648            {
8649                break;
8650            }
8651            let end = range.end.to_point(&display_snapshot.buffer_snapshot);
8652            if let Some(current_row) = &end_row {
8653                if end.row == current_row.row {
8654                    continue;
8655                }
8656            }
8657            let start = range.start.to_point(&display_snapshot.buffer_snapshot);
8658            if start_row.is_none() {
8659                assert_eq!(end_row, None);
8660                start_row = Some(start);
8661                end_row = Some(end);
8662                continue;
8663            }
8664            if let Some(current_end) = end_row.as_mut() {
8665                if start.row > current_end.row + 1 {
8666                    push_region(start_row, end_row);
8667                    start_row = Some(start);
8668                    end_row = Some(end);
8669                } else {
8670                    // Merge two hunks.
8671                    *current_end = end;
8672                }
8673            } else {
8674                unreachable!();
8675            }
8676        }
8677        // We might still have a hunk that was not rendered (if there was a search hit on the last line)
8678        push_region(start_row, end_row);
8679        results
8680    }
8681
8682    pub fn highlight_text<T: 'static>(
8683        &mut self,
8684        ranges: Vec<Range<Anchor>>,
8685        style: HighlightStyle,
8686        cx: &mut ViewContext<Self>,
8687    ) {
8688        self.display_map.update(cx, |map, _| {
8689            map.highlight_text(TypeId::of::<T>(), ranges, style)
8690        });
8691        cx.notify();
8692    }
8693
8694    pub fn highlight_inlays<T: 'static>(
8695        &mut self,
8696        highlights: Vec<InlayHighlight>,
8697        style: HighlightStyle,
8698        cx: &mut ViewContext<Self>,
8699    ) {
8700        self.display_map.update(cx, |map, _| {
8701            map.highlight_inlays(TypeId::of::<T>(), highlights, style)
8702        });
8703        cx.notify();
8704    }
8705
8706    pub fn text_highlights<'a, T: 'static>(
8707        &'a self,
8708        cx: &'a AppContext,
8709    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
8710        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
8711    }
8712
8713    pub fn clear_highlights<T: 'static>(&mut self, cx: &mut ViewContext<Self>) {
8714        let cleared = self
8715            .display_map
8716            .update(cx, |map, _| map.clear_highlights(TypeId::of::<T>()));
8717        if cleared {
8718            cx.notify();
8719        }
8720    }
8721
8722    pub fn show_local_cursors(&self, cx: &WindowContext) -> bool {
8723        (self.read_only(cx) || self.blink_manager.read(cx).visible())
8724            && self.focus_handle.is_focused(cx)
8725    }
8726
8727    fn on_buffer_changed(&mut self, _: Model<MultiBuffer>, cx: &mut ViewContext<Self>) {
8728        cx.notify();
8729    }
8730
8731    fn on_buffer_event(
8732        &mut self,
8733        multibuffer: Model<MultiBuffer>,
8734        event: &multi_buffer::Event,
8735        cx: &mut ViewContext<Self>,
8736    ) {
8737        match event {
8738            multi_buffer::Event::Edited {
8739                sigleton_buffer_edited,
8740            } => {
8741                self.refresh_active_diagnostics(cx);
8742                self.refresh_code_actions(cx);
8743                if self.has_active_copilot_suggestion(cx) {
8744                    self.update_visible_copilot_suggestion(cx);
8745                }
8746                cx.emit(EditorEvent::BufferEdited);
8747                cx.emit(SearchEvent::MatchesInvalidated);
8748
8749                if *sigleton_buffer_edited {
8750                    if let Some(project) = &self.project {
8751                        let project = project.read(cx);
8752                        let languages_affected = multibuffer
8753                            .read(cx)
8754                            .all_buffers()
8755                            .into_iter()
8756                            .filter_map(|buffer| {
8757                                let buffer = buffer.read(cx);
8758                                let language = buffer.language()?;
8759                                if project.is_local()
8760                                    && project.language_servers_for_buffer(buffer, cx).count() == 0
8761                                {
8762                                    None
8763                                } else {
8764                                    Some(language)
8765                                }
8766                            })
8767                            .cloned()
8768                            .collect::<HashSet<_>>();
8769                        if !languages_affected.is_empty() {
8770                            self.refresh_inlay_hints(
8771                                InlayHintRefreshReason::BufferEdited(languages_affected),
8772                                cx,
8773                            );
8774                        }
8775                    }
8776                }
8777
8778                let Some(project) = &self.project else { return };
8779                let telemetry = project.read(cx).client().telemetry().clone();
8780                telemetry.log_edit_event("editor");
8781            }
8782            multi_buffer::Event::ExcerptsAdded {
8783                buffer,
8784                predecessor,
8785                excerpts,
8786            } => {
8787                cx.emit(EditorEvent::ExcerptsAdded {
8788                    buffer: buffer.clone(),
8789                    predecessor: *predecessor,
8790                    excerpts: excerpts.clone(),
8791                });
8792                self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
8793            }
8794            multi_buffer::Event::ExcerptsRemoved { ids } => {
8795                self.refresh_inlay_hints(InlayHintRefreshReason::ExcerptsRemoved(ids.clone()), cx);
8796                cx.emit(EditorEvent::ExcerptsRemoved { ids: ids.clone() })
8797            }
8798            multi_buffer::Event::Reparsed => cx.emit(EditorEvent::Reparsed),
8799            multi_buffer::Event::DirtyChanged => cx.emit(EditorEvent::DirtyChanged),
8800            multi_buffer::Event::Saved => cx.emit(EditorEvent::Saved),
8801            multi_buffer::Event::FileHandleChanged | multi_buffer::Event::Reloaded => {
8802                cx.emit(EditorEvent::TitleChanged)
8803            }
8804            multi_buffer::Event::DiffBaseChanged => cx.emit(EditorEvent::DiffBaseChanged),
8805            multi_buffer::Event::Closed => cx.emit(EditorEvent::Closed),
8806            multi_buffer::Event::DiagnosticsUpdated => {
8807                self.refresh_active_diagnostics(cx);
8808            }
8809            _ => {}
8810        };
8811    }
8812
8813    fn on_display_map_changed(&mut self, _: Model<DisplayMap>, cx: &mut ViewContext<Self>) {
8814        cx.notify();
8815    }
8816
8817    fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
8818        self.refresh_copilot_suggestions(true, cx);
8819        self.refresh_inlay_hints(
8820            InlayHintRefreshReason::SettingsChange(inlay_hint_settings(
8821                self.selections.newest_anchor().head(),
8822                &self.buffer.read(cx).snapshot(cx),
8823                cx,
8824            )),
8825            cx,
8826        );
8827        cx.notify();
8828    }
8829
8830    pub fn set_searchable(&mut self, searchable: bool) {
8831        self.searchable = searchable;
8832    }
8833
8834    pub fn searchable(&self) -> bool {
8835        self.searchable
8836    }
8837
8838    fn open_excerpts(&mut self, _: &OpenExcerpts, cx: &mut ViewContext<Self>) {
8839        let buffer = self.buffer.read(cx);
8840        if buffer.is_singleton() {
8841            cx.propagate();
8842            return;
8843        }
8844
8845        let Some(workspace) = self.workspace() else {
8846            cx.propagate();
8847            return;
8848        };
8849
8850        let mut new_selections_by_buffer = HashMap::default();
8851        for selection in self.selections.all::<usize>(cx) {
8852            for (buffer, mut range, _) in
8853                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
8854            {
8855                if selection.reversed {
8856                    mem::swap(&mut range.start, &mut range.end);
8857                }
8858                new_selections_by_buffer
8859                    .entry(buffer)
8860                    .or_insert(Vec::new())
8861                    .push(range)
8862            }
8863        }
8864
8865        self.push_to_nav_history(self.selections.newest_anchor().head(), None, cx);
8866
8867        // We defer the pane interaction because we ourselves are a workspace item
8868        // and activating a new item causes the pane to call a method on us reentrantly,
8869        // which panics if we're on the stack.
8870        cx.window_context().defer(move |cx| {
8871            workspace.update(cx, |workspace, cx| {
8872                let pane = workspace.active_pane().clone();
8873                pane.update(cx, |pane, _| pane.disable_history());
8874
8875                for (buffer, ranges) in new_selections_by_buffer.into_iter() {
8876                    let editor = workspace.open_project_item::<Self>(buffer, cx);
8877                    editor.update(cx, |editor, cx| {
8878                        editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
8879                            s.select_ranges(ranges);
8880                        });
8881                    });
8882                }
8883
8884                pane.update(cx, |pane, _| pane.enable_history());
8885            })
8886        });
8887    }
8888
8889    fn jump(
8890        &mut self,
8891        path: ProjectPath,
8892        position: Point,
8893        anchor: language::Anchor,
8894        cx: &mut ViewContext<Self>,
8895    ) {
8896        let workspace = self.workspace();
8897        cx.spawn(|_, mut cx| async move {
8898            let workspace = workspace.ok_or_else(|| anyhow!("cannot jump without workspace"))?;
8899            let editor = workspace.update(&mut cx, |workspace, cx| {
8900                workspace.open_path(path, None, true, cx)
8901            })?;
8902            let editor = editor
8903                .await?
8904                .downcast::<Editor>()
8905                .ok_or_else(|| anyhow!("opened item was not an editor"))?
8906                .downgrade();
8907            editor.update(&mut cx, |editor, cx| {
8908                let buffer = editor
8909                    .buffer()
8910                    .read(cx)
8911                    .as_singleton()
8912                    .ok_or_else(|| anyhow!("cannot jump in a multi-buffer"))?;
8913                let buffer = buffer.read(cx);
8914                let cursor = if buffer.can_resolve(&anchor) {
8915                    language::ToPoint::to_point(&anchor, buffer)
8916                } else {
8917                    buffer.clip_point(position, Bias::Left)
8918                };
8919
8920                let nav_history = editor.nav_history.take();
8921                editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
8922                    s.select_ranges([cursor..cursor]);
8923                });
8924                editor.nav_history = nav_history;
8925
8926                anyhow::Ok(())
8927            })??;
8928
8929            anyhow::Ok(())
8930        })
8931        .detach_and_log_err(cx);
8932    }
8933
8934    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
8935        let snapshot = self.buffer.read(cx).read(cx);
8936        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
8937        Some(
8938            ranges
8939                .iter()
8940                .map(move |range| {
8941                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
8942                })
8943                .collect(),
8944        )
8945    }
8946
8947    fn selection_replacement_ranges(
8948        &self,
8949        range: Range<OffsetUtf16>,
8950        cx: &AppContext,
8951    ) -> Vec<Range<OffsetUtf16>> {
8952        let selections = self.selections.all::<OffsetUtf16>(cx);
8953        let newest_selection = selections
8954            .iter()
8955            .max_by_key(|selection| selection.id)
8956            .unwrap();
8957        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
8958        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
8959        let snapshot = self.buffer.read(cx).read(cx);
8960        selections
8961            .into_iter()
8962            .map(|mut selection| {
8963                selection.start.0 =
8964                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
8965                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
8966                snapshot.clip_offset_utf16(selection.start, Bias::Left)
8967                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
8968            })
8969            .collect()
8970    }
8971
8972    fn report_copilot_event(
8973        &self,
8974        suggestion_id: Option<String>,
8975        suggestion_accepted: bool,
8976        cx: &AppContext,
8977    ) {
8978        let Some(project) = &self.project else { return };
8979
8980        // If None, we are either getting suggestions in a new, unsaved file, or in a file without an extension
8981        let file_extension = self
8982            .buffer
8983            .read(cx)
8984            .as_singleton()
8985            .and_then(|b| b.read(cx).file())
8986            .and_then(|file| Path::new(file.file_name(cx)).extension())
8987            .and_then(|e| e.to_str())
8988            .map(|a| a.to_string());
8989
8990        let telemetry = project.read(cx).client().telemetry().clone();
8991
8992        telemetry.report_copilot_event(suggestion_id, suggestion_accepted, file_extension)
8993    }
8994
8995    #[cfg(any(test, feature = "test-support"))]
8996    fn report_editor_event(
8997        &self,
8998        _operation: &'static str,
8999        _file_extension: Option<String>,
9000        _cx: &AppContext,
9001    ) {
9002    }
9003
9004    #[cfg(not(any(test, feature = "test-support")))]
9005    fn report_editor_event(
9006        &self,
9007        operation: &'static str,
9008        file_extension: Option<String>,
9009        cx: &AppContext,
9010    ) {
9011        let Some(project) = &self.project else { return };
9012
9013        // If None, we are in a file without an extension
9014        let file = self
9015            .buffer
9016            .read(cx)
9017            .as_singleton()
9018            .and_then(|b| b.read(cx).file());
9019        let file_extension = file_extension.or(file
9020            .as_ref()
9021            .and_then(|file| Path::new(file.file_name(cx)).extension())
9022            .and_then(|e| e.to_str())
9023            .map(|a| a.to_string()));
9024
9025        let vim_mode = cx
9026            .global::<SettingsStore>()
9027            .raw_user_settings()
9028            .get("vim_mode")
9029            == Some(&serde_json::Value::Bool(true));
9030        let copilot_enabled = all_language_settings(file, cx).copilot_enabled(None, None);
9031        let copilot_enabled_for_language = self
9032            .buffer
9033            .read(cx)
9034            .settings_at(0, cx)
9035            .show_copilot_suggestions;
9036
9037        let telemetry = project.read(cx).client().telemetry().clone();
9038        telemetry.report_editor_event(
9039            file_extension,
9040            vim_mode,
9041            operation,
9042            copilot_enabled,
9043            copilot_enabled_for_language,
9044        )
9045    }
9046
9047    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
9048    /// with each line being an array of {text, highlight} objects.
9049    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
9050        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
9051            return;
9052        };
9053
9054        #[derive(Serialize)]
9055        struct Chunk<'a> {
9056            text: String,
9057            highlight: Option<&'a str>,
9058        }
9059
9060        let snapshot = buffer.read(cx).snapshot();
9061        let range = self
9062            .selected_text_range(cx)
9063            .and_then(|selected_range| {
9064                if selected_range.is_empty() {
9065                    None
9066                } else {
9067                    Some(selected_range)
9068                }
9069            })
9070            .unwrap_or_else(|| 0..snapshot.len());
9071
9072        let chunks = snapshot.chunks(range, true);
9073        let mut lines = Vec::new();
9074        let mut line: VecDeque<Chunk> = VecDeque::new();
9075
9076        let Some(style) = self.style.as_ref() else {
9077            return;
9078        };
9079
9080        for chunk in chunks {
9081            let highlight = chunk
9082                .syntax_highlight_id
9083                .and_then(|id| id.name(&style.syntax));
9084            let mut chunk_lines = chunk.text.split("\n").peekable();
9085            while let Some(text) = chunk_lines.next() {
9086                let mut merged_with_last_token = false;
9087                if let Some(last_token) = line.back_mut() {
9088                    if last_token.highlight == highlight {
9089                        last_token.text.push_str(text);
9090                        merged_with_last_token = true;
9091                    }
9092                }
9093
9094                if !merged_with_last_token {
9095                    line.push_back(Chunk {
9096                        text: text.into(),
9097                        highlight,
9098                    });
9099                }
9100
9101                if chunk_lines.peek().is_some() {
9102                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
9103                        line.pop_front();
9104                    }
9105                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
9106                        line.pop_back();
9107                    }
9108
9109                    lines.push(mem::take(&mut line));
9110                }
9111            }
9112        }
9113
9114        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else {
9115            return;
9116        };
9117        cx.write_to_clipboard(ClipboardItem::new(lines));
9118    }
9119
9120    pub fn inlay_hint_cache(&self) -> &InlayHintCache {
9121        &self.inlay_hint_cache
9122    }
9123
9124    pub fn replay_insert_event(
9125        &mut self,
9126        text: &str,
9127        relative_utf16_range: Option<Range<isize>>,
9128        cx: &mut ViewContext<Self>,
9129    ) {
9130        if !self.input_enabled {
9131            cx.emit(EditorEvent::InputIgnored { text: text.into() });
9132            return;
9133        }
9134        if let Some(relative_utf16_range) = relative_utf16_range {
9135            let selections = self.selections.all::<OffsetUtf16>(cx);
9136            self.change_selections(None, cx, |s| {
9137                let new_ranges = selections.into_iter().map(|range| {
9138                    let start = OffsetUtf16(
9139                        range
9140                            .head()
9141                            .0
9142                            .saturating_add_signed(relative_utf16_range.start),
9143                    );
9144                    let end = OffsetUtf16(
9145                        range
9146                            .head()
9147                            .0
9148                            .saturating_add_signed(relative_utf16_range.end),
9149                    );
9150                    start..end
9151                });
9152                s.select_ranges(new_ranges);
9153            });
9154        }
9155
9156        self.handle_input(text, cx);
9157    }
9158
9159    pub fn supports_inlay_hints(&self, cx: &AppContext) -> bool {
9160        let Some(project) = self.project.as_ref() else {
9161            return false;
9162        };
9163        let project = project.read(cx);
9164
9165        let mut supports = false;
9166        self.buffer().read(cx).for_each_buffer(|buffer| {
9167            if !supports {
9168                supports = project
9169                    .language_servers_for_buffer(buffer.read(cx), cx)
9170                    .any(
9171                        |(_, server)| match server.capabilities().inlay_hint_provider {
9172                            Some(lsp::OneOf::Left(enabled)) => enabled,
9173                            Some(lsp::OneOf::Right(_)) => true,
9174                            None => false,
9175                        },
9176                    )
9177            }
9178        });
9179        supports
9180    }
9181
9182    pub fn focus(&self, cx: &mut WindowContext) {
9183        cx.focus(&self.focus_handle)
9184    }
9185
9186    pub fn is_focused(&self, cx: &WindowContext) -> bool {
9187        self.focus_handle.is_focused(cx)
9188    }
9189
9190    fn handle_focus(&mut self, cx: &mut ViewContext<Self>) {
9191        cx.emit(EditorEvent::Focused);
9192
9193        if let Some(rename) = self.pending_rename.as_ref() {
9194            let rename_editor_focus_handle = rename.editor.read(cx).focus_handle.clone();
9195            cx.focus(&rename_editor_focus_handle);
9196        } else {
9197            self.blink_manager.update(cx, BlinkManager::enable);
9198            self.buffer.update(cx, |buffer, cx| {
9199                buffer.finalize_last_transaction(cx);
9200                if self.leader_peer_id.is_none() {
9201                    buffer.set_active_selections(
9202                        &self.selections.disjoint_anchors(),
9203                        self.selections.line_mode,
9204                        self.cursor_shape,
9205                        cx,
9206                    );
9207                }
9208            });
9209        }
9210    }
9211
9212    pub fn handle_blur(&mut self, cx: &mut ViewContext<Self>) {
9213        self.blink_manager.update(cx, BlinkManager::disable);
9214        self.buffer
9215            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
9216        self.hide_context_menu(cx);
9217        hide_hover(self, cx);
9218        cx.emit(EditorEvent::Blurred);
9219        cx.notify();
9220    }
9221
9222    pub fn register_action<A: Action>(
9223        &mut self,
9224        listener: impl Fn(&A, &mut WindowContext) + 'static,
9225    ) -> &mut Self {
9226        let listener = Arc::new(listener);
9227
9228        self.editor_actions.push(Box::new(move |cx| {
9229            let _view = cx.view().clone();
9230            let cx = cx.window_context();
9231            let listener = listener.clone();
9232            cx.on_action(TypeId::of::<A>(), move |action, phase, cx| {
9233                let action = action.downcast_ref().unwrap();
9234                if phase == DispatchPhase::Bubble {
9235                    listener(action, cx)
9236                }
9237            })
9238        }));
9239        self
9240    }
9241}
9242
9243pub trait CollaborationHub {
9244    fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator>;
9245    fn user_participant_indices<'a>(
9246        &self,
9247        cx: &'a AppContext,
9248    ) -> &'a HashMap<u64, ParticipantIndex>;
9249}
9250
9251impl CollaborationHub for Model<Project> {
9252    fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator> {
9253        self.read(cx).collaborators()
9254    }
9255
9256    fn user_participant_indices<'a>(
9257        &self,
9258        cx: &'a AppContext,
9259    ) -> &'a HashMap<u64, ParticipantIndex> {
9260        self.read(cx).user_store().read(cx).participant_indices()
9261    }
9262}
9263
9264fn inlay_hint_settings(
9265    location: Anchor,
9266    snapshot: &MultiBufferSnapshot,
9267    cx: &mut ViewContext<'_, Editor>,
9268) -> InlayHintSettings {
9269    let file = snapshot.file_at(location);
9270    let language = snapshot.language_at(location);
9271    let settings = all_language_settings(file, cx);
9272    settings
9273        .language(language.map(|l| l.name()).as_deref())
9274        .inlay_hints
9275}
9276
9277fn consume_contiguous_rows(
9278    contiguous_row_selections: &mut Vec<Selection<Point>>,
9279    selection: &Selection<Point>,
9280    display_map: &DisplaySnapshot,
9281    selections: &mut std::iter::Peekable<std::slice::Iter<Selection<Point>>>,
9282) -> (u32, u32) {
9283    contiguous_row_selections.push(selection.clone());
9284    let start_row = selection.start.row;
9285    let mut end_row = ending_row(selection, display_map);
9286
9287    while let Some(next_selection) = selections.peek() {
9288        if next_selection.start.row <= end_row {
9289            end_row = ending_row(next_selection, display_map);
9290            contiguous_row_selections.push(selections.next().unwrap().clone());
9291        } else {
9292            break;
9293        }
9294    }
9295    (start_row, end_row)
9296}
9297
9298fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> u32 {
9299    if next_selection.end.column > 0 || next_selection.is_empty() {
9300        display_map.next_line_boundary(next_selection.end).0.row + 1
9301    } else {
9302        next_selection.end.row
9303    }
9304}
9305
9306impl EditorSnapshot {
9307    pub fn remote_selections_in_range<'a>(
9308        &'a self,
9309        range: &'a Range<Anchor>,
9310        collaboration_hub: &dyn CollaborationHub,
9311        cx: &'a AppContext,
9312    ) -> impl 'a + Iterator<Item = RemoteSelection> {
9313        let participant_indices = collaboration_hub.user_participant_indices(cx);
9314        let collaborators_by_peer_id = collaboration_hub.collaborators(cx);
9315        let collaborators_by_replica_id = collaborators_by_peer_id
9316            .iter()
9317            .map(|(_, collaborator)| (collaborator.replica_id, collaborator))
9318            .collect::<HashMap<_, _>>();
9319        self.buffer_snapshot
9320            .remote_selections_in_range(range)
9321            .filter_map(move |(replica_id, line_mode, cursor_shape, selection)| {
9322                let collaborator = collaborators_by_replica_id.get(&replica_id)?;
9323                let participant_index = participant_indices.get(&collaborator.user_id).copied();
9324                Some(RemoteSelection {
9325                    replica_id,
9326                    selection,
9327                    cursor_shape,
9328                    line_mode,
9329                    participant_index,
9330                    peer_id: collaborator.peer_id,
9331                })
9332            })
9333    }
9334
9335    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
9336        self.display_snapshot.buffer_snapshot.language_at(position)
9337    }
9338
9339    pub fn is_focused(&self) -> bool {
9340        self.is_focused
9341    }
9342
9343    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
9344        self.placeholder_text.as_ref()
9345    }
9346
9347    pub fn scroll_position(&self) -> gpui::Point<f32> {
9348        self.scroll_anchor.scroll_position(&self.display_snapshot)
9349    }
9350}
9351
9352impl Deref for EditorSnapshot {
9353    type Target = DisplaySnapshot;
9354
9355    fn deref(&self) -> &Self::Target {
9356        &self.display_snapshot
9357    }
9358}
9359
9360#[derive(Clone, Debug, PartialEq, Eq)]
9361pub enum EditorEvent {
9362    InputIgnored {
9363        text: Arc<str>,
9364    },
9365    InputHandled {
9366        utf16_range_to_replace: Option<Range<isize>>,
9367        text: Arc<str>,
9368    },
9369    ExcerptsAdded {
9370        buffer: Model<Buffer>,
9371        predecessor: ExcerptId,
9372        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
9373    },
9374    ExcerptsRemoved {
9375        ids: Vec<ExcerptId>,
9376    },
9377    BufferEdited,
9378    Edited,
9379    Reparsed,
9380    Focused,
9381    Blurred,
9382    DirtyChanged,
9383    Saved,
9384    TitleChanged,
9385    DiffBaseChanged,
9386    SelectionsChanged {
9387        local: bool,
9388    },
9389    ScrollPositionChanged {
9390        local: bool,
9391        autoscroll: bool,
9392    },
9393    Closed,
9394}
9395
9396impl EventEmitter<EditorEvent> for Editor {}
9397
9398impl FocusableView for Editor {
9399    fn focus_handle(&self, _cx: &AppContext) -> FocusHandle {
9400        self.focus_handle.clone()
9401    }
9402}
9403
9404impl Render for Editor {
9405    fn render<'a>(&mut self, cx: &mut ViewContext<'a, Self>) -> impl IntoElement {
9406        let settings = ThemeSettings::get_global(cx);
9407        let text_style = match self.mode {
9408            EditorMode::SingleLine | EditorMode::AutoHeight { .. } => TextStyle {
9409                color: cx.theme().colors().editor_foreground,
9410                font_family: settings.ui_font.family.clone(),
9411                font_features: settings.ui_font.features,
9412                font_size: rems(0.875).into(),
9413                font_weight: FontWeight::NORMAL,
9414                font_style: FontStyle::Normal,
9415                line_height: relative(settings.buffer_line_height.value()),
9416                background_color: None,
9417                underline: None,
9418                white_space: WhiteSpace::Normal,
9419            },
9420
9421            EditorMode::Full => TextStyle {
9422                color: cx.theme().colors().editor_foreground,
9423                font_family: settings.buffer_font.family.clone(),
9424                font_features: settings.buffer_font.features,
9425                font_size: settings.buffer_font_size(cx).into(),
9426                font_weight: FontWeight::NORMAL,
9427                font_style: FontStyle::Normal,
9428                line_height: relative(settings.buffer_line_height.value()),
9429                background_color: None,
9430                underline: None,
9431                white_space: WhiteSpace::Normal,
9432            },
9433        };
9434
9435        let background = match self.mode {
9436            EditorMode::SingleLine => cx.theme().system().transparent,
9437            EditorMode::AutoHeight { max_lines: _ } => cx.theme().system().transparent,
9438            EditorMode::Full => cx.theme().colors().editor_background,
9439        };
9440
9441        EditorElement::new(
9442            cx.view(),
9443            EditorStyle {
9444                background,
9445                local_player: cx.theme().players().local(),
9446                text: text_style,
9447                scrollbar_width: px(12.),
9448                syntax: cx.theme().syntax().clone(),
9449                status: cx.theme().status().clone(),
9450                inlays_style: HighlightStyle {
9451                    color: Some(cx.theme().status().hint),
9452                    font_weight: Some(FontWeight::BOLD),
9453                    ..HighlightStyle::default()
9454                },
9455                suggestions_style: HighlightStyle {
9456                    color: Some(cx.theme().status().predictive),
9457                    ..HighlightStyle::default()
9458                },
9459            },
9460        )
9461    }
9462}
9463
9464impl InputHandler for Editor {
9465    fn text_for_range(
9466        &mut self,
9467        range_utf16: Range<usize>,
9468        cx: &mut ViewContext<Self>,
9469    ) -> Option<String> {
9470        Some(
9471            self.buffer
9472                .read(cx)
9473                .read(cx)
9474                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
9475                .collect(),
9476        )
9477    }
9478
9479    fn selected_text_range(&mut self, cx: &mut ViewContext<Self>) -> Option<Range<usize>> {
9480        // Prevent the IME menu from appearing when holding down an alphabetic key
9481        // while input is disabled.
9482        if !self.input_enabled {
9483            return None;
9484        }
9485
9486        let range = self.selections.newest::<OffsetUtf16>(cx).range();
9487        Some(range.start.0..range.end.0)
9488    }
9489
9490    fn marked_text_range(&self, cx: &mut ViewContext<Self>) -> Option<Range<usize>> {
9491        let snapshot = self.buffer.read(cx).read(cx);
9492        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
9493        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
9494    }
9495
9496    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
9497        self.clear_highlights::<InputComposition>(cx);
9498        self.ime_transaction.take();
9499    }
9500
9501    fn replace_text_in_range(
9502        &mut self,
9503        range_utf16: Option<Range<usize>>,
9504        text: &str,
9505        cx: &mut ViewContext<Self>,
9506    ) {
9507        if !self.input_enabled {
9508            cx.emit(EditorEvent::InputIgnored { text: text.into() });
9509            return;
9510        }
9511
9512        self.transact(cx, |this, cx| {
9513            let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
9514                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
9515                Some(this.selection_replacement_ranges(range_utf16, cx))
9516            } else {
9517                this.marked_text_ranges(cx)
9518            };
9519
9520            let range_to_replace = new_selected_ranges.as_ref().and_then(|ranges_to_replace| {
9521                let newest_selection_id = this.selections.newest_anchor().id;
9522                this.selections
9523                    .all::<OffsetUtf16>(cx)
9524                    .iter()
9525                    .zip(ranges_to_replace.iter())
9526                    .find_map(|(selection, range)| {
9527                        if selection.id == newest_selection_id {
9528                            Some(
9529                                (range.start.0 as isize - selection.head().0 as isize)
9530                                    ..(range.end.0 as isize - selection.head().0 as isize),
9531                            )
9532                        } else {
9533                            None
9534                        }
9535                    })
9536            });
9537
9538            cx.emit(EditorEvent::InputHandled {
9539                utf16_range_to_replace: range_to_replace,
9540                text: text.into(),
9541            });
9542
9543            if let Some(new_selected_ranges) = new_selected_ranges {
9544                this.change_selections(None, cx, |selections| {
9545                    selections.select_ranges(new_selected_ranges)
9546                });
9547            }
9548
9549            this.handle_input(text, cx);
9550        });
9551
9552        if let Some(transaction) = self.ime_transaction {
9553            self.buffer.update(cx, |buffer, cx| {
9554                buffer.group_until_transaction(transaction, cx);
9555            });
9556        }
9557
9558        self.unmark_text(cx);
9559    }
9560
9561    fn replace_and_mark_text_in_range(
9562        &mut self,
9563        range_utf16: Option<Range<usize>>,
9564        text: &str,
9565        new_selected_range_utf16: Option<Range<usize>>,
9566        cx: &mut ViewContext<Self>,
9567    ) {
9568        if !self.input_enabled {
9569            cx.emit(EditorEvent::InputIgnored { text: text.into() });
9570            return;
9571        }
9572
9573        let transaction = self.transact(cx, |this, cx| {
9574            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
9575                let snapshot = this.buffer.read(cx).read(cx);
9576                if let Some(relative_range_utf16) = range_utf16.as_ref() {
9577                    for marked_range in &mut marked_ranges {
9578                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
9579                        marked_range.start.0 += relative_range_utf16.start;
9580                        marked_range.start =
9581                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
9582                        marked_range.end =
9583                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
9584                    }
9585                }
9586                Some(marked_ranges)
9587            } else if let Some(range_utf16) = range_utf16 {
9588                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
9589                Some(this.selection_replacement_ranges(range_utf16, cx))
9590            } else {
9591                None
9592            };
9593
9594            let range_to_replace = ranges_to_replace.as_ref().and_then(|ranges_to_replace| {
9595                let newest_selection_id = this.selections.newest_anchor().id;
9596                this.selections
9597                    .all::<OffsetUtf16>(cx)
9598                    .iter()
9599                    .zip(ranges_to_replace.iter())
9600                    .find_map(|(selection, range)| {
9601                        if selection.id == newest_selection_id {
9602                            Some(
9603                                (range.start.0 as isize - selection.head().0 as isize)
9604                                    ..(range.end.0 as isize - selection.head().0 as isize),
9605                            )
9606                        } else {
9607                            None
9608                        }
9609                    })
9610            });
9611
9612            cx.emit(EditorEvent::InputHandled {
9613                utf16_range_to_replace: range_to_replace,
9614                text: text.into(),
9615            });
9616
9617            if let Some(ranges) = ranges_to_replace {
9618                this.change_selections(None, cx, |s| s.select_ranges(ranges));
9619            }
9620
9621            let marked_ranges = {
9622                let snapshot = this.buffer.read(cx).read(cx);
9623                this.selections
9624                    .disjoint_anchors()
9625                    .iter()
9626                    .map(|selection| {
9627                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
9628                    })
9629                    .collect::<Vec<_>>()
9630            };
9631
9632            if text.is_empty() {
9633                this.unmark_text(cx);
9634            } else {
9635                this.highlight_text::<InputComposition>(
9636                    marked_ranges.clone(),
9637                    HighlightStyle::default(), // todo!() this.style(cx).composition_mark,
9638                    cx,
9639                );
9640            }
9641
9642            this.handle_input(text, cx);
9643
9644            if let Some(new_selected_range) = new_selected_range_utf16 {
9645                let snapshot = this.buffer.read(cx).read(cx);
9646                let new_selected_ranges = marked_ranges
9647                    .into_iter()
9648                    .map(|marked_range| {
9649                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
9650                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
9651                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
9652                        snapshot.clip_offset_utf16(new_start, Bias::Left)
9653                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
9654                    })
9655                    .collect::<Vec<_>>();
9656
9657                drop(snapshot);
9658                this.change_selections(None, cx, |selections| {
9659                    selections.select_ranges(new_selected_ranges)
9660                });
9661            }
9662        });
9663
9664        self.ime_transaction = self.ime_transaction.or(transaction);
9665        if let Some(transaction) = self.ime_transaction {
9666            self.buffer.update(cx, |buffer, cx| {
9667                buffer.group_until_transaction(transaction, cx);
9668            });
9669        }
9670
9671        if self.text_highlights::<InputComposition>(cx).is_none() {
9672            self.ime_transaction.take();
9673        }
9674    }
9675
9676    fn bounds_for_range(
9677        &mut self,
9678        range_utf16: Range<usize>,
9679        element_bounds: gpui::Bounds<Pixels>,
9680        cx: &mut ViewContext<Self>,
9681    ) -> Option<gpui::Bounds<Pixels>> {
9682        let text_layout_details = self.text_layout_details(cx);
9683        let style = &text_layout_details.editor_style;
9684        let font_id = cx.text_system().resolve_font(&style.text.font());
9685        let font_size = style.text.font_size.to_pixels(cx.rem_size());
9686        let line_height = style.text.line_height_in_pixels(cx.rem_size());
9687        let em_width = cx
9688            .text_system()
9689            .typographic_bounds(font_id, font_size, 'm')
9690            .unwrap()
9691            .size
9692            .width;
9693
9694        let snapshot = self.snapshot(cx);
9695        let scroll_position = snapshot.scroll_position();
9696        let scroll_left = scroll_position.x * em_width;
9697
9698        let start = OffsetUtf16(range_utf16.start).to_display_point(&snapshot);
9699        let x = snapshot.x_for_display_point(start, &text_layout_details) - scroll_left
9700            + self.gutter_width;
9701        let y = line_height * (start.row() as f32 - scroll_position.y);
9702
9703        Some(Bounds {
9704            origin: element_bounds.origin + point(x, y),
9705            size: size(em_width, line_height),
9706        })
9707    }
9708}
9709
9710trait SelectionExt {
9711    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
9712    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
9713    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
9714    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
9715        -> Range<u32>;
9716}
9717
9718impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
9719    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
9720        let start = self.start.to_point(buffer);
9721        let end = self.end.to_point(buffer);
9722        if self.reversed {
9723            end..start
9724        } else {
9725            start..end
9726        }
9727    }
9728
9729    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
9730        let start = self.start.to_offset(buffer);
9731        let end = self.end.to_offset(buffer);
9732        if self.reversed {
9733            end..start
9734        } else {
9735            start..end
9736        }
9737    }
9738
9739    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
9740        let start = self
9741            .start
9742            .to_point(&map.buffer_snapshot)
9743            .to_display_point(map);
9744        let end = self
9745            .end
9746            .to_point(&map.buffer_snapshot)
9747            .to_display_point(map);
9748        if self.reversed {
9749            end..start
9750        } else {
9751            start..end
9752        }
9753    }
9754
9755    fn spanned_rows(
9756        &self,
9757        include_end_if_at_line_start: bool,
9758        map: &DisplaySnapshot,
9759    ) -> Range<u32> {
9760        let start = self.start.to_point(&map.buffer_snapshot);
9761        let mut end = self.end.to_point(&map.buffer_snapshot);
9762        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
9763            end.row -= 1;
9764        }
9765
9766        let buffer_start = map.prev_line_boundary(start).0;
9767        let buffer_end = map.next_line_boundary(end).0;
9768        buffer_start.row..buffer_end.row + 1
9769    }
9770}
9771
9772impl<T: InvalidationRegion> InvalidationStack<T> {
9773    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
9774    where
9775        S: Clone + ToOffset,
9776    {
9777        while let Some(region) = self.last() {
9778            let all_selections_inside_invalidation_ranges =
9779                if selections.len() == region.ranges().len() {
9780                    selections
9781                        .iter()
9782                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
9783                        .all(|(selection, invalidation_range)| {
9784                            let head = selection.head().to_offset(buffer);
9785                            invalidation_range.start <= head && invalidation_range.end >= head
9786                        })
9787                } else {
9788                    false
9789                };
9790
9791            if all_selections_inside_invalidation_ranges {
9792                break;
9793            } else {
9794                self.pop();
9795            }
9796        }
9797    }
9798}
9799
9800impl<T> Default for InvalidationStack<T> {
9801    fn default() -> Self {
9802        Self(Default::default())
9803    }
9804}
9805
9806impl<T> Deref for InvalidationStack<T> {
9807    type Target = Vec<T>;
9808
9809    fn deref(&self) -> &Self::Target {
9810        &self.0
9811    }
9812}
9813
9814impl<T> DerefMut for InvalidationStack<T> {
9815    fn deref_mut(&mut self) -> &mut Self::Target {
9816        &mut self.0
9817    }
9818}
9819
9820impl InvalidationRegion for SnippetState {
9821    fn ranges(&self) -> &[Range<Anchor>] {
9822        &self.ranges[self.active_index]
9823    }
9824}
9825
9826pub fn diagnostic_block_renderer(diagnostic: Diagnostic, _is_valid: bool) -> RenderBlock {
9827    let (text_without_backticks, code_ranges) = highlight_diagnostic_message(&diagnostic);
9828
9829    Arc::new(move |cx: &mut BlockContext| {
9830        let color = Some(cx.theme().colors().text_accent);
9831        let group_id: SharedString = cx.block_id.to_string().into();
9832        // TODO: Nate: We should tint the background of the block with the severity color
9833        // We need to extend the theme before we can do this
9834        h_flex()
9835            .id(cx.block_id)
9836            .group(group_id.clone())
9837            .relative()
9838            .pl(cx.anchor_x)
9839            .size_full()
9840            .gap_2()
9841            .child(
9842                StyledText::new(text_without_backticks.clone()).with_highlights(
9843                    &cx.text_style(),
9844                    code_ranges.iter().map(|range| {
9845                        (
9846                            range.clone(),
9847                            HighlightStyle {
9848                                color,
9849                                ..Default::default()
9850                            },
9851                        )
9852                    }),
9853                ),
9854            )
9855            .child(
9856                IconButton::new(("copy-block", cx.block_id), IconName::Copy)
9857                    .icon_color(Color::Muted)
9858                    .size(ButtonSize::Compact)
9859                    .style(ButtonStyle::Transparent)
9860                    .visible_on_hover(group_id)
9861                    .on_click(cx.listener({
9862                        let message = diagnostic.message.clone();
9863                        move |_, _, cx| cx.write_to_clipboard(ClipboardItem::new(message.clone()))
9864                    }))
9865                    .tooltip(|cx| Tooltip::text("Copy diagnostic message", cx)),
9866            )
9867            .into_any_element()
9868    })
9869}
9870
9871pub fn highlight_diagnostic_message(diagnostic: &Diagnostic) -> (SharedString, Vec<Range<usize>>) {
9872    let mut text_without_backticks = String::new();
9873    let mut code_ranges = Vec::new();
9874
9875    if let Some(source) = &diagnostic.source {
9876        text_without_backticks.push_str(&source);
9877        code_ranges.push(0..source.len());
9878        text_without_backticks.push_str(": ");
9879    }
9880
9881    let mut prev_offset = 0;
9882    let mut in_code_block = false;
9883    for (ix, _) in diagnostic
9884        .message
9885        .match_indices('`')
9886        .chain([(diagnostic.message.len(), "")])
9887    {
9888        let prev_len = text_without_backticks.len();
9889        text_without_backticks.push_str(&diagnostic.message[prev_offset..ix]);
9890        prev_offset = ix + 1;
9891        if in_code_block {
9892            code_ranges.push(prev_len..text_without_backticks.len());
9893            in_code_block = false;
9894        } else {
9895            in_code_block = true;
9896        }
9897    }
9898
9899    (text_without_backticks.into(), code_ranges)
9900}
9901
9902pub fn diagnostic_style(severity: DiagnosticSeverity, valid: bool, colors: &StatusColors) -> Hsla {
9903    match (severity, valid) {
9904        (DiagnosticSeverity::ERROR, true) => colors.error,
9905        (DiagnosticSeverity::ERROR, false) => colors.error,
9906        (DiagnosticSeverity::WARNING, true) => colors.warning,
9907        (DiagnosticSeverity::WARNING, false) => colors.warning,
9908        (DiagnosticSeverity::INFORMATION, true) => colors.info,
9909        (DiagnosticSeverity::INFORMATION, false) => colors.info,
9910        (DiagnosticSeverity::HINT, true) => colors.info,
9911        (DiagnosticSeverity::HINT, false) => colors.info,
9912        _ => colors.ignored,
9913    }
9914}
9915
9916pub fn styled_runs_for_code_label<'a>(
9917    label: &'a CodeLabel,
9918    syntax_theme: &'a theme::SyntaxTheme,
9919) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
9920    let fade_out = HighlightStyle {
9921        fade_out: Some(0.35),
9922        ..Default::default()
9923    };
9924
9925    let mut prev_end = label.filter_range.end;
9926    label
9927        .runs
9928        .iter()
9929        .enumerate()
9930        .flat_map(move |(ix, (range, highlight_id))| {
9931            let style = if let Some(style) = highlight_id.style(syntax_theme) {
9932                style
9933            } else {
9934                return Default::default();
9935            };
9936            let mut muted_style = style;
9937            muted_style.highlight(fade_out);
9938
9939            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
9940            if range.start >= label.filter_range.end {
9941                if range.start > prev_end {
9942                    runs.push((prev_end..range.start, fade_out));
9943                }
9944                runs.push((range.clone(), muted_style));
9945            } else if range.end <= label.filter_range.end {
9946                runs.push((range.clone(), style));
9947            } else {
9948                runs.push((range.start..label.filter_range.end, style));
9949                runs.push((label.filter_range.end..range.end, muted_style));
9950            }
9951            prev_end = cmp::max(prev_end, range.end);
9952
9953            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
9954                runs.push((prev_end..label.text.len(), fade_out));
9955            }
9956
9957            runs
9958        })
9959}
9960
9961pub fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
9962    let mut index = 0;
9963    let mut codepoints = text.char_indices().peekable();
9964
9965    std::iter::from_fn(move || {
9966        let start_index = index;
9967        while let Some((new_index, codepoint)) = codepoints.next() {
9968            index = new_index + codepoint.len_utf8();
9969            let current_upper = codepoint.is_uppercase();
9970            let next_upper = codepoints
9971                .peek()
9972                .map(|(_, c)| c.is_uppercase())
9973                .unwrap_or(false);
9974
9975            if !current_upper && next_upper {
9976                return Some(&text[start_index..index]);
9977            }
9978        }
9979
9980        index = text.len();
9981        if start_index < text.len() {
9982            return Some(&text[start_index..]);
9983        }
9984        None
9985    })
9986    .flat_map(|word| word.split_inclusive('_'))
9987    .flat_map(|word| word.split_inclusive('-'))
9988}
9989
9990trait RangeToAnchorExt {
9991    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
9992}
9993
9994impl<T: ToOffset> RangeToAnchorExt for Range<T> {
9995    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
9996        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
9997    }
9998}