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