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