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