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