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