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