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