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