editor.rs

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