editor.rs

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