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, DiagnosticStyle, PlayerColor, 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 diagnostic_style: DiagnosticStyle,
 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                                                diagnostic_style: cx
7666                                                    .editor_style
7667                                                    .diagnostic_style
7668                                                    .clone(),
7669                                                // todo!("what about the rest of the highlight style parts for inlays and suggestions?")
7670                                                inlays_style: HighlightStyle {
7671                                                    color: Some(cx.theme().status().hint),
7672                                                    font_weight: Some(FontWeight::BOLD),
7673                                                    ..HighlightStyle::default()
7674                                                },
7675                                                suggestions_style: HighlightStyle {
7676                                                    color: Some(cx.theme().status().predictive),
7677                                                    ..HighlightStyle::default()
7678                                                },
7679                                            },
7680                                        ))
7681                                        .into_any_element()
7682                                }
7683                            }),
7684                            disposition: BlockDisposition::Below,
7685                        }],
7686                        Some(Autoscroll::fit()),
7687                        cx,
7688                    )[0];
7689                    this.pending_rename = Some(RenameState {
7690                        range,
7691                        old_name,
7692                        editor: rename_editor,
7693                        block_id,
7694                    });
7695                })?;
7696            }
7697
7698            Ok(())
7699        }))
7700    }
7701
7702    pub fn confirm_rename(
7703        &mut self,
7704        _: &ConfirmRename,
7705        cx: &mut ViewContext<Self>,
7706    ) -> Option<Task<Result<()>>> {
7707        let rename = self.take_rename(false, cx)?;
7708        let workspace = self.workspace()?;
7709        let (start_buffer, start) = self
7710            .buffer
7711            .read(cx)
7712            .text_anchor_for_position(rename.range.start.clone(), cx)?;
7713        let (end_buffer, end) = self
7714            .buffer
7715            .read(cx)
7716            .text_anchor_for_position(rename.range.end.clone(), cx)?;
7717        if start_buffer != end_buffer {
7718            return None;
7719        }
7720
7721        let buffer = start_buffer;
7722        let range = start..end;
7723        let old_name = rename.old_name;
7724        let new_name = rename.editor.read(cx).text(cx);
7725
7726        let rename = workspace
7727            .read(cx)
7728            .project()
7729            .clone()
7730            .update(cx, |project, cx| {
7731                project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
7732            });
7733        let workspace = workspace.downgrade();
7734
7735        Some(cx.spawn(|editor, mut cx| async move {
7736            let project_transaction = rename.await?;
7737            Self::open_project_transaction(
7738                &editor,
7739                workspace,
7740                project_transaction,
7741                format!("Rename: {}{}", old_name, new_name),
7742                cx.clone(),
7743            )
7744            .await?;
7745
7746            editor.update(&mut cx, |editor, cx| {
7747                editor.refresh_document_highlights(cx);
7748            })?;
7749            Ok(())
7750        }))
7751    }
7752
7753    fn take_rename(
7754        &mut self,
7755        moving_cursor: bool,
7756        cx: &mut ViewContext<Self>,
7757    ) -> Option<RenameState> {
7758        let rename = self.pending_rename.take()?;
7759        if rename.editor.focus_handle(cx).is_focused(cx) {
7760            cx.focus(&self.focus_handle);
7761        }
7762
7763        self.remove_blocks(
7764            [rename.block_id].into_iter().collect(),
7765            Some(Autoscroll::fit()),
7766            cx,
7767        );
7768        self.clear_highlights::<Rename>(cx);
7769        self.show_local_selections = true;
7770
7771        if moving_cursor {
7772            let rename_editor = rename.editor.read(cx);
7773            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
7774
7775            // Update the selection to match the position of the selection inside
7776            // the rename editor.
7777            let snapshot = self.buffer.read(cx).read(cx);
7778            let rename_range = rename.range.to_offset(&snapshot);
7779            let cursor_in_editor = snapshot
7780                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
7781                .min(rename_range.end);
7782            drop(snapshot);
7783
7784            self.change_selections(None, cx, |s| {
7785                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
7786            });
7787        } else {
7788            self.refresh_document_highlights(cx);
7789        }
7790
7791        Some(rename)
7792    }
7793
7794    #[cfg(any(test, feature = "test-support"))]
7795    pub fn pending_rename(&self) -> Option<&RenameState> {
7796        self.pending_rename.as_ref()
7797    }
7798
7799    fn format(&mut self, _: &Format, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
7800        let project = match &self.project {
7801            Some(project) => project.clone(),
7802            None => return None,
7803        };
7804
7805        Some(self.perform_format(project, FormatTrigger::Manual, cx))
7806    }
7807
7808    fn perform_format(
7809        &mut self,
7810        project: Model<Project>,
7811        trigger: FormatTrigger,
7812        cx: &mut ViewContext<Self>,
7813    ) -> Task<Result<()>> {
7814        let buffer = self.buffer().clone();
7815        let buffers = buffer.read(cx).all_buffers();
7816
7817        let mut timeout = cx.background_executor().timer(FORMAT_TIMEOUT).fuse();
7818        let format = project.update(cx, |project, cx| project.format(buffers, true, trigger, cx));
7819
7820        cx.spawn(|_, mut cx| async move {
7821            let transaction = futures::select_biased! {
7822                _ = timeout => {
7823                    log::warn!("timed out waiting for formatting");
7824                    None
7825                }
7826                transaction = format.log_err().fuse() => transaction,
7827            };
7828
7829            buffer
7830                .update(&mut cx, |buffer, cx| {
7831                    if let Some(transaction) = transaction {
7832                        if !buffer.is_singleton() {
7833                            buffer.push_transaction(&transaction.0, cx);
7834                        }
7835                    }
7836
7837                    cx.notify();
7838                })
7839                .ok();
7840
7841            Ok(())
7842        })
7843    }
7844
7845    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
7846        if let Some(project) = self.project.clone() {
7847            self.buffer.update(cx, |multi_buffer, cx| {
7848                project.update(cx, |project, cx| {
7849                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
7850                });
7851            })
7852        }
7853    }
7854
7855    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
7856        cx.show_character_palette();
7857    }
7858
7859    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
7860        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
7861            let buffer = self.buffer.read(cx).snapshot(cx);
7862            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
7863            let is_valid = buffer
7864                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
7865                .any(|entry| {
7866                    entry.diagnostic.is_primary
7867                        && !entry.range.is_empty()
7868                        && entry.range.start == primary_range_start
7869                        && entry.diagnostic.message == active_diagnostics.primary_message
7870                });
7871
7872            if is_valid != active_diagnostics.is_valid {
7873                active_diagnostics.is_valid = is_valid;
7874                let mut new_styles = HashMap::default();
7875                for (block_id, diagnostic) in &active_diagnostics.blocks {
7876                    new_styles.insert(
7877                        *block_id,
7878                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
7879                    );
7880                }
7881                self.display_map
7882                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
7883            }
7884        }
7885    }
7886
7887    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
7888        self.dismiss_diagnostics(cx);
7889        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
7890            let buffer = self.buffer.read(cx).snapshot(cx);
7891
7892            let mut primary_range = None;
7893            let mut primary_message = None;
7894            let mut group_end = Point::zero();
7895            let diagnostic_group = buffer
7896                .diagnostic_group::<Point>(group_id)
7897                .map(|entry| {
7898                    if entry.range.end > group_end {
7899                        group_end = entry.range.end;
7900                    }
7901                    if entry.diagnostic.is_primary {
7902                        primary_range = Some(entry.range.clone());
7903                        primary_message = Some(entry.diagnostic.message.clone());
7904                    }
7905                    entry
7906                })
7907                .collect::<Vec<_>>();
7908            let primary_range = primary_range?;
7909            let primary_message = primary_message?;
7910            let primary_range =
7911                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
7912
7913            let blocks = display_map
7914                .insert_blocks(
7915                    diagnostic_group.iter().map(|entry| {
7916                        let diagnostic = entry.diagnostic.clone();
7917                        let message_height = diagnostic.message.lines().count() as u8;
7918                        BlockProperties {
7919                            style: BlockStyle::Fixed,
7920                            position: buffer.anchor_after(entry.range.start),
7921                            height: message_height,
7922                            render: diagnostic_block_renderer(diagnostic, true),
7923                            disposition: BlockDisposition::Below,
7924                        }
7925                    }),
7926                    cx,
7927                )
7928                .into_iter()
7929                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
7930                .collect();
7931
7932            Some(ActiveDiagnosticGroup {
7933                primary_range,
7934                primary_message,
7935                blocks,
7936                is_valid: true,
7937            })
7938        });
7939        self.active_diagnostics.is_some()
7940    }
7941
7942    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
7943        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
7944            self.display_map.update(cx, |display_map, cx| {
7945                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
7946            });
7947            cx.notify();
7948        }
7949    }
7950
7951    pub fn set_selections_from_remote(
7952        &mut self,
7953        selections: Vec<Selection<Anchor>>,
7954        pending_selection: Option<Selection<Anchor>>,
7955        cx: &mut ViewContext<Self>,
7956    ) {
7957        let old_cursor_position = self.selections.newest_anchor().head();
7958        self.selections.change_with(cx, |s| {
7959            s.select_anchors(selections);
7960            if let Some(pending_selection) = pending_selection {
7961                s.set_pending(pending_selection, SelectMode::Character);
7962            } else {
7963                s.clear_pending();
7964            }
7965        });
7966        self.selections_did_change(false, &old_cursor_position, cx);
7967    }
7968
7969    fn push_to_selection_history(&mut self) {
7970        self.selection_history.push(SelectionHistoryEntry {
7971            selections: self.selections.disjoint_anchors(),
7972            select_next_state: self.select_next_state.clone(),
7973            select_prev_state: self.select_prev_state.clone(),
7974            add_selections_state: self.add_selections_state.clone(),
7975        });
7976    }
7977
7978    pub fn transact(
7979        &mut self,
7980        cx: &mut ViewContext<Self>,
7981        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
7982    ) -> Option<TransactionId> {
7983        self.start_transaction_at(Instant::now(), cx);
7984        update(self, cx);
7985        self.end_transaction_at(Instant::now(), cx)
7986    }
7987
7988    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
7989        self.end_selection(cx);
7990        if let Some(tx_id) = self
7991            .buffer
7992            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
7993        {
7994            self.selection_history
7995                .insert_transaction(tx_id, self.selections.disjoint_anchors());
7996        }
7997    }
7998
7999    fn end_transaction_at(
8000        &mut self,
8001        now: Instant,
8002        cx: &mut ViewContext<Self>,
8003    ) -> Option<TransactionId> {
8004        if let Some(tx_id) = self
8005            .buffer
8006            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
8007        {
8008            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
8009                *end_selections = Some(self.selections.disjoint_anchors());
8010            } else {
8011                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
8012            }
8013
8014            cx.emit(EditorEvent::Edited);
8015            Some(tx_id)
8016        } else {
8017            None
8018        }
8019    }
8020
8021    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
8022        let mut fold_ranges = Vec::new();
8023
8024        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
8025
8026        let selections = self.selections.all_adjusted(cx);
8027        for selection in selections {
8028            let range = selection.range().sorted();
8029            let buffer_start_row = range.start.row;
8030
8031            for row in (0..=range.end.row).rev() {
8032                let fold_range = display_map.foldable_range(row);
8033
8034                if let Some(fold_range) = fold_range {
8035                    if fold_range.end.row >= buffer_start_row {
8036                        fold_ranges.push(fold_range);
8037                        if row <= range.start.row {
8038                            break;
8039                        }
8040                    }
8041                }
8042            }
8043        }
8044
8045        self.fold_ranges(fold_ranges, true, cx);
8046    }
8047
8048    pub fn fold_at(&mut self, fold_at: &FoldAt, cx: &mut ViewContext<Self>) {
8049        let buffer_row = fold_at.buffer_row;
8050        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
8051
8052        if let Some(fold_range) = display_map.foldable_range(buffer_row) {
8053            let autoscroll = self
8054                .selections
8055                .all::<Point>(cx)
8056                .iter()
8057                .any(|selection| fold_range.overlaps(&selection.range()));
8058
8059            self.fold_ranges(std::iter::once(fold_range), autoscroll, cx);
8060        }
8061    }
8062
8063    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
8064        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
8065        let buffer = &display_map.buffer_snapshot;
8066        let selections = self.selections.all::<Point>(cx);
8067        let ranges = selections
8068            .iter()
8069            .map(|s| {
8070                let range = s.display_range(&display_map).sorted();
8071                let mut start = range.start.to_point(&display_map);
8072                let mut end = range.end.to_point(&display_map);
8073                start.column = 0;
8074                end.column = buffer.line_len(end.row);
8075                start..end
8076            })
8077            .collect::<Vec<_>>();
8078
8079        self.unfold_ranges(ranges, true, true, cx);
8080    }
8081
8082    pub fn unfold_at(&mut self, unfold_at: &UnfoldAt, cx: &mut ViewContext<Self>) {
8083        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
8084
8085        let intersection_range = Point::new(unfold_at.buffer_row, 0)
8086            ..Point::new(
8087                unfold_at.buffer_row,
8088                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
8089            );
8090
8091        let autoscroll = self
8092            .selections
8093            .all::<Point>(cx)
8094            .iter()
8095            .any(|selection| selection.range().overlaps(&intersection_range));
8096
8097        self.unfold_ranges(std::iter::once(intersection_range), true, autoscroll, cx)
8098    }
8099
8100    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
8101        let selections = self.selections.all::<Point>(cx);
8102        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
8103        let line_mode = self.selections.line_mode;
8104        let ranges = selections.into_iter().map(|s| {
8105            if line_mode {
8106                let start = Point::new(s.start.row, 0);
8107                let end = Point::new(s.end.row, display_map.buffer_snapshot.line_len(s.end.row));
8108                start..end
8109            } else {
8110                s.start..s.end
8111            }
8112        });
8113        self.fold_ranges(ranges, true, cx);
8114    }
8115
8116    pub fn fold_ranges<T: ToOffset + Clone>(
8117        &mut self,
8118        ranges: impl IntoIterator<Item = Range<T>>,
8119        auto_scroll: bool,
8120        cx: &mut ViewContext<Self>,
8121    ) {
8122        let mut ranges = ranges.into_iter().peekable();
8123        if ranges.peek().is_some() {
8124            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
8125
8126            if auto_scroll {
8127                self.request_autoscroll(Autoscroll::fit(), cx);
8128            }
8129
8130            cx.notify();
8131        }
8132    }
8133
8134    pub fn unfold_ranges<T: ToOffset + Clone>(
8135        &mut self,
8136        ranges: impl IntoIterator<Item = Range<T>>,
8137        inclusive: bool,
8138        auto_scroll: bool,
8139        cx: &mut ViewContext<Self>,
8140    ) {
8141        let mut ranges = ranges.into_iter().peekable();
8142        if ranges.peek().is_some() {
8143            self.display_map
8144                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
8145            if auto_scroll {
8146                self.request_autoscroll(Autoscroll::fit(), cx);
8147            }
8148
8149            cx.notify();
8150        }
8151    }
8152
8153    pub fn set_gutter_hovered(&mut self, hovered: bool, cx: &mut ViewContext<Self>) {
8154        if hovered != self.gutter_hovered {
8155            self.gutter_hovered = hovered;
8156            cx.notify();
8157        }
8158    }
8159
8160    pub fn insert_blocks(
8161        &mut self,
8162        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
8163        autoscroll: Option<Autoscroll>,
8164        cx: &mut ViewContext<Self>,
8165    ) -> Vec<BlockId> {
8166        let blocks = self
8167            .display_map
8168            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
8169        if let Some(autoscroll) = autoscroll {
8170            self.request_autoscroll(autoscroll, cx);
8171        }
8172        blocks
8173    }
8174
8175    pub fn replace_blocks(
8176        &mut self,
8177        blocks: HashMap<BlockId, RenderBlock>,
8178        autoscroll: Option<Autoscroll>,
8179        cx: &mut ViewContext<Self>,
8180    ) {
8181        self.display_map
8182            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
8183        if let Some(autoscroll) = autoscroll {
8184            self.request_autoscroll(autoscroll, cx);
8185        }
8186    }
8187
8188    pub fn remove_blocks(
8189        &mut self,
8190        block_ids: HashSet<BlockId>,
8191        autoscroll: Option<Autoscroll>,
8192        cx: &mut ViewContext<Self>,
8193    ) {
8194        self.display_map.update(cx, |display_map, cx| {
8195            display_map.remove_blocks(block_ids, cx)
8196        });
8197        if let Some(autoscroll) = autoscroll {
8198            self.request_autoscroll(autoscroll, cx);
8199        }
8200    }
8201
8202    pub fn longest_row(&self, cx: &mut AppContext) -> u32 {
8203        self.display_map
8204            .update(cx, |map, cx| map.snapshot(cx))
8205            .longest_row()
8206    }
8207
8208    pub fn max_point(&self, cx: &mut AppContext) -> DisplayPoint {
8209        self.display_map
8210            .update(cx, |map, cx| map.snapshot(cx))
8211            .max_point()
8212    }
8213
8214    pub fn text(&self, cx: &AppContext) -> String {
8215        self.buffer.read(cx).read(cx).text()
8216    }
8217
8218    pub fn text_option(&self, cx: &AppContext) -> Option<String> {
8219        let text = self.text(cx);
8220        let text = text.trim();
8221
8222        if text.is_empty() {
8223            return None;
8224        }
8225
8226        Some(text.to_string())
8227    }
8228
8229    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
8230        self.transact(cx, |this, cx| {
8231            this.buffer
8232                .read(cx)
8233                .as_singleton()
8234                .expect("you can only call set_text on editors for singleton buffers")
8235                .update(cx, |buffer, cx| buffer.set_text(text, cx));
8236        });
8237    }
8238
8239    pub fn display_text(&self, cx: &mut AppContext) -> String {
8240        self.display_map
8241            .update(cx, |map, cx| map.snapshot(cx))
8242            .text()
8243    }
8244
8245    pub fn wrap_guides(&self, cx: &AppContext) -> SmallVec<[(usize, bool); 2]> {
8246        let mut wrap_guides = smallvec::smallvec![];
8247
8248        if self.show_wrap_guides == Some(false) {
8249            return wrap_guides;
8250        }
8251
8252        let settings = self.buffer.read(cx).settings_at(0, cx);
8253        if settings.show_wrap_guides {
8254            if let SoftWrap::Column(soft_wrap) = self.soft_wrap_mode(cx) {
8255                wrap_guides.push((soft_wrap as usize, true));
8256            }
8257            wrap_guides.extend(settings.wrap_guides.iter().map(|guide| (*guide, false)))
8258        }
8259
8260        wrap_guides
8261    }
8262
8263    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
8264        let settings = self.buffer.read(cx).settings_at(0, cx);
8265        let mode = self
8266            .soft_wrap_mode_override
8267            .unwrap_or_else(|| settings.soft_wrap);
8268        match mode {
8269            language_settings::SoftWrap::None => SoftWrap::None,
8270            language_settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
8271            language_settings::SoftWrap::PreferredLineLength => {
8272                SoftWrap::Column(settings.preferred_line_length)
8273            }
8274        }
8275    }
8276
8277    pub fn set_soft_wrap_mode(
8278        &mut self,
8279        mode: language_settings::SoftWrap,
8280        cx: &mut ViewContext<Self>,
8281    ) {
8282        self.soft_wrap_mode_override = Some(mode);
8283        cx.notify();
8284    }
8285
8286    pub fn set_style(&mut self, style: EditorStyle, cx: &mut ViewContext<Self>) {
8287        let rem_size = cx.rem_size();
8288        self.display_map.update(cx, |map, cx| {
8289            map.set_font(
8290                style.text.font(),
8291                style.text.font_size.to_pixels(rem_size),
8292                cx,
8293            )
8294        });
8295        self.style = Some(style);
8296    }
8297
8298    #[cfg(any(test, feature = "test-support"))]
8299    pub fn style(&self) -> Option<&EditorStyle> {
8300        self.style.as_ref()
8301    }
8302
8303    // Called by the element. This method is not designed to be called outside of the editor
8304    // element's layout code because it does not notify when rewrapping is computed synchronously.
8305    pub(crate) fn set_wrap_width(&self, width: Option<Pixels>, cx: &mut AppContext) -> bool {
8306        self.display_map
8307            .update(cx, |map, cx| map.set_wrap_width(width, cx))
8308    }
8309
8310    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
8311        if self.soft_wrap_mode_override.is_some() {
8312            self.soft_wrap_mode_override.take();
8313        } else {
8314            let soft_wrap = match self.soft_wrap_mode(cx) {
8315                SoftWrap::None => language_settings::SoftWrap::EditorWidth,
8316                SoftWrap::EditorWidth | SoftWrap::Column(_) => language_settings::SoftWrap::None,
8317            };
8318            self.soft_wrap_mode_override = Some(soft_wrap);
8319        }
8320        cx.notify();
8321    }
8322
8323    pub fn set_show_gutter(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
8324        self.show_gutter = show_gutter;
8325        cx.notify();
8326    }
8327
8328    pub fn set_show_wrap_guides(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
8329        self.show_wrap_guides = Some(show_gutter);
8330        cx.notify();
8331    }
8332
8333    pub fn reveal_in_finder(&mut self, _: &RevealInFinder, cx: &mut ViewContext<Self>) {
8334        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
8335            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
8336                cx.reveal_path(&file.abs_path(cx));
8337            }
8338        }
8339    }
8340
8341    pub fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
8342        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
8343            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
8344                if let Some(path) = file.abs_path(cx).to_str() {
8345                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
8346                }
8347            }
8348        }
8349    }
8350
8351    pub fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
8352        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
8353            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
8354                if let Some(path) = file.path().to_str() {
8355                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
8356                }
8357            }
8358        }
8359    }
8360
8361    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
8362        self.highlighted_rows = rows;
8363    }
8364
8365    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
8366        self.highlighted_rows.clone()
8367    }
8368
8369    pub fn highlight_background<T: 'static>(
8370        &mut self,
8371        ranges: Vec<Range<Anchor>>,
8372        color_fetcher: fn(&ThemeColors) -> Hsla,
8373        cx: &mut ViewContext<Self>,
8374    ) {
8375        self.background_highlights
8376            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
8377        cx.notify();
8378    }
8379
8380    pub fn highlight_inlay_background<T: 'static>(
8381        &mut self,
8382        ranges: Vec<InlayHighlight>,
8383        color_fetcher: fn(&ThemeColors) -> Hsla,
8384        cx: &mut ViewContext<Self>,
8385    ) {
8386        // TODO: no actual highlights happen for inlays currently, find a way to do that
8387        self.inlay_background_highlights
8388            .insert(Some(TypeId::of::<T>()), (color_fetcher, ranges));
8389        cx.notify();
8390    }
8391
8392    pub fn clear_background_highlights<T: 'static>(
8393        &mut self,
8394        cx: &mut ViewContext<Self>,
8395    ) -> Option<BackgroundHighlight> {
8396        let text_highlights = self.background_highlights.remove(&TypeId::of::<T>());
8397        let inlay_highlights = self
8398            .inlay_background_highlights
8399            .remove(&Some(TypeId::of::<T>()));
8400        if text_highlights.is_some() || inlay_highlights.is_some() {
8401            cx.notify();
8402        }
8403        text_highlights
8404    }
8405
8406    #[cfg(feature = "test-support")]
8407    pub fn all_text_background_highlights(
8408        &mut self,
8409        cx: &mut ViewContext<Self>,
8410    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
8411        let snapshot = self.snapshot(cx);
8412        let buffer = &snapshot.buffer_snapshot;
8413        let start = buffer.anchor_before(0);
8414        let end = buffer.anchor_after(buffer.len());
8415        let theme = cx.theme().colors();
8416        self.background_highlights_in_range(start..end, &snapshot, theme)
8417    }
8418
8419    fn document_highlights_for_position<'a>(
8420        &'a self,
8421        position: Anchor,
8422        buffer: &'a MultiBufferSnapshot,
8423    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
8424        let read_highlights = self
8425            .background_highlights
8426            .get(&TypeId::of::<DocumentHighlightRead>())
8427            .map(|h| &h.1);
8428        let write_highlights = self
8429            .background_highlights
8430            .get(&TypeId::of::<DocumentHighlightWrite>())
8431            .map(|h| &h.1);
8432        let left_position = position.bias_left(buffer);
8433        let right_position = position.bias_right(buffer);
8434        read_highlights
8435            .into_iter()
8436            .chain(write_highlights)
8437            .flat_map(move |ranges| {
8438                let start_ix = match ranges.binary_search_by(|probe| {
8439                    let cmp = probe.end.cmp(&left_position, buffer);
8440                    if cmp.is_ge() {
8441                        Ordering::Greater
8442                    } else {
8443                        Ordering::Less
8444                    }
8445                }) {
8446                    Ok(i) | Err(i) => i,
8447                };
8448
8449                let right_position = right_position.clone();
8450                ranges[start_ix..]
8451                    .iter()
8452                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
8453            })
8454    }
8455
8456    pub fn background_highlights_in_range(
8457        &self,
8458        search_range: Range<Anchor>,
8459        display_snapshot: &DisplaySnapshot,
8460        theme: &ThemeColors,
8461    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
8462        let mut results = Vec::new();
8463        for (color_fetcher, ranges) in self.background_highlights.values() {
8464            let color = color_fetcher(theme);
8465            let start_ix = match ranges.binary_search_by(|probe| {
8466                let cmp = probe
8467                    .end
8468                    .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
8469                if cmp.is_gt() {
8470                    Ordering::Greater
8471                } else {
8472                    Ordering::Less
8473                }
8474            }) {
8475                Ok(i) | Err(i) => i,
8476            };
8477            for range in &ranges[start_ix..] {
8478                if range
8479                    .start
8480                    .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
8481                    .is_ge()
8482                {
8483                    break;
8484                }
8485
8486                let start = range.start.to_display_point(&display_snapshot);
8487                let end = range.end.to_display_point(&display_snapshot);
8488                results.push((start..end, color))
8489            }
8490        }
8491        results
8492    }
8493
8494    pub fn background_highlight_row_ranges<T: 'static>(
8495        &self,
8496        search_range: Range<Anchor>,
8497        display_snapshot: &DisplaySnapshot,
8498        count: usize,
8499    ) -> Vec<RangeInclusive<DisplayPoint>> {
8500        let mut results = Vec::new();
8501        let Some((_, ranges)) = self.background_highlights.get(&TypeId::of::<T>()) else {
8502            return vec![];
8503        };
8504
8505        let start_ix = match ranges.binary_search_by(|probe| {
8506            let cmp = probe
8507                .end
8508                .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
8509            if cmp.is_gt() {
8510                Ordering::Greater
8511            } else {
8512                Ordering::Less
8513            }
8514        }) {
8515            Ok(i) | Err(i) => i,
8516        };
8517        let mut push_region = |start: Option<Point>, end: Option<Point>| {
8518            if let (Some(start_display), Some(end_display)) = (start, end) {
8519                results.push(
8520                    start_display.to_display_point(display_snapshot)
8521                        ..=end_display.to_display_point(display_snapshot),
8522                );
8523            }
8524        };
8525        let mut start_row: Option<Point> = None;
8526        let mut end_row: Option<Point> = None;
8527        if ranges.len() > count {
8528            return Vec::new();
8529        }
8530        for range in &ranges[start_ix..] {
8531            if range
8532                .start
8533                .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
8534                .is_ge()
8535            {
8536                break;
8537            }
8538            let end = range.end.to_point(&display_snapshot.buffer_snapshot);
8539            if let Some(current_row) = &end_row {
8540                if end.row == current_row.row {
8541                    continue;
8542                }
8543            }
8544            let start = range.start.to_point(&display_snapshot.buffer_snapshot);
8545            if start_row.is_none() {
8546                assert_eq!(end_row, None);
8547                start_row = Some(start);
8548                end_row = Some(end);
8549                continue;
8550            }
8551            if let Some(current_end) = end_row.as_mut() {
8552                if start.row > current_end.row + 1 {
8553                    push_region(start_row, end_row);
8554                    start_row = Some(start);
8555                    end_row = Some(end);
8556                } else {
8557                    // Merge two hunks.
8558                    *current_end = end;
8559                }
8560            } else {
8561                unreachable!();
8562            }
8563        }
8564        // We might still have a hunk that was not rendered (if there was a search hit on the last line)
8565        push_region(start_row, end_row);
8566        results
8567    }
8568
8569    pub fn highlight_text<T: 'static>(
8570        &mut self,
8571        ranges: Vec<Range<Anchor>>,
8572        style: HighlightStyle,
8573        cx: &mut ViewContext<Self>,
8574    ) {
8575        self.display_map.update(cx, |map, _| {
8576            map.highlight_text(TypeId::of::<T>(), ranges, style)
8577        });
8578        cx.notify();
8579    }
8580
8581    pub fn highlight_inlays<T: 'static>(
8582        &mut self,
8583        highlights: Vec<InlayHighlight>,
8584        style: HighlightStyle,
8585        cx: &mut ViewContext<Self>,
8586    ) {
8587        self.display_map.update(cx, |map, _| {
8588            map.highlight_inlays(TypeId::of::<T>(), highlights, style)
8589        });
8590        cx.notify();
8591    }
8592
8593    pub fn text_highlights<'a, T: 'static>(
8594        &'a self,
8595        cx: &'a AppContext,
8596    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
8597        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
8598    }
8599
8600    pub fn clear_highlights<T: 'static>(&mut self, cx: &mut ViewContext<Self>) {
8601        let cleared = self
8602            .display_map
8603            .update(cx, |map, _| map.clear_highlights(TypeId::of::<T>()));
8604        if cleared {
8605            cx.notify();
8606        }
8607    }
8608
8609    pub fn show_local_cursors(&self, cx: &WindowContext) -> bool {
8610        self.blink_manager.read(cx).visible() && self.focus_handle.is_focused(cx)
8611    }
8612
8613    fn on_buffer_changed(&mut self, _: Model<MultiBuffer>, cx: &mut ViewContext<Self>) {
8614        cx.notify();
8615    }
8616
8617    fn on_buffer_event(
8618        &mut self,
8619        multibuffer: Model<MultiBuffer>,
8620        event: &multi_buffer::Event,
8621        cx: &mut ViewContext<Self>,
8622    ) {
8623        match event {
8624            multi_buffer::Event::Edited {
8625                sigleton_buffer_edited,
8626            } => {
8627                self.refresh_active_diagnostics(cx);
8628                self.refresh_code_actions(cx);
8629                if self.has_active_copilot_suggestion(cx) {
8630                    self.update_visible_copilot_suggestion(cx);
8631                }
8632                cx.emit(EditorEvent::BufferEdited);
8633                cx.emit(SearchEvent::MatchesInvalidated);
8634
8635                if *sigleton_buffer_edited {
8636                    if let Some(project) = &self.project {
8637                        let project = project.read(cx);
8638                        let languages_affected = multibuffer
8639                            .read(cx)
8640                            .all_buffers()
8641                            .into_iter()
8642                            .filter_map(|buffer| {
8643                                let buffer = buffer.read(cx);
8644                                let language = buffer.language()?;
8645                                if project.is_local()
8646                                    && project.language_servers_for_buffer(buffer, cx).count() == 0
8647                                {
8648                                    None
8649                                } else {
8650                                    Some(language)
8651                                }
8652                            })
8653                            .cloned()
8654                            .collect::<HashSet<_>>();
8655                        if !languages_affected.is_empty() {
8656                            self.refresh_inlay_hints(
8657                                InlayHintRefreshReason::BufferEdited(languages_affected),
8658                                cx,
8659                            );
8660                        }
8661                    }
8662                }
8663            }
8664            multi_buffer::Event::ExcerptsAdded {
8665                buffer,
8666                predecessor,
8667                excerpts,
8668            } => {
8669                cx.emit(EditorEvent::ExcerptsAdded {
8670                    buffer: buffer.clone(),
8671                    predecessor: *predecessor,
8672                    excerpts: excerpts.clone(),
8673                });
8674                self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
8675            }
8676            multi_buffer::Event::ExcerptsRemoved { ids } => {
8677                self.refresh_inlay_hints(InlayHintRefreshReason::ExcerptsRemoved(ids.clone()), cx);
8678                cx.emit(EditorEvent::ExcerptsRemoved { ids: ids.clone() })
8679            }
8680            multi_buffer::Event::Reparsed => cx.emit(EditorEvent::Reparsed),
8681            multi_buffer::Event::DirtyChanged => cx.emit(EditorEvent::DirtyChanged),
8682            multi_buffer::Event::Saved => cx.emit(EditorEvent::Saved),
8683            multi_buffer::Event::FileHandleChanged | multi_buffer::Event::Reloaded => {
8684                cx.emit(EditorEvent::TitleChanged)
8685            }
8686            multi_buffer::Event::DiffBaseChanged => cx.emit(EditorEvent::DiffBaseChanged),
8687            multi_buffer::Event::Closed => cx.emit(EditorEvent::Closed),
8688            multi_buffer::Event::DiagnosticsUpdated => {
8689                self.refresh_active_diagnostics(cx);
8690            }
8691            _ => {}
8692        };
8693    }
8694
8695    fn on_display_map_changed(&mut self, _: Model<DisplayMap>, cx: &mut ViewContext<Self>) {
8696        cx.notify();
8697    }
8698
8699    fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
8700        self.refresh_copilot_suggestions(true, cx);
8701        self.refresh_inlay_hints(
8702            InlayHintRefreshReason::SettingsChange(inlay_hint_settings(
8703                self.selections.newest_anchor().head(),
8704                &self.buffer.read(cx).snapshot(cx),
8705                cx,
8706            )),
8707            cx,
8708        );
8709    }
8710
8711    pub fn set_searchable(&mut self, searchable: bool) {
8712        self.searchable = searchable;
8713    }
8714
8715    pub fn searchable(&self) -> bool {
8716        self.searchable
8717    }
8718
8719    fn open_excerpts(&mut self, _: &OpenExcerpts, cx: &mut ViewContext<Self>) {
8720        let buffer = self.buffer.read(cx);
8721        if buffer.is_singleton() {
8722            cx.propagate();
8723            return;
8724        }
8725
8726        let Some(workspace) = self.workspace() else {
8727            cx.propagate();
8728            return;
8729        };
8730
8731        let mut new_selections_by_buffer = HashMap::default();
8732        for selection in self.selections.all::<usize>(cx) {
8733            for (buffer, mut range, _) in
8734                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
8735            {
8736                if selection.reversed {
8737                    mem::swap(&mut range.start, &mut range.end);
8738                }
8739                new_selections_by_buffer
8740                    .entry(buffer)
8741                    .or_insert(Vec::new())
8742                    .push(range)
8743            }
8744        }
8745
8746        self.push_to_nav_history(self.selections.newest_anchor().head(), None, cx);
8747
8748        // We defer the pane interaction because we ourselves are a workspace item
8749        // and activating a new item causes the pane to call a method on us reentrantly,
8750        // which panics if we're on the stack.
8751        cx.window_context().defer(move |cx| {
8752            workspace.update(cx, |workspace, cx| {
8753                let pane = workspace.active_pane().clone();
8754                pane.update(cx, |pane, _| pane.disable_history());
8755
8756                for (buffer, ranges) in new_selections_by_buffer.into_iter() {
8757                    let editor = workspace.open_project_item::<Self>(buffer, cx);
8758                    editor.update(cx, |editor, cx| {
8759                        editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
8760                            s.select_ranges(ranges);
8761                        });
8762                    });
8763                }
8764
8765                pane.update(cx, |pane, _| pane.enable_history());
8766            })
8767        });
8768    }
8769
8770    fn jump(
8771        &mut self,
8772        path: ProjectPath,
8773        position: Point,
8774        anchor: language::Anchor,
8775        cx: &mut ViewContext<Self>,
8776    ) {
8777        let workspace = self.workspace();
8778        cx.spawn(|_, mut cx| async move {
8779            let workspace = workspace.ok_or_else(|| anyhow!("cannot jump without workspace"))?;
8780            let editor = workspace.update(&mut cx, |workspace, cx| {
8781                workspace.open_path(path, None, true, cx)
8782            })?;
8783            let editor = editor
8784                .await?
8785                .downcast::<Editor>()
8786                .ok_or_else(|| anyhow!("opened item was not an editor"))?
8787                .downgrade();
8788            editor.update(&mut cx, |editor, cx| {
8789                let buffer = editor
8790                    .buffer()
8791                    .read(cx)
8792                    .as_singleton()
8793                    .ok_or_else(|| anyhow!("cannot jump in a multi-buffer"))?;
8794                let buffer = buffer.read(cx);
8795                let cursor = if buffer.can_resolve(&anchor) {
8796                    language::ToPoint::to_point(&anchor, buffer)
8797                } else {
8798                    buffer.clip_point(position, Bias::Left)
8799                };
8800
8801                let nav_history = editor.nav_history.take();
8802                editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
8803                    s.select_ranges([cursor..cursor]);
8804                });
8805                editor.nav_history = nav_history;
8806
8807                anyhow::Ok(())
8808            })??;
8809
8810            anyhow::Ok(())
8811        })
8812        .detach_and_log_err(cx);
8813    }
8814
8815    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
8816        let snapshot = self.buffer.read(cx).read(cx);
8817        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
8818        Some(
8819            ranges
8820                .iter()
8821                .map(move |range| {
8822                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
8823                })
8824                .collect(),
8825        )
8826    }
8827
8828    fn selection_replacement_ranges(
8829        &self,
8830        range: Range<OffsetUtf16>,
8831        cx: &AppContext,
8832    ) -> Vec<Range<OffsetUtf16>> {
8833        let selections = self.selections.all::<OffsetUtf16>(cx);
8834        let newest_selection = selections
8835            .iter()
8836            .max_by_key(|selection| selection.id)
8837            .unwrap();
8838        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
8839        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
8840        let snapshot = self.buffer.read(cx).read(cx);
8841        selections
8842            .into_iter()
8843            .map(|mut selection| {
8844                selection.start.0 =
8845                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
8846                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
8847                snapshot.clip_offset_utf16(selection.start, Bias::Left)
8848                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
8849            })
8850            .collect()
8851    }
8852
8853    fn report_copilot_event(
8854        &self,
8855        suggestion_id: Option<String>,
8856        suggestion_accepted: bool,
8857        cx: &AppContext,
8858    ) {
8859        let Some(project) = &self.project else { return };
8860
8861        // If None, we are either getting suggestions in a new, unsaved file, or in a file without an extension
8862        let file_extension = self
8863            .buffer
8864            .read(cx)
8865            .as_singleton()
8866            .and_then(|b| b.read(cx).file())
8867            .and_then(|file| Path::new(file.file_name(cx)).extension())
8868            .and_then(|e| e.to_str())
8869            .map(|a| a.to_string());
8870
8871        let telemetry = project.read(cx).client().telemetry().clone();
8872        let telemetry_settings = *TelemetrySettings::get_global(cx);
8873
8874        telemetry.report_copilot_event(
8875            telemetry_settings,
8876            suggestion_id,
8877            suggestion_accepted,
8878            file_extension,
8879        )
8880    }
8881
8882    #[cfg(any(test, feature = "test-support"))]
8883    fn report_editor_event(
8884        &self,
8885        _operation: &'static str,
8886        _file_extension: Option<String>,
8887        _cx: &AppContext,
8888    ) {
8889    }
8890
8891    #[cfg(not(any(test, feature = "test-support")))]
8892    fn report_editor_event(
8893        &self,
8894        operation: &'static str,
8895        file_extension: Option<String>,
8896        cx: &AppContext,
8897    ) {
8898        let Some(project) = &self.project else { return };
8899
8900        // If None, we are in a file without an extension
8901        let file = self
8902            .buffer
8903            .read(cx)
8904            .as_singleton()
8905            .and_then(|b| b.read(cx).file());
8906        let file_extension = file_extension.or(file
8907            .as_ref()
8908            .and_then(|file| Path::new(file.file_name(cx)).extension())
8909            .and_then(|e| e.to_str())
8910            .map(|a| a.to_string()));
8911
8912        let vim_mode = cx
8913            .global::<SettingsStore>()
8914            .raw_user_settings()
8915            .get("vim_mode")
8916            == Some(&serde_json::Value::Bool(true));
8917        let telemetry_settings = *TelemetrySettings::get_global(cx);
8918        let copilot_enabled = all_language_settings(file, cx).copilot_enabled(None, None);
8919        let copilot_enabled_for_language = self
8920            .buffer
8921            .read(cx)
8922            .settings_at(0, cx)
8923            .show_copilot_suggestions;
8924
8925        let telemetry = project.read(cx).client().telemetry().clone();
8926        telemetry.report_editor_event(
8927            telemetry_settings,
8928            file_extension,
8929            vim_mode,
8930            operation,
8931            copilot_enabled,
8932            copilot_enabled_for_language,
8933        )
8934    }
8935
8936    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
8937    /// with each line being an array of {text, highlight} objects.
8938    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
8939        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
8940            return;
8941        };
8942
8943        #[derive(Serialize)]
8944        struct Chunk<'a> {
8945            text: String,
8946            highlight: Option<&'a str>,
8947        }
8948
8949        let snapshot = buffer.read(cx).snapshot();
8950        let range = self
8951            .selected_text_range(cx)
8952            .and_then(|selected_range| {
8953                if selected_range.is_empty() {
8954                    None
8955                } else {
8956                    Some(selected_range)
8957                }
8958            })
8959            .unwrap_or_else(|| 0..snapshot.len());
8960
8961        let chunks = snapshot.chunks(range, true);
8962        let mut lines = Vec::new();
8963        let mut line: VecDeque<Chunk> = VecDeque::new();
8964
8965        let Some(style) = self.style.as_ref() else {
8966            return;
8967        };
8968
8969        for chunk in chunks {
8970            let highlight = chunk
8971                .syntax_highlight_id
8972                .and_then(|id| id.name(&style.syntax));
8973            let mut chunk_lines = chunk.text.split("\n").peekable();
8974            while let Some(text) = chunk_lines.next() {
8975                let mut merged_with_last_token = false;
8976                if let Some(last_token) = line.back_mut() {
8977                    if last_token.highlight == highlight {
8978                        last_token.text.push_str(text);
8979                        merged_with_last_token = true;
8980                    }
8981                }
8982
8983                if !merged_with_last_token {
8984                    line.push_back(Chunk {
8985                        text: text.into(),
8986                        highlight,
8987                    });
8988                }
8989
8990                if chunk_lines.peek().is_some() {
8991                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
8992                        line.pop_front();
8993                    }
8994                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
8995                        line.pop_back();
8996                    }
8997
8998                    lines.push(mem::take(&mut line));
8999                }
9000            }
9001        }
9002
9003        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else {
9004            return;
9005        };
9006        cx.write_to_clipboard(ClipboardItem::new(lines));
9007    }
9008
9009    pub fn inlay_hint_cache(&self) -> &InlayHintCache {
9010        &self.inlay_hint_cache
9011    }
9012
9013    pub fn replay_insert_event(
9014        &mut self,
9015        text: &str,
9016        relative_utf16_range: Option<Range<isize>>,
9017        cx: &mut ViewContext<Self>,
9018    ) {
9019        if !self.input_enabled {
9020            cx.emit(EditorEvent::InputIgnored { text: text.into() });
9021            return;
9022        }
9023        if let Some(relative_utf16_range) = relative_utf16_range {
9024            let selections = self.selections.all::<OffsetUtf16>(cx);
9025            self.change_selections(None, cx, |s| {
9026                let new_ranges = selections.into_iter().map(|range| {
9027                    let start = OffsetUtf16(
9028                        range
9029                            .head()
9030                            .0
9031                            .saturating_add_signed(relative_utf16_range.start),
9032                    );
9033                    let end = OffsetUtf16(
9034                        range
9035                            .head()
9036                            .0
9037                            .saturating_add_signed(relative_utf16_range.end),
9038                    );
9039                    start..end
9040                });
9041                s.select_ranges(new_ranges);
9042            });
9043        }
9044
9045        self.handle_input(text, cx);
9046    }
9047
9048    pub fn supports_inlay_hints(&self, cx: &AppContext) -> bool {
9049        let Some(project) = self.project.as_ref() else {
9050            return false;
9051        };
9052        let project = project.read(cx);
9053
9054        let mut supports = false;
9055        self.buffer().read(cx).for_each_buffer(|buffer| {
9056            if !supports {
9057                supports = project
9058                    .language_servers_for_buffer(buffer.read(cx), cx)
9059                    .any(
9060                        |(_, server)| match server.capabilities().inlay_hint_provider {
9061                            Some(lsp::OneOf::Left(enabled)) => enabled,
9062                            Some(lsp::OneOf::Right(_)) => true,
9063                            None => false,
9064                        },
9065                    )
9066            }
9067        });
9068        supports
9069    }
9070
9071    pub fn focus(&self, cx: &mut WindowContext) {
9072        cx.focus(&self.focus_handle)
9073    }
9074
9075    pub fn is_focused(&self, cx: &WindowContext) -> bool {
9076        self.focus_handle.is_focused(cx)
9077    }
9078
9079    fn handle_focus(&mut self, cx: &mut ViewContext<Self>) {
9080        cx.emit(EditorEvent::Focused);
9081
9082        if let Some(rename) = self.pending_rename.as_ref() {
9083            let rename_editor_focus_handle = rename.editor.read(cx).focus_handle.clone();
9084            cx.focus(&rename_editor_focus_handle);
9085        } else {
9086            self.blink_manager.update(cx, BlinkManager::enable);
9087            self.buffer.update(cx, |buffer, cx| {
9088                buffer.finalize_last_transaction(cx);
9089                if self.leader_peer_id.is_none() {
9090                    buffer.set_active_selections(
9091                        &self.selections.disjoint_anchors(),
9092                        self.selections.line_mode,
9093                        self.cursor_shape,
9094                        cx,
9095                    );
9096                }
9097            });
9098        }
9099    }
9100
9101    pub fn handle_blur(&mut self, cx: &mut ViewContext<Self>) {
9102        self.blink_manager.update(cx, BlinkManager::disable);
9103        self.buffer
9104            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
9105        self.hide_context_menu(cx);
9106        hide_hover(self, cx);
9107        cx.emit(EditorEvent::Blurred);
9108        cx.notify();
9109    }
9110
9111    pub fn register_action<A: Action>(
9112        &mut self,
9113        listener: impl Fn(&A, &mut WindowContext) + 'static,
9114    ) -> &mut Self {
9115        let listener = Arc::new(listener);
9116
9117        self.editor_actions.push(Box::new(move |cx| {
9118            let _view = cx.view().clone();
9119            let cx = cx.window_context();
9120            let listener = listener.clone();
9121            cx.on_action(TypeId::of::<A>(), move |action, phase, cx| {
9122                let action = action.downcast_ref().unwrap();
9123                if phase == DispatchPhase::Bubble {
9124                    listener(action, cx)
9125                }
9126            })
9127        }));
9128        self
9129    }
9130}
9131
9132pub trait CollaborationHub {
9133    fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator>;
9134    fn user_participant_indices<'a>(
9135        &self,
9136        cx: &'a AppContext,
9137    ) -> &'a HashMap<u64, ParticipantIndex>;
9138}
9139
9140impl CollaborationHub for Model<Project> {
9141    fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator> {
9142        self.read(cx).collaborators()
9143    }
9144
9145    fn user_participant_indices<'a>(
9146        &self,
9147        cx: &'a AppContext,
9148    ) -> &'a HashMap<u64, ParticipantIndex> {
9149        self.read(cx).user_store().read(cx).participant_indices()
9150    }
9151}
9152
9153fn inlay_hint_settings(
9154    location: Anchor,
9155    snapshot: &MultiBufferSnapshot,
9156    cx: &mut ViewContext<'_, Editor>,
9157) -> InlayHintSettings {
9158    let file = snapshot.file_at(location);
9159    let language = snapshot.language_at(location);
9160    let settings = all_language_settings(file, cx);
9161    settings
9162        .language(language.map(|l| l.name()).as_deref())
9163        .inlay_hints
9164}
9165
9166fn consume_contiguous_rows(
9167    contiguous_row_selections: &mut Vec<Selection<Point>>,
9168    selection: &Selection<Point>,
9169    display_map: &DisplaySnapshot,
9170    selections: &mut std::iter::Peekable<std::slice::Iter<Selection<Point>>>,
9171) -> (u32, u32) {
9172    contiguous_row_selections.push(selection.clone());
9173    let start_row = selection.start.row;
9174    let mut end_row = ending_row(selection, display_map);
9175
9176    while let Some(next_selection) = selections.peek() {
9177        if next_selection.start.row <= end_row {
9178            end_row = ending_row(next_selection, display_map);
9179            contiguous_row_selections.push(selections.next().unwrap().clone());
9180        } else {
9181            break;
9182        }
9183    }
9184    (start_row, end_row)
9185}
9186
9187fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> u32 {
9188    if next_selection.end.column > 0 || next_selection.is_empty() {
9189        display_map.next_line_boundary(next_selection.end).0.row + 1
9190    } else {
9191        next_selection.end.row
9192    }
9193}
9194
9195impl EditorSnapshot {
9196    pub fn remote_selections_in_range<'a>(
9197        &'a self,
9198        range: &'a Range<Anchor>,
9199        collaboration_hub: &dyn CollaborationHub,
9200        cx: &'a AppContext,
9201    ) -> impl 'a + Iterator<Item = RemoteSelection> {
9202        let participant_indices = collaboration_hub.user_participant_indices(cx);
9203        let collaborators_by_peer_id = collaboration_hub.collaborators(cx);
9204        let collaborators_by_replica_id = collaborators_by_peer_id
9205            .iter()
9206            .map(|(_, collaborator)| (collaborator.replica_id, collaborator))
9207            .collect::<HashMap<_, _>>();
9208        self.buffer_snapshot
9209            .remote_selections_in_range(range)
9210            .filter_map(move |(replica_id, line_mode, cursor_shape, selection)| {
9211                let collaborator = collaborators_by_replica_id.get(&replica_id)?;
9212                let participant_index = participant_indices.get(&collaborator.user_id).copied();
9213                Some(RemoteSelection {
9214                    replica_id,
9215                    selection,
9216                    cursor_shape,
9217                    line_mode,
9218                    participant_index,
9219                    peer_id: collaborator.peer_id,
9220                })
9221            })
9222    }
9223
9224    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
9225        self.display_snapshot.buffer_snapshot.language_at(position)
9226    }
9227
9228    pub fn is_focused(&self) -> bool {
9229        self.is_focused
9230    }
9231
9232    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
9233        self.placeholder_text.as_ref()
9234    }
9235
9236    pub fn scroll_position(&self) -> gpui::Point<f32> {
9237        self.scroll_anchor.scroll_position(&self.display_snapshot)
9238    }
9239}
9240
9241impl Deref for EditorSnapshot {
9242    type Target = DisplaySnapshot;
9243
9244    fn deref(&self) -> &Self::Target {
9245        &self.display_snapshot
9246    }
9247}
9248
9249#[derive(Clone, Debug, PartialEq, Eq)]
9250pub enum EditorEvent {
9251    InputIgnored {
9252        text: Arc<str>,
9253    },
9254    InputHandled {
9255        utf16_range_to_replace: Option<Range<isize>>,
9256        text: Arc<str>,
9257    },
9258    ExcerptsAdded {
9259        buffer: Model<Buffer>,
9260        predecessor: ExcerptId,
9261        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
9262    },
9263    ExcerptsRemoved {
9264        ids: Vec<ExcerptId>,
9265    },
9266    BufferEdited,
9267    Edited,
9268    Reparsed,
9269    Focused,
9270    Blurred,
9271    DirtyChanged,
9272    Saved,
9273    TitleChanged,
9274    DiffBaseChanged,
9275    SelectionsChanged {
9276        local: bool,
9277    },
9278    ScrollPositionChanged {
9279        local: bool,
9280        autoscroll: bool,
9281    },
9282    Closed,
9283}
9284
9285impl EventEmitter<EditorEvent> for Editor {}
9286
9287impl FocusableView for Editor {
9288    fn focus_handle(&self, _cx: &AppContext) -> FocusHandle {
9289        self.focus_handle.clone()
9290    }
9291}
9292
9293impl Render for Editor {
9294    fn render<'a>(&mut self, cx: &mut ViewContext<'a, Self>) -> impl IntoElement {
9295        let settings = ThemeSettings::get_global(cx);
9296        let text_style = match self.mode {
9297            EditorMode::SingleLine | EditorMode::AutoHeight { .. } => TextStyle {
9298                color: cx.theme().colors().editor_foreground,
9299                font_family: settings.ui_font.family.clone(),
9300                font_features: settings.ui_font.features,
9301                font_size: rems(0.875).into(),
9302                font_weight: FontWeight::NORMAL,
9303                font_style: FontStyle::Normal,
9304                line_height: relative(settings.buffer_line_height.value()),
9305                background_color: None,
9306                underline: None,
9307                white_space: WhiteSpace::Normal,
9308            },
9309
9310            EditorMode::Full => TextStyle {
9311                color: cx.theme().colors().editor_foreground,
9312                font_family: settings.buffer_font.family.clone(),
9313                font_features: settings.buffer_font.features,
9314                font_size: settings.buffer_font_size(cx).into(),
9315                font_weight: FontWeight::NORMAL,
9316                font_style: FontStyle::Normal,
9317                line_height: relative(settings.buffer_line_height.value()),
9318                background_color: None,
9319                underline: None,
9320                white_space: WhiteSpace::Normal,
9321            },
9322        };
9323
9324        let background = match self.mode {
9325            EditorMode::SingleLine => cx.theme().system().transparent,
9326            EditorMode::AutoHeight { max_lines: _ } => cx.theme().system().transparent,
9327            EditorMode::Full => cx.theme().colors().editor_background,
9328        };
9329
9330        EditorElement::new(
9331            cx.view(),
9332            EditorStyle {
9333                background,
9334                local_player: cx.theme().players().local(),
9335                text: text_style,
9336                scrollbar_width: px(12.),
9337                syntax: cx.theme().syntax().clone(),
9338                diagnostic_style: cx.theme().diagnostic_style(),
9339                // todo!("what about the rest of the highlight style parts?")
9340                inlays_style: HighlightStyle {
9341                    color: Some(cx.theme().status().hint),
9342                    font_weight: Some(FontWeight::BOLD),
9343                    ..HighlightStyle::default()
9344                },
9345                suggestions_style: HighlightStyle {
9346                    color: Some(cx.theme().status().predictive),
9347                    ..HighlightStyle::default()
9348                },
9349            },
9350        )
9351    }
9352}
9353
9354impl InputHandler for Editor {
9355    fn text_for_range(
9356        &mut self,
9357        range_utf16: Range<usize>,
9358        cx: &mut ViewContext<Self>,
9359    ) -> Option<String> {
9360        Some(
9361            self.buffer
9362                .read(cx)
9363                .read(cx)
9364                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
9365                .collect(),
9366        )
9367    }
9368
9369    fn selected_text_range(&mut self, cx: &mut ViewContext<Self>) -> Option<Range<usize>> {
9370        // Prevent the IME menu from appearing when holding down an alphabetic key
9371        // while input is disabled.
9372        if !self.input_enabled {
9373            return None;
9374        }
9375
9376        let range = self.selections.newest::<OffsetUtf16>(cx).range();
9377        Some(range.start.0..range.end.0)
9378    }
9379
9380    fn marked_text_range(&self, cx: &mut ViewContext<Self>) -> Option<Range<usize>> {
9381        let snapshot = self.buffer.read(cx).read(cx);
9382        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
9383        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
9384    }
9385
9386    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
9387        self.clear_highlights::<InputComposition>(cx);
9388        self.ime_transaction.take();
9389    }
9390
9391    fn replace_text_in_range(
9392        &mut self,
9393        range_utf16: Option<Range<usize>>,
9394        text: &str,
9395        cx: &mut ViewContext<Self>,
9396    ) {
9397        if !self.input_enabled {
9398            cx.emit(EditorEvent::InputIgnored { text: text.into() });
9399            return;
9400        }
9401
9402        self.transact(cx, |this, cx| {
9403            let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
9404                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
9405                Some(this.selection_replacement_ranges(range_utf16, cx))
9406            } else {
9407                this.marked_text_ranges(cx)
9408            };
9409
9410            let range_to_replace = new_selected_ranges.as_ref().and_then(|ranges_to_replace| {
9411                let newest_selection_id = this.selections.newest_anchor().id;
9412                this.selections
9413                    .all::<OffsetUtf16>(cx)
9414                    .iter()
9415                    .zip(ranges_to_replace.iter())
9416                    .find_map(|(selection, range)| {
9417                        if selection.id == newest_selection_id {
9418                            Some(
9419                                (range.start.0 as isize - selection.head().0 as isize)
9420                                    ..(range.end.0 as isize - selection.head().0 as isize),
9421                            )
9422                        } else {
9423                            None
9424                        }
9425                    })
9426            });
9427
9428            cx.emit(EditorEvent::InputHandled {
9429                utf16_range_to_replace: range_to_replace,
9430                text: text.into(),
9431            });
9432
9433            if let Some(new_selected_ranges) = new_selected_ranges {
9434                this.change_selections(None, cx, |selections| {
9435                    selections.select_ranges(new_selected_ranges)
9436                });
9437            }
9438
9439            this.handle_input(text, cx);
9440        });
9441
9442        if let Some(transaction) = self.ime_transaction {
9443            self.buffer.update(cx, |buffer, cx| {
9444                buffer.group_until_transaction(transaction, cx);
9445            });
9446        }
9447
9448        self.unmark_text(cx);
9449    }
9450
9451    fn replace_and_mark_text_in_range(
9452        &mut self,
9453        range_utf16: Option<Range<usize>>,
9454        text: &str,
9455        new_selected_range_utf16: Option<Range<usize>>,
9456        cx: &mut ViewContext<Self>,
9457    ) {
9458        if !self.input_enabled {
9459            cx.emit(EditorEvent::InputIgnored { text: text.into() });
9460            return;
9461        }
9462
9463        let transaction = self.transact(cx, |this, cx| {
9464            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
9465                let snapshot = this.buffer.read(cx).read(cx);
9466                if let Some(relative_range_utf16) = range_utf16.as_ref() {
9467                    for marked_range in &mut marked_ranges {
9468                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
9469                        marked_range.start.0 += relative_range_utf16.start;
9470                        marked_range.start =
9471                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
9472                        marked_range.end =
9473                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
9474                    }
9475                }
9476                Some(marked_ranges)
9477            } else if let Some(range_utf16) = range_utf16 {
9478                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
9479                Some(this.selection_replacement_ranges(range_utf16, cx))
9480            } else {
9481                None
9482            };
9483
9484            let range_to_replace = ranges_to_replace.as_ref().and_then(|ranges_to_replace| {
9485                let newest_selection_id = this.selections.newest_anchor().id;
9486                this.selections
9487                    .all::<OffsetUtf16>(cx)
9488                    .iter()
9489                    .zip(ranges_to_replace.iter())
9490                    .find_map(|(selection, range)| {
9491                        if selection.id == newest_selection_id {
9492                            Some(
9493                                (range.start.0 as isize - selection.head().0 as isize)
9494                                    ..(range.end.0 as isize - selection.head().0 as isize),
9495                            )
9496                        } else {
9497                            None
9498                        }
9499                    })
9500            });
9501
9502            cx.emit(EditorEvent::InputHandled {
9503                utf16_range_to_replace: range_to_replace,
9504                text: text.into(),
9505            });
9506
9507            if let Some(ranges) = ranges_to_replace {
9508                this.change_selections(None, cx, |s| s.select_ranges(ranges));
9509            }
9510
9511            let marked_ranges = {
9512                let snapshot = this.buffer.read(cx).read(cx);
9513                this.selections
9514                    .disjoint_anchors()
9515                    .iter()
9516                    .map(|selection| {
9517                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
9518                    })
9519                    .collect::<Vec<_>>()
9520            };
9521
9522            if text.is_empty() {
9523                this.unmark_text(cx);
9524            } else {
9525                this.highlight_text::<InputComposition>(
9526                    marked_ranges.clone(),
9527                    HighlightStyle::default(), // todo!() this.style(cx).composition_mark,
9528                    cx,
9529                );
9530            }
9531
9532            this.handle_input(text, cx);
9533
9534            if let Some(new_selected_range) = new_selected_range_utf16 {
9535                let snapshot = this.buffer.read(cx).read(cx);
9536                let new_selected_ranges = marked_ranges
9537                    .into_iter()
9538                    .map(|marked_range| {
9539                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
9540                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
9541                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
9542                        snapshot.clip_offset_utf16(new_start, Bias::Left)
9543                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
9544                    })
9545                    .collect::<Vec<_>>();
9546
9547                drop(snapshot);
9548                this.change_selections(None, cx, |selections| {
9549                    selections.select_ranges(new_selected_ranges)
9550                });
9551            }
9552        });
9553
9554        self.ime_transaction = self.ime_transaction.or(transaction);
9555        if let Some(transaction) = self.ime_transaction {
9556            self.buffer.update(cx, |buffer, cx| {
9557                buffer.group_until_transaction(transaction, cx);
9558            });
9559        }
9560
9561        if self.text_highlights::<InputComposition>(cx).is_none() {
9562            self.ime_transaction.take();
9563        }
9564    }
9565
9566    fn bounds_for_range(
9567        &mut self,
9568        range_utf16: Range<usize>,
9569        element_bounds: gpui::Bounds<Pixels>,
9570        cx: &mut ViewContext<Self>,
9571    ) -> Option<gpui::Bounds<Pixels>> {
9572        let text_layout_details = self.text_layout_details(cx);
9573        let style = &text_layout_details.editor_style;
9574        let font_id = cx.text_system().font_id(&style.text.font()).unwrap();
9575        let font_size = style.text.font_size.to_pixels(cx.rem_size());
9576        let line_height = style.text.line_height_in_pixels(cx.rem_size());
9577        let em_width = cx
9578            .text_system()
9579            .typographic_bounds(font_id, font_size, 'm')
9580            .unwrap()
9581            .size
9582            .width;
9583
9584        let snapshot = self.snapshot(cx);
9585        let scroll_position = snapshot.scroll_position();
9586        let scroll_left = scroll_position.x * em_width;
9587
9588        let start = OffsetUtf16(range_utf16.start).to_display_point(&snapshot);
9589        let x = snapshot.x_for_display_point(start, &text_layout_details) - scroll_left
9590            + self.gutter_width;
9591        let y = line_height * (start.row() as f32 - scroll_position.y);
9592
9593        Some(Bounds {
9594            origin: element_bounds.origin + point(x, y),
9595            size: size(em_width, line_height),
9596        })
9597    }
9598}
9599
9600trait SelectionExt {
9601    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
9602    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
9603    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
9604    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
9605        -> Range<u32>;
9606}
9607
9608impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
9609    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
9610        let start = self.start.to_point(buffer);
9611        let end = self.end.to_point(buffer);
9612        if self.reversed {
9613            end..start
9614        } else {
9615            start..end
9616        }
9617    }
9618
9619    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
9620        let start = self.start.to_offset(buffer);
9621        let end = self.end.to_offset(buffer);
9622        if self.reversed {
9623            end..start
9624        } else {
9625            start..end
9626        }
9627    }
9628
9629    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
9630        let start = self
9631            .start
9632            .to_point(&map.buffer_snapshot)
9633            .to_display_point(map);
9634        let end = self
9635            .end
9636            .to_point(&map.buffer_snapshot)
9637            .to_display_point(map);
9638        if self.reversed {
9639            end..start
9640        } else {
9641            start..end
9642        }
9643    }
9644
9645    fn spanned_rows(
9646        &self,
9647        include_end_if_at_line_start: bool,
9648        map: &DisplaySnapshot,
9649    ) -> Range<u32> {
9650        let start = self.start.to_point(&map.buffer_snapshot);
9651        let mut end = self.end.to_point(&map.buffer_snapshot);
9652        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
9653            end.row -= 1;
9654        }
9655
9656        let buffer_start = map.prev_line_boundary(start).0;
9657        let buffer_end = map.next_line_boundary(end).0;
9658        buffer_start.row..buffer_end.row + 1
9659    }
9660}
9661
9662impl<T: InvalidationRegion> InvalidationStack<T> {
9663    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
9664    where
9665        S: Clone + ToOffset,
9666    {
9667        while let Some(region) = self.last() {
9668            let all_selections_inside_invalidation_ranges =
9669                if selections.len() == region.ranges().len() {
9670                    selections
9671                        .iter()
9672                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
9673                        .all(|(selection, invalidation_range)| {
9674                            let head = selection.head().to_offset(buffer);
9675                            invalidation_range.start <= head && invalidation_range.end >= head
9676                        })
9677                } else {
9678                    false
9679                };
9680
9681            if all_selections_inside_invalidation_ranges {
9682                break;
9683            } else {
9684                self.pop();
9685            }
9686        }
9687    }
9688}
9689
9690impl<T> Default for InvalidationStack<T> {
9691    fn default() -> Self {
9692        Self(Default::default())
9693    }
9694}
9695
9696impl<T> Deref for InvalidationStack<T> {
9697    type Target = Vec<T>;
9698
9699    fn deref(&self) -> &Self::Target {
9700        &self.0
9701    }
9702}
9703
9704impl<T> DerefMut for InvalidationStack<T> {
9705    fn deref_mut(&mut self) -> &mut Self::Target {
9706        &mut self.0
9707    }
9708}
9709
9710impl InvalidationRegion for SnippetState {
9711    fn ranges(&self) -> &[Range<Anchor>] {
9712        &self.ranges[self.active_index]
9713    }
9714}
9715
9716pub fn diagnostic_block_renderer(diagnostic: Diagnostic, _is_valid: bool) -> RenderBlock {
9717    let (text_without_backticks, code_ranges) = highlight_diagnostic_message(&diagnostic);
9718
9719    Arc::new(move |cx: &mut BlockContext| {
9720        let color = Some(cx.theme().colors().text_accent);
9721        let group_id: SharedString = cx.block_id.to_string().into();
9722        // TODO: Nate: We should tint the background of the block with the severity color
9723        // We need to extend the theme before we can do this
9724        h_stack()
9725            .id(cx.block_id)
9726            .group(group_id.clone())
9727            .relative()
9728            .pl(cx.anchor_x)
9729            .size_full()
9730            .gap_2()
9731            .child(
9732                StyledText::new(text_without_backticks.clone()).with_highlights(
9733                    &cx.text_style(),
9734                    code_ranges.iter().map(|range| {
9735                        (
9736                            range.clone(),
9737                            HighlightStyle {
9738                                color,
9739                                ..Default::default()
9740                            },
9741                        )
9742                    }),
9743                ),
9744            )
9745            .child(
9746                IconButton::new(("copy-block", cx.block_id), Icon::Copy)
9747                    .icon_color(Color::Muted)
9748                    .size(ButtonSize::Compact)
9749                    .style(ButtonStyle::Transparent)
9750                    .visible_on_hover(group_id)
9751                    .on_click(cx.listener({
9752                        let message = diagnostic.message.clone();
9753                        move |_, _, cx| cx.write_to_clipboard(ClipboardItem::new(message.clone()))
9754                    }))
9755                    .tooltip(|cx| Tooltip::text("Copy diagnostic message", cx)),
9756            )
9757            .into_any_element()
9758    })
9759}
9760
9761pub fn highlight_diagnostic_message(diagnostic: &Diagnostic) -> (SharedString, Vec<Range<usize>>) {
9762    let mut text_without_backticks = String::new();
9763    let mut code_ranges = Vec::new();
9764
9765    if let Some(source) = &diagnostic.source {
9766        text_without_backticks.push_str(&source);
9767        code_ranges.push(0..source.len());
9768        text_without_backticks.push_str(": ");
9769    }
9770
9771    let mut prev_offset = 0;
9772    let mut in_code_block = false;
9773    for (ix, _) in diagnostic
9774        .message
9775        .match_indices('`')
9776        .chain([(diagnostic.message.len(), "")])
9777    {
9778        let prev_len = text_without_backticks.len();
9779        text_without_backticks.push_str(&diagnostic.message[prev_offset..ix]);
9780        prev_offset = ix + 1;
9781        if in_code_block {
9782            code_ranges.push(prev_len..text_without_backticks.len());
9783            in_code_block = false;
9784        } else {
9785            in_code_block = true;
9786        }
9787    }
9788
9789    (text_without_backticks.into(), code_ranges)
9790}
9791
9792pub fn diagnostic_style(
9793    severity: DiagnosticSeverity,
9794    valid: bool,
9795    style: &DiagnosticStyle,
9796) -> Hsla {
9797    match (severity, valid) {
9798        (DiagnosticSeverity::ERROR, true) => style.error,
9799        (DiagnosticSeverity::ERROR, false) => style.error,
9800        (DiagnosticSeverity::WARNING, true) => style.warning,
9801        (DiagnosticSeverity::WARNING, false) => style.warning,
9802        (DiagnosticSeverity::INFORMATION, true) => style.info,
9803        (DiagnosticSeverity::INFORMATION, false) => style.info,
9804        (DiagnosticSeverity::HINT, true) => style.info,
9805        (DiagnosticSeverity::HINT, false) => style.info,
9806        _ => style.ignored,
9807    }
9808}
9809
9810pub fn styled_runs_for_code_label<'a>(
9811    label: &'a CodeLabel,
9812    syntax_theme: &'a theme::SyntaxTheme,
9813) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
9814    let fade_out = HighlightStyle {
9815        fade_out: Some(0.35),
9816        ..Default::default()
9817    };
9818
9819    let mut prev_end = label.filter_range.end;
9820    label
9821        .runs
9822        .iter()
9823        .enumerate()
9824        .flat_map(move |(ix, (range, highlight_id))| {
9825            let style = if let Some(style) = highlight_id.style(syntax_theme) {
9826                style
9827            } else {
9828                return Default::default();
9829            };
9830            let mut muted_style = style;
9831            muted_style.highlight(fade_out);
9832
9833            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
9834            if range.start >= label.filter_range.end {
9835                if range.start > prev_end {
9836                    runs.push((prev_end..range.start, fade_out));
9837                }
9838                runs.push((range.clone(), muted_style));
9839            } else if range.end <= label.filter_range.end {
9840                runs.push((range.clone(), style));
9841            } else {
9842                runs.push((range.start..label.filter_range.end, style));
9843                runs.push((label.filter_range.end..range.end, muted_style));
9844            }
9845            prev_end = cmp::max(prev_end, range.end);
9846
9847            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
9848                runs.push((prev_end..label.text.len(), fade_out));
9849            }
9850
9851            runs
9852        })
9853}
9854
9855pub fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
9856    let mut index = 0;
9857    let mut codepoints = text.char_indices().peekable();
9858
9859    std::iter::from_fn(move || {
9860        let start_index = index;
9861        while let Some((new_index, codepoint)) = codepoints.next() {
9862            index = new_index + codepoint.len_utf8();
9863            let current_upper = codepoint.is_uppercase();
9864            let next_upper = codepoints
9865                .peek()
9866                .map(|(_, c)| c.is_uppercase())
9867                .unwrap_or(false);
9868
9869            if !current_upper && next_upper {
9870                return Some(&text[start_index..index]);
9871            }
9872        }
9873
9874        index = text.len();
9875        if start_index < text.len() {
9876            return Some(&text[start_index..]);
9877        }
9878        None
9879    })
9880    .flat_map(|word| word.split_inclusive('_'))
9881    .flat_map(|word| word.split_inclusive('-'))
9882}
9883
9884trait RangeToAnchorExt {
9885    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
9886}
9887
9888impl<T: ToOffset> RangeToAnchorExt for Range<T> {
9889    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
9890        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
9891    }
9892}