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.completion_tasks.clear();
3600                        this.discard_copilot_suggestion(cx);
3601                        cx.notify();
3602                    } else if this.completion_tasks.is_empty() {
3603                        // If there are no more completion tasks and the last menu was
3604                        // empty, we should hide it. If it was already hidden, we should
3605                        // also show the copilot suggestion when available.
3606                        drop(context_menu);
3607                        if this.hide_context_menu(cx).is_none() {
3608                            this.update_visible_copilot_suggestion(cx);
3609                        }
3610                    }
3611                })?;
3612
3613                Ok::<_, anyhow::Error>(())
3614            }
3615            .log_err()
3616        });
3617        self.completion_tasks.push((id, task));
3618    }
3619
3620    pub fn confirm_completion(
3621        &mut self,
3622        action: &ConfirmCompletion,
3623        cx: &mut ViewContext<Self>,
3624    ) -> Option<Task<Result<()>>> {
3625        use language::ToOffset as _;
3626
3627        let completions_menu = if let ContextMenu::Completions(menu) = self.hide_context_menu(cx)? {
3628            menu
3629        } else {
3630            return None;
3631        };
3632
3633        let mat = completions_menu
3634            .matches
3635            .get(action.item_ix.unwrap_or(completions_menu.selected_item))?;
3636        let buffer_handle = completions_menu.buffer;
3637        let completions = completions_menu.completions.read();
3638        let completion = completions.get(mat.candidate_id)?;
3639
3640        let snippet;
3641        let text;
3642        if completion.is_snippet() {
3643            snippet = Some(Snippet::parse(&completion.new_text).log_err()?);
3644            text = snippet.as_ref().unwrap().text.clone();
3645        } else {
3646            snippet = None;
3647            text = completion.new_text.clone();
3648        };
3649        let selections = self.selections.all::<usize>(cx);
3650        let buffer = buffer_handle.read(cx);
3651        let old_range = completion.old_range.to_offset(buffer);
3652        let old_text = buffer.text_for_range(old_range.clone()).collect::<String>();
3653
3654        let newest_selection = self.selections.newest_anchor();
3655        if newest_selection.start.buffer_id != Some(buffer_handle.read(cx).remote_id()) {
3656            return None;
3657        }
3658
3659        let lookbehind = newest_selection
3660            .start
3661            .text_anchor
3662            .to_offset(buffer)
3663            .saturating_sub(old_range.start);
3664        let lookahead = old_range
3665            .end
3666            .saturating_sub(newest_selection.end.text_anchor.to_offset(buffer));
3667        let mut common_prefix_len = old_text
3668            .bytes()
3669            .zip(text.bytes())
3670            .take_while(|(a, b)| a == b)
3671            .count();
3672
3673        let snapshot = self.buffer.read(cx).snapshot(cx);
3674        let mut range_to_replace: Option<Range<isize>> = None;
3675        let mut ranges = Vec::new();
3676        for selection in &selections {
3677            if snapshot.contains_str_at(selection.start.saturating_sub(lookbehind), &old_text) {
3678                let start = selection.start.saturating_sub(lookbehind);
3679                let end = selection.end + lookahead;
3680                if selection.id == newest_selection.id {
3681                    range_to_replace = Some(
3682                        ((start + common_prefix_len) as isize - selection.start as isize)
3683                            ..(end as isize - selection.start as isize),
3684                    );
3685                }
3686                ranges.push(start + common_prefix_len..end);
3687            } else {
3688                common_prefix_len = 0;
3689                ranges.clear();
3690                ranges.extend(selections.iter().map(|s| {
3691                    if s.id == newest_selection.id {
3692                        range_to_replace = Some(
3693                            old_range.start.to_offset_utf16(&snapshot).0 as isize
3694                                - selection.start as isize
3695                                ..old_range.end.to_offset_utf16(&snapshot).0 as isize
3696                                    - selection.start as isize,
3697                        );
3698                        old_range.clone()
3699                    } else {
3700                        s.start..s.end
3701                    }
3702                }));
3703                break;
3704            }
3705        }
3706        let text = &text[common_prefix_len..];
3707
3708        cx.emit(Event::InputHandled {
3709            utf16_range_to_replace: range_to_replace,
3710            text: text.into(),
3711        });
3712
3713        self.transact(cx, |this, cx| {
3714            if let Some(mut snippet) = snippet {
3715                snippet.text = text.to_string();
3716                for tabstop in snippet.tabstops.iter_mut().flatten() {
3717                    tabstop.start -= common_prefix_len as isize;
3718                    tabstop.end -= common_prefix_len as isize;
3719                }
3720
3721                this.insert_snippet(&ranges, snippet, cx).log_err();
3722            } else {
3723                this.buffer.update(cx, |buffer, cx| {
3724                    buffer.edit(
3725                        ranges.iter().map(|range| (range.clone(), text)),
3726                        this.autoindent_mode.clone(),
3727                        cx,
3728                    );
3729                });
3730            }
3731
3732            this.refresh_copilot_suggestions(true, cx);
3733        });
3734
3735        let project = self.project.clone()?;
3736        let apply_edits = project.update(cx, |project, cx| {
3737            project.apply_additional_edits_for_completion(
3738                buffer_handle,
3739                completion.clone(),
3740                true,
3741                cx,
3742            )
3743        });
3744        Some(cx.foreground().spawn(async move {
3745            apply_edits.await?;
3746            Ok(())
3747        }))
3748    }
3749
3750    pub fn toggle_code_actions(&mut self, action: &ToggleCodeActions, cx: &mut ViewContext<Self>) {
3751        let mut context_menu = self.context_menu.write();
3752        if matches!(context_menu.as_ref(), Some(ContextMenu::CodeActions(_))) {
3753            *context_menu = None;
3754            cx.notify();
3755            return;
3756        }
3757        drop(context_menu);
3758
3759        let deployed_from_indicator = action.deployed_from_indicator;
3760        let mut task = self.code_actions_task.take();
3761        cx.spawn(|this, mut cx| async move {
3762            while let Some(prev_task) = task {
3763                prev_task.await;
3764                task = this.update(&mut cx, |this, _| this.code_actions_task.take())?;
3765            }
3766
3767            this.update(&mut cx, |this, cx| {
3768                if this.focused {
3769                    if let Some((buffer, actions)) = this.available_code_actions.clone() {
3770                        this.completion_tasks.clear();
3771                        this.discard_copilot_suggestion(cx);
3772                        *this.context_menu.write() =
3773                            Some(ContextMenu::CodeActions(CodeActionsMenu {
3774                                buffer,
3775                                actions,
3776                                selected_item: Default::default(),
3777                                list: Default::default(),
3778                                deployed_from_indicator,
3779                            }));
3780                    }
3781                }
3782            })?;
3783
3784            Ok::<_, anyhow::Error>(())
3785        })
3786        .detach_and_log_err(cx);
3787    }
3788
3789    pub fn confirm_code_action(
3790        workspace: &mut Workspace,
3791        action: &ConfirmCodeAction,
3792        cx: &mut ViewContext<Workspace>,
3793    ) -> Option<Task<Result<()>>> {
3794        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
3795        let actions_menu = if let ContextMenu::CodeActions(menu) =
3796            editor.update(cx, |editor, cx| editor.hide_context_menu(cx))?
3797        {
3798            menu
3799        } else {
3800            return None;
3801        };
3802        let action_ix = action.item_ix.unwrap_or(actions_menu.selected_item);
3803        let action = actions_menu.actions.get(action_ix)?.clone();
3804        let title = action.lsp_action.title.clone();
3805        let buffer = actions_menu.buffer;
3806
3807        let apply_code_actions = workspace.project().clone().update(cx, |project, cx| {
3808            project.apply_code_action(buffer, action, true, cx)
3809        });
3810        let editor = editor.downgrade();
3811        Some(cx.spawn(|workspace, cx| async move {
3812            let project_transaction = apply_code_actions.await?;
3813            Self::open_project_transaction(&editor, workspace, project_transaction, title, cx).await
3814        }))
3815    }
3816
3817    async fn open_project_transaction(
3818        this: &WeakViewHandle<Editor>,
3819        workspace: WeakViewHandle<Workspace>,
3820        transaction: ProjectTransaction,
3821        title: String,
3822        mut cx: AsyncAppContext,
3823    ) -> Result<()> {
3824        let replica_id = this.read_with(&cx, |this, cx| this.replica_id(cx))?;
3825
3826        let mut entries = transaction.0.into_iter().collect::<Vec<_>>();
3827        entries.sort_unstable_by_key(|(buffer, _)| {
3828            buffer.read_with(&cx, |buffer, _| buffer.file().map(|f| f.path().clone()))
3829        });
3830
3831        // If the project transaction's edits are all contained within this editor, then
3832        // avoid opening a new editor to display them.
3833
3834        if let Some((buffer, transaction)) = entries.first() {
3835            if entries.len() == 1 {
3836                let excerpt = this.read_with(&cx, |editor, cx| {
3837                    editor
3838                        .buffer()
3839                        .read(cx)
3840                        .excerpt_containing(editor.selections.newest_anchor().head(), cx)
3841                })?;
3842                if let Some((_, excerpted_buffer, excerpt_range)) = excerpt {
3843                    if excerpted_buffer == *buffer {
3844                        let all_edits_within_excerpt = buffer.read_with(&cx, |buffer, _| {
3845                            let excerpt_range = excerpt_range.to_offset(buffer);
3846                            buffer
3847                                .edited_ranges_for_transaction::<usize>(transaction)
3848                                .all(|range| {
3849                                    excerpt_range.start <= range.start
3850                                        && excerpt_range.end >= range.end
3851                                })
3852                        });
3853
3854                        if all_edits_within_excerpt {
3855                            return Ok(());
3856                        }
3857                    }
3858                }
3859            }
3860        } else {
3861            return Ok(());
3862        }
3863
3864        let mut ranges_to_highlight = Vec::new();
3865        let excerpt_buffer = cx.add_model(|cx| {
3866            let mut multibuffer = MultiBuffer::new(replica_id).with_title(title);
3867            for (buffer_handle, transaction) in &entries {
3868                let buffer = buffer_handle.read(cx);
3869                ranges_to_highlight.extend(
3870                    multibuffer.push_excerpts_with_context_lines(
3871                        buffer_handle.clone(),
3872                        buffer
3873                            .edited_ranges_for_transaction::<usize>(transaction)
3874                            .collect(),
3875                        1,
3876                        cx,
3877                    ),
3878                );
3879            }
3880            multibuffer.push_transaction(entries.iter().map(|(b, t)| (b, t)), cx);
3881            multibuffer
3882        });
3883
3884        workspace.update(&mut cx, |workspace, cx| {
3885            let project = workspace.project().clone();
3886            let editor =
3887                cx.add_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
3888            workspace.add_item(Box::new(editor.clone()), cx);
3889            editor.update(cx, |editor, cx| {
3890                editor.highlight_background::<Self>(
3891                    ranges_to_highlight,
3892                    |theme| theme.editor.highlighted_line_background,
3893                    cx,
3894                );
3895            });
3896        })?;
3897
3898        Ok(())
3899    }
3900
3901    fn refresh_code_actions(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
3902        let project = self.project.clone()?;
3903        let buffer = self.buffer.read(cx);
3904        let newest_selection = self.selections.newest_anchor().clone();
3905        let (start_buffer, start) = buffer.text_anchor_for_position(newest_selection.start, cx)?;
3906        let (end_buffer, end) = buffer.text_anchor_for_position(newest_selection.end, cx)?;
3907        if start_buffer != end_buffer {
3908            return None;
3909        }
3910
3911        self.code_actions_task = Some(cx.spawn(|this, mut cx| async move {
3912            cx.background().timer(CODE_ACTIONS_DEBOUNCE_TIMEOUT).await;
3913
3914            let actions = project
3915                .update(&mut cx, |project, cx| {
3916                    project.code_actions(&start_buffer, start..end, cx)
3917                })
3918                .await;
3919
3920            this.update(&mut cx, |this, cx| {
3921                this.available_code_actions = actions.log_err().and_then(|actions| {
3922                    if actions.is_empty() {
3923                        None
3924                    } else {
3925                        Some((start_buffer, actions.into()))
3926                    }
3927                });
3928                cx.notify();
3929            })
3930            .log_err();
3931        }));
3932        None
3933    }
3934
3935    fn refresh_document_highlights(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
3936        if self.pending_rename.is_some() {
3937            return None;
3938        }
3939
3940        let project = self.project.clone()?;
3941        let buffer = self.buffer.read(cx);
3942        let newest_selection = self.selections.newest_anchor().clone();
3943        let cursor_position = newest_selection.head();
3944        let (cursor_buffer, cursor_buffer_position) =
3945            buffer.text_anchor_for_position(cursor_position.clone(), cx)?;
3946        let (tail_buffer, _) = buffer.text_anchor_for_position(newest_selection.tail(), cx)?;
3947        if cursor_buffer != tail_buffer {
3948            return None;
3949        }
3950
3951        self.document_highlights_task = Some(cx.spawn(|this, mut cx| async move {
3952            cx.background()
3953                .timer(DOCUMENT_HIGHLIGHTS_DEBOUNCE_TIMEOUT)
3954                .await;
3955
3956            let highlights = project
3957                .update(&mut cx, |project, cx| {
3958                    project.document_highlights(&cursor_buffer, cursor_buffer_position, cx)
3959                })
3960                .await
3961                .log_err();
3962
3963            if let Some(highlights) = highlights {
3964                this.update(&mut cx, |this, cx| {
3965                    if this.pending_rename.is_some() {
3966                        return;
3967                    }
3968
3969                    let buffer_id = cursor_position.buffer_id;
3970                    let buffer = this.buffer.read(cx);
3971                    if !buffer
3972                        .text_anchor_for_position(cursor_position, cx)
3973                        .map_or(false, |(buffer, _)| buffer == cursor_buffer)
3974                    {
3975                        return;
3976                    }
3977
3978                    let cursor_buffer_snapshot = cursor_buffer.read(cx);
3979                    let mut write_ranges = Vec::new();
3980                    let mut read_ranges = Vec::new();
3981                    for highlight in highlights {
3982                        for (excerpt_id, excerpt_range) in
3983                            buffer.excerpts_for_buffer(&cursor_buffer, cx)
3984                        {
3985                            let start = highlight
3986                                .range
3987                                .start
3988                                .max(&excerpt_range.context.start, cursor_buffer_snapshot);
3989                            let end = highlight
3990                                .range
3991                                .end
3992                                .min(&excerpt_range.context.end, cursor_buffer_snapshot);
3993                            if start.cmp(&end, cursor_buffer_snapshot).is_ge() {
3994                                continue;
3995                            }
3996
3997                            let range = Anchor {
3998                                buffer_id,
3999                                excerpt_id: excerpt_id.clone(),
4000                                text_anchor: start,
4001                            }..Anchor {
4002                                buffer_id,
4003                                excerpt_id,
4004                                text_anchor: end,
4005                            };
4006                            if highlight.kind == lsp::DocumentHighlightKind::WRITE {
4007                                write_ranges.push(range);
4008                            } else {
4009                                read_ranges.push(range);
4010                            }
4011                        }
4012                    }
4013
4014                    this.highlight_background::<DocumentHighlightRead>(
4015                        read_ranges,
4016                        |theme| theme.editor.document_highlight_read_background,
4017                        cx,
4018                    );
4019                    this.highlight_background::<DocumentHighlightWrite>(
4020                        write_ranges,
4021                        |theme| theme.editor.document_highlight_write_background,
4022                        cx,
4023                    );
4024                    cx.notify();
4025                })
4026                .log_err();
4027            }
4028        }));
4029        None
4030    }
4031
4032    fn refresh_copilot_suggestions(
4033        &mut self,
4034        debounce: bool,
4035        cx: &mut ViewContext<Self>,
4036    ) -> Option<()> {
4037        let copilot = Copilot::global(cx)?;
4038        if self.mode != EditorMode::Full || !copilot.read(cx).status().is_authorized() {
4039            self.clear_copilot_suggestions(cx);
4040            return None;
4041        }
4042        self.update_visible_copilot_suggestion(cx);
4043
4044        let snapshot = self.buffer.read(cx).snapshot(cx);
4045        let cursor = self.selections.newest_anchor().head();
4046        if !self.is_copilot_enabled_at(cursor, &snapshot, cx) {
4047            self.clear_copilot_suggestions(cx);
4048            return None;
4049        }
4050
4051        let (buffer, buffer_position) =
4052            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
4053        self.copilot_state.pending_refresh = cx.spawn(|this, mut cx| async move {
4054            if debounce {
4055                cx.background().timer(COPILOT_DEBOUNCE_TIMEOUT).await;
4056            }
4057
4058            let completions = copilot
4059                .update(&mut cx, |copilot, cx| {
4060                    copilot.completions(&buffer, buffer_position, cx)
4061                })
4062                .await
4063                .log_err()
4064                .into_iter()
4065                .flatten()
4066                .collect_vec();
4067
4068            this.update(&mut cx, |this, cx| {
4069                if !completions.is_empty() {
4070                    this.copilot_state.cycled = false;
4071                    this.copilot_state.pending_cycling_refresh = Task::ready(None);
4072                    this.copilot_state.completions.clear();
4073                    this.copilot_state.active_completion_index = 0;
4074                    this.copilot_state.excerpt_id = Some(cursor.excerpt_id);
4075                    for completion in completions {
4076                        this.copilot_state.push_completion(completion);
4077                    }
4078                    this.update_visible_copilot_suggestion(cx);
4079                }
4080            })
4081            .log_err()?;
4082            Some(())
4083        });
4084
4085        Some(())
4086    }
4087
4088    fn cycle_copilot_suggestions(
4089        &mut self,
4090        direction: Direction,
4091        cx: &mut ViewContext<Self>,
4092    ) -> Option<()> {
4093        let copilot = Copilot::global(cx)?;
4094        if self.mode != EditorMode::Full || !copilot.read(cx).status().is_authorized() {
4095            return None;
4096        }
4097
4098        if self.copilot_state.cycled {
4099            self.copilot_state.cycle_completions(direction);
4100            self.update_visible_copilot_suggestion(cx);
4101        } else {
4102            let cursor = self.selections.newest_anchor().head();
4103            let (buffer, buffer_position) =
4104                self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
4105            self.copilot_state.pending_cycling_refresh = cx.spawn(|this, mut cx| async move {
4106                let completions = copilot
4107                    .update(&mut cx, |copilot, cx| {
4108                        copilot.completions_cycling(&buffer, buffer_position, cx)
4109                    })
4110                    .await;
4111
4112                this.update(&mut cx, |this, cx| {
4113                    this.copilot_state.cycled = true;
4114                    for completion in completions.log_err().into_iter().flatten() {
4115                        this.copilot_state.push_completion(completion);
4116                    }
4117                    this.copilot_state.cycle_completions(direction);
4118                    this.update_visible_copilot_suggestion(cx);
4119                })
4120                .log_err()?;
4121
4122                Some(())
4123            });
4124        }
4125
4126        Some(())
4127    }
4128
4129    fn copilot_suggest(&mut self, _: &copilot::Suggest, cx: &mut ViewContext<Self>) {
4130        if !self.has_active_copilot_suggestion(cx) {
4131            self.refresh_copilot_suggestions(false, cx);
4132            return;
4133        }
4134
4135        self.update_visible_copilot_suggestion(cx);
4136    }
4137
4138    fn next_copilot_suggestion(&mut self, _: &copilot::NextSuggestion, cx: &mut ViewContext<Self>) {
4139        if self.has_active_copilot_suggestion(cx) {
4140            self.cycle_copilot_suggestions(Direction::Next, cx);
4141        } else {
4142            self.refresh_copilot_suggestions(false, cx);
4143        }
4144    }
4145
4146    fn previous_copilot_suggestion(
4147        &mut self,
4148        _: &copilot::PreviousSuggestion,
4149        cx: &mut ViewContext<Self>,
4150    ) {
4151        if self.has_active_copilot_suggestion(cx) {
4152            self.cycle_copilot_suggestions(Direction::Prev, cx);
4153        } else {
4154            self.refresh_copilot_suggestions(false, cx);
4155        }
4156    }
4157
4158    fn accept_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
4159        if let Some(suggestion) = self.take_active_copilot_suggestion(cx) {
4160            if let Some((copilot, completion)) =
4161                Copilot::global(cx).zip(self.copilot_state.active_completion())
4162            {
4163                copilot
4164                    .update(cx, |copilot, cx| copilot.accept_completion(completion, cx))
4165                    .detach_and_log_err(cx);
4166
4167                self.report_copilot_event(Some(completion.uuid.clone()), true, cx)
4168            }
4169            cx.emit(Event::InputHandled {
4170                utf16_range_to_replace: None,
4171                text: suggestion.text.to_string().into(),
4172            });
4173            self.insert_with_autoindent_mode(&suggestion.text.to_string(), None, cx);
4174            cx.notify();
4175            true
4176        } else {
4177            false
4178        }
4179    }
4180
4181    fn discard_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
4182        if let Some(suggestion) = self.take_active_copilot_suggestion(cx) {
4183            if let Some(copilot) = Copilot::global(cx) {
4184                copilot
4185                    .update(cx, |copilot, cx| {
4186                        copilot.discard_completions(&self.copilot_state.completions, cx)
4187                    })
4188                    .detach_and_log_err(cx);
4189
4190                self.report_copilot_event(None, false, cx)
4191            }
4192
4193            self.display_map.update(cx, |map, cx| {
4194                map.splice_inlays(vec![suggestion.id], Vec::new(), cx)
4195            });
4196            cx.notify();
4197            true
4198        } else {
4199            false
4200        }
4201    }
4202
4203    fn is_copilot_enabled_at(
4204        &self,
4205        location: Anchor,
4206        snapshot: &MultiBufferSnapshot,
4207        cx: &mut ViewContext<Self>,
4208    ) -> bool {
4209        let file = snapshot.file_at(location);
4210        let language = snapshot.language_at(location);
4211        let settings = all_language_settings(file, cx);
4212        settings.copilot_enabled(language, file.map(|f| f.path().as_ref()))
4213    }
4214
4215    fn has_active_copilot_suggestion(&self, cx: &AppContext) -> bool {
4216        if let Some(suggestion) = self.copilot_state.suggestion.as_ref() {
4217            let buffer = self.buffer.read(cx).read(cx);
4218            suggestion.position.is_valid(&buffer)
4219        } else {
4220            false
4221        }
4222    }
4223
4224    fn take_active_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> Option<Inlay> {
4225        let suggestion = self.copilot_state.suggestion.take()?;
4226        self.display_map.update(cx, |map, cx| {
4227            map.splice_inlays(vec![suggestion.id], Default::default(), cx);
4228        });
4229        let buffer = self.buffer.read(cx).read(cx);
4230
4231        if suggestion.position.is_valid(&buffer) {
4232            Some(suggestion)
4233        } else {
4234            None
4235        }
4236    }
4237
4238    fn update_visible_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) {
4239        let snapshot = self.buffer.read(cx).snapshot(cx);
4240        let selection = self.selections.newest_anchor();
4241        let cursor = selection.head();
4242
4243        if self.context_menu.read().is_some()
4244            || !self.completion_tasks.is_empty()
4245            || selection.start != selection.end
4246        {
4247            self.discard_copilot_suggestion(cx);
4248        } else if let Some(text) = self
4249            .copilot_state
4250            .text_for_active_completion(cursor, &snapshot)
4251        {
4252            let text = Rope::from(text);
4253            let mut to_remove = Vec::new();
4254            if let Some(suggestion) = self.copilot_state.suggestion.take() {
4255                to_remove.push(suggestion.id);
4256            }
4257
4258            let suggestion_inlay =
4259                Inlay::suggestion(post_inc(&mut self.next_inlay_id), cursor, text);
4260            self.copilot_state.suggestion = Some(suggestion_inlay.clone());
4261            self.display_map.update(cx, move |map, cx| {
4262                map.splice_inlays(to_remove, vec![suggestion_inlay], cx)
4263            });
4264            cx.notify();
4265        } else {
4266            self.discard_copilot_suggestion(cx);
4267        }
4268    }
4269
4270    fn clear_copilot_suggestions(&mut self, cx: &mut ViewContext<Self>) {
4271        self.copilot_state = Default::default();
4272        self.discard_copilot_suggestion(cx);
4273    }
4274
4275    pub fn render_code_actions_indicator(
4276        &self,
4277        style: &EditorStyle,
4278        is_active: bool,
4279        cx: &mut ViewContext<Self>,
4280    ) -> Option<AnyElement<Self>> {
4281        if self.available_code_actions.is_some() {
4282            enum CodeActions {}
4283            Some(
4284                MouseEventHandler::new::<CodeActions, _>(0, cx, |state, _| {
4285                    Svg::new("icons/bolt.svg").with_color(
4286                        style
4287                            .code_actions
4288                            .indicator
4289                            .in_state(is_active)
4290                            .style_for(state)
4291                            .color,
4292                    )
4293                })
4294                .with_cursor_style(CursorStyle::PointingHand)
4295                .with_padding(Padding::uniform(3.))
4296                .on_down(MouseButton::Left, |_, this, cx| {
4297                    this.toggle_code_actions(
4298                        &ToggleCodeActions {
4299                            deployed_from_indicator: true,
4300                        },
4301                        cx,
4302                    );
4303                })
4304                .into_any(),
4305            )
4306        } else {
4307            None
4308        }
4309    }
4310
4311    pub fn render_fold_indicators(
4312        &self,
4313        fold_data: Vec<Option<(FoldStatus, u32, bool)>>,
4314        style: &EditorStyle,
4315        gutter_hovered: bool,
4316        line_height: f32,
4317        gutter_margin: f32,
4318        cx: &mut ViewContext<Self>,
4319    ) -> Vec<Option<AnyElement<Self>>> {
4320        enum FoldIndicators {}
4321
4322        let style = style.folds.clone();
4323
4324        fold_data
4325            .iter()
4326            .enumerate()
4327            .map(|(ix, fold_data)| {
4328                fold_data
4329                    .map(|(fold_status, buffer_row, active)| {
4330                        (active || gutter_hovered || fold_status == FoldStatus::Folded).then(|| {
4331                            MouseEventHandler::new::<FoldIndicators, _>(
4332                                ix as usize,
4333                                cx,
4334                                |mouse_state, _| {
4335                                    Svg::new(match fold_status {
4336                                        FoldStatus::Folded => style.folded_icon.clone(),
4337                                        FoldStatus::Foldable => style.foldable_icon.clone(),
4338                                    })
4339                                    .with_color(
4340                                        style
4341                                            .indicator
4342                                            .in_state(fold_status == FoldStatus::Folded)
4343                                            .style_for(mouse_state)
4344                                            .color,
4345                                    )
4346                                    .constrained()
4347                                    .with_width(gutter_margin * style.icon_margin_scale)
4348                                    .aligned()
4349                                    .constrained()
4350                                    .with_height(line_height)
4351                                    .with_width(gutter_margin)
4352                                    .aligned()
4353                                },
4354                            )
4355                            .with_cursor_style(CursorStyle::PointingHand)
4356                            .with_padding(Padding::uniform(3.))
4357                            .on_click(MouseButton::Left, {
4358                                move |_, editor, cx| match fold_status {
4359                                    FoldStatus::Folded => {
4360                                        editor.unfold_at(&UnfoldAt { buffer_row }, cx);
4361                                    }
4362                                    FoldStatus::Foldable => {
4363                                        editor.fold_at(&FoldAt { buffer_row }, cx);
4364                                    }
4365                                }
4366                            })
4367                            .into_any()
4368                        })
4369                    })
4370                    .flatten()
4371            })
4372            .collect()
4373    }
4374
4375    pub fn context_menu_visible(&self) -> bool {
4376        self.context_menu
4377            .read()
4378            .as_ref()
4379            .map_or(false, |menu| menu.visible())
4380    }
4381
4382    pub fn render_context_menu(
4383        &self,
4384        cursor_position: DisplayPoint,
4385        style: EditorStyle,
4386        cx: &mut ViewContext<Editor>,
4387    ) -> Option<(DisplayPoint, AnyElement<Editor>)> {
4388        self.context_menu.read().as_ref().map(|menu| {
4389            menu.render(
4390                cursor_position,
4391                style,
4392                self.workspace.as_ref().map(|(w, _)| w.clone()),
4393                cx,
4394            )
4395        })
4396    }
4397
4398    fn hide_context_menu(&mut self, cx: &mut ViewContext<Self>) -> Option<ContextMenu> {
4399        cx.notify();
4400        self.completion_tasks.clear();
4401        let context_menu = self.context_menu.write().take();
4402        if context_menu.is_some() {
4403            self.update_visible_copilot_suggestion(cx);
4404        }
4405        context_menu
4406    }
4407
4408    pub fn insert_snippet(
4409        &mut self,
4410        insertion_ranges: &[Range<usize>],
4411        snippet: Snippet,
4412        cx: &mut ViewContext<Self>,
4413    ) -> Result<()> {
4414        let tabstops = self.buffer.update(cx, |buffer, cx| {
4415            let snippet_text: Arc<str> = snippet.text.clone().into();
4416            buffer.edit(
4417                insertion_ranges
4418                    .iter()
4419                    .cloned()
4420                    .map(|range| (range, snippet_text.clone())),
4421                Some(AutoindentMode::EachLine),
4422                cx,
4423            );
4424
4425            let snapshot = &*buffer.read(cx);
4426            let snippet = &snippet;
4427            snippet
4428                .tabstops
4429                .iter()
4430                .map(|tabstop| {
4431                    let mut tabstop_ranges = tabstop
4432                        .iter()
4433                        .flat_map(|tabstop_range| {
4434                            let mut delta = 0_isize;
4435                            insertion_ranges.iter().map(move |insertion_range| {
4436                                let insertion_start = insertion_range.start as isize + delta;
4437                                delta +=
4438                                    snippet.text.len() as isize - insertion_range.len() as isize;
4439
4440                                let start = snapshot.anchor_before(
4441                                    (insertion_start + tabstop_range.start) as usize,
4442                                );
4443                                let end = snapshot
4444                                    .anchor_after((insertion_start + tabstop_range.end) as usize);
4445                                start..end
4446                            })
4447                        })
4448                        .collect::<Vec<_>>();
4449                    tabstop_ranges.sort_unstable_by(|a, b| a.start.cmp(&b.start, snapshot));
4450                    tabstop_ranges
4451                })
4452                .collect::<Vec<_>>()
4453        });
4454
4455        if let Some(tabstop) = tabstops.first() {
4456            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4457                s.select_ranges(tabstop.iter().cloned());
4458            });
4459            self.snippet_stack.push(SnippetState {
4460                active_index: 0,
4461                ranges: tabstops,
4462            });
4463        }
4464
4465        Ok(())
4466    }
4467
4468    pub fn move_to_next_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
4469        self.move_to_snippet_tabstop(Bias::Right, cx)
4470    }
4471
4472    pub fn move_to_prev_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
4473        self.move_to_snippet_tabstop(Bias::Left, cx)
4474    }
4475
4476    pub fn move_to_snippet_tabstop(&mut self, bias: Bias, cx: &mut ViewContext<Self>) -> bool {
4477        if let Some(mut snippet) = self.snippet_stack.pop() {
4478            match bias {
4479                Bias::Left => {
4480                    if snippet.active_index > 0 {
4481                        snippet.active_index -= 1;
4482                    } else {
4483                        self.snippet_stack.push(snippet);
4484                        return false;
4485                    }
4486                }
4487                Bias::Right => {
4488                    if snippet.active_index + 1 < snippet.ranges.len() {
4489                        snippet.active_index += 1;
4490                    } else {
4491                        self.snippet_stack.push(snippet);
4492                        return false;
4493                    }
4494                }
4495            }
4496            if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
4497                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4498                    s.select_anchor_ranges(current_ranges.iter().cloned())
4499                });
4500                // If snippet state is not at the last tabstop, push it back on the stack
4501                if snippet.active_index + 1 < snippet.ranges.len() {
4502                    self.snippet_stack.push(snippet);
4503                }
4504                return true;
4505            }
4506        }
4507
4508        false
4509    }
4510
4511    pub fn clear(&mut self, cx: &mut ViewContext<Self>) {
4512        self.transact(cx, |this, cx| {
4513            this.select_all(&SelectAll, cx);
4514            this.insert("", cx);
4515        });
4516    }
4517
4518    pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
4519        self.transact(cx, |this, cx| {
4520            this.select_autoclose_pair(cx);
4521            let mut selections = this.selections.all::<Point>(cx);
4522            if !this.selections.line_mode {
4523                let display_map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
4524                for selection in &mut selections {
4525                    if selection.is_empty() {
4526                        let old_head = selection.head();
4527                        let mut new_head =
4528                            movement::left(&display_map, old_head.to_display_point(&display_map))
4529                                .to_point(&display_map);
4530                        if let Some((buffer, line_buffer_range)) = display_map
4531                            .buffer_snapshot
4532                            .buffer_line_for_row(old_head.row)
4533                        {
4534                            let indent_size =
4535                                buffer.indent_size_for_line(line_buffer_range.start.row);
4536                            let indent_len = match indent_size.kind {
4537                                IndentKind::Space => {
4538                                    buffer.settings_at(line_buffer_range.start, cx).tab_size
4539                                }
4540                                IndentKind::Tab => NonZeroU32::new(1).unwrap(),
4541                            };
4542                            if old_head.column <= indent_size.len && old_head.column > 0 {
4543                                let indent_len = indent_len.get();
4544                                new_head = cmp::min(
4545                                    new_head,
4546                                    Point::new(
4547                                        old_head.row,
4548                                        ((old_head.column - 1) / indent_len) * indent_len,
4549                                    ),
4550                                );
4551                            }
4552                        }
4553
4554                        selection.set_head(new_head, SelectionGoal::None);
4555                    }
4556                }
4557            }
4558
4559            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4560            this.insert("", cx);
4561            this.refresh_copilot_suggestions(true, cx);
4562        });
4563    }
4564
4565    pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
4566        self.transact(cx, |this, cx| {
4567            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4568                let line_mode = s.line_mode;
4569                s.move_with(|map, selection| {
4570                    if selection.is_empty() && !line_mode {
4571                        let cursor = movement::right(map, selection.head());
4572                        selection.end = cursor;
4573                        selection.reversed = true;
4574                        selection.goal = SelectionGoal::None;
4575                    }
4576                })
4577            });
4578            this.insert("", cx);
4579            this.refresh_copilot_suggestions(true, cx);
4580        });
4581    }
4582
4583    pub fn tab_prev(&mut self, _: &TabPrev, cx: &mut ViewContext<Self>) {
4584        if self.move_to_prev_snippet_tabstop(cx) {
4585            return;
4586        }
4587
4588        self.outdent(&Outdent, cx);
4589    }
4590
4591    pub fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
4592        if self.move_to_next_snippet_tabstop(cx) {
4593            return;
4594        }
4595
4596        let mut selections = self.selections.all_adjusted(cx);
4597        let buffer = self.buffer.read(cx);
4598        let snapshot = buffer.snapshot(cx);
4599        let rows_iter = selections.iter().map(|s| s.head().row);
4600        let suggested_indents = snapshot.suggested_indents(rows_iter, cx);
4601
4602        let mut edits = Vec::new();
4603        let mut prev_edited_row = 0;
4604        let mut row_delta = 0;
4605        for selection in &mut selections {
4606            if selection.start.row != prev_edited_row {
4607                row_delta = 0;
4608            }
4609            prev_edited_row = selection.end.row;
4610
4611            // If the selection is non-empty, then increase the indentation of the selected lines.
4612            if !selection.is_empty() {
4613                row_delta =
4614                    Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
4615                continue;
4616            }
4617
4618            // If the selection is empty and the cursor is in the leading whitespace before the
4619            // suggested indentation, then auto-indent the line.
4620            let cursor = selection.head();
4621            let current_indent = snapshot.indent_size_for_line(cursor.row);
4622            if let Some(suggested_indent) = suggested_indents.get(&cursor.row).copied() {
4623                if cursor.column < suggested_indent.len
4624                    && cursor.column <= current_indent.len
4625                    && current_indent.len <= suggested_indent.len
4626                {
4627                    selection.start = Point::new(cursor.row, suggested_indent.len);
4628                    selection.end = selection.start;
4629                    if row_delta == 0 {
4630                        edits.extend(Buffer::edit_for_indent_size_adjustment(
4631                            cursor.row,
4632                            current_indent,
4633                            suggested_indent,
4634                        ));
4635                        row_delta = suggested_indent.len - current_indent.len;
4636                    }
4637                    continue;
4638                }
4639            }
4640
4641            // Accept copilot suggestion if there is only one selection and the cursor is not
4642            // in the leading whitespace.
4643            if self.selections.count() == 1
4644                && cursor.column >= current_indent.len
4645                && self.has_active_copilot_suggestion(cx)
4646            {
4647                self.accept_copilot_suggestion(cx);
4648                return;
4649            }
4650
4651            // Otherwise, insert a hard or soft tab.
4652            let settings = buffer.settings_at(cursor, cx);
4653            let tab_size = if settings.hard_tabs {
4654                IndentSize::tab()
4655            } else {
4656                let tab_size = settings.tab_size.get();
4657                let char_column = snapshot
4658                    .text_for_range(Point::new(cursor.row, 0)..cursor)
4659                    .flat_map(str::chars)
4660                    .count()
4661                    + row_delta as usize;
4662                let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
4663                IndentSize::spaces(chars_to_next_tab_stop)
4664            };
4665            selection.start = Point::new(cursor.row, cursor.column + row_delta + tab_size.len);
4666            selection.end = selection.start;
4667            edits.push((cursor..cursor, tab_size.chars().collect::<String>()));
4668            row_delta += tab_size.len;
4669        }
4670
4671        self.transact(cx, |this, cx| {
4672            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
4673            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4674            this.refresh_copilot_suggestions(true, cx);
4675        });
4676    }
4677
4678    pub fn indent(&mut self, _: &Indent, cx: &mut ViewContext<Self>) {
4679        let mut selections = self.selections.all::<Point>(cx);
4680        let mut prev_edited_row = 0;
4681        let mut row_delta = 0;
4682        let mut edits = Vec::new();
4683        let buffer = self.buffer.read(cx);
4684        let snapshot = buffer.snapshot(cx);
4685        for selection in &mut selections {
4686            if selection.start.row != prev_edited_row {
4687                row_delta = 0;
4688            }
4689            prev_edited_row = selection.end.row;
4690
4691            row_delta =
4692                Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
4693        }
4694
4695        self.transact(cx, |this, cx| {
4696            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
4697            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4698        });
4699    }
4700
4701    fn indent_selection(
4702        buffer: &MultiBuffer,
4703        snapshot: &MultiBufferSnapshot,
4704        selection: &mut Selection<Point>,
4705        edits: &mut Vec<(Range<Point>, String)>,
4706        delta_for_start_row: u32,
4707        cx: &AppContext,
4708    ) -> u32 {
4709        let settings = buffer.settings_at(selection.start, cx);
4710        let tab_size = settings.tab_size.get();
4711        let indent_kind = if settings.hard_tabs {
4712            IndentKind::Tab
4713        } else {
4714            IndentKind::Space
4715        };
4716        let mut start_row = selection.start.row;
4717        let mut end_row = selection.end.row + 1;
4718
4719        // If a selection ends at the beginning of a line, don't indent
4720        // that last line.
4721        if selection.end.column == 0 {
4722            end_row -= 1;
4723        }
4724
4725        // Avoid re-indenting a row that has already been indented by a
4726        // previous selection, but still update this selection's column
4727        // to reflect that indentation.
4728        if delta_for_start_row > 0 {
4729            start_row += 1;
4730            selection.start.column += delta_for_start_row;
4731            if selection.end.row == selection.start.row {
4732                selection.end.column += delta_for_start_row;
4733            }
4734        }
4735
4736        let mut delta_for_end_row = 0;
4737        for row in start_row..end_row {
4738            let current_indent = snapshot.indent_size_for_line(row);
4739            let indent_delta = match (current_indent.kind, indent_kind) {
4740                (IndentKind::Space, IndentKind::Space) => {
4741                    let columns_to_next_tab_stop = tab_size - (current_indent.len % tab_size);
4742                    IndentSize::spaces(columns_to_next_tab_stop)
4743                }
4744                (IndentKind::Tab, IndentKind::Space) => IndentSize::spaces(tab_size),
4745                (_, IndentKind::Tab) => IndentSize::tab(),
4746            };
4747
4748            let row_start = Point::new(row, 0);
4749            edits.push((
4750                row_start..row_start,
4751                indent_delta.chars().collect::<String>(),
4752            ));
4753
4754            // Update this selection's endpoints to reflect the indentation.
4755            if row == selection.start.row {
4756                selection.start.column += indent_delta.len;
4757            }
4758            if row == selection.end.row {
4759                selection.end.column += indent_delta.len;
4760                delta_for_end_row = indent_delta.len;
4761            }
4762        }
4763
4764        if selection.start.row == selection.end.row {
4765            delta_for_start_row + delta_for_end_row
4766        } else {
4767            delta_for_end_row
4768        }
4769    }
4770
4771    pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
4772        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4773        let selections = self.selections.all::<Point>(cx);
4774        let mut deletion_ranges = Vec::new();
4775        let mut last_outdent = None;
4776        {
4777            let buffer = self.buffer.read(cx);
4778            let snapshot = buffer.snapshot(cx);
4779            for selection in &selections {
4780                let settings = buffer.settings_at(selection.start, cx);
4781                let tab_size = settings.tab_size.get();
4782                let mut rows = selection.spanned_rows(false, &display_map);
4783
4784                // Avoid re-outdenting a row that has already been outdented by a
4785                // previous selection.
4786                if let Some(last_row) = last_outdent {
4787                    if last_row == rows.start {
4788                        rows.start += 1;
4789                    }
4790                }
4791
4792                for row in rows {
4793                    let indent_size = snapshot.indent_size_for_line(row);
4794                    if indent_size.len > 0 {
4795                        let deletion_len = match indent_size.kind {
4796                            IndentKind::Space => {
4797                                let columns_to_prev_tab_stop = indent_size.len % tab_size;
4798                                if columns_to_prev_tab_stop == 0 {
4799                                    tab_size
4800                                } else {
4801                                    columns_to_prev_tab_stop
4802                                }
4803                            }
4804                            IndentKind::Tab => 1,
4805                        };
4806                        deletion_ranges.push(Point::new(row, 0)..Point::new(row, deletion_len));
4807                        last_outdent = Some(row);
4808                    }
4809                }
4810            }
4811        }
4812
4813        self.transact(cx, |this, cx| {
4814            this.buffer.update(cx, |buffer, cx| {
4815                let empty_str: Arc<str> = "".into();
4816                buffer.edit(
4817                    deletion_ranges
4818                        .into_iter()
4819                        .map(|range| (range, empty_str.clone())),
4820                    None,
4821                    cx,
4822                );
4823            });
4824            let selections = this.selections.all::<usize>(cx);
4825            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4826        });
4827    }
4828
4829    pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
4830        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4831        let selections = self.selections.all::<Point>(cx);
4832
4833        let mut new_cursors = Vec::new();
4834        let mut edit_ranges = Vec::new();
4835        let mut selections = selections.iter().peekable();
4836        while let Some(selection) = selections.next() {
4837            let mut rows = selection.spanned_rows(false, &display_map);
4838            let goal_display_column = selection.head().to_display_point(&display_map).column();
4839
4840            // Accumulate contiguous regions of rows that we want to delete.
4841            while let Some(next_selection) = selections.peek() {
4842                let next_rows = next_selection.spanned_rows(false, &display_map);
4843                if next_rows.start <= rows.end {
4844                    rows.end = next_rows.end;
4845                    selections.next().unwrap();
4846                } else {
4847                    break;
4848                }
4849            }
4850
4851            let buffer = &display_map.buffer_snapshot;
4852            let mut edit_start = Point::new(rows.start, 0).to_offset(buffer);
4853            let edit_end;
4854            let cursor_buffer_row;
4855            if buffer.max_point().row >= rows.end {
4856                // If there's a line after the range, delete the \n from the end of the row range
4857                // and position the cursor on the next line.
4858                edit_end = Point::new(rows.end, 0).to_offset(buffer);
4859                cursor_buffer_row = rows.end;
4860            } else {
4861                // If there isn't a line after the range, delete the \n from the line before the
4862                // start of the row range and position the cursor there.
4863                edit_start = edit_start.saturating_sub(1);
4864                edit_end = buffer.len();
4865                cursor_buffer_row = rows.start.saturating_sub(1);
4866            }
4867
4868            let mut cursor = Point::new(cursor_buffer_row, 0).to_display_point(&display_map);
4869            *cursor.column_mut() =
4870                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
4871
4872            new_cursors.push((
4873                selection.id,
4874                buffer.anchor_after(cursor.to_point(&display_map)),
4875            ));
4876            edit_ranges.push(edit_start..edit_end);
4877        }
4878
4879        self.transact(cx, |this, cx| {
4880            let buffer = this.buffer.update(cx, |buffer, cx| {
4881                let empty_str: Arc<str> = "".into();
4882                buffer.edit(
4883                    edit_ranges
4884                        .into_iter()
4885                        .map(|range| (range, empty_str.clone())),
4886                    None,
4887                    cx,
4888                );
4889                buffer.snapshot(cx)
4890            });
4891            let new_selections = new_cursors
4892                .into_iter()
4893                .map(|(id, cursor)| {
4894                    let cursor = cursor.to_point(&buffer);
4895                    Selection {
4896                        id,
4897                        start: cursor,
4898                        end: cursor,
4899                        reversed: false,
4900                        goal: SelectionGoal::None,
4901                    }
4902                })
4903                .collect();
4904
4905            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4906                s.select(new_selections);
4907            });
4908        });
4909    }
4910
4911    pub fn join_lines(&mut self, _: &JoinLines, cx: &mut ViewContext<Self>) {
4912        let mut row_ranges = Vec::<Range<u32>>::new();
4913        for selection in self.selections.all::<Point>(cx) {
4914            let start = selection.start.row;
4915            let end = if selection.start.row == selection.end.row {
4916                selection.start.row + 1
4917            } else {
4918                selection.end.row
4919            };
4920
4921            if let Some(last_row_range) = row_ranges.last_mut() {
4922                if start <= last_row_range.end {
4923                    last_row_range.end = end;
4924                    continue;
4925                }
4926            }
4927            row_ranges.push(start..end);
4928        }
4929
4930        let snapshot = self.buffer.read(cx).snapshot(cx);
4931        let mut cursor_positions = Vec::new();
4932        for row_range in &row_ranges {
4933            let anchor = snapshot.anchor_before(Point::new(
4934                row_range.end - 1,
4935                snapshot.line_len(row_range.end - 1),
4936            ));
4937            cursor_positions.push(anchor.clone()..anchor);
4938        }
4939
4940        self.transact(cx, |this, cx| {
4941            for row_range in row_ranges.into_iter().rev() {
4942                for row in row_range.rev() {
4943                    let end_of_line = Point::new(row, snapshot.line_len(row));
4944                    let indent = snapshot.indent_size_for_line(row + 1);
4945                    let start_of_next_line = Point::new(row + 1, indent.len);
4946
4947                    let replace = if snapshot.line_len(row + 1) > indent.len {
4948                        " "
4949                    } else {
4950                        ""
4951                    };
4952
4953                    this.buffer.update(cx, |buffer, cx| {
4954                        buffer.edit([(end_of_line..start_of_next_line, replace)], None, cx)
4955                    });
4956                }
4957            }
4958
4959            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4960                s.select_anchor_ranges(cursor_positions)
4961            });
4962        });
4963    }
4964
4965    pub fn sort_lines_case_sensitive(
4966        &mut self,
4967        _: &SortLinesCaseSensitive,
4968        cx: &mut ViewContext<Self>,
4969    ) {
4970        self.manipulate_lines(cx, |lines| lines.sort())
4971    }
4972
4973    pub fn sort_lines_case_insensitive(
4974        &mut self,
4975        _: &SortLinesCaseInsensitive,
4976        cx: &mut ViewContext<Self>,
4977    ) {
4978        self.manipulate_lines(cx, |lines| lines.sort_by_key(|line| line.to_lowercase()))
4979    }
4980
4981    pub fn reverse_lines(&mut self, _: &ReverseLines, cx: &mut ViewContext<Self>) {
4982        self.manipulate_lines(cx, |lines| lines.reverse())
4983    }
4984
4985    pub fn shuffle_lines(&mut self, _: &ShuffleLines, cx: &mut ViewContext<Self>) {
4986        self.manipulate_lines(cx, |lines| lines.shuffle(&mut thread_rng()))
4987    }
4988
4989    fn manipulate_lines<Fn>(&mut self, cx: &mut ViewContext<Self>, mut callback: Fn)
4990    where
4991        Fn: FnMut(&mut [&str]),
4992    {
4993        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4994        let buffer = self.buffer.read(cx).snapshot(cx);
4995
4996        let mut edits = Vec::new();
4997
4998        let selections = self.selections.all::<Point>(cx);
4999        let mut selections = selections.iter().peekable();
5000        let mut contiguous_row_selections = Vec::new();
5001        let mut new_selections = Vec::new();
5002
5003        while let Some(selection) = selections.next() {
5004            let (start_row, end_row) = consume_contiguous_rows(
5005                &mut contiguous_row_selections,
5006                selection,
5007                &display_map,
5008                &mut selections,
5009            );
5010
5011            let start_point = Point::new(start_row, 0);
5012            let end_point = Point::new(end_row - 1, buffer.line_len(end_row - 1));
5013            let text = buffer
5014                .text_for_range(start_point..end_point)
5015                .collect::<String>();
5016            let mut lines = text.split("\n").collect_vec();
5017
5018            let lines_len = lines.len();
5019            callback(&mut lines);
5020
5021            // This is a current limitation with selections.
5022            // If we wanted to support removing or adding lines, we'd need to fix the logic associated with selections.
5023            debug_assert!(
5024                lines.len() == lines_len,
5025                "callback should not change the number of lines"
5026            );
5027
5028            edits.push((start_point..end_point, lines.join("\n")));
5029            let start_anchor = buffer.anchor_after(start_point);
5030            let end_anchor = buffer.anchor_before(end_point);
5031
5032            // Make selection and push
5033            new_selections.push(Selection {
5034                id: selection.id,
5035                start: start_anchor.to_offset(&buffer),
5036                end: end_anchor.to_offset(&buffer),
5037                goal: SelectionGoal::None,
5038                reversed: selection.reversed,
5039            });
5040        }
5041
5042        self.transact(cx, |this, cx| {
5043            this.buffer.update(cx, |buffer, cx| {
5044                buffer.edit(edits, None, cx);
5045            });
5046
5047            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5048                s.select(new_selections);
5049            });
5050
5051            this.request_autoscroll(Autoscroll::fit(), cx);
5052        });
5053    }
5054
5055    pub fn convert_to_upper_case(&mut self, _: &ConvertToUpperCase, cx: &mut ViewContext<Self>) {
5056        self.manipulate_text(cx, |text| text.to_uppercase())
5057    }
5058
5059    pub fn convert_to_lower_case(&mut self, _: &ConvertToLowerCase, cx: &mut ViewContext<Self>) {
5060        self.manipulate_text(cx, |text| text.to_lowercase())
5061    }
5062
5063    pub fn convert_to_title_case(&mut self, _: &ConvertToTitleCase, cx: &mut ViewContext<Self>) {
5064        self.manipulate_text(cx, |text| {
5065            // Hack to get around the fact that to_case crate doesn't support '\n' as a word boundary
5066            // https://github.com/rutrum/convert-case/issues/16
5067            text.split("\n")
5068                .map(|line| line.to_case(Case::Title))
5069                .join("\n")
5070        })
5071    }
5072
5073    pub fn convert_to_snake_case(&mut self, _: &ConvertToSnakeCase, cx: &mut ViewContext<Self>) {
5074        self.manipulate_text(cx, |text| text.to_case(Case::Snake))
5075    }
5076
5077    pub fn convert_to_kebab_case(&mut self, _: &ConvertToKebabCase, cx: &mut ViewContext<Self>) {
5078        self.manipulate_text(cx, |text| text.to_case(Case::Kebab))
5079    }
5080
5081    pub fn convert_to_upper_camel_case(
5082        &mut self,
5083        _: &ConvertToUpperCamelCase,
5084        cx: &mut ViewContext<Self>,
5085    ) {
5086        self.manipulate_text(cx, |text| {
5087            // Hack to get around the fact that to_case crate doesn't support '\n' as a word boundary
5088            // https://github.com/rutrum/convert-case/issues/16
5089            text.split("\n")
5090                .map(|line| line.to_case(Case::UpperCamel))
5091                .join("\n")
5092        })
5093    }
5094
5095    pub fn convert_to_lower_camel_case(
5096        &mut self,
5097        _: &ConvertToLowerCamelCase,
5098        cx: &mut ViewContext<Self>,
5099    ) {
5100        self.manipulate_text(cx, |text| text.to_case(Case::Camel))
5101    }
5102
5103    fn manipulate_text<Fn>(&mut self, cx: &mut ViewContext<Self>, mut callback: Fn)
5104    where
5105        Fn: FnMut(&str) -> String,
5106    {
5107        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5108        let buffer = self.buffer.read(cx).snapshot(cx);
5109
5110        let mut new_selections = Vec::new();
5111        let mut edits = Vec::new();
5112        let mut selection_adjustment = 0i32;
5113
5114        for selection in self.selections.all::<usize>(cx) {
5115            let selection_is_empty = selection.is_empty();
5116
5117            let (start, end) = if selection_is_empty {
5118                let word_range = movement::surrounding_word(
5119                    &display_map,
5120                    selection.start.to_display_point(&display_map),
5121                );
5122                let start = word_range.start.to_offset(&display_map, Bias::Left);
5123                let end = word_range.end.to_offset(&display_map, Bias::Left);
5124                (start, end)
5125            } else {
5126                (selection.start, selection.end)
5127            };
5128
5129            let text = buffer.text_for_range(start..end).collect::<String>();
5130            let old_length = text.len() as i32;
5131            let text = callback(&text);
5132
5133            new_selections.push(Selection {
5134                start: (start as i32 - selection_adjustment) as usize,
5135                end: ((start + text.len()) as i32 - selection_adjustment) as usize,
5136                goal: SelectionGoal::None,
5137                ..selection
5138            });
5139
5140            selection_adjustment += old_length - text.len() as i32;
5141
5142            edits.push((start..end, text));
5143        }
5144
5145        self.transact(cx, |this, cx| {
5146            this.buffer.update(cx, |buffer, cx| {
5147                buffer.edit(edits, None, cx);
5148            });
5149
5150            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5151                s.select(new_selections);
5152            });
5153
5154            this.request_autoscroll(Autoscroll::fit(), cx);
5155        });
5156    }
5157
5158    pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
5159        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5160        let buffer = &display_map.buffer_snapshot;
5161        let selections = self.selections.all::<Point>(cx);
5162
5163        let mut edits = Vec::new();
5164        let mut selections_iter = selections.iter().peekable();
5165        while let Some(selection) = selections_iter.next() {
5166            // Avoid duplicating the same lines twice.
5167            let mut rows = selection.spanned_rows(false, &display_map);
5168
5169            while let Some(next_selection) = selections_iter.peek() {
5170                let next_rows = next_selection.spanned_rows(false, &display_map);
5171                if next_rows.start < rows.end {
5172                    rows.end = next_rows.end;
5173                    selections_iter.next().unwrap();
5174                } else {
5175                    break;
5176                }
5177            }
5178
5179            // Copy the text from the selected row region and splice it at the start of the region.
5180            let start = Point::new(rows.start, 0);
5181            let end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1));
5182            let text = buffer
5183                .text_for_range(start..end)
5184                .chain(Some("\n"))
5185                .collect::<String>();
5186            edits.push((start..start, text));
5187        }
5188
5189        self.transact(cx, |this, cx| {
5190            this.buffer.update(cx, |buffer, cx| {
5191                buffer.edit(edits, None, cx);
5192            });
5193
5194            this.request_autoscroll(Autoscroll::fit(), cx);
5195        });
5196    }
5197
5198    pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
5199        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5200        let buffer = self.buffer.read(cx).snapshot(cx);
5201
5202        let mut edits = Vec::new();
5203        let mut unfold_ranges = Vec::new();
5204        let mut refold_ranges = Vec::new();
5205
5206        let selections = self.selections.all::<Point>(cx);
5207        let mut selections = selections.iter().peekable();
5208        let mut contiguous_row_selections = Vec::new();
5209        let mut new_selections = Vec::new();
5210
5211        while let Some(selection) = selections.next() {
5212            // Find all the selections that span a contiguous row range
5213            let (start_row, end_row) = consume_contiguous_rows(
5214                &mut contiguous_row_selections,
5215                selection,
5216                &display_map,
5217                &mut selections,
5218            );
5219
5220            // Move the text spanned by the row range to be before the line preceding the row range
5221            if start_row > 0 {
5222                let range_to_move = Point::new(start_row - 1, buffer.line_len(start_row - 1))
5223                    ..Point::new(end_row - 1, buffer.line_len(end_row - 1));
5224                let insertion_point = display_map
5225                    .prev_line_boundary(Point::new(start_row - 1, 0))
5226                    .0;
5227
5228                // Don't move lines across excerpts
5229                if buffer
5230                    .excerpt_boundaries_in_range((
5231                        Bound::Excluded(insertion_point),
5232                        Bound::Included(range_to_move.end),
5233                    ))
5234                    .next()
5235                    .is_none()
5236                {
5237                    let text = buffer
5238                        .text_for_range(range_to_move.clone())
5239                        .flat_map(|s| s.chars())
5240                        .skip(1)
5241                        .chain(['\n'])
5242                        .collect::<String>();
5243
5244                    edits.push((
5245                        buffer.anchor_after(range_to_move.start)
5246                            ..buffer.anchor_before(range_to_move.end),
5247                        String::new(),
5248                    ));
5249                    let insertion_anchor = buffer.anchor_after(insertion_point);
5250                    edits.push((insertion_anchor..insertion_anchor, text));
5251
5252                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
5253
5254                    // Move selections up
5255                    new_selections.extend(contiguous_row_selections.drain(..).map(
5256                        |mut selection| {
5257                            selection.start.row -= row_delta;
5258                            selection.end.row -= row_delta;
5259                            selection
5260                        },
5261                    ));
5262
5263                    // Move folds up
5264                    unfold_ranges.push(range_to_move.clone());
5265                    for fold in display_map.folds_in_range(
5266                        buffer.anchor_before(range_to_move.start)
5267                            ..buffer.anchor_after(range_to_move.end),
5268                    ) {
5269                        let mut start = fold.start.to_point(&buffer);
5270                        let mut end = fold.end.to_point(&buffer);
5271                        start.row -= row_delta;
5272                        end.row -= row_delta;
5273                        refold_ranges.push(start..end);
5274                    }
5275                }
5276            }
5277
5278            // If we didn't move line(s), preserve the existing selections
5279            new_selections.append(&mut contiguous_row_selections);
5280        }
5281
5282        self.transact(cx, |this, cx| {
5283            this.unfold_ranges(unfold_ranges, true, true, cx);
5284            this.buffer.update(cx, |buffer, cx| {
5285                for (range, text) in edits {
5286                    buffer.edit([(range, text)], None, cx);
5287                }
5288            });
5289            this.fold_ranges(refold_ranges, true, cx);
5290            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5291                s.select(new_selections);
5292            })
5293        });
5294    }
5295
5296    pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
5297        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5298        let buffer = self.buffer.read(cx).snapshot(cx);
5299
5300        let mut edits = Vec::new();
5301        let mut unfold_ranges = Vec::new();
5302        let mut refold_ranges = Vec::new();
5303
5304        let selections = self.selections.all::<Point>(cx);
5305        let mut selections = selections.iter().peekable();
5306        let mut contiguous_row_selections = Vec::new();
5307        let mut new_selections = Vec::new();
5308
5309        while let Some(selection) = selections.next() {
5310            // Find all the selections that span a contiguous row range
5311            let (start_row, end_row) = consume_contiguous_rows(
5312                &mut contiguous_row_selections,
5313                selection,
5314                &display_map,
5315                &mut selections,
5316            );
5317
5318            // Move the text spanned by the row range to be after the last line of the row range
5319            if end_row <= buffer.max_point().row {
5320                let range_to_move = Point::new(start_row, 0)..Point::new(end_row, 0);
5321                let insertion_point = display_map.next_line_boundary(Point::new(end_row, 0)).0;
5322
5323                // Don't move lines across excerpt boundaries
5324                if buffer
5325                    .excerpt_boundaries_in_range((
5326                        Bound::Excluded(range_to_move.start),
5327                        Bound::Included(insertion_point),
5328                    ))
5329                    .next()
5330                    .is_none()
5331                {
5332                    let mut text = String::from("\n");
5333                    text.extend(buffer.text_for_range(range_to_move.clone()));
5334                    text.pop(); // Drop trailing newline
5335                    edits.push((
5336                        buffer.anchor_after(range_to_move.start)
5337                            ..buffer.anchor_before(range_to_move.end),
5338                        String::new(),
5339                    ));
5340                    let insertion_anchor = buffer.anchor_after(insertion_point);
5341                    edits.push((insertion_anchor..insertion_anchor, text));
5342
5343                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
5344
5345                    // Move selections down
5346                    new_selections.extend(contiguous_row_selections.drain(..).map(
5347                        |mut selection| {
5348                            selection.start.row += row_delta;
5349                            selection.end.row += row_delta;
5350                            selection
5351                        },
5352                    ));
5353
5354                    // Move folds down
5355                    unfold_ranges.push(range_to_move.clone());
5356                    for fold in display_map.folds_in_range(
5357                        buffer.anchor_before(range_to_move.start)
5358                            ..buffer.anchor_after(range_to_move.end),
5359                    ) {
5360                        let mut start = fold.start.to_point(&buffer);
5361                        let mut end = fold.end.to_point(&buffer);
5362                        start.row += row_delta;
5363                        end.row += row_delta;
5364                        refold_ranges.push(start..end);
5365                    }
5366                }
5367            }
5368
5369            // If we didn't move line(s), preserve the existing selections
5370            new_selections.append(&mut contiguous_row_selections);
5371        }
5372
5373        self.transact(cx, |this, cx| {
5374            this.unfold_ranges(unfold_ranges, true, true, cx);
5375            this.buffer.update(cx, |buffer, cx| {
5376                for (range, text) in edits {
5377                    buffer.edit([(range, text)], None, cx);
5378                }
5379            });
5380            this.fold_ranges(refold_ranges, true, cx);
5381            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
5382        });
5383    }
5384
5385    pub fn transpose(&mut self, _: &Transpose, cx: &mut ViewContext<Self>) {
5386        self.transact(cx, |this, cx| {
5387            let edits = this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5388                let mut edits: Vec<(Range<usize>, String)> = Default::default();
5389                let line_mode = s.line_mode;
5390                s.move_with(|display_map, selection| {
5391                    if !selection.is_empty() || line_mode {
5392                        return;
5393                    }
5394
5395                    let mut head = selection.head();
5396                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
5397                    if head.column() == display_map.line_len(head.row()) {
5398                        transpose_offset = display_map
5399                            .buffer_snapshot
5400                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
5401                    }
5402
5403                    if transpose_offset == 0 {
5404                        return;
5405                    }
5406
5407                    *head.column_mut() += 1;
5408                    head = display_map.clip_point(head, Bias::Right);
5409                    selection.collapse_to(head, SelectionGoal::Column(head.column()));
5410
5411                    let transpose_start = display_map
5412                        .buffer_snapshot
5413                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
5414                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
5415                        let transpose_end = display_map
5416                            .buffer_snapshot
5417                            .clip_offset(transpose_offset + 1, Bias::Right);
5418                        if let Some(ch) =
5419                            display_map.buffer_snapshot.chars_at(transpose_start).next()
5420                        {
5421                            edits.push((transpose_start..transpose_offset, String::new()));
5422                            edits.push((transpose_end..transpose_end, ch.to_string()));
5423                        }
5424                    }
5425                });
5426                edits
5427            });
5428            this.buffer
5429                .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
5430            let selections = this.selections.all::<usize>(cx);
5431            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5432                s.select(selections);
5433            });
5434        });
5435    }
5436
5437    pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
5438        let mut text = String::new();
5439        let buffer = self.buffer.read(cx).snapshot(cx);
5440        let mut selections = self.selections.all::<Point>(cx);
5441        let mut clipboard_selections = Vec::with_capacity(selections.len());
5442        {
5443            let max_point = buffer.max_point();
5444            let mut is_first = true;
5445            for selection in &mut selections {
5446                let is_entire_line = selection.is_empty() || self.selections.line_mode;
5447                if is_entire_line {
5448                    selection.start = Point::new(selection.start.row, 0);
5449                    selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
5450                    selection.goal = SelectionGoal::None;
5451                }
5452                if is_first {
5453                    is_first = false;
5454                } else {
5455                    text += "\n";
5456                }
5457                let mut len = 0;
5458                for chunk in buffer.text_for_range(selection.start..selection.end) {
5459                    text.push_str(chunk);
5460                    len += chunk.len();
5461                }
5462                clipboard_selections.push(ClipboardSelection {
5463                    len,
5464                    is_entire_line,
5465                    first_line_indent: buffer.indent_size_for_line(selection.start.row).len,
5466                });
5467            }
5468        }
5469
5470        self.transact(cx, |this, cx| {
5471            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5472                s.select(selections);
5473            });
5474            this.insert("", cx);
5475            cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
5476        });
5477    }
5478
5479    pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
5480        let selections = self.selections.all::<Point>(cx);
5481        let buffer = self.buffer.read(cx).read(cx);
5482        let mut text = String::new();
5483
5484        let mut clipboard_selections = Vec::with_capacity(selections.len());
5485        {
5486            let max_point = buffer.max_point();
5487            let mut is_first = true;
5488            for selection in selections.iter() {
5489                let mut start = selection.start;
5490                let mut end = selection.end;
5491                let is_entire_line = selection.is_empty() || self.selections.line_mode;
5492                if is_entire_line {
5493                    start = Point::new(start.row, 0);
5494                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
5495                }
5496                if is_first {
5497                    is_first = false;
5498                } else {
5499                    text += "\n";
5500                }
5501                let mut len = 0;
5502                for chunk in buffer.text_for_range(start..end) {
5503                    text.push_str(chunk);
5504                    len += chunk.len();
5505                }
5506                clipboard_selections.push(ClipboardSelection {
5507                    len,
5508                    is_entire_line,
5509                    first_line_indent: buffer.indent_size_for_line(start.row).len,
5510                });
5511            }
5512        }
5513
5514        cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
5515    }
5516
5517    pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
5518        self.transact(cx, |this, cx| {
5519            if let Some(item) = cx.read_from_clipboard() {
5520                let clipboard_text = Cow::Borrowed(item.text());
5521                if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
5522                    let old_selections = this.selections.all::<usize>(cx);
5523                    let all_selections_were_entire_line =
5524                        clipboard_selections.iter().all(|s| s.is_entire_line);
5525                    let first_selection_indent_column =
5526                        clipboard_selections.first().map(|s| s.first_line_indent);
5527                    if clipboard_selections.len() != old_selections.len() {
5528                        clipboard_selections.drain(..);
5529                    }
5530
5531                    this.buffer.update(cx, |buffer, cx| {
5532                        let snapshot = buffer.read(cx);
5533                        let mut start_offset = 0;
5534                        let mut edits = Vec::new();
5535                        let mut original_indent_columns = Vec::new();
5536                        let line_mode = this.selections.line_mode;
5537                        for (ix, selection) in old_selections.iter().enumerate() {
5538                            let to_insert;
5539                            let entire_line;
5540                            let original_indent_column;
5541                            if let Some(clipboard_selection) = clipboard_selections.get(ix) {
5542                                let end_offset = start_offset + clipboard_selection.len;
5543                                to_insert = &clipboard_text[start_offset..end_offset];
5544                                entire_line = clipboard_selection.is_entire_line;
5545                                start_offset = end_offset + 1;
5546                                original_indent_column =
5547                                    Some(clipboard_selection.first_line_indent);
5548                            } else {
5549                                to_insert = clipboard_text.as_str();
5550                                entire_line = all_selections_were_entire_line;
5551                                original_indent_column = first_selection_indent_column
5552                            }
5553
5554                            // If the corresponding selection was empty when this slice of the
5555                            // clipboard text was written, then the entire line containing the
5556                            // selection was copied. If this selection is also currently empty,
5557                            // then paste the line before the current line of the buffer.
5558                            let range = if selection.is_empty() && !line_mode && entire_line {
5559                                let column = selection.start.to_point(&snapshot).column as usize;
5560                                let line_start = selection.start - column;
5561                                line_start..line_start
5562                            } else {
5563                                selection.range()
5564                            };
5565
5566                            edits.push((range, to_insert));
5567                            original_indent_columns.extend(original_indent_column);
5568                        }
5569                        drop(snapshot);
5570
5571                        buffer.edit(
5572                            edits,
5573                            Some(AutoindentMode::Block {
5574                                original_indent_columns,
5575                            }),
5576                            cx,
5577                        );
5578                    });
5579
5580                    let selections = this.selections.all::<usize>(cx);
5581                    this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
5582                } else {
5583                    this.insert(&clipboard_text, cx);
5584                }
5585            }
5586        });
5587    }
5588
5589    pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
5590        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
5591            if let Some((selections, _)) = self.selection_history.transaction(tx_id).cloned() {
5592                self.change_selections(None, cx, |s| {
5593                    s.select_anchors(selections.to_vec());
5594                });
5595            }
5596            self.request_autoscroll(Autoscroll::fit(), cx);
5597            self.unmark_text(cx);
5598            self.refresh_copilot_suggestions(true, cx);
5599            cx.emit(Event::Edited);
5600        }
5601    }
5602
5603    pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
5604        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
5605            if let Some((_, Some(selections))) = self.selection_history.transaction(tx_id).cloned()
5606            {
5607                self.change_selections(None, cx, |s| {
5608                    s.select_anchors(selections.to_vec());
5609                });
5610            }
5611            self.request_autoscroll(Autoscroll::fit(), cx);
5612            self.unmark_text(cx);
5613            self.refresh_copilot_suggestions(true, cx);
5614            cx.emit(Event::Edited);
5615        }
5616    }
5617
5618    pub fn finalize_last_transaction(&mut self, cx: &mut ViewContext<Self>) {
5619        self.buffer
5620            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
5621    }
5622
5623    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
5624        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5625            let line_mode = s.line_mode;
5626            s.move_with(|map, selection| {
5627                let cursor = if selection.is_empty() && !line_mode {
5628                    movement::left(map, selection.start)
5629                } else {
5630                    selection.start
5631                };
5632                selection.collapse_to(cursor, SelectionGoal::None);
5633            });
5634        })
5635    }
5636
5637    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
5638        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5639            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
5640        })
5641    }
5642
5643    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
5644        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5645            let line_mode = s.line_mode;
5646            s.move_with(|map, selection| {
5647                let cursor = if selection.is_empty() && !line_mode {
5648                    movement::right(map, selection.end)
5649                } else {
5650                    selection.end
5651                };
5652                selection.collapse_to(cursor, SelectionGoal::None)
5653            });
5654        })
5655    }
5656
5657    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
5658        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5659            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
5660        })
5661    }
5662
5663    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
5664        if self.take_rename(true, cx).is_some() {
5665            return;
5666        }
5667
5668        if matches!(self.mode, EditorMode::SingleLine) {
5669            cx.propagate_action();
5670            return;
5671        }
5672
5673        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5674            let line_mode = s.line_mode;
5675            s.move_with(|map, selection| {
5676                if !selection.is_empty() && !line_mode {
5677                    selection.goal = SelectionGoal::None;
5678                }
5679                let (cursor, goal) = movement::up(map, selection.start, selection.goal, false);
5680                selection.collapse_to(cursor, goal);
5681            });
5682        })
5683    }
5684
5685    pub fn move_page_up(&mut self, action: &MovePageUp, cx: &mut ViewContext<Self>) {
5686        if self.take_rename(true, cx).is_some() {
5687            return;
5688        }
5689
5690        if matches!(self.mode, EditorMode::SingleLine) {
5691            cx.propagate_action();
5692            return;
5693        }
5694
5695        let row_count = if let Some(row_count) = self.visible_line_count() {
5696            row_count as u32 - 1
5697        } else {
5698            return;
5699        };
5700
5701        let autoscroll = if action.center_cursor {
5702            Autoscroll::center()
5703        } else {
5704            Autoscroll::fit()
5705        };
5706
5707        self.change_selections(Some(autoscroll), cx, |s| {
5708            let line_mode = s.line_mode;
5709            s.move_with(|map, selection| {
5710                if !selection.is_empty() && !line_mode {
5711                    selection.goal = SelectionGoal::None;
5712                }
5713                let (cursor, goal) =
5714                    movement::up_by_rows(map, selection.end, row_count, selection.goal, false);
5715                selection.collapse_to(cursor, goal);
5716            });
5717        });
5718    }
5719
5720    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
5721        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5722            s.move_heads_with(|map, head, goal| movement::up(map, head, goal, false))
5723        })
5724    }
5725
5726    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
5727        self.take_rename(true, cx);
5728
5729        if self.mode == EditorMode::SingleLine {
5730            cx.propagate_action();
5731            return;
5732        }
5733
5734        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5735            let line_mode = s.line_mode;
5736            s.move_with(|map, selection| {
5737                if !selection.is_empty() && !line_mode {
5738                    selection.goal = SelectionGoal::None;
5739                }
5740                let (cursor, goal) = movement::down(map, selection.end, selection.goal, false);
5741                selection.collapse_to(cursor, goal);
5742            });
5743        });
5744    }
5745
5746    pub fn move_page_down(&mut self, action: &MovePageDown, cx: &mut ViewContext<Self>) {
5747        if self.take_rename(true, cx).is_some() {
5748            return;
5749        }
5750
5751        if self
5752            .context_menu
5753            .write()
5754            .as_mut()
5755            .map(|menu| menu.select_last(self.project.as_ref(), cx))
5756            .unwrap_or(false)
5757        {
5758            return;
5759        }
5760
5761        if matches!(self.mode, EditorMode::SingleLine) {
5762            cx.propagate_action();
5763            return;
5764        }
5765
5766        let row_count = if let Some(row_count) = self.visible_line_count() {
5767            row_count as u32 - 1
5768        } else {
5769            return;
5770        };
5771
5772        let autoscroll = if action.center_cursor {
5773            Autoscroll::center()
5774        } else {
5775            Autoscroll::fit()
5776        };
5777
5778        self.change_selections(Some(autoscroll), cx, |s| {
5779            let line_mode = s.line_mode;
5780            s.move_with(|map, selection| {
5781                if !selection.is_empty() && !line_mode {
5782                    selection.goal = SelectionGoal::None;
5783                }
5784                let (cursor, goal) =
5785                    movement::down_by_rows(map, selection.end, row_count, selection.goal, false);
5786                selection.collapse_to(cursor, goal);
5787            });
5788        });
5789    }
5790
5791    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
5792        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5793            s.move_heads_with(|map, head, goal| movement::down(map, head, goal, false))
5794        });
5795    }
5796
5797    pub fn context_menu_first(&mut self, _: &ContextMenuFirst, cx: &mut ViewContext<Self>) {
5798        if let Some(context_menu) = self.context_menu.write().as_mut() {
5799            context_menu.select_first(self.project.as_ref(), cx);
5800        }
5801    }
5802
5803    pub fn context_menu_prev(&mut self, _: &ContextMenuPrev, cx: &mut ViewContext<Self>) {
5804        if let Some(context_menu) = self.context_menu.write().as_mut() {
5805            context_menu.select_prev(self.project.as_ref(), cx);
5806        }
5807    }
5808
5809    pub fn context_menu_next(&mut self, _: &ContextMenuNext, cx: &mut ViewContext<Self>) {
5810        if let Some(context_menu) = self.context_menu.write().as_mut() {
5811            context_menu.select_next(self.project.as_ref(), cx);
5812        }
5813    }
5814
5815    pub fn context_menu_last(&mut self, _: &ContextMenuLast, cx: &mut ViewContext<Self>) {
5816        if let Some(context_menu) = self.context_menu.write().as_mut() {
5817            context_menu.select_last(self.project.as_ref(), cx);
5818        }
5819    }
5820
5821    pub fn move_to_previous_word_start(
5822        &mut self,
5823        _: &MoveToPreviousWordStart,
5824        cx: &mut ViewContext<Self>,
5825    ) {
5826        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5827            s.move_cursors_with(|map, head, _| {
5828                (
5829                    movement::previous_word_start(map, head),
5830                    SelectionGoal::None,
5831                )
5832            });
5833        })
5834    }
5835
5836    pub fn move_to_previous_subword_start(
5837        &mut self,
5838        _: &MoveToPreviousSubwordStart,
5839        cx: &mut ViewContext<Self>,
5840    ) {
5841        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5842            s.move_cursors_with(|map, head, _| {
5843                (
5844                    movement::previous_subword_start(map, head),
5845                    SelectionGoal::None,
5846                )
5847            });
5848        })
5849    }
5850
5851    pub fn select_to_previous_word_start(
5852        &mut self,
5853        _: &SelectToPreviousWordStart,
5854        cx: &mut ViewContext<Self>,
5855    ) {
5856        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5857            s.move_heads_with(|map, head, _| {
5858                (
5859                    movement::previous_word_start(map, head),
5860                    SelectionGoal::None,
5861                )
5862            });
5863        })
5864    }
5865
5866    pub fn select_to_previous_subword_start(
5867        &mut self,
5868        _: &SelectToPreviousSubwordStart,
5869        cx: &mut ViewContext<Self>,
5870    ) {
5871        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5872            s.move_heads_with(|map, head, _| {
5873                (
5874                    movement::previous_subword_start(map, head),
5875                    SelectionGoal::None,
5876                )
5877            });
5878        })
5879    }
5880
5881    pub fn delete_to_previous_word_start(
5882        &mut self,
5883        _: &DeleteToPreviousWordStart,
5884        cx: &mut ViewContext<Self>,
5885    ) {
5886        self.transact(cx, |this, cx| {
5887            this.select_autoclose_pair(cx);
5888            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5889                let line_mode = s.line_mode;
5890                s.move_with(|map, selection| {
5891                    if selection.is_empty() && !line_mode {
5892                        let cursor = movement::previous_word_start(map, selection.head());
5893                        selection.set_head(cursor, SelectionGoal::None);
5894                    }
5895                });
5896            });
5897            this.insert("", cx);
5898        });
5899    }
5900
5901    pub fn delete_to_previous_subword_start(
5902        &mut self,
5903        _: &DeleteToPreviousSubwordStart,
5904        cx: &mut ViewContext<Self>,
5905    ) {
5906        self.transact(cx, |this, cx| {
5907            this.select_autoclose_pair(cx);
5908            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5909                let line_mode = s.line_mode;
5910                s.move_with(|map, selection| {
5911                    if selection.is_empty() && !line_mode {
5912                        let cursor = movement::previous_subword_start(map, selection.head());
5913                        selection.set_head(cursor, SelectionGoal::None);
5914                    }
5915                });
5916            });
5917            this.insert("", cx);
5918        });
5919    }
5920
5921    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
5922        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5923            s.move_cursors_with(|map, head, _| {
5924                (movement::next_word_end(map, head), SelectionGoal::None)
5925            });
5926        })
5927    }
5928
5929    pub fn move_to_next_subword_end(
5930        &mut self,
5931        _: &MoveToNextSubwordEnd,
5932        cx: &mut ViewContext<Self>,
5933    ) {
5934        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5935            s.move_cursors_with(|map, head, _| {
5936                (movement::next_subword_end(map, head), SelectionGoal::None)
5937            });
5938        })
5939    }
5940
5941    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
5942        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5943            s.move_heads_with(|map, head, _| {
5944                (movement::next_word_end(map, head), SelectionGoal::None)
5945            });
5946        })
5947    }
5948
5949    pub fn select_to_next_subword_end(
5950        &mut self,
5951        _: &SelectToNextSubwordEnd,
5952        cx: &mut ViewContext<Self>,
5953    ) {
5954        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5955            s.move_heads_with(|map, head, _| {
5956                (movement::next_subword_end(map, head), SelectionGoal::None)
5957            });
5958        })
5959    }
5960
5961    pub fn delete_to_next_word_end(&mut self, _: &DeleteToNextWordEnd, cx: &mut ViewContext<Self>) {
5962        self.transact(cx, |this, cx| {
5963            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5964                let line_mode = s.line_mode;
5965                s.move_with(|map, selection| {
5966                    if selection.is_empty() && !line_mode {
5967                        let cursor = movement::next_word_end(map, selection.head());
5968                        selection.set_head(cursor, SelectionGoal::None);
5969                    }
5970                });
5971            });
5972            this.insert("", cx);
5973        });
5974    }
5975
5976    pub fn delete_to_next_subword_end(
5977        &mut self,
5978        _: &DeleteToNextSubwordEnd,
5979        cx: &mut ViewContext<Self>,
5980    ) {
5981        self.transact(cx, |this, cx| {
5982            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5983                s.move_with(|map, selection| {
5984                    if selection.is_empty() {
5985                        let cursor = movement::next_subword_end(map, selection.head());
5986                        selection.set_head(cursor, SelectionGoal::None);
5987                    }
5988                });
5989            });
5990            this.insert("", cx);
5991        });
5992    }
5993
5994    pub fn move_to_beginning_of_line(
5995        &mut self,
5996        _: &MoveToBeginningOfLine,
5997        cx: &mut ViewContext<Self>,
5998    ) {
5999        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6000            s.move_cursors_with(|map, head, _| {
6001                (
6002                    movement::indented_line_beginning(map, head, true),
6003                    SelectionGoal::None,
6004                )
6005            });
6006        })
6007    }
6008
6009    pub fn select_to_beginning_of_line(
6010        &mut self,
6011        action: &SelectToBeginningOfLine,
6012        cx: &mut ViewContext<Self>,
6013    ) {
6014        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6015            s.move_heads_with(|map, head, _| {
6016                (
6017                    movement::indented_line_beginning(map, head, action.stop_at_soft_wraps),
6018                    SelectionGoal::None,
6019                )
6020            });
6021        });
6022    }
6023
6024    pub fn delete_to_beginning_of_line(
6025        &mut self,
6026        _: &DeleteToBeginningOfLine,
6027        cx: &mut ViewContext<Self>,
6028    ) {
6029        self.transact(cx, |this, cx| {
6030            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
6031                s.move_with(|_, selection| {
6032                    selection.reversed = true;
6033                });
6034            });
6035
6036            this.select_to_beginning_of_line(
6037                &SelectToBeginningOfLine {
6038                    stop_at_soft_wraps: false,
6039                },
6040                cx,
6041            );
6042            this.backspace(&Backspace, cx);
6043        });
6044    }
6045
6046    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
6047        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6048            s.move_cursors_with(|map, head, _| {
6049                (movement::line_end(map, head, true), SelectionGoal::None)
6050            });
6051        })
6052    }
6053
6054    pub fn select_to_end_of_line(
6055        &mut self,
6056        action: &SelectToEndOfLine,
6057        cx: &mut ViewContext<Self>,
6058    ) {
6059        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6060            s.move_heads_with(|map, head, _| {
6061                (
6062                    movement::line_end(map, head, action.stop_at_soft_wraps),
6063                    SelectionGoal::None,
6064                )
6065            });
6066        })
6067    }
6068
6069    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
6070        self.transact(cx, |this, cx| {
6071            this.select_to_end_of_line(
6072                &SelectToEndOfLine {
6073                    stop_at_soft_wraps: false,
6074                },
6075                cx,
6076            );
6077            this.delete(&Delete, cx);
6078        });
6079    }
6080
6081    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
6082        self.transact(cx, |this, cx| {
6083            this.select_to_end_of_line(
6084                &SelectToEndOfLine {
6085                    stop_at_soft_wraps: false,
6086                },
6087                cx,
6088            );
6089            this.cut(&Cut, cx);
6090        });
6091    }
6092
6093    pub fn move_to_start_of_paragraph(
6094        &mut self,
6095        _: &MoveToStartOfParagraph,
6096        cx: &mut ViewContext<Self>,
6097    ) {
6098        if matches!(self.mode, EditorMode::SingleLine) {
6099            cx.propagate_action();
6100            return;
6101        }
6102
6103        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6104            s.move_with(|map, selection| {
6105                selection.collapse_to(
6106                    movement::start_of_paragraph(map, selection.head(), 1),
6107                    SelectionGoal::None,
6108                )
6109            });
6110        })
6111    }
6112
6113    pub fn move_to_end_of_paragraph(
6114        &mut self,
6115        _: &MoveToEndOfParagraph,
6116        cx: &mut ViewContext<Self>,
6117    ) {
6118        if matches!(self.mode, EditorMode::SingleLine) {
6119            cx.propagate_action();
6120            return;
6121        }
6122
6123        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6124            s.move_with(|map, selection| {
6125                selection.collapse_to(
6126                    movement::end_of_paragraph(map, selection.head(), 1),
6127                    SelectionGoal::None,
6128                )
6129            });
6130        })
6131    }
6132
6133    pub fn select_to_start_of_paragraph(
6134        &mut self,
6135        _: &SelectToStartOfParagraph,
6136        cx: &mut ViewContext<Self>,
6137    ) {
6138        if matches!(self.mode, EditorMode::SingleLine) {
6139            cx.propagate_action();
6140            return;
6141        }
6142
6143        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6144            s.move_heads_with(|map, head, _| {
6145                (
6146                    movement::start_of_paragraph(map, head, 1),
6147                    SelectionGoal::None,
6148                )
6149            });
6150        })
6151    }
6152
6153    pub fn select_to_end_of_paragraph(
6154        &mut self,
6155        _: &SelectToEndOfParagraph,
6156        cx: &mut ViewContext<Self>,
6157    ) {
6158        if matches!(self.mode, EditorMode::SingleLine) {
6159            cx.propagate_action();
6160            return;
6161        }
6162
6163        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6164            s.move_heads_with(|map, head, _| {
6165                (
6166                    movement::end_of_paragraph(map, head, 1),
6167                    SelectionGoal::None,
6168                )
6169            });
6170        })
6171    }
6172
6173    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
6174        if matches!(self.mode, EditorMode::SingleLine) {
6175            cx.propagate_action();
6176            return;
6177        }
6178
6179        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6180            s.select_ranges(vec![0..0]);
6181        });
6182    }
6183
6184    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
6185        let mut selection = self.selections.last::<Point>(cx);
6186        selection.set_head(Point::zero(), SelectionGoal::None);
6187
6188        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6189            s.select(vec![selection]);
6190        });
6191    }
6192
6193    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
6194        if matches!(self.mode, EditorMode::SingleLine) {
6195            cx.propagate_action();
6196            return;
6197        }
6198
6199        let cursor = self.buffer.read(cx).read(cx).len();
6200        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6201            s.select_ranges(vec![cursor..cursor])
6202        });
6203    }
6204
6205    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
6206        self.nav_history = nav_history;
6207    }
6208
6209    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
6210        self.nav_history.as_ref()
6211    }
6212
6213    fn push_to_nav_history(
6214        &mut self,
6215        cursor_anchor: Anchor,
6216        new_position: Option<Point>,
6217        cx: &mut ViewContext<Self>,
6218    ) {
6219        if let Some(nav_history) = self.nav_history.as_mut() {
6220            let buffer = self.buffer.read(cx).read(cx);
6221            let cursor_position = cursor_anchor.to_point(&buffer);
6222            let scroll_state = self.scroll_manager.anchor();
6223            let scroll_top_row = scroll_state.top_row(&buffer);
6224            drop(buffer);
6225
6226            if let Some(new_position) = new_position {
6227                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
6228                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
6229                    return;
6230                }
6231            }
6232
6233            nav_history.push(
6234                Some(NavigationData {
6235                    cursor_anchor,
6236                    cursor_position,
6237                    scroll_anchor: scroll_state,
6238                    scroll_top_row,
6239                }),
6240                cx,
6241            );
6242        }
6243    }
6244
6245    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
6246        let buffer = self.buffer.read(cx).snapshot(cx);
6247        let mut selection = self.selections.first::<usize>(cx);
6248        selection.set_head(buffer.len(), SelectionGoal::None);
6249        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6250            s.select(vec![selection]);
6251        });
6252    }
6253
6254    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
6255        let end = self.buffer.read(cx).read(cx).len();
6256        self.change_selections(None, cx, |s| {
6257            s.select_ranges(vec![0..end]);
6258        });
6259    }
6260
6261    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
6262        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6263        let mut selections = self.selections.all::<Point>(cx);
6264        let max_point = display_map.buffer_snapshot.max_point();
6265        for selection in &mut selections {
6266            let rows = selection.spanned_rows(true, &display_map);
6267            selection.start = Point::new(rows.start, 0);
6268            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
6269            selection.reversed = false;
6270        }
6271        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6272            s.select(selections);
6273        });
6274    }
6275
6276    pub fn split_selection_into_lines(
6277        &mut self,
6278        _: &SplitSelectionIntoLines,
6279        cx: &mut ViewContext<Self>,
6280    ) {
6281        let mut to_unfold = Vec::new();
6282        let mut new_selection_ranges = Vec::new();
6283        {
6284            let selections = self.selections.all::<Point>(cx);
6285            let buffer = self.buffer.read(cx).read(cx);
6286            for selection in selections {
6287                for row in selection.start.row..selection.end.row {
6288                    let cursor = Point::new(row, buffer.line_len(row));
6289                    new_selection_ranges.push(cursor..cursor);
6290                }
6291                new_selection_ranges.push(selection.end..selection.end);
6292                to_unfold.push(selection.start..selection.end);
6293            }
6294        }
6295        self.unfold_ranges(to_unfold, true, true, cx);
6296        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6297            s.select_ranges(new_selection_ranges);
6298        });
6299    }
6300
6301    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
6302        self.add_selection(true, cx);
6303    }
6304
6305    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
6306        self.add_selection(false, cx);
6307    }
6308
6309    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
6310        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6311        let mut selections = self.selections.all::<Point>(cx);
6312        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
6313            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
6314            let range = oldest_selection.display_range(&display_map).sorted();
6315            let columns = cmp::min(range.start.column(), range.end.column())
6316                ..cmp::max(range.start.column(), range.end.column());
6317
6318            selections.clear();
6319            let mut stack = Vec::new();
6320            for row in range.start.row()..=range.end.row() {
6321                if let Some(selection) = self.selections.build_columnar_selection(
6322                    &display_map,
6323                    row,
6324                    &columns,
6325                    oldest_selection.reversed,
6326                ) {
6327                    stack.push(selection.id);
6328                    selections.push(selection);
6329                }
6330            }
6331
6332            if above {
6333                stack.reverse();
6334            }
6335
6336            AddSelectionsState { above, stack }
6337        });
6338
6339        let last_added_selection = *state.stack.last().unwrap();
6340        let mut new_selections = Vec::new();
6341        if above == state.above {
6342            let end_row = if above {
6343                0
6344            } else {
6345                display_map.max_point().row()
6346            };
6347
6348            'outer: for selection in selections {
6349                if selection.id == last_added_selection {
6350                    let range = selection.display_range(&display_map).sorted();
6351                    debug_assert_eq!(range.start.row(), range.end.row());
6352                    let mut row = range.start.row();
6353                    let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
6354                    {
6355                        start..end
6356                    } else {
6357                        cmp::min(range.start.column(), range.end.column())
6358                            ..cmp::max(range.start.column(), range.end.column())
6359                    };
6360
6361                    while row != end_row {
6362                        if above {
6363                            row -= 1;
6364                        } else {
6365                            row += 1;
6366                        }
6367
6368                        if let Some(new_selection) = self.selections.build_columnar_selection(
6369                            &display_map,
6370                            row,
6371                            &columns,
6372                            selection.reversed,
6373                        ) {
6374                            state.stack.push(new_selection.id);
6375                            if above {
6376                                new_selections.push(new_selection);
6377                                new_selections.push(selection);
6378                            } else {
6379                                new_selections.push(selection);
6380                                new_selections.push(new_selection);
6381                            }
6382
6383                            continue 'outer;
6384                        }
6385                    }
6386                }
6387
6388                new_selections.push(selection);
6389            }
6390        } else {
6391            new_selections = selections;
6392            new_selections.retain(|s| s.id != last_added_selection);
6393            state.stack.pop();
6394        }
6395
6396        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6397            s.select(new_selections);
6398        });
6399        if state.stack.len() > 1 {
6400            self.add_selections_state = Some(state);
6401        }
6402    }
6403
6404    pub fn select_next_match_internal(
6405        &mut self,
6406        display_map: &DisplaySnapshot,
6407        replace_newest: bool,
6408        autoscroll: Option<Autoscroll>,
6409        cx: &mut ViewContext<Self>,
6410    ) -> Result<()> {
6411        fn select_next_match_ranges(
6412            this: &mut Editor,
6413            range: Range<usize>,
6414            replace_newest: bool,
6415            auto_scroll: Option<Autoscroll>,
6416            cx: &mut ViewContext<Editor>,
6417        ) {
6418            this.unfold_ranges([range.clone()], false, true, cx);
6419            this.change_selections(auto_scroll, cx, |s| {
6420                if replace_newest {
6421                    s.delete(s.newest_anchor().id);
6422                }
6423                s.insert_range(range.clone());
6424            });
6425        }
6426
6427        let buffer = &display_map.buffer_snapshot;
6428        let mut selections = self.selections.all::<usize>(cx);
6429        if let Some(mut select_next_state) = self.select_next_state.take() {
6430            let query = &select_next_state.query;
6431            if !select_next_state.done {
6432                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
6433                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
6434                let mut next_selected_range = None;
6435
6436                let bytes_after_last_selection =
6437                    buffer.bytes_in_range(last_selection.end..buffer.len());
6438                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
6439                let query_matches = query
6440                    .stream_find_iter(bytes_after_last_selection)
6441                    .map(|result| (last_selection.end, result))
6442                    .chain(
6443                        query
6444                            .stream_find_iter(bytes_before_first_selection)
6445                            .map(|result| (0, result)),
6446                    );
6447
6448                for (start_offset, query_match) in query_matches {
6449                    let query_match = query_match.unwrap(); // can only fail due to I/O
6450                    let offset_range =
6451                        start_offset + query_match.start()..start_offset + query_match.end();
6452                    let display_range = offset_range.start.to_display_point(&display_map)
6453                        ..offset_range.end.to_display_point(&display_map);
6454
6455                    if !select_next_state.wordwise
6456                        || (!movement::is_inside_word(&display_map, display_range.start)
6457                            && !movement::is_inside_word(&display_map, display_range.end))
6458                    {
6459                        if selections
6460                            .iter()
6461                            .find(|selection| selection.equals(&offset_range))
6462                            .is_none()
6463                        {
6464                            next_selected_range = Some(offset_range);
6465                            break;
6466                        }
6467                    }
6468                }
6469
6470                if let Some(next_selected_range) = next_selected_range {
6471                    select_next_match_ranges(
6472                        self,
6473                        next_selected_range,
6474                        replace_newest,
6475                        autoscroll,
6476                        cx,
6477                    );
6478                } else {
6479                    select_next_state.done = true;
6480                }
6481            }
6482
6483            self.select_next_state = Some(select_next_state);
6484        } else if selections.len() == 1 {
6485            let selection = selections.last_mut().unwrap();
6486            if selection.start == selection.end {
6487                let word_range = movement::surrounding_word(
6488                    &display_map,
6489                    selection.start.to_display_point(&display_map),
6490                );
6491                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
6492                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
6493                selection.goal = SelectionGoal::None;
6494                selection.reversed = false;
6495
6496                let query = buffer
6497                    .text_for_range(selection.start..selection.end)
6498                    .collect::<String>();
6499
6500                let is_empty = query.is_empty();
6501                let select_state = SelectNextState {
6502                    query: AhoCorasick::new(&[query])?,
6503                    wordwise: true,
6504                    done: is_empty,
6505                };
6506                select_next_match_ranges(
6507                    self,
6508                    selection.start..selection.end,
6509                    replace_newest,
6510                    autoscroll,
6511                    cx,
6512                );
6513                self.select_next_state = Some(select_state);
6514            } else {
6515                let query = buffer
6516                    .text_for_range(selection.start..selection.end)
6517                    .collect::<String>();
6518                self.select_next_state = Some(SelectNextState {
6519                    query: AhoCorasick::new(&[query])?,
6520                    wordwise: false,
6521                    done: false,
6522                });
6523                self.select_next_match_internal(display_map, replace_newest, autoscroll, cx)?;
6524            }
6525        }
6526        Ok(())
6527    }
6528
6529    pub fn select_all_matches(
6530        &mut self,
6531        action: &SelectAllMatches,
6532        cx: &mut ViewContext<Self>,
6533    ) -> Result<()> {
6534        self.push_to_selection_history();
6535        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6536
6537        loop {
6538            self.select_next_match_internal(&display_map, action.replace_newest, None, cx)?;
6539
6540            if self
6541                .select_next_state
6542                .as_ref()
6543                .map(|selection_state| selection_state.done)
6544                .unwrap_or(true)
6545            {
6546                break;
6547            }
6548        }
6549
6550        Ok(())
6551    }
6552
6553    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) -> Result<()> {
6554        self.push_to_selection_history();
6555        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6556        self.select_next_match_internal(
6557            &display_map,
6558            action.replace_newest,
6559            Some(Autoscroll::newest()),
6560            cx,
6561        )?;
6562        Ok(())
6563    }
6564
6565    pub fn select_previous(
6566        &mut self,
6567        action: &SelectPrevious,
6568        cx: &mut ViewContext<Self>,
6569    ) -> Result<()> {
6570        self.push_to_selection_history();
6571        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6572        let buffer = &display_map.buffer_snapshot;
6573        let mut selections = self.selections.all::<usize>(cx);
6574        if let Some(mut select_prev_state) = self.select_prev_state.take() {
6575            let query = &select_prev_state.query;
6576            if !select_prev_state.done {
6577                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
6578                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
6579                let mut next_selected_range = None;
6580                // When we're iterating matches backwards, the oldest match will actually be the furthest one in the buffer.
6581                let bytes_before_last_selection =
6582                    buffer.reversed_bytes_in_range(0..last_selection.start);
6583                let bytes_after_first_selection =
6584                    buffer.reversed_bytes_in_range(first_selection.end..buffer.len());
6585                let query_matches = query
6586                    .stream_find_iter(bytes_before_last_selection)
6587                    .map(|result| (last_selection.start, result))
6588                    .chain(
6589                        query
6590                            .stream_find_iter(bytes_after_first_selection)
6591                            .map(|result| (buffer.len(), result)),
6592                    );
6593                for (end_offset, query_match) in query_matches {
6594                    let query_match = query_match.unwrap(); // can only fail due to I/O
6595                    let offset_range =
6596                        end_offset - query_match.end()..end_offset - query_match.start();
6597                    let display_range = offset_range.start.to_display_point(&display_map)
6598                        ..offset_range.end.to_display_point(&display_map);
6599
6600                    if !select_prev_state.wordwise
6601                        || (!movement::is_inside_word(&display_map, display_range.start)
6602                            && !movement::is_inside_word(&display_map, display_range.end))
6603                    {
6604                        next_selected_range = Some(offset_range);
6605                        break;
6606                    }
6607                }
6608
6609                if let Some(next_selected_range) = next_selected_range {
6610                    self.unfold_ranges([next_selected_range.clone()], false, true, cx);
6611                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
6612                        if action.replace_newest {
6613                            s.delete(s.newest_anchor().id);
6614                        }
6615                        s.insert_range(next_selected_range);
6616                    });
6617                } else {
6618                    select_prev_state.done = true;
6619                }
6620            }
6621
6622            self.select_prev_state = Some(select_prev_state);
6623        } else if selections.len() == 1 {
6624            let selection = selections.last_mut().unwrap();
6625            if selection.start == selection.end {
6626                let word_range = movement::surrounding_word(
6627                    &display_map,
6628                    selection.start.to_display_point(&display_map),
6629                );
6630                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
6631                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
6632                selection.goal = SelectionGoal::None;
6633                selection.reversed = false;
6634
6635                let query = buffer
6636                    .text_for_range(selection.start..selection.end)
6637                    .collect::<String>();
6638                let query = query.chars().rev().collect::<String>();
6639                let select_state = SelectNextState {
6640                    query: AhoCorasick::new(&[query])?,
6641                    wordwise: true,
6642                    done: false,
6643                };
6644                self.unfold_ranges([selection.start..selection.end], false, true, cx);
6645                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
6646                    s.select(selections);
6647                });
6648                self.select_prev_state = Some(select_state);
6649            } else {
6650                let query = buffer
6651                    .text_for_range(selection.start..selection.end)
6652                    .collect::<String>();
6653                let query = query.chars().rev().collect::<String>();
6654                self.select_prev_state = Some(SelectNextState {
6655                    query: AhoCorasick::new(&[query])?,
6656                    wordwise: false,
6657                    done: false,
6658                });
6659                self.select_previous(action, cx)?;
6660            }
6661        }
6662        Ok(())
6663    }
6664
6665    pub fn toggle_comments(&mut self, action: &ToggleComments, cx: &mut ViewContext<Self>) {
6666        self.transact(cx, |this, cx| {
6667            let mut selections = this.selections.all::<Point>(cx);
6668            let mut edits = Vec::new();
6669            let mut selection_edit_ranges = Vec::new();
6670            let mut last_toggled_row = None;
6671            let snapshot = this.buffer.read(cx).read(cx);
6672            let empty_str: Arc<str> = "".into();
6673            let mut suffixes_inserted = Vec::new();
6674
6675            fn comment_prefix_range(
6676                snapshot: &MultiBufferSnapshot,
6677                row: u32,
6678                comment_prefix: &str,
6679                comment_prefix_whitespace: &str,
6680            ) -> Range<Point> {
6681                let start = Point::new(row, snapshot.indent_size_for_line(row).len);
6682
6683                let mut line_bytes = snapshot
6684                    .bytes_in_range(start..snapshot.max_point())
6685                    .flatten()
6686                    .copied();
6687
6688                // If this line currently begins with the line comment prefix, then record
6689                // the range containing the prefix.
6690                if line_bytes
6691                    .by_ref()
6692                    .take(comment_prefix.len())
6693                    .eq(comment_prefix.bytes())
6694                {
6695                    // Include any whitespace that matches the comment prefix.
6696                    let matching_whitespace_len = line_bytes
6697                        .zip(comment_prefix_whitespace.bytes())
6698                        .take_while(|(a, b)| a == b)
6699                        .count() as u32;
6700                    let end = Point::new(
6701                        start.row,
6702                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
6703                    );
6704                    start..end
6705                } else {
6706                    start..start
6707                }
6708            }
6709
6710            fn comment_suffix_range(
6711                snapshot: &MultiBufferSnapshot,
6712                row: u32,
6713                comment_suffix: &str,
6714                comment_suffix_has_leading_space: bool,
6715            ) -> Range<Point> {
6716                let end = Point::new(row, snapshot.line_len(row));
6717                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
6718
6719                let mut line_end_bytes = snapshot
6720                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
6721                    .flatten()
6722                    .copied();
6723
6724                let leading_space_len = if suffix_start_column > 0
6725                    && line_end_bytes.next() == Some(b' ')
6726                    && comment_suffix_has_leading_space
6727                {
6728                    1
6729                } else {
6730                    0
6731                };
6732
6733                // If this line currently begins with the line comment prefix, then record
6734                // the range containing the prefix.
6735                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
6736                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
6737                    start..end
6738                } else {
6739                    end..end
6740                }
6741            }
6742
6743            // TODO: Handle selections that cross excerpts
6744            for selection in &mut selections {
6745                let start_column = snapshot.indent_size_for_line(selection.start.row).len;
6746                let language = if let Some(language) =
6747                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
6748                {
6749                    language
6750                } else {
6751                    continue;
6752                };
6753
6754                selection_edit_ranges.clear();
6755
6756                // If multiple selections contain a given row, avoid processing that
6757                // row more than once.
6758                let mut start_row = selection.start.row;
6759                if last_toggled_row == Some(start_row) {
6760                    start_row += 1;
6761                }
6762                let end_row =
6763                    if selection.end.row > selection.start.row && selection.end.column == 0 {
6764                        selection.end.row - 1
6765                    } else {
6766                        selection.end.row
6767                    };
6768                last_toggled_row = Some(end_row);
6769
6770                if start_row > end_row {
6771                    continue;
6772                }
6773
6774                // If the language has line comments, toggle those.
6775                if let Some(full_comment_prefix) = language.line_comment_prefix() {
6776                    // Split the comment prefix's trailing whitespace into a separate string,
6777                    // as that portion won't be used for detecting if a line is a comment.
6778                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
6779                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
6780                    let mut all_selection_lines_are_comments = true;
6781
6782                    for row in start_row..=end_row {
6783                        if snapshot.is_line_blank(row) && start_row < end_row {
6784                            continue;
6785                        }
6786
6787                        let prefix_range = comment_prefix_range(
6788                            snapshot.deref(),
6789                            row,
6790                            comment_prefix,
6791                            comment_prefix_whitespace,
6792                        );
6793                        if prefix_range.is_empty() {
6794                            all_selection_lines_are_comments = false;
6795                        }
6796                        selection_edit_ranges.push(prefix_range);
6797                    }
6798
6799                    if all_selection_lines_are_comments {
6800                        edits.extend(
6801                            selection_edit_ranges
6802                                .iter()
6803                                .cloned()
6804                                .map(|range| (range, empty_str.clone())),
6805                        );
6806                    } else {
6807                        let min_column = selection_edit_ranges
6808                            .iter()
6809                            .map(|r| r.start.column)
6810                            .min()
6811                            .unwrap_or(0);
6812                        edits.extend(selection_edit_ranges.iter().map(|range| {
6813                            let position = Point::new(range.start.row, min_column);
6814                            (position..position, full_comment_prefix.clone())
6815                        }));
6816                    }
6817                } else if let Some((full_comment_prefix, comment_suffix)) =
6818                    language.block_comment_delimiters()
6819                {
6820                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
6821                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
6822                    let prefix_range = comment_prefix_range(
6823                        snapshot.deref(),
6824                        start_row,
6825                        comment_prefix,
6826                        comment_prefix_whitespace,
6827                    );
6828                    let suffix_range = comment_suffix_range(
6829                        snapshot.deref(),
6830                        end_row,
6831                        comment_suffix.trim_start_matches(' '),
6832                        comment_suffix.starts_with(' '),
6833                    );
6834
6835                    if prefix_range.is_empty() || suffix_range.is_empty() {
6836                        edits.push((
6837                            prefix_range.start..prefix_range.start,
6838                            full_comment_prefix.clone(),
6839                        ));
6840                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
6841                        suffixes_inserted.push((end_row, comment_suffix.len()));
6842                    } else {
6843                        edits.push((prefix_range, empty_str.clone()));
6844                        edits.push((suffix_range, empty_str.clone()));
6845                    }
6846                } else {
6847                    continue;
6848                }
6849            }
6850
6851            drop(snapshot);
6852            this.buffer.update(cx, |buffer, cx| {
6853                buffer.edit(edits, None, cx);
6854            });
6855
6856            // Adjust selections so that they end before any comment suffixes that
6857            // were inserted.
6858            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
6859            let mut selections = this.selections.all::<Point>(cx);
6860            let snapshot = this.buffer.read(cx).read(cx);
6861            for selection in &mut selections {
6862                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
6863                    match row.cmp(&selection.end.row) {
6864                        Ordering::Less => {
6865                            suffixes_inserted.next();
6866                            continue;
6867                        }
6868                        Ordering::Greater => break,
6869                        Ordering::Equal => {
6870                            if selection.end.column == snapshot.line_len(row) {
6871                                if selection.is_empty() {
6872                                    selection.start.column -= suffix_len as u32;
6873                                }
6874                                selection.end.column -= suffix_len as u32;
6875                            }
6876                            break;
6877                        }
6878                    }
6879                }
6880            }
6881
6882            drop(snapshot);
6883            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
6884
6885            let selections = this.selections.all::<Point>(cx);
6886            let selections_on_single_row = selections.windows(2).all(|selections| {
6887                selections[0].start.row == selections[1].start.row
6888                    && selections[0].end.row == selections[1].end.row
6889                    && selections[0].start.row == selections[0].end.row
6890            });
6891            let selections_selecting = selections
6892                .iter()
6893                .any(|selection| selection.start != selection.end);
6894            let advance_downwards = action.advance_downwards
6895                && selections_on_single_row
6896                && !selections_selecting
6897                && this.mode != EditorMode::SingleLine;
6898
6899            if advance_downwards {
6900                let snapshot = this.buffer.read(cx).snapshot(cx);
6901
6902                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
6903                    s.move_cursors_with(|display_snapshot, display_point, _| {
6904                        let mut point = display_point.to_point(display_snapshot);
6905                        point.row += 1;
6906                        point = snapshot.clip_point(point, Bias::Left);
6907                        let display_point = point.to_display_point(display_snapshot);
6908                        (display_point, SelectionGoal::Column(display_point.column()))
6909                    })
6910                });
6911            }
6912        });
6913    }
6914
6915    pub fn select_larger_syntax_node(
6916        &mut self,
6917        _: &SelectLargerSyntaxNode,
6918        cx: &mut ViewContext<Self>,
6919    ) {
6920        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6921        let buffer = self.buffer.read(cx).snapshot(cx);
6922        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
6923
6924        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
6925        let mut selected_larger_node = false;
6926        let new_selections = old_selections
6927            .iter()
6928            .map(|selection| {
6929                let old_range = selection.start..selection.end;
6930                let mut new_range = old_range.clone();
6931                while let Some(containing_range) =
6932                    buffer.range_for_syntax_ancestor(new_range.clone())
6933                {
6934                    new_range = containing_range;
6935                    if !display_map.intersects_fold(new_range.start)
6936                        && !display_map.intersects_fold(new_range.end)
6937                    {
6938                        break;
6939                    }
6940                }
6941
6942                selected_larger_node |= new_range != old_range;
6943                Selection {
6944                    id: selection.id,
6945                    start: new_range.start,
6946                    end: new_range.end,
6947                    goal: SelectionGoal::None,
6948                    reversed: selection.reversed,
6949                }
6950            })
6951            .collect::<Vec<_>>();
6952
6953        if selected_larger_node {
6954            stack.push(old_selections);
6955            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6956                s.select(new_selections);
6957            });
6958        }
6959        self.select_larger_syntax_node_stack = stack;
6960    }
6961
6962    pub fn select_smaller_syntax_node(
6963        &mut self,
6964        _: &SelectSmallerSyntaxNode,
6965        cx: &mut ViewContext<Self>,
6966    ) {
6967        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
6968        if let Some(selections) = stack.pop() {
6969            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6970                s.select(selections.to_vec());
6971            });
6972        }
6973        self.select_larger_syntax_node_stack = stack;
6974    }
6975
6976    pub fn move_to_enclosing_bracket(
6977        &mut self,
6978        _: &MoveToEnclosingBracket,
6979        cx: &mut ViewContext<Self>,
6980    ) {
6981        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6982            s.move_offsets_with(|snapshot, selection| {
6983                let Some(enclosing_bracket_ranges) =
6984                    snapshot.enclosing_bracket_ranges(selection.start..selection.end)
6985                else {
6986                    return;
6987                };
6988
6989                let mut best_length = usize::MAX;
6990                let mut best_inside = false;
6991                let mut best_in_bracket_range = false;
6992                let mut best_destination = None;
6993                for (open, close) in enclosing_bracket_ranges {
6994                    let close = close.to_inclusive();
6995                    let length = close.end() - open.start;
6996                    let inside = selection.start >= open.end && selection.end <= *close.start();
6997                    let in_bracket_range = open.to_inclusive().contains(&selection.head())
6998                        || close.contains(&selection.head());
6999
7000                    // If best is next to a bracket and current isn't, skip
7001                    if !in_bracket_range && best_in_bracket_range {
7002                        continue;
7003                    }
7004
7005                    // Prefer smaller lengths unless best is inside and current isn't
7006                    if length > best_length && (best_inside || !inside) {
7007                        continue;
7008                    }
7009
7010                    best_length = length;
7011                    best_inside = inside;
7012                    best_in_bracket_range = in_bracket_range;
7013                    best_destination = Some(
7014                        if close.contains(&selection.start) && close.contains(&selection.end) {
7015                            if inside {
7016                                open.end
7017                            } else {
7018                                open.start
7019                            }
7020                        } else {
7021                            if inside {
7022                                *close.start()
7023                            } else {
7024                                *close.end()
7025                            }
7026                        },
7027                    );
7028                }
7029
7030                if let Some(destination) = best_destination {
7031                    selection.collapse_to(destination, SelectionGoal::None);
7032                }
7033            })
7034        });
7035    }
7036
7037    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
7038        self.end_selection(cx);
7039        self.selection_history.mode = SelectionHistoryMode::Undoing;
7040        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
7041            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
7042            self.select_next_state = entry.select_next_state;
7043            self.select_prev_state = entry.select_prev_state;
7044            self.add_selections_state = entry.add_selections_state;
7045            self.request_autoscroll(Autoscroll::newest(), cx);
7046        }
7047        self.selection_history.mode = SelectionHistoryMode::Normal;
7048    }
7049
7050    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
7051        self.end_selection(cx);
7052        self.selection_history.mode = SelectionHistoryMode::Redoing;
7053        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
7054            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
7055            self.select_next_state = entry.select_next_state;
7056            self.select_prev_state = entry.select_prev_state;
7057            self.add_selections_state = entry.add_selections_state;
7058            self.request_autoscroll(Autoscroll::newest(), cx);
7059        }
7060        self.selection_history.mode = SelectionHistoryMode::Normal;
7061    }
7062
7063    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
7064        self.go_to_diagnostic_impl(Direction::Next, cx)
7065    }
7066
7067    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
7068        self.go_to_diagnostic_impl(Direction::Prev, cx)
7069    }
7070
7071    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
7072        let buffer = self.buffer.read(cx).snapshot(cx);
7073        let selection = self.selections.newest::<usize>(cx);
7074
7075        // If there is an active Diagnostic Popover. Jump to it's diagnostic instead.
7076        if direction == Direction::Next {
7077            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
7078                let (group_id, jump_to) = popover.activation_info();
7079                if self.activate_diagnostics(group_id, cx) {
7080                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
7081                        let mut new_selection = s.newest_anchor().clone();
7082                        new_selection.collapse_to(jump_to, SelectionGoal::None);
7083                        s.select_anchors(vec![new_selection.clone()]);
7084                    });
7085                }
7086                return;
7087            }
7088        }
7089
7090        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
7091            active_diagnostics
7092                .primary_range
7093                .to_offset(&buffer)
7094                .to_inclusive()
7095        });
7096        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
7097            if active_primary_range.contains(&selection.head()) {
7098                *active_primary_range.end()
7099            } else {
7100                selection.head()
7101            }
7102        } else {
7103            selection.head()
7104        };
7105
7106        loop {
7107            let mut diagnostics = if direction == Direction::Prev {
7108                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
7109            } else {
7110                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
7111            };
7112            let group = diagnostics.find_map(|entry| {
7113                if entry.diagnostic.is_primary
7114                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
7115                    && !entry.range.is_empty()
7116                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
7117                {
7118                    Some((entry.range, entry.diagnostic.group_id))
7119                } else {
7120                    None
7121                }
7122            });
7123
7124            if let Some((primary_range, group_id)) = group {
7125                if self.activate_diagnostics(group_id, cx) {
7126                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
7127                        s.select(vec![Selection {
7128                            id: selection.id,
7129                            start: primary_range.start,
7130                            end: primary_range.start,
7131                            reversed: false,
7132                            goal: SelectionGoal::None,
7133                        }]);
7134                    });
7135                }
7136                break;
7137            } else {
7138                // Cycle around to the start of the buffer, potentially moving back to the start of
7139                // the currently active diagnostic.
7140                active_primary_range.take();
7141                if direction == Direction::Prev {
7142                    if search_start == buffer.len() {
7143                        break;
7144                    } else {
7145                        search_start = buffer.len();
7146                    }
7147                } else if search_start == 0 {
7148                    break;
7149                } else {
7150                    search_start = 0;
7151                }
7152            }
7153        }
7154    }
7155
7156    fn go_to_hunk(&mut self, _: &GoToHunk, cx: &mut ViewContext<Self>) {
7157        let snapshot = self
7158            .display_map
7159            .update(cx, |display_map, cx| display_map.snapshot(cx));
7160        let selection = self.selections.newest::<Point>(cx);
7161
7162        if !self.seek_in_direction(
7163            &snapshot,
7164            selection.head(),
7165            false,
7166            snapshot
7167                .buffer_snapshot
7168                .git_diff_hunks_in_range((selection.head().row + 1)..u32::MAX),
7169            cx,
7170        ) {
7171            let wrapped_point = Point::zero();
7172            self.seek_in_direction(
7173                &snapshot,
7174                wrapped_point,
7175                true,
7176                snapshot
7177                    .buffer_snapshot
7178                    .git_diff_hunks_in_range((wrapped_point.row + 1)..u32::MAX),
7179                cx,
7180            );
7181        }
7182    }
7183
7184    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
7185        let snapshot = self
7186            .display_map
7187            .update(cx, |display_map, cx| display_map.snapshot(cx));
7188        let selection = self.selections.newest::<Point>(cx);
7189
7190        if !self.seek_in_direction(
7191            &snapshot,
7192            selection.head(),
7193            false,
7194            snapshot
7195                .buffer_snapshot
7196                .git_diff_hunks_in_range_rev(0..selection.head().row),
7197            cx,
7198        ) {
7199            let wrapped_point = snapshot.buffer_snapshot.max_point();
7200            self.seek_in_direction(
7201                &snapshot,
7202                wrapped_point,
7203                true,
7204                snapshot
7205                    .buffer_snapshot
7206                    .git_diff_hunks_in_range_rev(0..wrapped_point.row),
7207                cx,
7208            );
7209        }
7210    }
7211
7212    fn seek_in_direction(
7213        &mut self,
7214        snapshot: &DisplaySnapshot,
7215        initial_point: Point,
7216        is_wrapped: bool,
7217        hunks: impl Iterator<Item = DiffHunk<u32>>,
7218        cx: &mut ViewContext<Editor>,
7219    ) -> bool {
7220        let display_point = initial_point.to_display_point(snapshot);
7221        let mut hunks = hunks
7222            .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
7223            .skip_while(|hunk| {
7224                if is_wrapped {
7225                    false
7226                } else {
7227                    hunk.contains_display_row(display_point.row())
7228                }
7229            })
7230            .dedup();
7231
7232        if let Some(hunk) = hunks.next() {
7233            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
7234                let row = hunk.start_display_row();
7235                let point = DisplayPoint::new(row, 0);
7236                s.select_display_ranges([point..point]);
7237            });
7238
7239            true
7240        } else {
7241            false
7242        }
7243    }
7244
7245    pub fn go_to_definition(&mut self, _: &GoToDefinition, cx: &mut ViewContext<Self>) {
7246        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, false, cx);
7247    }
7248
7249    pub fn go_to_type_definition(&mut self, _: &GoToTypeDefinition, cx: &mut ViewContext<Self>) {
7250        self.go_to_definition_of_kind(GotoDefinitionKind::Type, false, cx);
7251    }
7252
7253    pub fn go_to_definition_split(&mut self, _: &GoToDefinitionSplit, cx: &mut ViewContext<Self>) {
7254        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, true, cx);
7255    }
7256
7257    pub fn go_to_type_definition_split(
7258        &mut self,
7259        _: &GoToTypeDefinitionSplit,
7260        cx: &mut ViewContext<Self>,
7261    ) {
7262        self.go_to_definition_of_kind(GotoDefinitionKind::Type, true, cx);
7263    }
7264
7265    fn go_to_definition_of_kind(
7266        &mut self,
7267        kind: GotoDefinitionKind,
7268        split: bool,
7269        cx: &mut ViewContext<Self>,
7270    ) {
7271        let Some(workspace) = self.workspace(cx) else {
7272            return;
7273        };
7274        let buffer = self.buffer.read(cx);
7275        let head = self.selections.newest::<usize>(cx).head();
7276        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
7277            text_anchor
7278        } else {
7279            return;
7280        };
7281
7282        let project = workspace.read(cx).project().clone();
7283        let definitions = project.update(cx, |project, cx| match kind {
7284            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
7285            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
7286        });
7287
7288        cx.spawn_labeled("Fetching Definition...", |editor, mut cx| async move {
7289            let definitions = definitions.await?;
7290            editor.update(&mut cx, |editor, cx| {
7291                editor.navigate_to_definitions(
7292                    definitions
7293                        .into_iter()
7294                        .map(GoToDefinitionLink::Text)
7295                        .collect(),
7296                    split,
7297                    cx,
7298                );
7299            })?;
7300            Ok::<(), anyhow::Error>(())
7301        })
7302        .detach_and_log_err(cx);
7303    }
7304
7305    pub fn navigate_to_definitions(
7306        &mut self,
7307        mut definitions: Vec<GoToDefinitionLink>,
7308        split: bool,
7309        cx: &mut ViewContext<Editor>,
7310    ) {
7311        let Some(workspace) = self.workspace(cx) else {
7312            return;
7313        };
7314        let pane = workspace.read(cx).active_pane().clone();
7315        // If there is one definition, just open it directly
7316        if definitions.len() == 1 {
7317            let definition = definitions.pop().unwrap();
7318            let target_task = match definition {
7319                GoToDefinitionLink::Text(link) => Task::Ready(Some(Ok(Some(link.target)))),
7320                GoToDefinitionLink::InlayHint(lsp_location, server_id) => {
7321                    self.compute_target_location(lsp_location, server_id, cx)
7322                }
7323            };
7324            cx.spawn(|editor, mut cx| async move {
7325                let target = target_task.await.context("target resolution task")?;
7326                if let Some(target) = target {
7327                    editor.update(&mut cx, |editor, cx| {
7328                        let range = target.range.to_offset(target.buffer.read(cx));
7329                        let range = editor.range_for_match(&range);
7330                        if Some(&target.buffer) == editor.buffer.read(cx).as_singleton().as_ref() {
7331                            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
7332                                s.select_ranges([range]);
7333                            });
7334                        } else {
7335                            cx.window_context().defer(move |cx| {
7336                                let target_editor: ViewHandle<Self> =
7337                                    workspace.update(cx, |workspace, cx| {
7338                                        if split {
7339                                            workspace.split_project_item(target.buffer.clone(), cx)
7340                                        } else {
7341                                            workspace.open_project_item(target.buffer.clone(), cx)
7342                                        }
7343                                    });
7344                                target_editor.update(cx, |target_editor, cx| {
7345                                    // When selecting a definition in a different buffer, disable the nav history
7346                                    // to avoid creating a history entry at the previous cursor location.
7347                                    pane.update(cx, |pane, _| pane.disable_history());
7348                                    target_editor.change_selections(
7349                                        Some(Autoscroll::fit()),
7350                                        cx,
7351                                        |s| {
7352                                            s.select_ranges([range]);
7353                                        },
7354                                    );
7355                                    pane.update(cx, |pane, _| pane.enable_history());
7356                                });
7357                            });
7358                        }
7359                    })
7360                } else {
7361                    Ok(())
7362                }
7363            })
7364            .detach_and_log_err(cx);
7365        } else if !definitions.is_empty() {
7366            let replica_id = self.replica_id(cx);
7367            cx.spawn(|editor, mut cx| async move {
7368                let (title, location_tasks) = editor
7369                    .update(&mut cx, |editor, cx| {
7370                        let title = definitions
7371                            .iter()
7372                            .find_map(|definition| match definition {
7373                                GoToDefinitionLink::Text(link) => {
7374                                    link.origin.as_ref().map(|origin| {
7375                                        let buffer = origin.buffer.read(cx);
7376                                        format!(
7377                                            "Definitions for {}",
7378                                            buffer
7379                                                .text_for_range(origin.range.clone())
7380                                                .collect::<String>()
7381                                        )
7382                                    })
7383                                }
7384                                GoToDefinitionLink::InlayHint(_, _) => None,
7385                            })
7386                            .unwrap_or("Definitions".to_string());
7387                        let location_tasks = definitions
7388                            .into_iter()
7389                            .map(|definition| match definition {
7390                                GoToDefinitionLink::Text(link) => {
7391                                    Task::Ready(Some(Ok(Some(link.target))))
7392                                }
7393                                GoToDefinitionLink::InlayHint(lsp_location, server_id) => {
7394                                    editor.compute_target_location(lsp_location, server_id, cx)
7395                                }
7396                            })
7397                            .collect::<Vec<_>>();
7398                        (title, location_tasks)
7399                    })
7400                    .context("location tasks preparation")?;
7401
7402                let locations = futures::future::join_all(location_tasks)
7403                    .await
7404                    .into_iter()
7405                    .filter_map(|location| location.transpose())
7406                    .collect::<Result<_>>()
7407                    .context("location tasks")?;
7408                workspace.update(&mut cx, |workspace, cx| {
7409                    Self::open_locations_in_multibuffer(
7410                        workspace, locations, replica_id, title, split, cx,
7411                    )
7412                });
7413
7414                anyhow::Ok(())
7415            })
7416            .detach_and_log_err(cx);
7417        }
7418    }
7419
7420    fn compute_target_location(
7421        &self,
7422        lsp_location: lsp::Location,
7423        server_id: LanguageServerId,
7424        cx: &mut ViewContext<Editor>,
7425    ) -> Task<anyhow::Result<Option<Location>>> {
7426        let Some(project) = self.project.clone() else {
7427            return Task::Ready(Some(Ok(None)));
7428        };
7429
7430        cx.spawn(move |editor, mut cx| async move {
7431            let location_task = editor.update(&mut cx, |editor, cx| {
7432                project.update(cx, |project, cx| {
7433                    let language_server_name =
7434                        editor.buffer.read(cx).as_singleton().and_then(|buffer| {
7435                            project
7436                                .language_server_for_buffer(buffer.read(cx), server_id, cx)
7437                                .map(|(_, lsp_adapter)| {
7438                                    LanguageServerName(Arc::from(lsp_adapter.name()))
7439                                })
7440                        });
7441                    language_server_name.map(|language_server_name| {
7442                        project.open_local_buffer_via_lsp(
7443                            lsp_location.uri.clone(),
7444                            server_id,
7445                            language_server_name,
7446                            cx,
7447                        )
7448                    })
7449                })
7450            })?;
7451            let location = match location_task {
7452                Some(task) => Some({
7453                    let target_buffer_handle = task.await.context("open local buffer")?;
7454                    let range = {
7455                        target_buffer_handle.update(&mut cx, |target_buffer, _| {
7456                            let target_start = target_buffer.clip_point_utf16(
7457                                point_from_lsp(lsp_location.range.start),
7458                                Bias::Left,
7459                            );
7460                            let target_end = target_buffer.clip_point_utf16(
7461                                point_from_lsp(lsp_location.range.end),
7462                                Bias::Left,
7463                            );
7464                            target_buffer.anchor_after(target_start)
7465                                ..target_buffer.anchor_before(target_end)
7466                        })
7467                    };
7468                    Location {
7469                        buffer: target_buffer_handle,
7470                        range,
7471                    }
7472                }),
7473                None => None,
7474            };
7475            Ok(location)
7476        })
7477    }
7478
7479    pub fn find_all_references(
7480        workspace: &mut Workspace,
7481        _: &FindAllReferences,
7482        cx: &mut ViewContext<Workspace>,
7483    ) -> Option<Task<Result<()>>> {
7484        let active_item = workspace.active_item(cx)?;
7485        let editor_handle = active_item.act_as::<Self>(cx)?;
7486
7487        let editor = editor_handle.read(cx);
7488        let buffer = editor.buffer.read(cx);
7489        let head = editor.selections.newest::<usize>(cx).head();
7490        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
7491        let replica_id = editor.replica_id(cx);
7492
7493        let project = workspace.project().clone();
7494        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
7495        Some(cx.spawn_labeled(
7496            "Finding All References...",
7497            |workspace, mut cx| async move {
7498                let locations = references.await?;
7499                if locations.is_empty() {
7500                    return Ok(());
7501                }
7502
7503                workspace.update(&mut cx, |workspace, cx| {
7504                    let title = locations
7505                        .first()
7506                        .as_ref()
7507                        .map(|location| {
7508                            let buffer = location.buffer.read(cx);
7509                            format!(
7510                                "References to `{}`",
7511                                buffer
7512                                    .text_for_range(location.range.clone())
7513                                    .collect::<String>()
7514                            )
7515                        })
7516                        .unwrap();
7517                    Self::open_locations_in_multibuffer(
7518                        workspace, locations, replica_id, title, false, cx,
7519                    );
7520                })?;
7521
7522                Ok(())
7523            },
7524        ))
7525    }
7526
7527    /// Opens a multibuffer with the given project locations in it
7528    pub fn open_locations_in_multibuffer(
7529        workspace: &mut Workspace,
7530        mut locations: Vec<Location>,
7531        replica_id: ReplicaId,
7532        title: String,
7533        split: bool,
7534        cx: &mut ViewContext<Workspace>,
7535    ) {
7536        // If there are multiple definitions, open them in a multibuffer
7537        locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
7538        let mut locations = locations.into_iter().peekable();
7539        let mut ranges_to_highlight = Vec::new();
7540
7541        let excerpt_buffer = cx.add_model(|cx| {
7542            let mut multibuffer = MultiBuffer::new(replica_id);
7543            while let Some(location) = locations.next() {
7544                let buffer = location.buffer.read(cx);
7545                let mut ranges_for_buffer = Vec::new();
7546                let range = location.range.to_offset(buffer);
7547                ranges_for_buffer.push(range.clone());
7548
7549                while let Some(next_location) = locations.peek() {
7550                    if next_location.buffer == location.buffer {
7551                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
7552                        locations.next();
7553                    } else {
7554                        break;
7555                    }
7556                }
7557
7558                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
7559                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
7560                    location.buffer.clone(),
7561                    ranges_for_buffer,
7562                    1,
7563                    cx,
7564                ))
7565            }
7566
7567            multibuffer.with_title(title)
7568        });
7569
7570        let editor = cx.add_view(|cx| {
7571            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx)
7572        });
7573        editor.update(cx, |editor, cx| {
7574            editor.highlight_background::<Self>(
7575                ranges_to_highlight,
7576                |theme| theme.editor.highlighted_line_background,
7577                cx,
7578            );
7579        });
7580        if split {
7581            workspace.split_item(SplitDirection::Right, Box::new(editor), cx);
7582        } else {
7583            workspace.add_item(Box::new(editor), cx);
7584        }
7585    }
7586
7587    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
7588        use language::ToOffset as _;
7589
7590        let project = self.project.clone()?;
7591        let selection = self.selections.newest_anchor().clone();
7592        let (cursor_buffer, cursor_buffer_position) = self
7593            .buffer
7594            .read(cx)
7595            .text_anchor_for_position(selection.head(), cx)?;
7596        let (tail_buffer, _) = self
7597            .buffer
7598            .read(cx)
7599            .text_anchor_for_position(selection.tail(), cx)?;
7600        if tail_buffer != cursor_buffer {
7601            return None;
7602        }
7603
7604        let snapshot = cursor_buffer.read(cx).snapshot();
7605        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
7606        let prepare_rename = project.update(cx, |project, cx| {
7607            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
7608        });
7609
7610        Some(cx.spawn(|this, mut cx| async move {
7611            let rename_range = if let Some(range) = prepare_rename.await? {
7612                Some(range)
7613            } else {
7614                this.update(&mut cx, |this, cx| {
7615                    let buffer = this.buffer.read(cx).snapshot(cx);
7616                    let mut buffer_highlights = this
7617                        .document_highlights_for_position(selection.head(), &buffer)
7618                        .filter(|highlight| {
7619                            highlight.start.excerpt_id() == selection.head().excerpt_id()
7620                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
7621                        });
7622                    buffer_highlights
7623                        .next()
7624                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
7625                })?
7626            };
7627            if let Some(rename_range) = rename_range {
7628                let rename_buffer_range = rename_range.to_offset(&snapshot);
7629                let cursor_offset_in_rename_range =
7630                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
7631
7632                this.update(&mut cx, |this, cx| {
7633                    this.take_rename(false, cx);
7634                    let style = this.style(cx);
7635                    let buffer = this.buffer.read(cx).read(cx);
7636                    let cursor_offset = selection.head().to_offset(&buffer);
7637                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
7638                    let rename_end = rename_start + rename_buffer_range.len();
7639                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
7640                    let mut old_highlight_id = None;
7641                    let old_name: Arc<str> = buffer
7642                        .chunks(rename_start..rename_end, true)
7643                        .map(|chunk| {
7644                            if old_highlight_id.is_none() {
7645                                old_highlight_id = chunk.syntax_highlight_id;
7646                            }
7647                            chunk.text
7648                        })
7649                        .collect::<String>()
7650                        .into();
7651
7652                    drop(buffer);
7653
7654                    // Position the selection in the rename editor so that it matches the current selection.
7655                    this.show_local_selections = false;
7656                    let rename_editor = cx.add_view(|cx| {
7657                        let mut editor = Editor::single_line(None, cx);
7658                        if let Some(old_highlight_id) = old_highlight_id {
7659                            editor.override_text_style =
7660                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
7661                        }
7662                        editor.buffer.update(cx, |buffer, cx| {
7663                            buffer.edit([(0..0, old_name.clone())], None, cx)
7664                        });
7665                        editor.select_all(&SelectAll, cx);
7666                        editor
7667                    });
7668
7669                    let ranges = this
7670                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
7671                        .into_iter()
7672                        .flat_map(|(_, ranges)| ranges.into_iter())
7673                        .chain(
7674                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
7675                                .into_iter()
7676                                .flat_map(|(_, ranges)| ranges.into_iter()),
7677                        )
7678                        .collect();
7679
7680                    this.highlight_text::<Rename>(
7681                        ranges,
7682                        HighlightStyle {
7683                            fade_out: Some(style.rename_fade),
7684                            ..Default::default()
7685                        },
7686                        cx,
7687                    );
7688                    cx.focus(&rename_editor);
7689                    let block_id = this.insert_blocks(
7690                        [BlockProperties {
7691                            style: BlockStyle::Flex,
7692                            position: range.start.clone(),
7693                            height: 1,
7694                            render: Arc::new({
7695                                let editor = rename_editor.clone();
7696                                move |cx: &mut BlockContext| {
7697                                    ChildView::new(&editor, cx)
7698                                        .contained()
7699                                        .with_padding_left(cx.anchor_x)
7700                                        .into_any()
7701                                }
7702                            }),
7703                            disposition: BlockDisposition::Below,
7704                        }],
7705                        Some(Autoscroll::fit()),
7706                        cx,
7707                    )[0];
7708                    this.pending_rename = Some(RenameState {
7709                        range,
7710                        old_name,
7711                        editor: rename_editor,
7712                        block_id,
7713                    });
7714                })?;
7715            }
7716
7717            Ok(())
7718        }))
7719    }
7720
7721    pub fn confirm_rename(
7722        workspace: &mut Workspace,
7723        _: &ConfirmRename,
7724        cx: &mut ViewContext<Workspace>,
7725    ) -> Option<Task<Result<()>>> {
7726        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
7727
7728        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
7729            let rename = editor.take_rename(false, cx)?;
7730            let buffer = editor.buffer.read(cx);
7731            let (start_buffer, start) =
7732                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
7733            let (end_buffer, end) =
7734                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
7735            if start_buffer == end_buffer {
7736                let new_name = rename.editor.read(cx).text(cx);
7737                Some((start_buffer, start..end, rename.old_name, new_name))
7738            } else {
7739                None
7740            }
7741        })?;
7742
7743        let rename = workspace.project().clone().update(cx, |project, cx| {
7744            project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
7745        });
7746
7747        let editor = editor.downgrade();
7748        Some(cx.spawn(|workspace, mut cx| async move {
7749            let project_transaction = rename.await?;
7750            Self::open_project_transaction(
7751                &editor,
7752                workspace,
7753                project_transaction,
7754                format!("Rename: {}{}", old_name, new_name),
7755                cx.clone(),
7756            )
7757            .await?;
7758
7759            editor.update(&mut cx, |editor, cx| {
7760                editor.refresh_document_highlights(cx);
7761            })?;
7762            Ok(())
7763        }))
7764    }
7765
7766    fn take_rename(
7767        &mut self,
7768        moving_cursor: bool,
7769        cx: &mut ViewContext<Self>,
7770    ) -> Option<RenameState> {
7771        let rename = self.pending_rename.take()?;
7772        self.remove_blocks(
7773            [rename.block_id].into_iter().collect(),
7774            Some(Autoscroll::fit()),
7775            cx,
7776        );
7777        self.clear_highlights::<Rename>(cx);
7778        self.show_local_selections = true;
7779
7780        if moving_cursor {
7781            let rename_editor = rename.editor.read(cx);
7782            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
7783
7784            // Update the selection to match the position of the selection inside
7785            // the rename editor.
7786            let snapshot = self.buffer.read(cx).read(cx);
7787            let rename_range = rename.range.to_offset(&snapshot);
7788            let cursor_in_editor = snapshot
7789                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
7790                .min(rename_range.end);
7791            drop(snapshot);
7792
7793            self.change_selections(None, cx, |s| {
7794                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
7795            });
7796        } else {
7797            self.refresh_document_highlights(cx);
7798        }
7799
7800        Some(rename)
7801    }
7802
7803    #[cfg(any(test, feature = "test-support"))]
7804    pub fn pending_rename(&self) -> Option<&RenameState> {
7805        self.pending_rename.as_ref()
7806    }
7807
7808    fn format(&mut self, _: &Format, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
7809        let project = match &self.project {
7810            Some(project) => project.clone(),
7811            None => return None,
7812        };
7813
7814        Some(self.perform_format(project, FormatTrigger::Manual, cx))
7815    }
7816
7817    fn perform_format(
7818        &mut self,
7819        project: ModelHandle<Project>,
7820        trigger: FormatTrigger,
7821        cx: &mut ViewContext<Self>,
7822    ) -> Task<Result<()>> {
7823        let buffer = self.buffer().clone();
7824        let buffers = buffer.read(cx).all_buffers();
7825
7826        let mut timeout = cx.background().timer(FORMAT_TIMEOUT).fuse();
7827        let format = project.update(cx, |project, cx| project.format(buffers, true, trigger, cx));
7828
7829        cx.spawn(|_, mut cx| async move {
7830            let transaction = futures::select_biased! {
7831                _ = timeout => {
7832                    log::warn!("timed out waiting for formatting");
7833                    None
7834                }
7835                transaction = format.log_err().fuse() => transaction,
7836            };
7837
7838            buffer.update(&mut cx, |buffer, cx| {
7839                if let Some(transaction) = transaction {
7840                    if !buffer.is_singleton() {
7841                        buffer.push_transaction(&transaction.0, cx);
7842                    }
7843                }
7844
7845                cx.notify();
7846            });
7847
7848            Ok(())
7849        })
7850    }
7851
7852    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
7853        if let Some(project) = self.project.clone() {
7854            self.buffer.update(cx, |multi_buffer, cx| {
7855                project.update(cx, |project, cx| {
7856                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
7857                });
7858            })
7859        }
7860    }
7861
7862    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
7863        cx.show_character_palette();
7864    }
7865
7866    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
7867        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
7868            let buffer = self.buffer.read(cx).snapshot(cx);
7869            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
7870            let is_valid = buffer
7871                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
7872                .any(|entry| {
7873                    entry.diagnostic.is_primary
7874                        && !entry.range.is_empty()
7875                        && entry.range.start == primary_range_start
7876                        && entry.diagnostic.message == active_diagnostics.primary_message
7877                });
7878
7879            if is_valid != active_diagnostics.is_valid {
7880                active_diagnostics.is_valid = is_valid;
7881                let mut new_styles = HashMap::default();
7882                for (block_id, diagnostic) in &active_diagnostics.blocks {
7883                    new_styles.insert(
7884                        *block_id,
7885                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
7886                    );
7887                }
7888                self.display_map
7889                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
7890            }
7891        }
7892    }
7893
7894    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
7895        self.dismiss_diagnostics(cx);
7896        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
7897            let buffer = self.buffer.read(cx).snapshot(cx);
7898
7899            let mut primary_range = None;
7900            let mut primary_message = None;
7901            let mut group_end = Point::zero();
7902            let diagnostic_group = buffer
7903                .diagnostic_group::<Point>(group_id)
7904                .map(|entry| {
7905                    if entry.range.end > group_end {
7906                        group_end = entry.range.end;
7907                    }
7908                    if entry.diagnostic.is_primary {
7909                        primary_range = Some(entry.range.clone());
7910                        primary_message = Some(entry.diagnostic.message.clone());
7911                    }
7912                    entry
7913                })
7914                .collect::<Vec<_>>();
7915            let primary_range = primary_range?;
7916            let primary_message = primary_message?;
7917            let primary_range =
7918                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
7919
7920            let blocks = display_map
7921                .insert_blocks(
7922                    diagnostic_group.iter().map(|entry| {
7923                        let diagnostic = entry.diagnostic.clone();
7924                        let message_height = diagnostic.message.lines().count() as u8;
7925                        BlockProperties {
7926                            style: BlockStyle::Fixed,
7927                            position: buffer.anchor_after(entry.range.start),
7928                            height: message_height,
7929                            render: diagnostic_block_renderer(diagnostic, true),
7930                            disposition: BlockDisposition::Below,
7931                        }
7932                    }),
7933                    cx,
7934                )
7935                .into_iter()
7936                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
7937                .collect();
7938
7939            Some(ActiveDiagnosticGroup {
7940                primary_range,
7941                primary_message,
7942                blocks,
7943                is_valid: true,
7944            })
7945        });
7946        self.active_diagnostics.is_some()
7947    }
7948
7949    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
7950        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
7951            self.display_map.update(cx, |display_map, cx| {
7952                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
7953            });
7954            cx.notify();
7955        }
7956    }
7957
7958    pub fn set_selections_from_remote(
7959        &mut self,
7960        selections: Vec<Selection<Anchor>>,
7961        pending_selection: Option<Selection<Anchor>>,
7962        cx: &mut ViewContext<Self>,
7963    ) {
7964        let old_cursor_position = self.selections.newest_anchor().head();
7965        self.selections.change_with(cx, |s| {
7966            s.select_anchors(selections);
7967            if let Some(pending_selection) = pending_selection {
7968                s.set_pending(pending_selection, SelectMode::Character);
7969            } else {
7970                s.clear_pending();
7971            }
7972        });
7973        self.selections_did_change(false, &old_cursor_position, cx);
7974    }
7975
7976    fn push_to_selection_history(&mut self) {
7977        self.selection_history.push(SelectionHistoryEntry {
7978            selections: self.selections.disjoint_anchors(),
7979            select_next_state: self.select_next_state.clone(),
7980            select_prev_state: self.select_prev_state.clone(),
7981            add_selections_state: self.add_selections_state.clone(),
7982        });
7983    }
7984
7985    pub fn transact(
7986        &mut self,
7987        cx: &mut ViewContext<Self>,
7988        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
7989    ) -> Option<TransactionId> {
7990        self.start_transaction_at(Instant::now(), cx);
7991        update(self, cx);
7992        self.end_transaction_at(Instant::now(), cx)
7993    }
7994
7995    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
7996        self.end_selection(cx);
7997        if let Some(tx_id) = self
7998            .buffer
7999            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
8000        {
8001            self.selection_history
8002                .insert_transaction(tx_id, self.selections.disjoint_anchors());
8003        }
8004    }
8005
8006    fn end_transaction_at(
8007        &mut self,
8008        now: Instant,
8009        cx: &mut ViewContext<Self>,
8010    ) -> Option<TransactionId> {
8011        if let Some(tx_id) = self
8012            .buffer
8013            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
8014        {
8015            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
8016                *end_selections = Some(self.selections.disjoint_anchors());
8017            } else {
8018                error!("unexpectedly ended a transaction that wasn't started by this editor");
8019            }
8020
8021            cx.emit(Event::Edited);
8022            Some(tx_id)
8023        } else {
8024            None
8025        }
8026    }
8027
8028    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
8029        let mut fold_ranges = Vec::new();
8030
8031        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
8032
8033        let selections = self.selections.all_adjusted(cx);
8034        for selection in selections {
8035            let range = selection.range().sorted();
8036            let buffer_start_row = range.start.row;
8037
8038            for row in (0..=range.end.row).rev() {
8039                let fold_range = display_map.foldable_range(row);
8040
8041                if let Some(fold_range) = fold_range {
8042                    if fold_range.end.row >= buffer_start_row {
8043                        fold_ranges.push(fold_range);
8044                        if row <= range.start.row {
8045                            break;
8046                        }
8047                    }
8048                }
8049            }
8050        }
8051
8052        self.fold_ranges(fold_ranges, true, cx);
8053    }
8054
8055    pub fn fold_at(&mut self, fold_at: &FoldAt, cx: &mut ViewContext<Self>) {
8056        let buffer_row = fold_at.buffer_row;
8057        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
8058
8059        if let Some(fold_range) = display_map.foldable_range(buffer_row) {
8060            let autoscroll = self
8061                .selections
8062                .all::<Point>(cx)
8063                .iter()
8064                .any(|selection| fold_range.overlaps(&selection.range()));
8065
8066            self.fold_ranges(std::iter::once(fold_range), autoscroll, cx);
8067        }
8068    }
8069
8070    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
8071        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
8072        let buffer = &display_map.buffer_snapshot;
8073        let selections = self.selections.all::<Point>(cx);
8074        let ranges = selections
8075            .iter()
8076            .map(|s| {
8077                let range = s.display_range(&display_map).sorted();
8078                let mut start = range.start.to_point(&display_map);
8079                let mut end = range.end.to_point(&display_map);
8080                start.column = 0;
8081                end.column = buffer.line_len(end.row);
8082                start..end
8083            })
8084            .collect::<Vec<_>>();
8085
8086        self.unfold_ranges(ranges, true, true, cx);
8087    }
8088
8089    pub fn unfold_at(&mut self, unfold_at: &UnfoldAt, cx: &mut ViewContext<Self>) {
8090        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
8091
8092        let intersection_range = Point::new(unfold_at.buffer_row, 0)
8093            ..Point::new(
8094                unfold_at.buffer_row,
8095                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
8096            );
8097
8098        let autoscroll = self
8099            .selections
8100            .all::<Point>(cx)
8101            .iter()
8102            .any(|selection| selection.range().overlaps(&intersection_range));
8103
8104        self.unfold_ranges(std::iter::once(intersection_range), true, autoscroll, cx)
8105    }
8106
8107    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
8108        let selections = self.selections.all::<Point>(cx);
8109        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
8110        let line_mode = self.selections.line_mode;
8111        let ranges = selections.into_iter().map(|s| {
8112            if line_mode {
8113                let start = Point::new(s.start.row, 0);
8114                let end = Point::new(s.end.row, display_map.buffer_snapshot.line_len(s.end.row));
8115                start..end
8116            } else {
8117                s.start..s.end
8118            }
8119        });
8120        self.fold_ranges(ranges, true, cx);
8121    }
8122
8123    pub fn fold_ranges<T: ToOffset + Clone>(
8124        &mut self,
8125        ranges: impl IntoIterator<Item = Range<T>>,
8126        auto_scroll: bool,
8127        cx: &mut ViewContext<Self>,
8128    ) {
8129        let mut ranges = ranges.into_iter().peekable();
8130        if ranges.peek().is_some() {
8131            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
8132
8133            if auto_scroll {
8134                self.request_autoscroll(Autoscroll::fit(), cx);
8135            }
8136
8137            cx.notify();
8138        }
8139    }
8140
8141    pub fn unfold_ranges<T: ToOffset + Clone>(
8142        &mut self,
8143        ranges: impl IntoIterator<Item = Range<T>>,
8144        inclusive: bool,
8145        auto_scroll: bool,
8146        cx: &mut ViewContext<Self>,
8147    ) {
8148        let mut ranges = ranges.into_iter().peekable();
8149        if ranges.peek().is_some() {
8150            self.display_map
8151                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
8152            if auto_scroll {
8153                self.request_autoscroll(Autoscroll::fit(), cx);
8154            }
8155
8156            cx.notify();
8157        }
8158    }
8159
8160    pub fn gutter_hover(
8161        &mut self,
8162        GutterHover { hovered }: &GutterHover,
8163        cx: &mut ViewContext<Self>,
8164    ) {
8165        self.gutter_hovered = *hovered;
8166        cx.notify();
8167    }
8168
8169    pub fn insert_blocks(
8170        &mut self,
8171        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
8172        autoscroll: Option<Autoscroll>,
8173        cx: &mut ViewContext<Self>,
8174    ) -> Vec<BlockId> {
8175        let blocks = self
8176            .display_map
8177            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
8178        if let Some(autoscroll) = autoscroll {
8179            self.request_autoscroll(autoscroll, cx);
8180        }
8181        blocks
8182    }
8183
8184    pub fn replace_blocks(
8185        &mut self,
8186        blocks: HashMap<BlockId, RenderBlock>,
8187        autoscroll: Option<Autoscroll>,
8188        cx: &mut ViewContext<Self>,
8189    ) {
8190        self.display_map
8191            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
8192        if let Some(autoscroll) = autoscroll {
8193            self.request_autoscroll(autoscroll, cx);
8194        }
8195    }
8196
8197    pub fn remove_blocks(
8198        &mut self,
8199        block_ids: HashSet<BlockId>,
8200        autoscroll: Option<Autoscroll>,
8201        cx: &mut ViewContext<Self>,
8202    ) {
8203        self.display_map.update(cx, |display_map, cx| {
8204            display_map.remove_blocks(block_ids, cx)
8205        });
8206        if let Some(autoscroll) = autoscroll {
8207            self.request_autoscroll(autoscroll, cx);
8208        }
8209    }
8210
8211    pub fn longest_row(&self, cx: &mut AppContext) -> u32 {
8212        self.display_map
8213            .update(cx, |map, cx| map.snapshot(cx))
8214            .longest_row()
8215    }
8216
8217    pub fn max_point(&self, cx: &mut AppContext) -> DisplayPoint {
8218        self.display_map
8219            .update(cx, |map, cx| map.snapshot(cx))
8220            .max_point()
8221    }
8222
8223    pub fn text(&self, cx: &AppContext) -> String {
8224        self.buffer.read(cx).read(cx).text()
8225    }
8226
8227    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
8228        self.transact(cx, |this, cx| {
8229            this.buffer
8230                .read(cx)
8231                .as_singleton()
8232                .expect("you can only call set_text on editors for singleton buffers")
8233                .update(cx, |buffer, cx| buffer.set_text(text, cx));
8234        });
8235    }
8236
8237    pub fn display_text(&self, cx: &mut AppContext) -> String {
8238        self.display_map
8239            .update(cx, |map, cx| map.snapshot(cx))
8240            .text()
8241    }
8242
8243    pub fn wrap_guides(&self, cx: &AppContext) -> SmallVec<[(usize, bool); 2]> {
8244        let mut wrap_guides = smallvec::smallvec![];
8245
8246        if self.show_wrap_guides == Some(false) {
8247            return wrap_guides;
8248        }
8249
8250        let settings = self.buffer.read(cx).settings_at(0, cx);
8251        if settings.show_wrap_guides {
8252            if let SoftWrap::Column(soft_wrap) = self.soft_wrap_mode(cx) {
8253                wrap_guides.push((soft_wrap as usize, true));
8254            }
8255            wrap_guides.extend(settings.wrap_guides.iter().map(|guide| (*guide, false)))
8256        }
8257
8258        wrap_guides
8259    }
8260
8261    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
8262        let settings = self.buffer.read(cx).settings_at(0, cx);
8263        let mode = self
8264            .soft_wrap_mode_override
8265            .unwrap_or_else(|| settings.soft_wrap);
8266        match mode {
8267            language_settings::SoftWrap::None => SoftWrap::None,
8268            language_settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
8269            language_settings::SoftWrap::PreferredLineLength => {
8270                SoftWrap::Column(settings.preferred_line_length)
8271            }
8272        }
8273    }
8274
8275    pub fn set_soft_wrap_mode(
8276        &mut self,
8277        mode: language_settings::SoftWrap,
8278        cx: &mut ViewContext<Self>,
8279    ) {
8280        self.soft_wrap_mode_override = Some(mode);
8281        cx.notify();
8282    }
8283
8284    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut AppContext) -> bool {
8285        self.display_map
8286            .update(cx, |map, cx| map.set_wrap_width(width, cx))
8287    }
8288
8289    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
8290        if self.soft_wrap_mode_override.is_some() {
8291            self.soft_wrap_mode_override.take();
8292        } else {
8293            let soft_wrap = match self.soft_wrap_mode(cx) {
8294                SoftWrap::None => language_settings::SoftWrap::EditorWidth,
8295                SoftWrap::EditorWidth | SoftWrap::Column(_) => language_settings::SoftWrap::None,
8296            };
8297            self.soft_wrap_mode_override = Some(soft_wrap);
8298        }
8299        cx.notify();
8300    }
8301
8302    pub fn set_show_gutter(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
8303        self.show_gutter = show_gutter;
8304        cx.notify();
8305    }
8306
8307    pub fn set_show_wrap_guides(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
8308        self.show_wrap_guides = Some(show_gutter);
8309        cx.notify();
8310    }
8311
8312    pub fn reveal_in_finder(&mut self, _: &RevealInFinder, cx: &mut ViewContext<Self>) {
8313        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
8314            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
8315                cx.reveal_path(&file.abs_path(cx));
8316            }
8317        }
8318    }
8319
8320    pub fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
8321        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
8322            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
8323                if let Some(path) = file.abs_path(cx).to_str() {
8324                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
8325                }
8326            }
8327        }
8328    }
8329
8330    pub fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
8331        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
8332            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
8333                if let Some(path) = file.path().to_str() {
8334                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
8335                }
8336            }
8337        }
8338    }
8339
8340    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
8341        self.highlighted_rows = rows;
8342    }
8343
8344    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
8345        self.highlighted_rows.clone()
8346    }
8347
8348    pub fn highlight_background<T: 'static>(
8349        &mut self,
8350        ranges: Vec<Range<Anchor>>,
8351        color_fetcher: fn(&Theme) -> Color,
8352        cx: &mut ViewContext<Self>,
8353    ) {
8354        self.background_highlights
8355            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
8356        cx.notify();
8357    }
8358
8359    pub fn highlight_inlay_background<T: 'static>(
8360        &mut self,
8361        ranges: Vec<InlayHighlight>,
8362        color_fetcher: fn(&Theme) -> Color,
8363        cx: &mut ViewContext<Self>,
8364    ) {
8365        // TODO: no actual highlights happen for inlays currently, find a way to do that
8366        self.inlay_background_highlights
8367            .insert(Some(TypeId::of::<T>()), (color_fetcher, ranges));
8368        cx.notify();
8369    }
8370
8371    pub fn clear_background_highlights<T: 'static>(
8372        &mut self,
8373        cx: &mut ViewContext<Self>,
8374    ) -> Option<BackgroundHighlight> {
8375        let text_highlights = self.background_highlights.remove(&TypeId::of::<T>());
8376        let inlay_highlights = self
8377            .inlay_background_highlights
8378            .remove(&Some(TypeId::of::<T>()));
8379        if text_highlights.is_some() || inlay_highlights.is_some() {
8380            cx.notify();
8381        }
8382        text_highlights
8383    }
8384
8385    #[cfg(feature = "test-support")]
8386    pub fn all_text_background_highlights(
8387        &mut self,
8388        cx: &mut ViewContext<Self>,
8389    ) -> Vec<(Range<DisplayPoint>, Color)> {
8390        let snapshot = self.snapshot(cx);
8391        let buffer = &snapshot.buffer_snapshot;
8392        let start = buffer.anchor_before(0);
8393        let end = buffer.anchor_after(buffer.len());
8394        let theme = theme::current(cx);
8395        self.background_highlights_in_range(start..end, &snapshot, theme.as_ref())
8396    }
8397
8398    fn document_highlights_for_position<'a>(
8399        &'a self,
8400        position: Anchor,
8401        buffer: &'a MultiBufferSnapshot,
8402    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
8403        let read_highlights = self
8404            .background_highlights
8405            .get(&TypeId::of::<DocumentHighlightRead>())
8406            .map(|h| &h.1);
8407        let write_highlights = self
8408            .background_highlights
8409            .get(&TypeId::of::<DocumentHighlightWrite>())
8410            .map(|h| &h.1);
8411        let left_position = position.bias_left(buffer);
8412        let right_position = position.bias_right(buffer);
8413        read_highlights
8414            .into_iter()
8415            .chain(write_highlights)
8416            .flat_map(move |ranges| {
8417                let start_ix = match ranges.binary_search_by(|probe| {
8418                    let cmp = probe.end.cmp(&left_position, buffer);
8419                    if cmp.is_ge() {
8420                        Ordering::Greater
8421                    } else {
8422                        Ordering::Less
8423                    }
8424                }) {
8425                    Ok(i) | Err(i) => i,
8426                };
8427
8428                let right_position = right_position.clone();
8429                ranges[start_ix..]
8430                    .iter()
8431                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
8432            })
8433    }
8434
8435    pub fn background_highlights_in_range(
8436        &self,
8437        search_range: Range<Anchor>,
8438        display_snapshot: &DisplaySnapshot,
8439        theme: &Theme,
8440    ) -> Vec<(Range<DisplayPoint>, Color)> {
8441        let mut results = Vec::new();
8442        for (color_fetcher, ranges) in self.background_highlights.values() {
8443            let color = color_fetcher(theme);
8444            let start_ix = match ranges.binary_search_by(|probe| {
8445                let cmp = probe
8446                    .end
8447                    .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
8448                if cmp.is_gt() {
8449                    Ordering::Greater
8450                } else {
8451                    Ordering::Less
8452                }
8453            }) {
8454                Ok(i) | Err(i) => i,
8455            };
8456            for range in &ranges[start_ix..] {
8457                if range
8458                    .start
8459                    .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
8460                    .is_ge()
8461                {
8462                    break;
8463                }
8464
8465                let start = range.start.to_display_point(&display_snapshot);
8466                let end = range.end.to_display_point(&display_snapshot);
8467                results.push((start..end, color))
8468            }
8469        }
8470        results
8471    }
8472
8473    pub fn background_highlight_row_ranges<T: 'static>(
8474        &self,
8475        search_range: Range<Anchor>,
8476        display_snapshot: &DisplaySnapshot,
8477        count: usize,
8478    ) -> Vec<RangeInclusive<DisplayPoint>> {
8479        let mut results = Vec::new();
8480        let Some((_, ranges)) = self.background_highlights.get(&TypeId::of::<T>()) else {
8481            return vec![];
8482        };
8483
8484        let start_ix = match ranges.binary_search_by(|probe| {
8485            let cmp = probe
8486                .end
8487                .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
8488            if cmp.is_gt() {
8489                Ordering::Greater
8490            } else {
8491                Ordering::Less
8492            }
8493        }) {
8494            Ok(i) | Err(i) => i,
8495        };
8496        let mut push_region = |start: Option<Point>, end: Option<Point>| {
8497            if let (Some(start_display), Some(end_display)) = (start, end) {
8498                results.push(
8499                    start_display.to_display_point(display_snapshot)
8500                        ..=end_display.to_display_point(display_snapshot),
8501                );
8502            }
8503        };
8504        let mut start_row: Option<Point> = None;
8505        let mut end_row: Option<Point> = None;
8506        if ranges.len() > count {
8507            return Vec::new();
8508        }
8509        for range in &ranges[start_ix..] {
8510            if range
8511                .start
8512                .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
8513                .is_ge()
8514            {
8515                break;
8516            }
8517            let end = range.end.to_point(&display_snapshot.buffer_snapshot);
8518            if let Some(current_row) = &end_row {
8519                if end.row == current_row.row {
8520                    continue;
8521                }
8522            }
8523            let start = range.start.to_point(&display_snapshot.buffer_snapshot);
8524            if start_row.is_none() {
8525                assert_eq!(end_row, None);
8526                start_row = Some(start);
8527                end_row = Some(end);
8528                continue;
8529            }
8530            if let Some(current_end) = end_row.as_mut() {
8531                if start.row > current_end.row + 1 {
8532                    push_region(start_row, end_row);
8533                    start_row = Some(start);
8534                    end_row = Some(end);
8535                } else {
8536                    // Merge two hunks.
8537                    *current_end = end;
8538                }
8539            } else {
8540                unreachable!();
8541            }
8542        }
8543        // We might still have a hunk that was not rendered (if there was a search hit on the last line)
8544        push_region(start_row, end_row);
8545        results
8546    }
8547
8548    pub fn highlight_text<T: 'static>(
8549        &mut self,
8550        ranges: Vec<Range<Anchor>>,
8551        style: HighlightStyle,
8552        cx: &mut ViewContext<Self>,
8553    ) {
8554        self.display_map.update(cx, |map, _| {
8555            map.highlight_text(TypeId::of::<T>(), ranges, style)
8556        });
8557        cx.notify();
8558    }
8559
8560    pub fn highlight_inlays<T: 'static>(
8561        &mut self,
8562        highlights: Vec<InlayHighlight>,
8563        style: HighlightStyle,
8564        cx: &mut ViewContext<Self>,
8565    ) {
8566        self.display_map.update(cx, |map, _| {
8567            map.highlight_inlays(TypeId::of::<T>(), highlights, style)
8568        });
8569        cx.notify();
8570    }
8571
8572    pub fn text_highlights<'a, T: 'static>(
8573        &'a self,
8574        cx: &'a AppContext,
8575    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
8576        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
8577    }
8578
8579    pub fn clear_highlights<T: 'static>(&mut self, cx: &mut ViewContext<Self>) {
8580        let cleared = self
8581            .display_map
8582            .update(cx, |map, _| map.clear_highlights(TypeId::of::<T>()));
8583        if cleared {
8584            cx.notify();
8585        }
8586    }
8587
8588    pub fn show_local_cursors(&self, cx: &AppContext) -> bool {
8589        self.blink_manager.read(cx).visible() && self.focused
8590    }
8591
8592    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
8593        cx.notify();
8594    }
8595
8596    fn on_buffer_event(
8597        &mut self,
8598        multibuffer: ModelHandle<MultiBuffer>,
8599        event: &multi_buffer::Event,
8600        cx: &mut ViewContext<Self>,
8601    ) {
8602        match event {
8603            multi_buffer::Event::Edited {
8604                sigleton_buffer_edited,
8605            } => {
8606                self.refresh_active_diagnostics(cx);
8607                self.refresh_code_actions(cx);
8608                if self.has_active_copilot_suggestion(cx) {
8609                    self.update_visible_copilot_suggestion(cx);
8610                }
8611                cx.emit(Event::BufferEdited);
8612
8613                if *sigleton_buffer_edited {
8614                    if let Some(project) = &self.project {
8615                        let project = project.read(cx);
8616                        let languages_affected = multibuffer
8617                            .read(cx)
8618                            .all_buffers()
8619                            .into_iter()
8620                            .filter_map(|buffer| {
8621                                let buffer = buffer.read(cx);
8622                                let language = buffer.language()?;
8623                                if project.is_local()
8624                                    && project.language_servers_for_buffer(buffer, cx).count() == 0
8625                                {
8626                                    None
8627                                } else {
8628                                    Some(language)
8629                                }
8630                            })
8631                            .cloned()
8632                            .collect::<HashSet<_>>();
8633                        if !languages_affected.is_empty() {
8634                            self.refresh_inlay_hints(
8635                                InlayHintRefreshReason::BufferEdited(languages_affected),
8636                                cx,
8637                            );
8638                        }
8639                    }
8640                }
8641            }
8642            multi_buffer::Event::ExcerptsAdded {
8643                buffer,
8644                predecessor,
8645                excerpts,
8646            } => {
8647                cx.emit(Event::ExcerptsAdded {
8648                    buffer: buffer.clone(),
8649                    predecessor: *predecessor,
8650                    excerpts: excerpts.clone(),
8651                });
8652                self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
8653            }
8654            multi_buffer::Event::ExcerptsRemoved { ids } => {
8655                self.refresh_inlay_hints(InlayHintRefreshReason::ExcerptsRemoved(ids.clone()), cx);
8656                cx.emit(Event::ExcerptsRemoved { ids: ids.clone() })
8657            }
8658            multi_buffer::Event::Reparsed => cx.emit(Event::Reparsed),
8659            multi_buffer::Event::DirtyChanged => cx.emit(Event::DirtyChanged),
8660            multi_buffer::Event::Saved => cx.emit(Event::Saved),
8661            multi_buffer::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
8662            multi_buffer::Event::Reloaded => cx.emit(Event::TitleChanged),
8663            multi_buffer::Event::DiffBaseChanged => cx.emit(Event::DiffBaseChanged),
8664            multi_buffer::Event::Closed => cx.emit(Event::Closed),
8665            multi_buffer::Event::DiagnosticsUpdated => {
8666                self.refresh_active_diagnostics(cx);
8667            }
8668            _ => {}
8669        };
8670    }
8671
8672    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
8673        cx.notify();
8674    }
8675
8676    fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
8677        self.refresh_copilot_suggestions(true, cx);
8678        self.refresh_inlay_hints(
8679            InlayHintRefreshReason::SettingsChange(inlay_hint_settings(
8680                self.selections.newest_anchor().head(),
8681                &self.buffer.read(cx).snapshot(cx),
8682                cx,
8683            )),
8684            cx,
8685        );
8686    }
8687
8688    pub fn set_searchable(&mut self, searchable: bool) {
8689        self.searchable = searchable;
8690    }
8691
8692    pub fn searchable(&self) -> bool {
8693        self.searchable
8694    }
8695
8696    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
8697        let active_item = workspace.active_item(cx);
8698        let editor_handle = if let Some(editor) = active_item
8699            .as_ref()
8700            .and_then(|item| item.act_as::<Self>(cx))
8701        {
8702            editor
8703        } else {
8704            cx.propagate_action();
8705            return;
8706        };
8707
8708        let editor = editor_handle.read(cx);
8709        let buffer = editor.buffer.read(cx);
8710        if buffer.is_singleton() {
8711            cx.propagate_action();
8712            return;
8713        }
8714
8715        let mut new_selections_by_buffer = HashMap::default();
8716        for selection in editor.selections.all::<usize>(cx) {
8717            for (buffer, mut range, _) in
8718                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
8719            {
8720                if selection.reversed {
8721                    mem::swap(&mut range.start, &mut range.end);
8722                }
8723                new_selections_by_buffer
8724                    .entry(buffer)
8725                    .or_insert(Vec::new())
8726                    .push(range)
8727            }
8728        }
8729
8730        editor_handle.update(cx, |editor, cx| {
8731            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
8732        });
8733        let pane = workspace.active_pane().clone();
8734        pane.update(cx, |pane, _| pane.disable_history());
8735
8736        // We defer the pane interaction because we ourselves are a workspace item
8737        // and activating a new item causes the pane to call a method on us reentrantly,
8738        // which panics if we're on the stack.
8739        cx.defer(move |workspace, cx| {
8740            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
8741                let editor = workspace.open_project_item::<Self>(buffer, cx);
8742                editor.update(cx, |editor, cx| {
8743                    editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
8744                        s.select_ranges(ranges);
8745                    });
8746                });
8747            }
8748
8749            pane.update(cx, |pane, _| pane.enable_history());
8750        });
8751    }
8752
8753    fn jump(
8754        workspace: &mut Workspace,
8755        path: ProjectPath,
8756        position: Point,
8757        anchor: language::Anchor,
8758        cx: &mut ViewContext<Workspace>,
8759    ) {
8760        let editor = workspace.open_path(path, None, true, cx);
8761        cx.spawn(|_, mut cx| async move {
8762            let editor = editor
8763                .await?
8764                .downcast::<Editor>()
8765                .ok_or_else(|| anyhow!("opened item was not an editor"))?
8766                .downgrade();
8767            editor.update(&mut cx, |editor, cx| {
8768                let buffer = editor
8769                    .buffer()
8770                    .read(cx)
8771                    .as_singleton()
8772                    .ok_or_else(|| anyhow!("cannot jump in a multi-buffer"))?;
8773                let buffer = buffer.read(cx);
8774                let cursor = if buffer.can_resolve(&anchor) {
8775                    language::ToPoint::to_point(&anchor, buffer)
8776                } else {
8777                    buffer.clip_point(position, Bias::Left)
8778                };
8779
8780                let nav_history = editor.nav_history.take();
8781                editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
8782                    s.select_ranges([cursor..cursor]);
8783                });
8784                editor.nav_history = nav_history;
8785
8786                anyhow::Ok(())
8787            })??;
8788
8789            anyhow::Ok(())
8790        })
8791        .detach_and_log_err(cx);
8792    }
8793
8794    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
8795        let snapshot = self.buffer.read(cx).read(cx);
8796        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
8797        Some(
8798            ranges
8799                .iter()
8800                .map(move |range| {
8801                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
8802                })
8803                .collect(),
8804        )
8805    }
8806
8807    fn selection_replacement_ranges(
8808        &self,
8809        range: Range<OffsetUtf16>,
8810        cx: &AppContext,
8811    ) -> Vec<Range<OffsetUtf16>> {
8812        let selections = self.selections.all::<OffsetUtf16>(cx);
8813        let newest_selection = selections
8814            .iter()
8815            .max_by_key(|selection| selection.id)
8816            .unwrap();
8817        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
8818        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
8819        let snapshot = self.buffer.read(cx).read(cx);
8820        selections
8821            .into_iter()
8822            .map(|mut selection| {
8823                selection.start.0 =
8824                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
8825                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
8826                snapshot.clip_offset_utf16(selection.start, Bias::Left)
8827                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
8828            })
8829            .collect()
8830    }
8831
8832    fn report_copilot_event(
8833        &self,
8834        suggestion_id: Option<String>,
8835        suggestion_accepted: bool,
8836        cx: &AppContext,
8837    ) {
8838        let Some(project) = &self.project else { return };
8839
8840        // If None, we are either getting suggestions in a new, unsaved file, or in a file without an extension
8841        let file_extension = self
8842            .buffer
8843            .read(cx)
8844            .as_singleton()
8845            .and_then(|b| b.read(cx).file())
8846            .and_then(|file| Path::new(file.file_name(cx)).extension())
8847            .and_then(|e| e.to_str())
8848            .map(|a| a.to_string());
8849
8850        let telemetry = project.read(cx).client().telemetry().clone();
8851        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
8852
8853        let event = ClickhouseEvent::Copilot {
8854            suggestion_id,
8855            suggestion_accepted,
8856            file_extension,
8857        };
8858        telemetry.report_clickhouse_event(event, telemetry_settings);
8859    }
8860
8861    fn report_editor_event(
8862        &self,
8863        operation: &'static str,
8864        file_extension: Option<String>,
8865        cx: &AppContext,
8866    ) {
8867        let Some(project) = &self.project else { return };
8868
8869        // If None, we are in a file without an extension
8870        let file = self
8871            .buffer
8872            .read(cx)
8873            .as_singleton()
8874            .and_then(|b| b.read(cx).file());
8875        let file_extension = file_extension.or(file
8876            .as_ref()
8877            .and_then(|file| Path::new(file.file_name(cx)).extension())
8878            .and_then(|e| e.to_str())
8879            .map(|a| a.to_string()));
8880
8881        let vim_mode = cx
8882            .global::<SettingsStore>()
8883            .raw_user_settings()
8884            .get("vim_mode")
8885            == Some(&serde_json::Value::Bool(true));
8886        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
8887        let copilot_enabled = all_language_settings(file, cx).copilot_enabled(None, None);
8888        let copilot_enabled_for_language = self
8889            .buffer
8890            .read(cx)
8891            .settings_at(0, cx)
8892            .show_copilot_suggestions;
8893
8894        let telemetry = project.read(cx).client().telemetry().clone();
8895        let event = ClickhouseEvent::Editor {
8896            file_extension,
8897            vim_mode,
8898            operation,
8899            copilot_enabled,
8900            copilot_enabled_for_language,
8901        };
8902        telemetry.report_clickhouse_event(event, telemetry_settings)
8903    }
8904
8905    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
8906    /// with each line being an array of {text, highlight} objects.
8907    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
8908        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
8909            return;
8910        };
8911
8912        #[derive(Serialize)]
8913        struct Chunk<'a> {
8914            text: String,
8915            highlight: Option<&'a str>,
8916        }
8917
8918        let snapshot = buffer.read(cx).snapshot();
8919        let range = self
8920            .selected_text_range(cx)
8921            .and_then(|selected_range| {
8922                if selected_range.is_empty() {
8923                    None
8924                } else {
8925                    Some(selected_range)
8926                }
8927            })
8928            .unwrap_or_else(|| 0..snapshot.len());
8929
8930        let chunks = snapshot.chunks(range, true);
8931        let mut lines = Vec::new();
8932        let mut line: VecDeque<Chunk> = VecDeque::new();
8933
8934        let theme = &theme::current(cx).editor.syntax;
8935
8936        for chunk in chunks {
8937            let highlight = chunk.syntax_highlight_id.and_then(|id| id.name(theme));
8938            let mut chunk_lines = chunk.text.split("\n").peekable();
8939            while let Some(text) = chunk_lines.next() {
8940                let mut merged_with_last_token = false;
8941                if let Some(last_token) = line.back_mut() {
8942                    if last_token.highlight == highlight {
8943                        last_token.text.push_str(text);
8944                        merged_with_last_token = true;
8945                    }
8946                }
8947
8948                if !merged_with_last_token {
8949                    line.push_back(Chunk {
8950                        text: text.into(),
8951                        highlight,
8952                    });
8953                }
8954
8955                if chunk_lines.peek().is_some() {
8956                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
8957                        line.pop_front();
8958                    }
8959                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
8960                        line.pop_back();
8961                    }
8962
8963                    lines.push(mem::take(&mut line));
8964                }
8965            }
8966        }
8967
8968        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else {
8969            return;
8970        };
8971        cx.write_to_clipboard(ClipboardItem::new(lines));
8972    }
8973
8974    pub fn inlay_hint_cache(&self) -> &InlayHintCache {
8975        &self.inlay_hint_cache
8976    }
8977
8978    pub fn replay_insert_event(
8979        &mut self,
8980        text: &str,
8981        relative_utf16_range: Option<Range<isize>>,
8982        cx: &mut ViewContext<Self>,
8983    ) {
8984        if !self.input_enabled {
8985            cx.emit(Event::InputIgnored { text: text.into() });
8986            return;
8987        }
8988        if let Some(relative_utf16_range) = relative_utf16_range {
8989            let selections = self.selections.all::<OffsetUtf16>(cx);
8990            self.change_selections(None, cx, |s| {
8991                let new_ranges = selections.into_iter().map(|range| {
8992                    let start = OffsetUtf16(
8993                        range
8994                            .head()
8995                            .0
8996                            .saturating_add_signed(relative_utf16_range.start),
8997                    );
8998                    let end = OffsetUtf16(
8999                        range
9000                            .head()
9001                            .0
9002                            .saturating_add_signed(relative_utf16_range.end),
9003                    );
9004                    start..end
9005                });
9006                s.select_ranges(new_ranges);
9007            });
9008        }
9009
9010        self.handle_input(text, cx);
9011    }
9012
9013    pub fn supports_inlay_hints(&self, cx: &AppContext) -> bool {
9014        let Some(project) = self.project.as_ref() else {
9015            return false;
9016        };
9017        let project = project.read(cx);
9018
9019        let mut supports = false;
9020        self.buffer().read(cx).for_each_buffer(|buffer| {
9021            if !supports {
9022                supports = project
9023                    .language_servers_for_buffer(buffer.read(cx), cx)
9024                    .any(
9025                        |(_, server)| match server.capabilities().inlay_hint_provider {
9026                            Some(lsp::OneOf::Left(enabled)) => enabled,
9027                            Some(lsp::OneOf::Right(_)) => true,
9028                            None => false,
9029                        },
9030                    )
9031            }
9032        });
9033        supports
9034    }
9035}
9036
9037pub trait CollaborationHub {
9038    fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator>;
9039    fn user_participant_indices<'a>(
9040        &self,
9041        cx: &'a AppContext,
9042    ) -> &'a HashMap<u64, ParticipantIndex>;
9043}
9044
9045impl CollaborationHub for ModelHandle<Project> {
9046    fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator> {
9047        self.read(cx).collaborators()
9048    }
9049
9050    fn user_participant_indices<'a>(
9051        &self,
9052        cx: &'a AppContext,
9053    ) -> &'a HashMap<u64, ParticipantIndex> {
9054        self.read(cx).user_store().read(cx).participant_indices()
9055    }
9056}
9057
9058fn inlay_hint_settings(
9059    location: Anchor,
9060    snapshot: &MultiBufferSnapshot,
9061    cx: &mut ViewContext<'_, '_, Editor>,
9062) -> InlayHintSettings {
9063    let file = snapshot.file_at(location);
9064    let language = snapshot.language_at(location);
9065    let settings = all_language_settings(file, cx);
9066    settings
9067        .language(language.map(|l| l.name()).as_deref())
9068        .inlay_hints
9069}
9070
9071fn consume_contiguous_rows(
9072    contiguous_row_selections: &mut Vec<Selection<Point>>,
9073    selection: &Selection<Point>,
9074    display_map: &DisplaySnapshot,
9075    selections: &mut std::iter::Peekable<std::slice::Iter<Selection<Point>>>,
9076) -> (u32, u32) {
9077    contiguous_row_selections.push(selection.clone());
9078    let start_row = selection.start.row;
9079    let mut end_row = ending_row(selection, display_map);
9080
9081    while let Some(next_selection) = selections.peek() {
9082        if next_selection.start.row <= end_row {
9083            end_row = ending_row(next_selection, display_map);
9084            contiguous_row_selections.push(selections.next().unwrap().clone());
9085        } else {
9086            break;
9087        }
9088    }
9089    (start_row, end_row)
9090}
9091
9092fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> u32 {
9093    if next_selection.end.column > 0 || next_selection.is_empty() {
9094        display_map.next_line_boundary(next_selection.end).0.row + 1
9095    } else {
9096        next_selection.end.row
9097    }
9098}
9099
9100impl EditorSnapshot {
9101    pub fn remote_selections_in_range<'a>(
9102        &'a self,
9103        range: &'a Range<Anchor>,
9104        collaboration_hub: &dyn CollaborationHub,
9105        cx: &'a AppContext,
9106    ) -> impl 'a + Iterator<Item = RemoteSelection> {
9107        let participant_indices = collaboration_hub.user_participant_indices(cx);
9108        let collaborators_by_peer_id = collaboration_hub.collaborators(cx);
9109        let collaborators_by_replica_id = collaborators_by_peer_id
9110            .iter()
9111            .map(|(_, collaborator)| (collaborator.replica_id, collaborator))
9112            .collect::<HashMap<_, _>>();
9113        self.buffer_snapshot
9114            .remote_selections_in_range(range)
9115            .filter_map(move |(replica_id, line_mode, cursor_shape, selection)| {
9116                let collaborator = collaborators_by_replica_id.get(&replica_id)?;
9117                let participant_index = participant_indices.get(&collaborator.user_id).copied();
9118                Some(RemoteSelection {
9119                    replica_id,
9120                    selection,
9121                    cursor_shape,
9122                    line_mode,
9123                    participant_index,
9124                    peer_id: collaborator.peer_id,
9125                })
9126            })
9127    }
9128
9129    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
9130        self.display_snapshot.buffer_snapshot.language_at(position)
9131    }
9132
9133    pub fn is_focused(&self) -> bool {
9134        self.is_focused
9135    }
9136
9137    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
9138        self.placeholder_text.as_ref()
9139    }
9140
9141    pub fn scroll_position(&self) -> Vector2F {
9142        self.scroll_anchor.scroll_position(&self.display_snapshot)
9143    }
9144}
9145
9146impl Deref for EditorSnapshot {
9147    type Target = DisplaySnapshot;
9148
9149    fn deref(&self) -> &Self::Target {
9150        &self.display_snapshot
9151    }
9152}
9153
9154#[derive(Clone, Debug, PartialEq, Eq)]
9155pub enum Event {
9156    InputIgnored {
9157        text: Arc<str>,
9158    },
9159    InputHandled {
9160        utf16_range_to_replace: Option<Range<isize>>,
9161        text: Arc<str>,
9162    },
9163    ExcerptsAdded {
9164        buffer: ModelHandle<Buffer>,
9165        predecessor: ExcerptId,
9166        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
9167    },
9168    ExcerptsRemoved {
9169        ids: Vec<ExcerptId>,
9170    },
9171    BufferEdited,
9172    Edited,
9173    Reparsed,
9174    Focused,
9175    Blurred,
9176    DirtyChanged,
9177    Saved,
9178    TitleChanged,
9179    DiffBaseChanged,
9180    SelectionsChanged {
9181        local: bool,
9182    },
9183    ScrollPositionChanged {
9184        local: bool,
9185        autoscroll: bool,
9186    },
9187    Closed,
9188}
9189
9190pub struct EditorFocused(pub ViewHandle<Editor>);
9191pub struct EditorBlurred(pub ViewHandle<Editor>);
9192pub struct EditorReleased(pub WeakViewHandle<Editor>);
9193
9194impl Entity for Editor {
9195    type Event = Event;
9196
9197    fn release(&mut self, cx: &mut AppContext) {
9198        cx.emit_global(EditorReleased(self.handle.clone()));
9199    }
9200}
9201
9202impl View for Editor {
9203    fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
9204        let style = self.style(cx);
9205        let font_changed = self.display_map.update(cx, |map, cx| {
9206            map.set_fold_ellipses_color(style.folds.ellipses.text_color);
9207            map.set_font(style.text.font_id, style.text.font_size, cx)
9208        });
9209
9210        if font_changed {
9211            cx.defer(move |editor, cx: &mut ViewContext<Editor>| {
9212                hide_hover(editor, cx);
9213                hide_link_definition(editor, cx);
9214            });
9215        }
9216
9217        Stack::new()
9218            .with_child(EditorElement::new(style.clone()))
9219            .with_child(ChildView::new(&self.mouse_context_menu, cx))
9220            .into_any()
9221    }
9222
9223    fn ui_name() -> &'static str {
9224        "Editor"
9225    }
9226
9227    fn focus_in(&mut self, focused: AnyViewHandle, cx: &mut ViewContext<Self>) {
9228        if cx.is_self_focused() {
9229            let focused_event = EditorFocused(cx.handle());
9230            cx.emit(Event::Focused);
9231            cx.emit_global(focused_event);
9232        }
9233        if let Some(rename) = self.pending_rename.as_ref() {
9234            cx.focus(&rename.editor);
9235        } else if cx.is_self_focused() || !focused.is::<Editor>() {
9236            if !self.focused {
9237                self.blink_manager.update(cx, BlinkManager::enable);
9238            }
9239            self.focused = true;
9240            self.buffer.update(cx, |buffer, cx| {
9241                buffer.finalize_last_transaction(cx);
9242                if self.leader_peer_id.is_none() {
9243                    buffer.set_active_selections(
9244                        &self.selections.disjoint_anchors(),
9245                        self.selections.line_mode,
9246                        self.cursor_shape,
9247                        cx,
9248                    );
9249                }
9250            });
9251        }
9252    }
9253
9254    fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
9255        let blurred_event = EditorBlurred(cx.handle());
9256        cx.emit_global(blurred_event);
9257        self.focused = false;
9258        self.blink_manager.update(cx, BlinkManager::disable);
9259        self.buffer
9260            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
9261        self.hide_context_menu(cx);
9262        hide_hover(self, cx);
9263        cx.emit(Event::Blurred);
9264        cx.notify();
9265    }
9266
9267    fn modifiers_changed(
9268        &mut self,
9269        event: &gpui::platform::ModifiersChangedEvent,
9270        cx: &mut ViewContext<Self>,
9271    ) -> bool {
9272        let pending_selection = self.has_pending_selection();
9273
9274        if let Some(point) = &self.link_go_to_definition_state.last_trigger_point {
9275            if event.cmd && !pending_selection {
9276                let point = point.clone();
9277                let snapshot = self.snapshot(cx);
9278                let kind = point.definition_kind(event.shift);
9279
9280                show_link_definition(kind, self, point, snapshot, cx);
9281                return false;
9282            }
9283        }
9284
9285        {
9286            if self.link_go_to_definition_state.symbol_range.is_some()
9287                || !self.link_go_to_definition_state.definitions.is_empty()
9288            {
9289                self.link_go_to_definition_state.symbol_range.take();
9290                self.link_go_to_definition_state.definitions.clear();
9291                cx.notify();
9292            }
9293
9294            self.link_go_to_definition_state.task = None;
9295
9296            self.clear_highlights::<LinkGoToDefinitionState>(cx);
9297        }
9298
9299        false
9300    }
9301
9302    fn update_keymap_context(&self, keymap: &mut KeymapContext, cx: &AppContext) {
9303        Self::reset_to_default_keymap_context(keymap);
9304        let mode = match self.mode {
9305            EditorMode::SingleLine => "single_line",
9306            EditorMode::AutoHeight { .. } => "auto_height",
9307            EditorMode::Full => "full",
9308        };
9309        keymap.add_key("mode", mode);
9310        if self.pending_rename.is_some() {
9311            keymap.add_identifier("renaming");
9312        }
9313        if self.context_menu_visible() {
9314            match self.context_menu.read().as_ref() {
9315                Some(ContextMenu::Completions(_)) => {
9316                    keymap.add_identifier("menu");
9317                    keymap.add_identifier("showing_completions")
9318                }
9319                Some(ContextMenu::CodeActions(_)) => {
9320                    keymap.add_identifier("menu");
9321                    keymap.add_identifier("showing_code_actions")
9322                }
9323                None => {}
9324            }
9325        }
9326
9327        for layer in self.keymap_context_layers.values() {
9328            keymap.extend(layer);
9329        }
9330
9331        if let Some(extension) = self
9332            .buffer
9333            .read(cx)
9334            .as_singleton()
9335            .and_then(|buffer| buffer.read(cx).file()?.path().extension()?.to_str())
9336        {
9337            keymap.add_key("extension", extension.to_string());
9338        }
9339    }
9340
9341    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
9342        Some(
9343            self.buffer
9344                .read(cx)
9345                .read(cx)
9346                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
9347                .collect(),
9348        )
9349    }
9350
9351    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
9352        // Prevent the IME menu from appearing when holding down an alphabetic key
9353        // while input is disabled.
9354        if !self.input_enabled {
9355            return None;
9356        }
9357
9358        let range = self.selections.newest::<OffsetUtf16>(cx).range();
9359        Some(range.start.0..range.end.0)
9360    }
9361
9362    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
9363        let snapshot = self.buffer.read(cx).read(cx);
9364        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
9365        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
9366    }
9367
9368    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
9369        self.clear_highlights::<InputComposition>(cx);
9370        self.ime_transaction.take();
9371    }
9372
9373    fn replace_text_in_range(
9374        &mut self,
9375        range_utf16: Option<Range<usize>>,
9376        text: &str,
9377        cx: &mut ViewContext<Self>,
9378    ) {
9379        if !self.input_enabled {
9380            cx.emit(Event::InputIgnored { text: text.into() });
9381            return;
9382        }
9383
9384        self.transact(cx, |this, cx| {
9385            let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
9386                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
9387                Some(this.selection_replacement_ranges(range_utf16, cx))
9388            } else {
9389                this.marked_text_ranges(cx)
9390            };
9391
9392            let range_to_replace = new_selected_ranges.as_ref().and_then(|ranges_to_replace| {
9393                let newest_selection_id = this.selections.newest_anchor().id;
9394                this.selections
9395                    .all::<OffsetUtf16>(cx)
9396                    .iter()
9397                    .zip(ranges_to_replace.iter())
9398                    .find_map(|(selection, range)| {
9399                        if selection.id == newest_selection_id {
9400                            Some(
9401                                (range.start.0 as isize - selection.head().0 as isize)
9402                                    ..(range.end.0 as isize - selection.head().0 as isize),
9403                            )
9404                        } else {
9405                            None
9406                        }
9407                    })
9408            });
9409
9410            cx.emit(Event::InputHandled {
9411                utf16_range_to_replace: range_to_replace,
9412                text: text.into(),
9413            });
9414
9415            if let Some(new_selected_ranges) = new_selected_ranges {
9416                this.change_selections(None, cx, |selections| {
9417                    selections.select_ranges(new_selected_ranges)
9418                });
9419            }
9420
9421            this.handle_input(text, cx);
9422        });
9423
9424        if let Some(transaction) = self.ime_transaction {
9425            self.buffer.update(cx, |buffer, cx| {
9426                buffer.group_until_transaction(transaction, cx);
9427            });
9428        }
9429
9430        self.unmark_text(cx);
9431    }
9432
9433    fn replace_and_mark_text_in_range(
9434        &mut self,
9435        range_utf16: Option<Range<usize>>,
9436        text: &str,
9437        new_selected_range_utf16: Option<Range<usize>>,
9438        cx: &mut ViewContext<Self>,
9439    ) {
9440        if !self.input_enabled {
9441            cx.emit(Event::InputIgnored { text: text.into() });
9442            return;
9443        }
9444
9445        let transaction = self.transact(cx, |this, cx| {
9446            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
9447                let snapshot = this.buffer.read(cx).read(cx);
9448                if let Some(relative_range_utf16) = range_utf16.as_ref() {
9449                    for marked_range in &mut marked_ranges {
9450                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
9451                        marked_range.start.0 += relative_range_utf16.start;
9452                        marked_range.start =
9453                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
9454                        marked_range.end =
9455                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
9456                    }
9457                }
9458                Some(marked_ranges)
9459            } else if let Some(range_utf16) = range_utf16 {
9460                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
9461                Some(this.selection_replacement_ranges(range_utf16, cx))
9462            } else {
9463                None
9464            };
9465
9466            let range_to_replace = ranges_to_replace.as_ref().and_then(|ranges_to_replace| {
9467                let newest_selection_id = this.selections.newest_anchor().id;
9468                this.selections
9469                    .all::<OffsetUtf16>(cx)
9470                    .iter()
9471                    .zip(ranges_to_replace.iter())
9472                    .find_map(|(selection, range)| {
9473                        if selection.id == newest_selection_id {
9474                            Some(
9475                                (range.start.0 as isize - selection.head().0 as isize)
9476                                    ..(range.end.0 as isize - selection.head().0 as isize),
9477                            )
9478                        } else {
9479                            None
9480                        }
9481                    })
9482            });
9483
9484            cx.emit(Event::InputHandled {
9485                utf16_range_to_replace: range_to_replace,
9486                text: text.into(),
9487            });
9488
9489            if let Some(ranges) = ranges_to_replace {
9490                this.change_selections(None, cx, |s| s.select_ranges(ranges));
9491            }
9492
9493            let marked_ranges = {
9494                let snapshot = this.buffer.read(cx).read(cx);
9495                this.selections
9496                    .disjoint_anchors()
9497                    .iter()
9498                    .map(|selection| {
9499                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
9500                    })
9501                    .collect::<Vec<_>>()
9502            };
9503
9504            if text.is_empty() {
9505                this.unmark_text(cx);
9506            } else {
9507                this.highlight_text::<InputComposition>(
9508                    marked_ranges.clone(),
9509                    this.style(cx).composition_mark,
9510                    cx,
9511                );
9512            }
9513
9514            this.handle_input(text, cx);
9515
9516            if let Some(new_selected_range) = new_selected_range_utf16 {
9517                let snapshot = this.buffer.read(cx).read(cx);
9518                let new_selected_ranges = marked_ranges
9519                    .into_iter()
9520                    .map(|marked_range| {
9521                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
9522                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
9523                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
9524                        snapshot.clip_offset_utf16(new_start, Bias::Left)
9525                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
9526                    })
9527                    .collect::<Vec<_>>();
9528
9529                drop(snapshot);
9530                this.change_selections(None, cx, |selections| {
9531                    selections.select_ranges(new_selected_ranges)
9532                });
9533            }
9534        });
9535
9536        self.ime_transaction = self.ime_transaction.or(transaction);
9537        if let Some(transaction) = self.ime_transaction {
9538            self.buffer.update(cx, |buffer, cx| {
9539                buffer.group_until_transaction(transaction, cx);
9540            });
9541        }
9542
9543        if self.text_highlights::<InputComposition>(cx).is_none() {
9544            self.ime_transaction.take();
9545        }
9546    }
9547}
9548
9549fn build_style(
9550    settings: &ThemeSettings,
9551    get_field_editor_theme: Option<&GetFieldEditorTheme>,
9552    override_text_style: Option<&OverrideTextStyle>,
9553    cx: &AppContext,
9554) -> EditorStyle {
9555    let font_cache = cx.font_cache();
9556    let line_height_scalar = settings.line_height();
9557    let theme_id = settings.theme.meta.id;
9558    let mut theme = settings.theme.editor.clone();
9559    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
9560        let field_editor_theme = get_field_editor_theme(&settings.theme);
9561        theme.text_color = field_editor_theme.text.color;
9562        theme.selection = field_editor_theme.selection;
9563        theme.background = field_editor_theme
9564            .container
9565            .background_color
9566            .unwrap_or_default();
9567        EditorStyle {
9568            text: field_editor_theme.text,
9569            placeholder_text: field_editor_theme.placeholder_text,
9570            line_height_scalar,
9571            theme,
9572            theme_id,
9573        }
9574    } else {
9575        let font_family_id = settings.buffer_font_family;
9576        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
9577        let font_properties = Default::default();
9578        let font_id = font_cache
9579            .select_font(font_family_id, &font_properties)
9580            .unwrap();
9581        let font_size = settings.buffer_font_size(cx);
9582        EditorStyle {
9583            text: TextStyle {
9584                color: settings.theme.editor.text_color,
9585                font_family_name,
9586                font_family_id,
9587                font_id,
9588                font_size,
9589                font_properties,
9590                underline: Default::default(),
9591                soft_wrap: false,
9592            },
9593            placeholder_text: None,
9594            line_height_scalar,
9595            theme,
9596            theme_id,
9597        }
9598    };
9599
9600    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
9601        if let Some(highlighted) = style
9602            .text
9603            .clone()
9604            .highlight(highlight_style, font_cache)
9605            .log_err()
9606        {
9607            style.text = highlighted;
9608        }
9609    }
9610
9611    style
9612}
9613
9614trait SelectionExt {
9615    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
9616    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
9617    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
9618    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
9619        -> Range<u32>;
9620}
9621
9622impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
9623    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
9624        let start = self.start.to_point(buffer);
9625        let end = self.end.to_point(buffer);
9626        if self.reversed {
9627            end..start
9628        } else {
9629            start..end
9630        }
9631    }
9632
9633    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
9634        let start = self.start.to_offset(buffer);
9635        let end = self.end.to_offset(buffer);
9636        if self.reversed {
9637            end..start
9638        } else {
9639            start..end
9640        }
9641    }
9642
9643    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
9644        let start = self
9645            .start
9646            .to_point(&map.buffer_snapshot)
9647            .to_display_point(map);
9648        let end = self
9649            .end
9650            .to_point(&map.buffer_snapshot)
9651            .to_display_point(map);
9652        if self.reversed {
9653            end..start
9654        } else {
9655            start..end
9656        }
9657    }
9658
9659    fn spanned_rows(
9660        &self,
9661        include_end_if_at_line_start: bool,
9662        map: &DisplaySnapshot,
9663    ) -> Range<u32> {
9664        let start = self.start.to_point(&map.buffer_snapshot);
9665        let mut end = self.end.to_point(&map.buffer_snapshot);
9666        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
9667            end.row -= 1;
9668        }
9669
9670        let buffer_start = map.prev_line_boundary(start).0;
9671        let buffer_end = map.next_line_boundary(end).0;
9672        buffer_start.row..buffer_end.row + 1
9673    }
9674}
9675
9676impl<T: InvalidationRegion> InvalidationStack<T> {
9677    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
9678    where
9679        S: Clone + ToOffset,
9680    {
9681        while let Some(region) = self.last() {
9682            let all_selections_inside_invalidation_ranges =
9683                if selections.len() == region.ranges().len() {
9684                    selections
9685                        .iter()
9686                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
9687                        .all(|(selection, invalidation_range)| {
9688                            let head = selection.head().to_offset(buffer);
9689                            invalidation_range.start <= head && invalidation_range.end >= head
9690                        })
9691                } else {
9692                    false
9693                };
9694
9695            if all_selections_inside_invalidation_ranges {
9696                break;
9697            } else {
9698                self.pop();
9699            }
9700        }
9701    }
9702}
9703
9704impl<T> Default for InvalidationStack<T> {
9705    fn default() -> Self {
9706        Self(Default::default())
9707    }
9708}
9709
9710impl<T> Deref for InvalidationStack<T> {
9711    type Target = Vec<T>;
9712
9713    fn deref(&self) -> &Self::Target {
9714        &self.0
9715    }
9716}
9717
9718impl<T> DerefMut for InvalidationStack<T> {
9719    fn deref_mut(&mut self) -> &mut Self::Target {
9720        &mut self.0
9721    }
9722}
9723
9724impl InvalidationRegion for SnippetState {
9725    fn ranges(&self) -> &[Range<Anchor>] {
9726        &self.ranges[self.active_index]
9727    }
9728}
9729
9730impl Deref for EditorStyle {
9731    type Target = theme::Editor;
9732
9733    fn deref(&self) -> &Self::Target {
9734        &self.theme
9735    }
9736}
9737
9738pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
9739    let mut highlighted_lines = Vec::new();
9740
9741    for (index, line) in diagnostic.message.lines().enumerate() {
9742        let line = match &diagnostic.source {
9743            Some(source) if index == 0 => {
9744                let source_highlight = Vec::from_iter(0..source.len());
9745                highlight_diagnostic_message(source_highlight, &format!("{source}: {line}"))
9746            }
9747
9748            _ => highlight_diagnostic_message(Vec::new(), line),
9749        };
9750        highlighted_lines.push(line);
9751    }
9752    let message = diagnostic.message;
9753    Arc::new(move |cx: &mut BlockContext| {
9754        let message = message.clone();
9755        let settings = settings::get::<ThemeSettings>(cx);
9756        let tooltip_style = settings.theme.tooltip.clone();
9757        let theme = &settings.theme.editor;
9758        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
9759        let font_size = (style.text_scale_factor * settings.buffer_font_size(cx)).round();
9760        let anchor_x = cx.anchor_x;
9761        enum BlockContextToolip {}
9762        MouseEventHandler::new::<BlockContext, _>(cx.block_id, cx, |_, _| {
9763            Flex::column()
9764                .with_children(highlighted_lines.iter().map(|(line, highlights)| {
9765                    Label::new(
9766                        line.clone(),
9767                        style.message.clone().with_font_size(font_size),
9768                    )
9769                    .with_highlights(highlights.clone())
9770                    .contained()
9771                    .with_margin_left(anchor_x)
9772                }))
9773                .aligned()
9774                .left()
9775                .into_any()
9776        })
9777        .with_cursor_style(CursorStyle::PointingHand)
9778        .on_click(MouseButton::Left, move |_, _, cx| {
9779            cx.write_to_clipboard(ClipboardItem::new(message.clone()));
9780        })
9781        // We really need to rethink this ID system...
9782        .with_tooltip::<BlockContextToolip>(
9783            cx.block_id,
9784            "Copy diagnostic message",
9785            None,
9786            tooltip_style,
9787            cx,
9788        )
9789        .into_any()
9790    })
9791}
9792
9793pub fn highlight_diagnostic_message(
9794    initial_highlights: Vec<usize>,
9795    message: &str,
9796) -> (String, Vec<usize>) {
9797    let mut message_without_backticks = String::new();
9798    let mut prev_offset = 0;
9799    let mut inside_block = false;
9800    let mut highlights = initial_highlights;
9801    for (match_ix, (offset, _)) in message
9802        .match_indices('`')
9803        .chain([(message.len(), "")])
9804        .enumerate()
9805    {
9806        message_without_backticks.push_str(&message[prev_offset..offset]);
9807        if inside_block {
9808            highlights.extend(prev_offset - match_ix..offset - match_ix);
9809        }
9810
9811        inside_block = !inside_block;
9812        prev_offset = offset + 1;
9813    }
9814
9815    (message_without_backticks, highlights)
9816}
9817
9818pub fn diagnostic_style(
9819    severity: DiagnosticSeverity,
9820    valid: bool,
9821    theme: &theme::Editor,
9822) -> DiagnosticStyle {
9823    match (severity, valid) {
9824        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
9825        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
9826        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
9827        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
9828        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
9829        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
9830        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
9831        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
9832        _ => theme.invalid_hint_diagnostic.clone(),
9833    }
9834}
9835
9836pub fn combine_syntax_and_fuzzy_match_highlights(
9837    text: &str,
9838    default_style: HighlightStyle,
9839    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
9840    match_indices: &[usize],
9841) -> Vec<(Range<usize>, HighlightStyle)> {
9842    let mut result = Vec::new();
9843    let mut match_indices = match_indices.iter().copied().peekable();
9844
9845    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
9846    {
9847        syntax_highlight.weight = None;
9848
9849        // Add highlights for any fuzzy match characters before the next
9850        // syntax highlight range.
9851        while let Some(&match_index) = match_indices.peek() {
9852            if match_index >= range.start {
9853                break;
9854            }
9855            match_indices.next();
9856            let end_index = char_ix_after(match_index, text);
9857            let mut match_style = default_style;
9858            match_style.weight = Some(fonts::Weight::BOLD);
9859            result.push((match_index..end_index, match_style));
9860        }
9861
9862        if range.start == usize::MAX {
9863            break;
9864        }
9865
9866        // Add highlights for any fuzzy match characters within the
9867        // syntax highlight range.
9868        let mut offset = range.start;
9869        while let Some(&match_index) = match_indices.peek() {
9870            if match_index >= range.end {
9871                break;
9872            }
9873
9874            match_indices.next();
9875            if match_index > offset {
9876                result.push((offset..match_index, syntax_highlight));
9877            }
9878
9879            let mut end_index = char_ix_after(match_index, text);
9880            while let Some(&next_match_index) = match_indices.peek() {
9881                if next_match_index == end_index && next_match_index < range.end {
9882                    end_index = char_ix_after(next_match_index, text);
9883                    match_indices.next();
9884                } else {
9885                    break;
9886                }
9887            }
9888
9889            let mut match_style = syntax_highlight;
9890            match_style.weight = Some(fonts::Weight::BOLD);
9891            result.push((match_index..end_index, match_style));
9892            offset = end_index;
9893        }
9894
9895        if offset < range.end {
9896            result.push((offset..range.end, syntax_highlight));
9897        }
9898    }
9899
9900    fn char_ix_after(ix: usize, text: &str) -> usize {
9901        ix + text[ix..].chars().next().unwrap().len_utf8()
9902    }
9903
9904    result
9905}
9906
9907pub fn styled_runs_for_code_label<'a>(
9908    label: &'a CodeLabel,
9909    syntax_theme: &'a theme::SyntaxTheme,
9910) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
9911    let fade_out = HighlightStyle {
9912        fade_out: Some(0.35),
9913        ..Default::default()
9914    };
9915
9916    let mut prev_end = label.filter_range.end;
9917    label
9918        .runs
9919        .iter()
9920        .enumerate()
9921        .flat_map(move |(ix, (range, highlight_id))| {
9922            let style = if let Some(style) = highlight_id.style(syntax_theme) {
9923                style
9924            } else {
9925                return Default::default();
9926            };
9927            let mut muted_style = style;
9928            muted_style.highlight(fade_out);
9929
9930            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
9931            if range.start >= label.filter_range.end {
9932                if range.start > prev_end {
9933                    runs.push((prev_end..range.start, fade_out));
9934                }
9935                runs.push((range.clone(), muted_style));
9936            } else if range.end <= label.filter_range.end {
9937                runs.push((range.clone(), style));
9938            } else {
9939                runs.push((range.start..label.filter_range.end, style));
9940                runs.push((label.filter_range.end..range.end, muted_style));
9941            }
9942            prev_end = cmp::max(prev_end, range.end);
9943
9944            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
9945                runs.push((prev_end..label.text.len(), fade_out));
9946            }
9947
9948            runs
9949        })
9950}
9951
9952pub fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
9953    let mut index = 0;
9954    let mut codepoints = text.char_indices().peekable();
9955
9956    std::iter::from_fn(move || {
9957        let start_index = index;
9958        while let Some((new_index, codepoint)) = codepoints.next() {
9959            index = new_index + codepoint.len_utf8();
9960            let current_upper = codepoint.is_uppercase();
9961            let next_upper = codepoints
9962                .peek()
9963                .map(|(_, c)| c.is_uppercase())
9964                .unwrap_or(false);
9965
9966            if !current_upper && next_upper {
9967                return Some(&text[start_index..index]);
9968            }
9969        }
9970
9971        index = text.len();
9972        if start_index < text.len() {
9973            return Some(&text[start_index..]);
9974        }
9975        None
9976    })
9977    .flat_map(|word| word.split_inclusive('_'))
9978    .flat_map(|word| word.split_inclusive('-'))
9979}
9980
9981trait RangeToAnchorExt {
9982    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
9983}
9984
9985impl<T: ToOffset> RangeToAnchorExt for Range<T> {
9986    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
9987        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
9988    }
9989}