editor.rs

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