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.is_empty() {
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    pub fn set_wrap_width(&self, width: Option<Pixels>, cx: &mut AppContext) -> bool {
8247        self.display_map
8248            .update(cx, |map, cx| map.set_wrap_width(width, cx))
8249    }
8250
8251    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
8252        if self.soft_wrap_mode_override.is_some() {
8253            self.soft_wrap_mode_override.take();
8254        } else {
8255            let soft_wrap = match self.soft_wrap_mode(cx) {
8256                SoftWrap::None => language_settings::SoftWrap::EditorWidth,
8257                SoftWrap::EditorWidth | SoftWrap::Column(_) => language_settings::SoftWrap::None,
8258            };
8259            self.soft_wrap_mode_override = Some(soft_wrap);
8260        }
8261        cx.notify();
8262    }
8263
8264    pub fn set_show_gutter(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
8265        self.show_gutter = show_gutter;
8266        cx.notify();
8267    }
8268
8269    pub fn set_show_wrap_guides(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
8270        self.show_wrap_guides = Some(show_gutter);
8271        cx.notify();
8272    }
8273
8274    pub fn reveal_in_finder(&mut self, _: &RevealInFinder, cx: &mut ViewContext<Self>) {
8275        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
8276            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
8277                cx.reveal_path(&file.abs_path(cx));
8278            }
8279        }
8280    }
8281
8282    pub fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
8283        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
8284            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
8285                if let Some(path) = file.abs_path(cx).to_str() {
8286                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
8287                }
8288            }
8289        }
8290    }
8291
8292    pub fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
8293        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
8294            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
8295                if let Some(path) = file.path().to_str() {
8296                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
8297                }
8298            }
8299        }
8300    }
8301
8302    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
8303        self.highlighted_rows = rows;
8304    }
8305
8306    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
8307        self.highlighted_rows.clone()
8308    }
8309
8310    pub fn highlight_background<T: 'static>(
8311        &mut self,
8312        ranges: Vec<Range<Anchor>>,
8313        color_fetcher: fn(&ThemeColors) -> Hsla,
8314        cx: &mut ViewContext<Self>,
8315    ) {
8316        self.background_highlights
8317            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
8318        cx.notify();
8319    }
8320
8321    pub fn highlight_inlay_background<T: 'static>(
8322        &mut self,
8323        ranges: Vec<InlayHighlight>,
8324        color_fetcher: fn(&ThemeColors) -> Hsla,
8325        cx: &mut ViewContext<Self>,
8326    ) {
8327        // TODO: no actual highlights happen for inlays currently, find a way to do that
8328        self.inlay_background_highlights
8329            .insert(Some(TypeId::of::<T>()), (color_fetcher, ranges));
8330        cx.notify();
8331    }
8332
8333    pub fn clear_background_highlights<T: 'static>(
8334        &mut self,
8335        cx: &mut ViewContext<Self>,
8336    ) -> Option<BackgroundHighlight> {
8337        let text_highlights = self.background_highlights.remove(&TypeId::of::<T>());
8338        let inlay_highlights = self
8339            .inlay_background_highlights
8340            .remove(&Some(TypeId::of::<T>()));
8341        if text_highlights.is_some() || inlay_highlights.is_some() {
8342            cx.notify();
8343        }
8344        text_highlights
8345    }
8346
8347    #[cfg(feature = "test-support")]
8348    pub fn all_text_background_highlights(
8349        &mut self,
8350        cx: &mut ViewContext<Self>,
8351    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
8352        let snapshot = self.snapshot(cx);
8353        let buffer = &snapshot.buffer_snapshot;
8354        let start = buffer.anchor_before(0);
8355        let end = buffer.anchor_after(buffer.len());
8356        let theme = cx.theme().colors();
8357        self.background_highlights_in_range(start..end, &snapshot, theme)
8358    }
8359
8360    fn document_highlights_for_position<'a>(
8361        &'a self,
8362        position: Anchor,
8363        buffer: &'a MultiBufferSnapshot,
8364    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
8365        let read_highlights = self
8366            .background_highlights
8367            .get(&TypeId::of::<DocumentHighlightRead>())
8368            .map(|h| &h.1);
8369        let write_highlights = self
8370            .background_highlights
8371            .get(&TypeId::of::<DocumentHighlightWrite>())
8372            .map(|h| &h.1);
8373        let left_position = position.bias_left(buffer);
8374        let right_position = position.bias_right(buffer);
8375        read_highlights
8376            .into_iter()
8377            .chain(write_highlights)
8378            .flat_map(move |ranges| {
8379                let start_ix = match ranges.binary_search_by(|probe| {
8380                    let cmp = probe.end.cmp(&left_position, buffer);
8381                    if cmp.is_ge() {
8382                        Ordering::Greater
8383                    } else {
8384                        Ordering::Less
8385                    }
8386                }) {
8387                    Ok(i) | Err(i) => i,
8388                };
8389
8390                let right_position = right_position.clone();
8391                ranges[start_ix..]
8392                    .iter()
8393                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
8394            })
8395    }
8396
8397    pub fn background_highlights_in_range(
8398        &self,
8399        search_range: Range<Anchor>,
8400        display_snapshot: &DisplaySnapshot,
8401        theme: &ThemeColors,
8402    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
8403        let mut results = Vec::new();
8404        for (color_fetcher, ranges) in self.background_highlights.values() {
8405            let color = color_fetcher(theme);
8406            let start_ix = match ranges.binary_search_by(|probe| {
8407                let cmp = probe
8408                    .end
8409                    .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
8410                if cmp.is_gt() {
8411                    Ordering::Greater
8412                } else {
8413                    Ordering::Less
8414                }
8415            }) {
8416                Ok(i) | Err(i) => i,
8417            };
8418            for range in &ranges[start_ix..] {
8419                if range
8420                    .start
8421                    .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
8422                    .is_ge()
8423                {
8424                    break;
8425                }
8426
8427                let start = range.start.to_display_point(&display_snapshot);
8428                let end = range.end.to_display_point(&display_snapshot);
8429                results.push((start..end, color))
8430            }
8431        }
8432        results
8433    }
8434
8435    pub fn background_highlight_row_ranges<T: 'static>(
8436        &self,
8437        search_range: Range<Anchor>,
8438        display_snapshot: &DisplaySnapshot,
8439        count: usize,
8440    ) -> Vec<RangeInclusive<DisplayPoint>> {
8441        let mut results = Vec::new();
8442        let Some((_, ranges)) = self.background_highlights.get(&TypeId::of::<T>()) else {
8443            return vec![];
8444        };
8445
8446        let start_ix = match ranges.binary_search_by(|probe| {
8447            let cmp = probe
8448                .end
8449                .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
8450            if cmp.is_gt() {
8451                Ordering::Greater
8452            } else {
8453                Ordering::Less
8454            }
8455        }) {
8456            Ok(i) | Err(i) => i,
8457        };
8458        let mut push_region = |start: Option<Point>, end: Option<Point>| {
8459            if let (Some(start_display), Some(end_display)) = (start, end) {
8460                results.push(
8461                    start_display.to_display_point(display_snapshot)
8462                        ..=end_display.to_display_point(display_snapshot),
8463                );
8464            }
8465        };
8466        let mut start_row: Option<Point> = None;
8467        let mut end_row: Option<Point> = None;
8468        if ranges.len() > count {
8469            return Vec::new();
8470        }
8471        for range in &ranges[start_ix..] {
8472            if range
8473                .start
8474                .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
8475                .is_ge()
8476            {
8477                break;
8478            }
8479            let end = range.end.to_point(&display_snapshot.buffer_snapshot);
8480            if let Some(current_row) = &end_row {
8481                if end.row == current_row.row {
8482                    continue;
8483                }
8484            }
8485            let start = range.start.to_point(&display_snapshot.buffer_snapshot);
8486            if start_row.is_none() {
8487                assert_eq!(end_row, None);
8488                start_row = Some(start);
8489                end_row = Some(end);
8490                continue;
8491            }
8492            if let Some(current_end) = end_row.as_mut() {
8493                if start.row > current_end.row + 1 {
8494                    push_region(start_row, end_row);
8495                    start_row = Some(start);
8496                    end_row = Some(end);
8497                } else {
8498                    // Merge two hunks.
8499                    *current_end = end;
8500                }
8501            } else {
8502                unreachable!();
8503            }
8504        }
8505        // We might still have a hunk that was not rendered (if there was a search hit on the last line)
8506        push_region(start_row, end_row);
8507        results
8508    }
8509
8510    pub fn highlight_text<T: 'static>(
8511        &mut self,
8512        ranges: Vec<Range<Anchor>>,
8513        style: HighlightStyle,
8514        cx: &mut ViewContext<Self>,
8515    ) {
8516        self.display_map.update(cx, |map, _| {
8517            map.highlight_text(TypeId::of::<T>(), ranges, style)
8518        });
8519        cx.notify();
8520    }
8521
8522    pub fn highlight_inlays<T: 'static>(
8523        &mut self,
8524        highlights: Vec<InlayHighlight>,
8525        style: HighlightStyle,
8526        cx: &mut ViewContext<Self>,
8527    ) {
8528        self.display_map.update(cx, |map, _| {
8529            map.highlight_inlays(TypeId::of::<T>(), highlights, style)
8530        });
8531        cx.notify();
8532    }
8533
8534    pub fn text_highlights<'a, T: 'static>(
8535        &'a self,
8536        cx: &'a AppContext,
8537    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
8538        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
8539    }
8540
8541    pub fn clear_highlights<T: 'static>(&mut self, cx: &mut ViewContext<Self>) {
8542        let cleared = self
8543            .display_map
8544            .update(cx, |map, _| map.clear_highlights(TypeId::of::<T>()));
8545        if cleared {
8546            cx.notify();
8547        }
8548    }
8549
8550    pub fn show_local_cursors(&self, cx: &WindowContext) -> bool {
8551        self.blink_manager.read(cx).visible() && self.focus_handle.is_focused(cx)
8552    }
8553
8554    fn on_buffer_changed(&mut self, _: Model<MultiBuffer>, cx: &mut ViewContext<Self>) {
8555        cx.notify();
8556    }
8557
8558    fn on_buffer_event(
8559        &mut self,
8560        multibuffer: Model<MultiBuffer>,
8561        event: &multi_buffer::Event,
8562        cx: &mut ViewContext<Self>,
8563    ) {
8564        match event {
8565            multi_buffer::Event::Edited {
8566                sigleton_buffer_edited,
8567            } => {
8568                self.refresh_active_diagnostics(cx);
8569                self.refresh_code_actions(cx);
8570                if self.has_active_copilot_suggestion(cx) {
8571                    self.update_visible_copilot_suggestion(cx);
8572                }
8573                cx.emit(EditorEvent::BufferEdited);
8574                cx.emit(ItemEvent::Edit);
8575                cx.emit(ItemEvent::UpdateBreadcrumbs);
8576                cx.emit(SearchEvent::MatchesInvalidated);
8577
8578                if *sigleton_buffer_edited {
8579                    if let Some(project) = &self.project {
8580                        let project = project.read(cx);
8581                        let languages_affected = multibuffer
8582                            .read(cx)
8583                            .all_buffers()
8584                            .into_iter()
8585                            .filter_map(|buffer| {
8586                                let buffer = buffer.read(cx);
8587                                let language = buffer.language()?;
8588                                if project.is_local()
8589                                    && project.language_servers_for_buffer(buffer, cx).count() == 0
8590                                {
8591                                    None
8592                                } else {
8593                                    Some(language)
8594                                }
8595                            })
8596                            .cloned()
8597                            .collect::<HashSet<_>>();
8598                        if !languages_affected.is_empty() {
8599                            self.refresh_inlay_hints(
8600                                InlayHintRefreshReason::BufferEdited(languages_affected),
8601                                cx,
8602                            );
8603                        }
8604                    }
8605                }
8606            }
8607            multi_buffer::Event::ExcerptsAdded {
8608                buffer,
8609                predecessor,
8610                excerpts,
8611            } => {
8612                cx.emit(EditorEvent::ExcerptsAdded {
8613                    buffer: buffer.clone(),
8614                    predecessor: *predecessor,
8615                    excerpts: excerpts.clone(),
8616                });
8617                self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
8618            }
8619            multi_buffer::Event::ExcerptsRemoved { ids } => {
8620                self.refresh_inlay_hints(InlayHintRefreshReason::ExcerptsRemoved(ids.clone()), cx);
8621                cx.emit(EditorEvent::ExcerptsRemoved { ids: ids.clone() })
8622            }
8623            multi_buffer::Event::Reparsed => {
8624                cx.emit(ItemEvent::UpdateBreadcrumbs);
8625            }
8626            multi_buffer::Event::DirtyChanged => {
8627                cx.emit(ItemEvent::UpdateTab);
8628            }
8629            multi_buffer::Event::Saved
8630            | multi_buffer::Event::FileHandleChanged
8631            | multi_buffer::Event::Reloaded => {
8632                cx.emit(ItemEvent::UpdateTab);
8633                cx.emit(ItemEvent::UpdateBreadcrumbs);
8634            }
8635            multi_buffer::Event::DiffBaseChanged => cx.emit(EditorEvent::DiffBaseChanged),
8636            multi_buffer::Event::Closed => cx.emit(ItemEvent::CloseItem),
8637            multi_buffer::Event::DiagnosticsUpdated => {
8638                self.refresh_active_diagnostics(cx);
8639            }
8640            _ => {}
8641        };
8642    }
8643
8644    fn on_display_map_changed(&mut self, _: Model<DisplayMap>, cx: &mut ViewContext<Self>) {
8645        cx.notify();
8646    }
8647
8648    fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
8649        self.refresh_copilot_suggestions(true, cx);
8650        self.refresh_inlay_hints(
8651            InlayHintRefreshReason::SettingsChange(inlay_hint_settings(
8652                self.selections.newest_anchor().head(),
8653                &self.buffer.read(cx).snapshot(cx),
8654                cx,
8655            )),
8656            cx,
8657        );
8658    }
8659
8660    //     pub fn set_searchable(&mut self, searchable: bool) {
8661    //         self.searchable = searchable;
8662    //     }
8663
8664    //     pub fn searchable(&self) -> bool {
8665    //         self.searchable
8666    //     }
8667
8668    fn open_excerpts(&mut self, _: &OpenExcerpts, cx: &mut ViewContext<Self>) {
8669        let buffer = self.buffer.read(cx);
8670        if buffer.is_singleton() {
8671            cx.propagate();
8672            return;
8673        }
8674
8675        let Some(workspace) = self.workspace() else {
8676            cx.propagate();
8677            return;
8678        };
8679
8680        let mut new_selections_by_buffer = HashMap::default();
8681        for selection in self.selections.all::<usize>(cx) {
8682            for (buffer, mut range, _) in
8683                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
8684            {
8685                if selection.reversed {
8686                    mem::swap(&mut range.start, &mut range.end);
8687                }
8688                new_selections_by_buffer
8689                    .entry(buffer)
8690                    .or_insert(Vec::new())
8691                    .push(range)
8692            }
8693        }
8694
8695        self.push_to_nav_history(self.selections.newest_anchor().head(), None, cx);
8696
8697        // We defer the pane interaction because we ourselves are a workspace item
8698        // and activating a new item causes the pane to call a method on us reentrantly,
8699        // which panics if we're on the stack.
8700        cx.window_context().defer(move |cx| {
8701            workspace.update(cx, |workspace, cx| {
8702                let pane = workspace.active_pane().clone();
8703                pane.update(cx, |pane, _| pane.disable_history());
8704
8705                for (buffer, ranges) in new_selections_by_buffer.into_iter() {
8706                    let editor = workspace.open_project_item::<Self>(buffer, cx);
8707                    editor.update(cx, |editor, cx| {
8708                        editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
8709                            s.select_ranges(ranges);
8710                        });
8711                    });
8712                }
8713
8714                pane.update(cx, |pane, _| pane.enable_history());
8715            })
8716        });
8717    }
8718
8719    fn jump(
8720        &mut self,
8721        path: ProjectPath,
8722        position: Point,
8723        anchor: language::Anchor,
8724        cx: &mut ViewContext<Self>,
8725    ) {
8726        let workspace = self.workspace();
8727        cx.spawn(|_, mut cx| async move {
8728            let workspace = workspace.ok_or_else(|| anyhow!("cannot jump without workspace"))?;
8729            let editor = workspace.update(&mut cx, |workspace, cx| {
8730                workspace.open_path(path, None, true, cx)
8731            })?;
8732            let editor = editor
8733                .await?
8734                .downcast::<Editor>()
8735                .ok_or_else(|| anyhow!("opened item was not an editor"))?
8736                .downgrade();
8737            editor.update(&mut cx, |editor, cx| {
8738                let buffer = editor
8739                    .buffer()
8740                    .read(cx)
8741                    .as_singleton()
8742                    .ok_or_else(|| anyhow!("cannot jump in a multi-buffer"))?;
8743                let buffer = buffer.read(cx);
8744                let cursor = if buffer.can_resolve(&anchor) {
8745                    language::ToPoint::to_point(&anchor, buffer)
8746                } else {
8747                    buffer.clip_point(position, Bias::Left)
8748                };
8749
8750                let nav_history = editor.nav_history.take();
8751                editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
8752                    s.select_ranges([cursor..cursor]);
8753                });
8754                editor.nav_history = nav_history;
8755
8756                anyhow::Ok(())
8757            })??;
8758
8759            anyhow::Ok(())
8760        })
8761        .detach_and_log_err(cx);
8762    }
8763
8764    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
8765        let snapshot = self.buffer.read(cx).read(cx);
8766        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
8767        Some(
8768            ranges
8769                .iter()
8770                .map(move |range| {
8771                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
8772                })
8773                .collect(),
8774        )
8775    }
8776
8777    fn selection_replacement_ranges(
8778        &self,
8779        range: Range<OffsetUtf16>,
8780        cx: &AppContext,
8781    ) -> Vec<Range<OffsetUtf16>> {
8782        let selections = self.selections.all::<OffsetUtf16>(cx);
8783        let newest_selection = selections
8784            .iter()
8785            .max_by_key(|selection| selection.id)
8786            .unwrap();
8787        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
8788        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
8789        let snapshot = self.buffer.read(cx).read(cx);
8790        selections
8791            .into_iter()
8792            .map(|mut selection| {
8793                selection.start.0 =
8794                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
8795                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
8796                snapshot.clip_offset_utf16(selection.start, Bias::Left)
8797                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
8798            })
8799            .collect()
8800    }
8801
8802    fn report_copilot_event(
8803        &self,
8804        suggestion_id: Option<String>,
8805        suggestion_accepted: bool,
8806        cx: &AppContext,
8807    ) {
8808        let Some(project) = &self.project else { return };
8809
8810        // If None, we are either getting suggestions in a new, unsaved file, or in a file without an extension
8811        let file_extension = self
8812            .buffer
8813            .read(cx)
8814            .as_singleton()
8815            .and_then(|b| b.read(cx).file())
8816            .and_then(|file| Path::new(file.file_name(cx)).extension())
8817            .and_then(|e| e.to_str())
8818            .map(|a| a.to_string());
8819
8820        let telemetry = project.read(cx).client().telemetry().clone();
8821        let telemetry_settings = *TelemetrySettings::get_global(cx);
8822
8823        telemetry.report_copilot_event(
8824            telemetry_settings,
8825            suggestion_id,
8826            suggestion_accepted,
8827            file_extension,
8828        )
8829    }
8830
8831    #[cfg(any(test, feature = "test-support"))]
8832    fn report_editor_event(
8833        &self,
8834        _operation: &'static str,
8835        _file_extension: Option<String>,
8836        _cx: &AppContext,
8837    ) {
8838    }
8839
8840    #[cfg(not(any(test, feature = "test-support")))]
8841    fn report_editor_event(
8842        &self,
8843        operation: &'static str,
8844        file_extension: Option<String>,
8845        cx: &AppContext,
8846    ) {
8847        let Some(project) = &self.project else { return };
8848
8849        // If None, we are in a file without an extension
8850        let file = self
8851            .buffer
8852            .read(cx)
8853            .as_singleton()
8854            .and_then(|b| b.read(cx).file());
8855        let file_extension = file_extension.or(file
8856            .as_ref()
8857            .and_then(|file| Path::new(file.file_name(cx)).extension())
8858            .and_then(|e| e.to_str())
8859            .map(|a| a.to_string()));
8860
8861        let vim_mode = cx
8862            .global::<SettingsStore>()
8863            .raw_user_settings()
8864            .get("vim_mode")
8865            == Some(&serde_json::Value::Bool(true));
8866        let telemetry_settings = *TelemetrySettings::get_global(cx);
8867        let copilot_enabled = all_language_settings(file, cx).copilot_enabled(None, None);
8868        let copilot_enabled_for_language = self
8869            .buffer
8870            .read(cx)
8871            .settings_at(0, cx)
8872            .show_copilot_suggestions;
8873
8874        let telemetry = project.read(cx).client().telemetry().clone();
8875        telemetry.report_editor_event(
8876            telemetry_settings,
8877            file_extension,
8878            vim_mode,
8879            operation,
8880            copilot_enabled,
8881            copilot_enabled_for_language,
8882        )
8883    }
8884
8885    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
8886    /// with each line being an array of {text, highlight} objects.
8887    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
8888        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
8889            return;
8890        };
8891
8892        #[derive(Serialize)]
8893        struct Chunk<'a> {
8894            text: String,
8895            highlight: Option<&'a str>,
8896        }
8897
8898        let snapshot = buffer.read(cx).snapshot();
8899        let range = self
8900            .selected_text_range(cx)
8901            .and_then(|selected_range| {
8902                if selected_range.is_empty() {
8903                    None
8904                } else {
8905                    Some(selected_range)
8906                }
8907            })
8908            .unwrap_or_else(|| 0..snapshot.len());
8909
8910        let chunks = snapshot.chunks(range, true);
8911        let mut lines = Vec::new();
8912        let mut line: VecDeque<Chunk> = VecDeque::new();
8913
8914        let Some(style) = self.style.as_ref() else {
8915            return;
8916        };
8917
8918        for chunk in chunks {
8919            let highlight = chunk
8920                .syntax_highlight_id
8921                .and_then(|id| id.name(&style.syntax));
8922            let mut chunk_lines = chunk.text.split("\n").peekable();
8923            while let Some(text) = chunk_lines.next() {
8924                let mut merged_with_last_token = false;
8925                if let Some(last_token) = line.back_mut() {
8926                    if last_token.highlight == highlight {
8927                        last_token.text.push_str(text);
8928                        merged_with_last_token = true;
8929                    }
8930                }
8931
8932                if !merged_with_last_token {
8933                    line.push_back(Chunk {
8934                        text: text.into(),
8935                        highlight,
8936                    });
8937                }
8938
8939                if chunk_lines.peek().is_some() {
8940                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
8941                        line.pop_front();
8942                    }
8943                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
8944                        line.pop_back();
8945                    }
8946
8947                    lines.push(mem::take(&mut line));
8948                }
8949            }
8950        }
8951
8952        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else {
8953            return;
8954        };
8955        cx.write_to_clipboard(ClipboardItem::new(lines));
8956    }
8957
8958    pub fn inlay_hint_cache(&self) -> &InlayHintCache {
8959        &self.inlay_hint_cache
8960    }
8961
8962    pub fn replay_insert_event(
8963        &mut self,
8964        text: &str,
8965        relative_utf16_range: Option<Range<isize>>,
8966        cx: &mut ViewContext<Self>,
8967    ) {
8968        if !self.input_enabled {
8969            cx.emit(EditorEvent::InputIgnored { text: text.into() });
8970            return;
8971        }
8972        if let Some(relative_utf16_range) = relative_utf16_range {
8973            let selections = self.selections.all::<OffsetUtf16>(cx);
8974            self.change_selections(None, cx, |s| {
8975                let new_ranges = selections.into_iter().map(|range| {
8976                    let start = OffsetUtf16(
8977                        range
8978                            .head()
8979                            .0
8980                            .saturating_add_signed(relative_utf16_range.start),
8981                    );
8982                    let end = OffsetUtf16(
8983                        range
8984                            .head()
8985                            .0
8986                            .saturating_add_signed(relative_utf16_range.end),
8987                    );
8988                    start..end
8989                });
8990                s.select_ranges(new_ranges);
8991            });
8992        }
8993
8994        self.handle_input(text, cx);
8995    }
8996
8997    pub fn supports_inlay_hints(&self, cx: &AppContext) -> bool {
8998        let Some(project) = self.project.as_ref() else {
8999            return false;
9000        };
9001        let project = project.read(cx);
9002
9003        let mut supports = false;
9004        self.buffer().read(cx).for_each_buffer(|buffer| {
9005            if !supports {
9006                supports = project
9007                    .language_servers_for_buffer(buffer.read(cx), cx)
9008                    .any(
9009                        |(_, server)| match server.capabilities().inlay_hint_provider {
9010                            Some(lsp::OneOf::Left(enabled)) => enabled,
9011                            Some(lsp::OneOf::Right(_)) => true,
9012                            None => false,
9013                        },
9014                    )
9015            }
9016        });
9017        supports
9018    }
9019
9020    pub fn focus(&self, cx: &mut WindowContext) {
9021        cx.focus(&self.focus_handle)
9022    }
9023
9024    pub fn is_focused(&self, cx: &WindowContext) -> bool {
9025        self.focus_handle.is_focused(cx)
9026    }
9027
9028    fn handle_focus(&mut self, cx: &mut ViewContext<Self>) {
9029        cx.emit(EditorEvent::Focused);
9030
9031        if let Some(rename) = self.pending_rename.as_ref() {
9032            let rename_editor_focus_handle = rename.editor.read(cx).focus_handle.clone();
9033            cx.focus(&rename_editor_focus_handle);
9034        } else {
9035            self.blink_manager.update(cx, BlinkManager::enable);
9036            self.buffer.update(cx, |buffer, cx| {
9037                buffer.finalize_last_transaction(cx);
9038                if self.leader_peer_id.is_none() {
9039                    buffer.set_active_selections(
9040                        &self.selections.disjoint_anchors(),
9041                        self.selections.line_mode,
9042                        self.cursor_shape,
9043                        cx,
9044                    );
9045                }
9046            });
9047        }
9048    }
9049
9050    fn handle_blur(&mut self, cx: &mut ViewContext<Self>) {
9051        // todo!()
9052        // let blurred_event = EditorBlurred(cx.handle());
9053        // cx.emit_global(blurred_event);
9054        self.blink_manager.update(cx, BlinkManager::disable);
9055        self.buffer
9056            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
9057        self.hide_context_menu(cx);
9058        hide_hover(self, cx);
9059        cx.emit(EditorEvent::Blurred);
9060        cx.notify();
9061    }
9062
9063    pub fn register_action<A: Action>(
9064        &mut self,
9065        listener: impl Fn(&A, &mut WindowContext) + 'static,
9066    ) -> &mut Self {
9067        let listener = Arc::new(listener);
9068
9069        self.editor_actions.push(Box::new(move |cx| {
9070            let view = cx.view().clone();
9071            let cx = cx.window_context();
9072            let listener = listener.clone();
9073            cx.on_action(TypeId::of::<A>(), move |action, phase, cx| {
9074                let action = action.downcast_ref().unwrap();
9075                if phase == DispatchPhase::Bubble {
9076                    listener(action, cx)
9077                }
9078            })
9079        }));
9080        self
9081    }
9082}
9083
9084pub trait CollaborationHub {
9085    fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator>;
9086    fn user_participant_indices<'a>(
9087        &self,
9088        cx: &'a AppContext,
9089    ) -> &'a HashMap<u64, ParticipantIndex>;
9090}
9091
9092impl CollaborationHub for Model<Project> {
9093    fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator> {
9094        self.read(cx).collaborators()
9095    }
9096
9097    fn user_participant_indices<'a>(
9098        &self,
9099        cx: &'a AppContext,
9100    ) -> &'a HashMap<u64, ParticipantIndex> {
9101        self.read(cx).user_store().read(cx).participant_indices()
9102    }
9103}
9104
9105fn inlay_hint_settings(
9106    location: Anchor,
9107    snapshot: &MultiBufferSnapshot,
9108    cx: &mut ViewContext<'_, Editor>,
9109) -> InlayHintSettings {
9110    let file = snapshot.file_at(location);
9111    let language = snapshot.language_at(location);
9112    let settings = all_language_settings(file, cx);
9113    settings
9114        .language(language.map(|l| l.name()).as_deref())
9115        .inlay_hints
9116}
9117
9118fn consume_contiguous_rows(
9119    contiguous_row_selections: &mut Vec<Selection<Point>>,
9120    selection: &Selection<Point>,
9121    display_map: &DisplaySnapshot,
9122    selections: &mut std::iter::Peekable<std::slice::Iter<Selection<Point>>>,
9123) -> (u32, u32) {
9124    contiguous_row_selections.push(selection.clone());
9125    let start_row = selection.start.row;
9126    let mut end_row = ending_row(selection, display_map);
9127
9128    while let Some(next_selection) = selections.peek() {
9129        if next_selection.start.row <= end_row {
9130            end_row = ending_row(next_selection, display_map);
9131            contiguous_row_selections.push(selections.next().unwrap().clone());
9132        } else {
9133            break;
9134        }
9135    }
9136    (start_row, end_row)
9137}
9138
9139fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> u32 {
9140    if next_selection.end.column > 0 || next_selection.is_empty() {
9141        display_map.next_line_boundary(next_selection.end).0.row + 1
9142    } else {
9143        next_selection.end.row
9144    }
9145}
9146
9147impl EditorSnapshot {
9148    pub fn remote_selections_in_range<'a>(
9149        &'a self,
9150        range: &'a Range<Anchor>,
9151        collaboration_hub: &dyn CollaborationHub,
9152        cx: &'a AppContext,
9153    ) -> impl 'a + Iterator<Item = RemoteSelection> {
9154        let participant_indices = collaboration_hub.user_participant_indices(cx);
9155        let collaborators_by_peer_id = collaboration_hub.collaborators(cx);
9156        let collaborators_by_replica_id = collaborators_by_peer_id
9157            .iter()
9158            .map(|(_, collaborator)| (collaborator.replica_id, collaborator))
9159            .collect::<HashMap<_, _>>();
9160        self.buffer_snapshot
9161            .remote_selections_in_range(range)
9162            .filter_map(move |(replica_id, line_mode, cursor_shape, selection)| {
9163                let collaborator = collaborators_by_replica_id.get(&replica_id)?;
9164                let participant_index = participant_indices.get(&collaborator.user_id).copied();
9165                Some(RemoteSelection {
9166                    replica_id,
9167                    selection,
9168                    cursor_shape,
9169                    line_mode,
9170                    participant_index,
9171                    peer_id: collaborator.peer_id,
9172                })
9173            })
9174    }
9175
9176    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
9177        self.display_snapshot.buffer_snapshot.language_at(position)
9178    }
9179
9180    pub fn is_focused(&self) -> bool {
9181        self.is_focused
9182    }
9183
9184    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
9185        self.placeholder_text.as_ref()
9186    }
9187
9188    pub fn scroll_position(&self) -> gpui::Point<f32> {
9189        self.scroll_anchor.scroll_position(&self.display_snapshot)
9190    }
9191}
9192
9193impl Deref for EditorSnapshot {
9194    type Target = DisplaySnapshot;
9195
9196    fn deref(&self) -> &Self::Target {
9197        &self.display_snapshot
9198    }
9199}
9200
9201#[derive(Clone, Debug, PartialEq, Eq)]
9202pub enum EditorEvent {
9203    InputIgnored {
9204        text: Arc<str>,
9205    },
9206    InputHandled {
9207        utf16_range_to_replace: Option<Range<isize>>,
9208        text: Arc<str>,
9209    },
9210    ExcerptsAdded {
9211        buffer: Model<Buffer>,
9212        predecessor: ExcerptId,
9213        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
9214    },
9215    ExcerptsRemoved {
9216        ids: Vec<ExcerptId>,
9217    },
9218    BufferEdited,
9219    Edited,
9220    Reparsed,
9221    Focused,
9222    Blurred,
9223    DirtyChanged,
9224    Saved,
9225    TitleChanged,
9226    DiffBaseChanged,
9227    SelectionsChanged {
9228        local: bool,
9229    },
9230    ScrollPositionChanged {
9231        local: bool,
9232        autoscroll: bool,
9233    },
9234    Closed,
9235}
9236
9237pub struct EditorFocused(pub View<Editor>);
9238pub struct EditorBlurred(pub View<Editor>);
9239pub struct EditorReleased(pub WeakView<Editor>);
9240
9241// impl Entity for Editor {
9242//     type Event = Event;
9243
9244//     fn release(&mut self, cx: &mut AppContext) {
9245//         cx.emit_global(EditorReleased(self.handle.clone()));
9246//     }
9247// }
9248//
9249impl EventEmitter<EditorEvent> for Editor {}
9250
9251impl FocusableView for Editor {
9252    fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
9253        self.focus_handle.clone()
9254    }
9255}
9256
9257impl Render for Editor {
9258    type Element = EditorElement;
9259
9260    fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
9261        let settings = ThemeSettings::get_global(cx);
9262        let text_style = match self.mode {
9263            EditorMode::SingleLine | EditorMode::AutoHeight { .. } => TextStyle {
9264                color: cx.theme().colors().text,
9265                font_family: settings.ui_font.family.clone(),
9266                font_features: settings.ui_font.features,
9267                font_size: rems(0.875).into(),
9268                font_weight: FontWeight::NORMAL,
9269                font_style: FontStyle::Normal,
9270                line_height: relative(1.).into(),
9271                background_color: None,
9272                underline: None,
9273                white_space: WhiteSpace::Normal,
9274            },
9275
9276            EditorMode::Full => TextStyle {
9277                color: cx.theme().colors().text,
9278                font_family: settings.buffer_font.family.clone(),
9279                font_features: settings.buffer_font.features,
9280                font_size: settings.buffer_font_size.into(),
9281                font_weight: FontWeight::NORMAL,
9282                font_style: FontStyle::Normal,
9283                line_height: relative(settings.buffer_line_height.value()),
9284                background_color: None,
9285                underline: None,
9286                white_space: WhiteSpace::Normal,
9287            },
9288        };
9289
9290        let background = match self.mode {
9291            EditorMode::SingleLine => cx.theme().system().transparent,
9292            EditorMode::AutoHeight { max_lines } => cx.theme().system().transparent,
9293            EditorMode::Full => cx.theme().colors().editor_background,
9294        };
9295
9296        EditorElement::new(
9297            cx.view(),
9298            EditorStyle {
9299                background,
9300                local_player: cx.theme().players().local(),
9301                text: text_style,
9302                scrollbar_width: px(12.),
9303                syntax: cx.theme().syntax().clone(),
9304                diagnostic_style: cx.theme().diagnostic_style(),
9305            },
9306        )
9307    }
9308}
9309
9310impl InputHandler for Editor {
9311    fn text_for_range(
9312        &mut self,
9313        range_utf16: Range<usize>,
9314        cx: &mut ViewContext<Self>,
9315    ) -> Option<String> {
9316        Some(
9317            self.buffer
9318                .read(cx)
9319                .read(cx)
9320                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
9321                .collect(),
9322        )
9323    }
9324
9325    fn selected_text_range(&mut self, cx: &mut ViewContext<Self>) -> Option<Range<usize>> {
9326        // Prevent the IME menu from appearing when holding down an alphabetic key
9327        // while input is disabled.
9328        if !self.input_enabled {
9329            return None;
9330        }
9331
9332        let range = self.selections.newest::<OffsetUtf16>(cx).range();
9333        Some(range.start.0..range.end.0)
9334    }
9335
9336    fn marked_text_range(&self, cx: &mut ViewContext<Self>) -> Option<Range<usize>> {
9337        let snapshot = self.buffer.read(cx).read(cx);
9338        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
9339        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
9340    }
9341
9342    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
9343        self.clear_highlights::<InputComposition>(cx);
9344        self.ime_transaction.take();
9345    }
9346
9347    fn replace_text_in_range(
9348        &mut self,
9349        range_utf16: Option<Range<usize>>,
9350        text: &str,
9351        cx: &mut ViewContext<Self>,
9352    ) {
9353        if !self.input_enabled {
9354            cx.emit(EditorEvent::InputIgnored { text: text.into() });
9355            return;
9356        }
9357
9358        self.transact(cx, |this, cx| {
9359            let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
9360                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
9361                Some(this.selection_replacement_ranges(range_utf16, cx))
9362            } else {
9363                this.marked_text_ranges(cx)
9364            };
9365
9366            let range_to_replace = new_selected_ranges.as_ref().and_then(|ranges_to_replace| {
9367                let newest_selection_id = this.selections.newest_anchor().id;
9368                this.selections
9369                    .all::<OffsetUtf16>(cx)
9370                    .iter()
9371                    .zip(ranges_to_replace.iter())
9372                    .find_map(|(selection, range)| {
9373                        if selection.id == newest_selection_id {
9374                            Some(
9375                                (range.start.0 as isize - selection.head().0 as isize)
9376                                    ..(range.end.0 as isize - selection.head().0 as isize),
9377                            )
9378                        } else {
9379                            None
9380                        }
9381                    })
9382            });
9383
9384            cx.emit(EditorEvent::InputHandled {
9385                utf16_range_to_replace: range_to_replace,
9386                text: text.into(),
9387            });
9388
9389            if let Some(new_selected_ranges) = new_selected_ranges {
9390                this.change_selections(None, cx, |selections| {
9391                    selections.select_ranges(new_selected_ranges)
9392                });
9393            }
9394
9395            this.handle_input(text, cx);
9396        });
9397
9398        if let Some(transaction) = self.ime_transaction {
9399            self.buffer.update(cx, |buffer, cx| {
9400                buffer.group_until_transaction(transaction, cx);
9401            });
9402        }
9403
9404        self.unmark_text(cx);
9405    }
9406
9407    fn replace_and_mark_text_in_range(
9408        &mut self,
9409        range_utf16: Option<Range<usize>>,
9410        text: &str,
9411        new_selected_range_utf16: Option<Range<usize>>,
9412        cx: &mut ViewContext<Self>,
9413    ) {
9414        if !self.input_enabled {
9415            cx.emit(EditorEvent::InputIgnored { text: text.into() });
9416            return;
9417        }
9418
9419        let transaction = self.transact(cx, |this, cx| {
9420            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
9421                let snapshot = this.buffer.read(cx).read(cx);
9422                if let Some(relative_range_utf16) = range_utf16.as_ref() {
9423                    for marked_range in &mut marked_ranges {
9424                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
9425                        marked_range.start.0 += relative_range_utf16.start;
9426                        marked_range.start =
9427                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
9428                        marked_range.end =
9429                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
9430                    }
9431                }
9432                Some(marked_ranges)
9433            } else if let Some(range_utf16) = range_utf16 {
9434                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
9435                Some(this.selection_replacement_ranges(range_utf16, cx))
9436            } else {
9437                None
9438            };
9439
9440            let range_to_replace = ranges_to_replace.as_ref().and_then(|ranges_to_replace| {
9441                let newest_selection_id = this.selections.newest_anchor().id;
9442                this.selections
9443                    .all::<OffsetUtf16>(cx)
9444                    .iter()
9445                    .zip(ranges_to_replace.iter())
9446                    .find_map(|(selection, range)| {
9447                        if selection.id == newest_selection_id {
9448                            Some(
9449                                (range.start.0 as isize - selection.head().0 as isize)
9450                                    ..(range.end.0 as isize - selection.head().0 as isize),
9451                            )
9452                        } else {
9453                            None
9454                        }
9455                    })
9456            });
9457
9458            cx.emit(EditorEvent::InputHandled {
9459                utf16_range_to_replace: range_to_replace,
9460                text: text.into(),
9461            });
9462
9463            if let Some(ranges) = ranges_to_replace {
9464                this.change_selections(None, cx, |s| s.select_ranges(ranges));
9465            }
9466
9467            let marked_ranges = {
9468                let snapshot = this.buffer.read(cx).read(cx);
9469                this.selections
9470                    .disjoint_anchors()
9471                    .iter()
9472                    .map(|selection| {
9473                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
9474                    })
9475                    .collect::<Vec<_>>()
9476            };
9477
9478            if text.is_empty() {
9479                this.unmark_text(cx);
9480            } else {
9481                this.highlight_text::<InputComposition>(
9482                    marked_ranges.clone(),
9483                    HighlightStyle::default(), // todo!() this.style(cx).composition_mark,
9484                    cx,
9485                );
9486            }
9487
9488            this.handle_input(text, cx);
9489
9490            if let Some(new_selected_range) = new_selected_range_utf16 {
9491                let snapshot = this.buffer.read(cx).read(cx);
9492                let new_selected_ranges = marked_ranges
9493                    .into_iter()
9494                    .map(|marked_range| {
9495                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
9496                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
9497                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
9498                        snapshot.clip_offset_utf16(new_start, Bias::Left)
9499                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
9500                    })
9501                    .collect::<Vec<_>>();
9502
9503                drop(snapshot);
9504                this.change_selections(None, cx, |selections| {
9505                    selections.select_ranges(new_selected_ranges)
9506                });
9507            }
9508        });
9509
9510        self.ime_transaction = self.ime_transaction.or(transaction);
9511        if let Some(transaction) = self.ime_transaction {
9512            self.buffer.update(cx, |buffer, cx| {
9513                buffer.group_until_transaction(transaction, cx);
9514            });
9515        }
9516
9517        if self.text_highlights::<InputComposition>(cx).is_none() {
9518            self.ime_transaction.take();
9519        }
9520    }
9521
9522    fn bounds_for_range(
9523        &mut self,
9524        range_utf16: Range<usize>,
9525        element_bounds: gpui::Bounds<Pixels>,
9526        cx: &mut ViewContext<Self>,
9527    ) -> Option<gpui::Bounds<Pixels>> {
9528        let text_layout_details = self.text_layout_details(cx);
9529        let style = &text_layout_details.editor_style;
9530        let font_id = cx.text_system().font_id(&style.text.font()).unwrap();
9531        let font_size = style.text.font_size.to_pixels(cx.rem_size());
9532        let line_height = style.text.line_height_in_pixels(cx.rem_size());
9533        let em_width = cx
9534            .text_system()
9535            .typographic_bounds(font_id, font_size, 'm')
9536            .unwrap()
9537            .size
9538            .width;
9539
9540        let snapshot = self.snapshot(cx);
9541        let scroll_position = snapshot.scroll_position();
9542        let scroll_left = scroll_position.x * em_width;
9543
9544        let start = OffsetUtf16(range_utf16.start).to_display_point(&snapshot);
9545        let x = snapshot.x_for_display_point(start, &text_layout_details) - scroll_left
9546            + self.gutter_width;
9547        let y = line_height * (start.row() as f32 - scroll_position.y);
9548
9549        Some(Bounds {
9550            origin: element_bounds.origin + point(x, y),
9551            size: size(em_width, line_height),
9552        })
9553    }
9554}
9555
9556trait SelectionExt {
9557    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
9558    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
9559    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
9560    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
9561        -> Range<u32>;
9562}
9563
9564impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
9565    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
9566        let start = self.start.to_point(buffer);
9567        let end = self.end.to_point(buffer);
9568        if self.reversed {
9569            end..start
9570        } else {
9571            start..end
9572        }
9573    }
9574
9575    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
9576        let start = self.start.to_offset(buffer);
9577        let end = self.end.to_offset(buffer);
9578        if self.reversed {
9579            end..start
9580        } else {
9581            start..end
9582        }
9583    }
9584
9585    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
9586        let start = self
9587            .start
9588            .to_point(&map.buffer_snapshot)
9589            .to_display_point(map);
9590        let end = self
9591            .end
9592            .to_point(&map.buffer_snapshot)
9593            .to_display_point(map);
9594        if self.reversed {
9595            end..start
9596        } else {
9597            start..end
9598        }
9599    }
9600
9601    fn spanned_rows(
9602        &self,
9603        include_end_if_at_line_start: bool,
9604        map: &DisplaySnapshot,
9605    ) -> Range<u32> {
9606        let start = self.start.to_point(&map.buffer_snapshot);
9607        let mut end = self.end.to_point(&map.buffer_snapshot);
9608        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
9609            end.row -= 1;
9610        }
9611
9612        let buffer_start = map.prev_line_boundary(start).0;
9613        let buffer_end = map.next_line_boundary(end).0;
9614        buffer_start.row..buffer_end.row + 1
9615    }
9616}
9617
9618impl<T: InvalidationRegion> InvalidationStack<T> {
9619    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
9620    where
9621        S: Clone + ToOffset,
9622    {
9623        while let Some(region) = self.last() {
9624            let all_selections_inside_invalidation_ranges =
9625                if selections.len() == region.ranges().len() {
9626                    selections
9627                        .iter()
9628                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
9629                        .all(|(selection, invalidation_range)| {
9630                            let head = selection.head().to_offset(buffer);
9631                            invalidation_range.start <= head && invalidation_range.end >= head
9632                        })
9633                } else {
9634                    false
9635                };
9636
9637            if all_selections_inside_invalidation_ranges {
9638                break;
9639            } else {
9640                self.pop();
9641            }
9642        }
9643    }
9644}
9645
9646impl<T> Default for InvalidationStack<T> {
9647    fn default() -> Self {
9648        Self(Default::default())
9649    }
9650}
9651
9652impl<T> Deref for InvalidationStack<T> {
9653    type Target = Vec<T>;
9654
9655    fn deref(&self) -> &Self::Target {
9656        &self.0
9657    }
9658}
9659
9660impl<T> DerefMut for InvalidationStack<T> {
9661    fn deref_mut(&mut self) -> &mut Self::Target {
9662        &mut self.0
9663    }
9664}
9665
9666impl InvalidationRegion for SnippetState {
9667    fn ranges(&self) -> &[Range<Anchor>] {
9668        &self.ranges[self.active_index]
9669    }
9670}
9671
9672// impl Deref for EditorStyle {
9673//     type Target = theme::Editor;
9674
9675//     fn deref(&self) -> &Self::Target {
9676//         &self.theme
9677//     }
9678// }
9679
9680pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
9681    let mut highlighted_lines = Vec::new();
9682
9683    for (index, line) in diagnostic.message.lines().enumerate() {
9684        let line = match &diagnostic.source {
9685            Some(source) if index == 0 => {
9686                let source_highlight = Vec::from_iter(0..source.len());
9687                highlight_diagnostic_message(source_highlight, &format!("{source}: {line}"))
9688            }
9689
9690            _ => highlight_diagnostic_message(Vec::new(), line),
9691        };
9692        highlighted_lines.push(line);
9693    }
9694    let message = diagnostic.message;
9695    Arc::new(move |cx: &mut BlockContext| {
9696        let message = message.clone();
9697        v_stack()
9698            .id(cx.block_id)
9699            .size_full()
9700            .bg(gpui::red())
9701            .children(highlighted_lines.iter().map(|(line, highlights)| {
9702                div()
9703                    .child(HighlightedLabel::new(line.clone(), highlights.clone()))
9704                    .ml(cx.anchor_x)
9705            }))
9706            .cursor_pointer()
9707            .on_click(cx.listener(move |_, _, cx| {
9708                cx.write_to_clipboard(ClipboardItem::new(message.clone()));
9709            }))
9710            .tooltip(|cx| Tooltip::text("Copy diagnostic message", cx))
9711            .into_any_element()
9712    })
9713}
9714
9715pub fn highlight_diagnostic_message(
9716    initial_highlights: Vec<usize>,
9717    message: &str,
9718) -> (String, Vec<usize>) {
9719    let mut message_without_backticks = String::new();
9720    let mut prev_offset = 0;
9721    let mut inside_block = false;
9722    let mut highlights = initial_highlights;
9723    for (match_ix, (offset, _)) in message
9724        .match_indices('`')
9725        .chain([(message.len(), "")])
9726        .enumerate()
9727    {
9728        message_without_backticks.push_str(&message[prev_offset..offset]);
9729        if inside_block {
9730            highlights.extend(prev_offset - match_ix..offset - match_ix);
9731        }
9732
9733        inside_block = !inside_block;
9734        prev_offset = offset + 1;
9735    }
9736
9737    (message_without_backticks, highlights)
9738}
9739
9740pub fn diagnostic_style(
9741    severity: DiagnosticSeverity,
9742    valid: bool,
9743    style: &DiagnosticStyle,
9744) -> Hsla {
9745    match (severity, valid) {
9746        (DiagnosticSeverity::ERROR, true) => style.error,
9747        (DiagnosticSeverity::ERROR, false) => style.error,
9748        (DiagnosticSeverity::WARNING, true) => style.warning,
9749        (DiagnosticSeverity::WARNING, false) => style.warning,
9750        (DiagnosticSeverity::INFORMATION, true) => style.info,
9751        (DiagnosticSeverity::INFORMATION, false) => style.info,
9752        (DiagnosticSeverity::HINT, true) => style.info,
9753        (DiagnosticSeverity::HINT, false) => style.info,
9754        _ => style.ignored,
9755    }
9756}
9757
9758pub fn text_runs_for_highlights(
9759    text: &str,
9760    default_style: &TextStyle,
9761    highlights: impl IntoIterator<Item = (Range<usize>, HighlightStyle)>,
9762) -> Vec<TextRun> {
9763    let mut runs = Vec::new();
9764    let mut ix = 0;
9765    for (range, highlight) in highlights {
9766        if ix < range.start {
9767            runs.push(default_style.clone().to_run(range.start - ix));
9768        }
9769        runs.push(
9770            default_style
9771                .clone()
9772                .highlight(highlight)
9773                .to_run(range.len()),
9774        );
9775        ix = range.end;
9776    }
9777    if ix < text.len() {
9778        runs.push(default_style.to_run(text.len() - ix));
9779    }
9780    runs
9781}
9782
9783pub fn styled_runs_for_code_label<'a>(
9784    label: &'a CodeLabel,
9785    syntax_theme: &'a theme::SyntaxTheme,
9786) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
9787    let fade_out = HighlightStyle {
9788        fade_out: Some(0.35),
9789        ..Default::default()
9790    };
9791
9792    let mut prev_end = label.filter_range.end;
9793    label
9794        .runs
9795        .iter()
9796        .enumerate()
9797        .flat_map(move |(ix, (range, highlight_id))| {
9798            let style = if let Some(style) = highlight_id.style(syntax_theme) {
9799                style
9800            } else {
9801                return Default::default();
9802            };
9803            let mut muted_style = style;
9804            muted_style.highlight(fade_out);
9805
9806            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
9807            if range.start >= label.filter_range.end {
9808                if range.start > prev_end {
9809                    runs.push((prev_end..range.start, fade_out));
9810                }
9811                runs.push((range.clone(), muted_style));
9812            } else if range.end <= label.filter_range.end {
9813                runs.push((range.clone(), style));
9814            } else {
9815                runs.push((range.start..label.filter_range.end, style));
9816                runs.push((label.filter_range.end..range.end, muted_style));
9817            }
9818            prev_end = cmp::max(prev_end, range.end);
9819
9820            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
9821                runs.push((prev_end..label.text.len(), fade_out));
9822            }
9823
9824            runs
9825        })
9826}
9827
9828pub fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
9829    let mut index = 0;
9830    let mut codepoints = text.char_indices().peekable();
9831
9832    std::iter::from_fn(move || {
9833        let start_index = index;
9834        while let Some((new_index, codepoint)) = codepoints.next() {
9835            index = new_index + codepoint.len_utf8();
9836            let current_upper = codepoint.is_uppercase();
9837            let next_upper = codepoints
9838                .peek()
9839                .map(|(_, c)| c.is_uppercase())
9840                .unwrap_or(false);
9841
9842            if !current_upper && next_upper {
9843                return Some(&text[start_index..index]);
9844            }
9845        }
9846
9847        index = text.len();
9848        if start_index < text.len() {
9849            return Some(&text[start_index..]);
9850        }
9851        None
9852    })
9853    .flat_map(|word| word.split_inclusive('_'))
9854    .flat_map(|word| word.split_inclusive('-'))
9855}
9856
9857trait RangeToAnchorExt {
9858    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
9859}
9860
9861impl<T: ToOffset> RangeToAnchorExt for Range<T> {
9862    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
9863        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
9864    }
9865}