editor.rs

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