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