editor.rs

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