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