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