editor.rs

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