editor.rs

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