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