editor.rs

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