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