editor.rs

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