editor.rs

   1mod blink_manager;
   2pub mod display_map;
   3mod editor_settings;
   4mod element;
   5mod inlay_hint_cache;
   6
   7mod git;
   8mod highlight_matching_bracket;
   9mod hover_popover;
  10pub mod items;
  11mod link_go_to_definition;
  12mod mouse_context_menu;
  13pub mod movement;
  14pub mod multi_buffer;
  15mod persistence;
  16pub mod scroll;
  17pub mod selections_collection;
  18
  19#[cfg(test)]
  20mod editor_tests;
  21#[cfg(any(test, feature = "test-support"))]
  22pub mod test;
  23
  24use ::git::diff::DiffHunk;
  25use aho_corasick::AhoCorasick;
  26use anyhow::{anyhow, Context, Result};
  27use blink_manager::BlinkManager;
  28use client::{ClickhouseEvent, Collaborator, ParticipantIndex, TelemetrySettings};
  29use clock::{Global, ReplicaId};
  30use collections::{BTreeMap, Bound, HashMap, HashSet, VecDeque};
  31use convert_case::{Case, Casing};
  32use copilot::Copilot;
  33pub use display_map::DisplayPoint;
  34use display_map::*;
  35pub use editor_settings::EditorSettings;
  36pub use element::{
  37    Cursor, EditorElement, HighlightedRange, HighlightedRangeLine, LineWithInvisibles,
  38};
  39use futures::FutureExt;
  40use fuzzy::{StringMatch, StringMatchCandidate};
  41use gpui::{
  42    actions,
  43    color::Color,
  44    elements::*,
  45    executor,
  46    fonts::{self, HighlightStyle, TextStyle},
  47    geometry::vector::{vec2f, Vector2F},
  48    impl_actions,
  49    keymap_matcher::KeymapContext,
  50    platform::{CursorStyle, MouseButton},
  51    serde_json, AnyElement, AnyViewHandle, AppContext, AsyncAppContext, ClipboardItem,
  52    CursorRegion, Element, Entity, ModelHandle, MouseRegion, Subscription, Task, View, ViewContext,
  53    ViewHandle, WeakViewHandle, WindowContext,
  54};
  55use highlight_matching_bracket::refresh_matching_bracket_highlights;
  56use hover_popover::{hide_hover, HoverState};
  57use inlay_hint_cache::{InlayHintCache, InlaySplice, InvalidationStrategy};
  58pub use items::MAX_TAB_TITLE_LEN;
  59use itertools::Itertools;
  60pub use language::{char_kind, CharKind};
  61use language::{
  62    language_settings::{self, all_language_settings, InlayHintSettings},
  63    markdown::MarkdownHighlight,
  64    point_from_lsp, AutoindentMode, BracketPair, Buffer, CodeAction, CodeLabel, Completion,
  65    CursorShape, Diagnostic, DiagnosticSeverity, Documentation, File, IndentKind, IndentSize,
  66    Language, LanguageServerName, OffsetRangeExt, OffsetUtf16, Point, Selection, SelectionGoal,
  67    TransactionId,
  68};
  69use link_go_to_definition::{
  70    hide_link_definition, show_link_definition, GoToDefinitionLink, InlayHighlight,
  71    LinkGoToDefinitionState,
  72};
  73use log::error;
  74use lsp::LanguageServerId;
  75use multi_buffer::ToOffsetUtf16;
  76pub use multi_buffer::{
  77    Anchor, AnchorRangeExt, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, ToOffset,
  78    ToPoint,
  79};
  80use ordered_float::OrderedFloat;
  81use parking_lot::RwLock;
  82use project::{FormatTrigger, Location, Project, ProjectPath, ProjectTransaction};
  83use rand::{seq::SliceRandom, thread_rng};
  84use rpc::proto::PeerId;
  85use scroll::{
  86    autoscroll::Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager, ScrollbarAutoHide,
  87};
  88use selections_collection::{resolve_multiple, MutableSelectionsCollection, SelectionsCollection};
  89use serde::{Deserialize, Serialize};
  90use settings::SettingsStore;
  91use smallvec::SmallVec;
  92use snippet::Snippet;
  93use std::{
  94    any::TypeId,
  95    borrow::Cow,
  96    cmp::{self, Ordering, Reverse},
  97    mem,
  98    num::NonZeroU32,
  99    ops::{ControlFlow, Deref, DerefMut, Range, RangeInclusive},
 100    path::Path,
 101    sync::Arc,
 102    time::{Duration, Instant},
 103};
 104pub use sum_tree::Bias;
 105use sum_tree::TreeMap;
 106use text::Rope;
 107use theme::{DiagnosticStyle, Theme, ThemeSettings};
 108use util::{post_inc, RangeExt, ResultExt, TryFutureExt};
 109use workspace::{ItemNavHistory, SplitDirection, ViewId, Workspace};
 110
 111use crate::git::diff_hunk_to_display;
 112
 113const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
 114const MAX_LINE_LEN: usize = 1024;
 115const MIN_NAVIGATION_HISTORY_ROW_DELTA: i64 = 10;
 116const MAX_SELECTION_HISTORY_LEN: usize = 1024;
 117const COPILOT_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(75);
 118pub const CODE_ACTIONS_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(250);
 119pub const DOCUMENT_HIGHLIGHTS_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(75);
 120
 121pub const FORMAT_TIMEOUT: Duration = Duration::from_secs(2);
 122
 123pub fn render_parsed_markdown(
 124    parsed: &language::ParsedMarkdown,
 125    editor_style: &EditorStyle,
 126    cx: &mut ViewContext<Editor>,
 127) -> Text {
 128    enum RenderedMarkdown {}
 129
 130    let parsed = parsed.clone();
 131    let view_id = cx.view_id();
 132    let code_span_background_color = editor_style.document_highlight_read_background;
 133
 134    let mut region_id = 0;
 135
 136    Text::new(parsed.text, editor_style.text.clone())
 137        .with_highlights(
 138            parsed
 139                .highlights
 140                .iter()
 141                .filter_map(|(range, highlight)| {
 142                    let highlight = match highlight {
 143                        MarkdownHighlight::Style(style) => {
 144                            let mut highlight = HighlightStyle::default();
 145
 146                            if style.italic {
 147                                highlight.italic = Some(true);
 148                            }
 149
 150                            if style.underline {
 151                                highlight.underline = Some(fonts::Underline {
 152                                    thickness: 1.0.into(),
 153                                    ..Default::default()
 154                                });
 155                            }
 156
 157                            if style.weight != fonts::Weight::default() {
 158                                highlight.weight = Some(style.weight);
 159                            }
 160
 161                            highlight
 162                        }
 163
 164                        MarkdownHighlight::Code(id) => id.style(&editor_style.syntax)?,
 165                    };
 166
 167                    Some((range.clone(), highlight))
 168                })
 169                .collect::<Vec<_>>(),
 170        )
 171        .with_custom_runs(parsed.region_ranges, move |ix, bounds, scene, _| {
 172            region_id += 1;
 173            let region = parsed.regions[ix].clone();
 174
 175            if let Some(url) = region.link_url {
 176                scene.push_cursor_region(CursorRegion {
 177                    bounds,
 178                    style: CursorStyle::PointingHand,
 179                });
 180                scene.push_mouse_region(
 181                    MouseRegion::new::<RenderedMarkdown>(view_id, region_id, bounds)
 182                        .on_click::<Editor, _>(MouseButton::Left, move |_, _, cx| {
 183                            cx.platform().open_url(&url)
 184                        }),
 185                );
 186            }
 187
 188            if region.code {
 189                scene.push_quad(gpui::Quad {
 190                    bounds,
 191                    background: Some(code_span_background_color),
 192                    border: Default::default(),
 193                    corner_radii: (2.0).into(),
 194                });
 195            }
 196        })
 197        .with_soft_wrap(true)
 198}
 199
 200#[derive(Clone, Deserialize, PartialEq, Default)]
 201pub struct SelectNext {
 202    #[serde(default)]
 203    pub replace_newest: bool,
 204}
 205
 206#[derive(Clone, Deserialize, PartialEq, Default)]
 207pub struct SelectPrevious {
 208    #[serde(default)]
 209    pub replace_newest: bool,
 210}
 211
 212#[derive(Clone, Deserialize, PartialEq, Default)]
 213pub struct SelectAllMatches {
 214    #[serde(default)]
 215    pub replace_newest: bool,
 216}
 217
 218#[derive(Clone, Deserialize, PartialEq)]
 219pub struct SelectToBeginningOfLine {
 220    #[serde(default)]
 221    stop_at_soft_wraps: bool,
 222}
 223
 224#[derive(Clone, Default, Deserialize, PartialEq)]
 225pub struct MovePageUp {
 226    #[serde(default)]
 227    center_cursor: bool,
 228}
 229
 230#[derive(Clone, Default, Deserialize, PartialEq)]
 231pub struct MovePageDown {
 232    #[serde(default)]
 233    center_cursor: bool,
 234}
 235
 236#[derive(Clone, Deserialize, PartialEq)]
 237pub struct SelectToEndOfLine {
 238    #[serde(default)]
 239    stop_at_soft_wraps: bool,
 240}
 241
 242#[derive(Clone, Deserialize, PartialEq)]
 243pub struct ToggleCodeActions {
 244    #[serde(default)]
 245    pub deployed_from_indicator: bool,
 246}
 247
 248#[derive(Clone, Default, Deserialize, PartialEq)]
 249pub struct ConfirmCompletion {
 250    #[serde(default)]
 251    pub item_ix: Option<usize>,
 252}
 253
 254#[derive(Clone, Default, Deserialize, PartialEq)]
 255pub struct ConfirmCodeAction {
 256    #[serde(default)]
 257    pub item_ix: Option<usize>,
 258}
 259
 260#[derive(Clone, Default, Deserialize, PartialEq)]
 261pub struct ToggleComments {
 262    #[serde(default)]
 263    pub advance_downwards: bool,
 264}
 265
 266#[derive(Clone, Default, Deserialize, PartialEq)]
 267pub struct FoldAt {
 268    pub buffer_row: u32,
 269}
 270
 271#[derive(Clone, Default, Deserialize, PartialEq)]
 272pub struct UnfoldAt {
 273    pub buffer_row: u32,
 274}
 275
 276#[derive(Clone, Default, Deserialize, PartialEq)]
 277pub struct GutterHover {
 278    pub hovered: bool,
 279}
 280
 281#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
 282pub enum InlayId {
 283    Suggestion(usize),
 284    Hint(usize),
 285}
 286
 287impl InlayId {
 288    fn id(&self) -> usize {
 289        match self {
 290            Self::Suggestion(id) => *id,
 291            Self::Hint(id) => *id,
 292        }
 293    }
 294}
 295
 296actions!(
 297    editor,
 298    [
 299        Cancel,
 300        Backspace,
 301        Delete,
 302        Newline,
 303        NewlineAbove,
 304        NewlineBelow,
 305        GoToDiagnostic,
 306        GoToPrevDiagnostic,
 307        GoToHunk,
 308        GoToPrevHunk,
 309        Indent,
 310        Outdent,
 311        DeleteLine,
 312        DeleteToPreviousWordStart,
 313        DeleteToPreviousSubwordStart,
 314        DeleteToNextWordEnd,
 315        DeleteToNextSubwordEnd,
 316        DeleteToBeginningOfLine,
 317        DeleteToEndOfLine,
 318        CutToEndOfLine,
 319        DuplicateLine,
 320        MoveLineUp,
 321        MoveLineDown,
 322        JoinLines,
 323        SortLinesCaseSensitive,
 324        SortLinesCaseInsensitive,
 325        ReverseLines,
 326        ShuffleLines,
 327        ConvertToUpperCase,
 328        ConvertToLowerCase,
 329        ConvertToTitleCase,
 330        ConvertToSnakeCase,
 331        ConvertToKebabCase,
 332        ConvertToUpperCamelCase,
 333        ConvertToLowerCamelCase,
 334        Transpose,
 335        Cut,
 336        Copy,
 337        Paste,
 338        Undo,
 339        Redo,
 340        MoveUp,
 341        PageUp,
 342        MoveDown,
 343        PageDown,
 344        MoveLeft,
 345        MoveRight,
 346        MoveToPreviousWordStart,
 347        MoveToPreviousSubwordStart,
 348        MoveToNextWordEnd,
 349        MoveToNextSubwordEnd,
 350        MoveToBeginningOfLine,
 351        MoveToEndOfLine,
 352        MoveToStartOfParagraph,
 353        MoveToEndOfParagraph,
 354        MoveToBeginning,
 355        MoveToEnd,
 356        SelectUp,
 357        SelectDown,
 358        SelectLeft,
 359        SelectRight,
 360        SelectToPreviousWordStart,
 361        SelectToPreviousSubwordStart,
 362        SelectToNextWordEnd,
 363        SelectToNextSubwordEnd,
 364        SelectToStartOfParagraph,
 365        SelectToEndOfParagraph,
 366        SelectToBeginning,
 367        SelectToEnd,
 368        SelectAll,
 369        SelectLine,
 370        SplitSelectionIntoLines,
 371        AddSelectionAbove,
 372        AddSelectionBelow,
 373        Tab,
 374        TabPrev,
 375        ShowCharacterPalette,
 376        SelectLargerSyntaxNode,
 377        SelectSmallerSyntaxNode,
 378        GoToDefinition,
 379        GoToDefinitionSplit,
 380        GoToTypeDefinition,
 381        GoToTypeDefinitionSplit,
 382        MoveToEnclosingBracket,
 383        UndoSelection,
 384        RedoSelection,
 385        FindAllReferences,
 386        Rename,
 387        ConfirmRename,
 388        Fold,
 389        UnfoldLines,
 390        FoldSelectedRanges,
 391        ShowCompletions,
 392        OpenExcerpts,
 393        RestartLanguageServer,
 394        Hover,
 395        Format,
 396        ToggleSoftWrap,
 397        ToggleInlayHints,
 398        RevealInFinder,
 399        CopyPath,
 400        CopyRelativePath,
 401        CopyHighlightJson,
 402        ContextMenuFirst,
 403        ContextMenuPrev,
 404        ContextMenuNext,
 405        ContextMenuLast,
 406    ]
 407);
 408
 409impl_actions!(
 410    editor,
 411    [
 412        SelectNext,
 413        SelectPrevious,
 414        SelectAllMatches,
 415        SelectToBeginningOfLine,
 416        SelectToEndOfLine,
 417        ToggleCodeActions,
 418        MovePageUp,
 419        MovePageDown,
 420        ConfirmCompletion,
 421        ConfirmCodeAction,
 422        ToggleComments,
 423        FoldAt,
 424        UnfoldAt,
 425        GutterHover
 426    ]
 427);
 428
 429enum DocumentHighlightRead {}
 430enum DocumentHighlightWrite {}
 431enum InputComposition {}
 432
 433#[derive(Copy, Clone, PartialEq, Eq)]
 434pub enum Direction {
 435    Prev,
 436    Next,
 437}
 438
 439pub fn init_settings(cx: &mut AppContext) {
 440    settings::register::<EditorSettings>(cx);
 441}
 442
 443pub fn init(cx: &mut AppContext) {
 444    init_settings(cx);
 445    cx.add_action(Editor::new_file);
 446    cx.add_action(Editor::new_file_in_direction);
 447    cx.add_action(Editor::cancel);
 448    cx.add_action(Editor::newline);
 449    cx.add_action(Editor::newline_above);
 450    cx.add_action(Editor::newline_below);
 451    cx.add_action(Editor::backspace);
 452    cx.add_action(Editor::delete);
 453    cx.add_action(Editor::tab);
 454    cx.add_action(Editor::tab_prev);
 455    cx.add_action(Editor::indent);
 456    cx.add_action(Editor::outdent);
 457    cx.add_action(Editor::delete_line);
 458    cx.add_action(Editor::join_lines);
 459    cx.add_action(Editor::sort_lines_case_sensitive);
 460    cx.add_action(Editor::sort_lines_case_insensitive);
 461    cx.add_action(Editor::reverse_lines);
 462    cx.add_action(Editor::shuffle_lines);
 463    cx.add_action(Editor::convert_to_upper_case);
 464    cx.add_action(Editor::convert_to_lower_case);
 465    cx.add_action(Editor::convert_to_title_case);
 466    cx.add_action(Editor::convert_to_snake_case);
 467    cx.add_action(Editor::convert_to_kebab_case);
 468    cx.add_action(Editor::convert_to_upper_camel_case);
 469    cx.add_action(Editor::convert_to_lower_camel_case);
 470    cx.add_action(Editor::delete_to_previous_word_start);
 471    cx.add_action(Editor::delete_to_previous_subword_start);
 472    cx.add_action(Editor::delete_to_next_word_end);
 473    cx.add_action(Editor::delete_to_next_subword_end);
 474    cx.add_action(Editor::delete_to_beginning_of_line);
 475    cx.add_action(Editor::delete_to_end_of_line);
 476    cx.add_action(Editor::cut_to_end_of_line);
 477    cx.add_action(Editor::duplicate_line);
 478    cx.add_action(Editor::move_line_up);
 479    cx.add_action(Editor::move_line_down);
 480    cx.add_action(Editor::transpose);
 481    cx.add_action(Editor::cut);
 482    cx.add_action(Editor::copy);
 483    cx.add_action(Editor::paste);
 484    cx.add_action(Editor::undo);
 485    cx.add_action(Editor::redo);
 486    cx.add_action(Editor::move_up);
 487    cx.add_action(Editor::move_page_up);
 488    cx.add_action(Editor::move_down);
 489    cx.add_action(Editor::move_page_down);
 490    cx.add_action(Editor::next_screen);
 491    cx.add_action(Editor::move_left);
 492    cx.add_action(Editor::move_right);
 493    cx.add_action(Editor::move_to_previous_word_start);
 494    cx.add_action(Editor::move_to_previous_subword_start);
 495    cx.add_action(Editor::move_to_next_word_end);
 496    cx.add_action(Editor::move_to_next_subword_end);
 497    cx.add_action(Editor::move_to_beginning_of_line);
 498    cx.add_action(Editor::move_to_end_of_line);
 499    cx.add_action(Editor::move_to_start_of_paragraph);
 500    cx.add_action(Editor::move_to_end_of_paragraph);
 501    cx.add_action(Editor::move_to_beginning);
 502    cx.add_action(Editor::move_to_end);
 503    cx.add_action(Editor::select_up);
 504    cx.add_action(Editor::select_down);
 505    cx.add_action(Editor::select_left);
 506    cx.add_action(Editor::select_right);
 507    cx.add_action(Editor::select_to_previous_word_start);
 508    cx.add_action(Editor::select_to_previous_subword_start);
 509    cx.add_action(Editor::select_to_next_word_end);
 510    cx.add_action(Editor::select_to_next_subword_end);
 511    cx.add_action(Editor::select_to_beginning_of_line);
 512    cx.add_action(Editor::select_to_end_of_line);
 513    cx.add_action(Editor::select_to_start_of_paragraph);
 514    cx.add_action(Editor::select_to_end_of_paragraph);
 515    cx.add_action(Editor::select_to_beginning);
 516    cx.add_action(Editor::select_to_end);
 517    cx.add_action(Editor::select_all);
 518    cx.add_action(Editor::select_all_matches);
 519    cx.add_action(Editor::select_line);
 520    cx.add_action(Editor::split_selection_into_lines);
 521    cx.add_action(Editor::add_selection_above);
 522    cx.add_action(Editor::add_selection_below);
 523    cx.add_action(Editor::select_next);
 524    cx.add_action(Editor::select_previous);
 525    cx.add_action(Editor::toggle_comments);
 526    cx.add_action(Editor::select_larger_syntax_node);
 527    cx.add_action(Editor::select_smaller_syntax_node);
 528    cx.add_action(Editor::move_to_enclosing_bracket);
 529    cx.add_action(Editor::undo_selection);
 530    cx.add_action(Editor::redo_selection);
 531    cx.add_action(Editor::go_to_diagnostic);
 532    cx.add_action(Editor::go_to_prev_diagnostic);
 533    cx.add_action(Editor::go_to_hunk);
 534    cx.add_action(Editor::go_to_prev_hunk);
 535    cx.add_action(Editor::go_to_definition);
 536    cx.add_action(Editor::go_to_definition_split);
 537    cx.add_action(Editor::go_to_type_definition);
 538    cx.add_action(Editor::go_to_type_definition_split);
 539    cx.add_action(Editor::fold);
 540    cx.add_action(Editor::fold_at);
 541    cx.add_action(Editor::unfold_lines);
 542    cx.add_action(Editor::unfold_at);
 543    cx.add_action(Editor::gutter_hover);
 544    cx.add_action(Editor::fold_selected_ranges);
 545    cx.add_action(Editor::show_completions);
 546    cx.add_action(Editor::toggle_code_actions);
 547    cx.add_action(Editor::open_excerpts);
 548    cx.add_action(Editor::toggle_soft_wrap);
 549    cx.add_action(Editor::toggle_inlay_hints);
 550    cx.add_action(Editor::reveal_in_finder);
 551    cx.add_action(Editor::copy_path);
 552    cx.add_action(Editor::copy_relative_path);
 553    cx.add_action(Editor::copy_highlight_json);
 554    cx.add_async_action(Editor::format);
 555    cx.add_action(Editor::restart_language_server);
 556    cx.add_action(Editor::show_character_palette);
 557    cx.add_async_action(Editor::confirm_completion);
 558    cx.add_async_action(Editor::confirm_code_action);
 559    cx.add_async_action(Editor::rename);
 560    cx.add_async_action(Editor::confirm_rename);
 561    cx.add_async_action(Editor::find_all_references);
 562    cx.add_action(Editor::next_copilot_suggestion);
 563    cx.add_action(Editor::previous_copilot_suggestion);
 564    cx.add_action(Editor::copilot_suggest);
 565    cx.add_action(Editor::context_menu_first);
 566    cx.add_action(Editor::context_menu_prev);
 567    cx.add_action(Editor::context_menu_next);
 568    cx.add_action(Editor::context_menu_last);
 569
 570    hover_popover::init(cx);
 571    scroll::actions::init(cx);
 572
 573    workspace::register_project_item::<Editor>(cx);
 574    workspace::register_followable_item::<Editor>(cx);
 575    workspace::register_deserializable_item::<Editor>(cx);
 576}
 577
 578trait InvalidationRegion {
 579    fn ranges(&self) -> &[Range<Anchor>];
 580}
 581
 582#[derive(Clone, Debug, PartialEq)]
 583pub enum SelectPhase {
 584    Begin {
 585        position: DisplayPoint,
 586        add: bool,
 587        click_count: usize,
 588    },
 589    BeginColumnar {
 590        position: DisplayPoint,
 591        goal_column: u32,
 592    },
 593    Extend {
 594        position: DisplayPoint,
 595        click_count: usize,
 596    },
 597    Update {
 598        position: DisplayPoint,
 599        goal_column: u32,
 600        scroll_position: Vector2F,
 601    },
 602    End,
 603}
 604
 605#[derive(Clone, Debug)]
 606pub enum SelectMode {
 607    Character,
 608    Word(Range<Anchor>),
 609    Line(Range<Anchor>),
 610    All,
 611}
 612
 613#[derive(Copy, Clone, PartialEq, Eq, Debug)]
 614pub enum EditorMode {
 615    SingleLine,
 616    AutoHeight { max_lines: usize },
 617    Full,
 618}
 619
 620#[derive(Clone, Debug)]
 621pub enum SoftWrap {
 622    None,
 623    EditorWidth,
 624    Column(u32),
 625}
 626
 627#[derive(Clone)]
 628pub struct EditorStyle {
 629    pub text: TextStyle,
 630    pub line_height_scalar: f32,
 631    pub placeholder_text: Option<TextStyle>,
 632    pub theme: theme::Editor,
 633    pub theme_id: usize,
 634}
 635
 636type CompletionId = usize;
 637
 638type GetFieldEditorTheme = dyn Fn(&theme::Theme) -> theme::FieldEditor;
 639type OverrideTextStyle = dyn Fn(&EditorStyle) -> Option<HighlightStyle>;
 640
 641type BackgroundHighlight = (fn(&Theme) -> Color, Vec<Range<Anchor>>);
 642type InlayBackgroundHighlight = (fn(&Theme) -> Color, Vec<InlayHighlight>);
 643
 644pub struct Editor {
 645    handle: WeakViewHandle<Self>,
 646    buffer: ModelHandle<MultiBuffer>,
 647    display_map: ModelHandle<DisplayMap>,
 648    pub selections: SelectionsCollection,
 649    pub scroll_manager: ScrollManager,
 650    columnar_selection_tail: Option<Anchor>,
 651    add_selections_state: Option<AddSelectionsState>,
 652    select_next_state: Option<SelectNextState>,
 653    select_prev_state: Option<SelectNextState>,
 654    selection_history: SelectionHistory,
 655    autoclose_regions: Vec<AutocloseRegion>,
 656    snippet_stack: InvalidationStack<SnippetState>,
 657    select_larger_syntax_node_stack: Vec<Box<[Selection<usize>]>>,
 658    ime_transaction: Option<TransactionId>,
 659    active_diagnostics: Option<ActiveDiagnosticGroup>,
 660    soft_wrap_mode_override: Option<language_settings::SoftWrap>,
 661    get_field_editor_theme: Option<Arc<GetFieldEditorTheme>>,
 662    override_text_style: Option<Box<OverrideTextStyle>>,
 663    project: Option<ModelHandle<Project>>,
 664    collaboration_hub: Option<Box<dyn CollaborationHub>>,
 665    focused: bool,
 666    blink_manager: ModelHandle<BlinkManager>,
 667    pub show_local_selections: bool,
 668    mode: EditorMode,
 669    show_gutter: bool,
 670    show_wrap_guides: Option<bool>,
 671    placeholder_text: Option<Arc<str>>,
 672    highlighted_rows: Option<Range<u32>>,
 673    background_highlights: BTreeMap<TypeId, BackgroundHighlight>,
 674    inlay_background_highlights: TreeMap<Option<TypeId>, InlayBackgroundHighlight>,
 675    nav_history: Option<ItemNavHistory>,
 676    context_menu: Option<ContextMenu>,
 677    mouse_context_menu: ViewHandle<context_menu::ContextMenu>,
 678    completion_tasks: Vec<(CompletionId, Task<Option<()>>)>,
 679    next_completion_id: CompletionId,
 680    available_code_actions: Option<(ModelHandle<Buffer>, Arc<[CodeAction]>)>,
 681    code_actions_task: Option<Task<()>>,
 682    document_highlights_task: Option<Task<()>>,
 683    pending_rename: Option<RenameState>,
 684    searchable: bool,
 685    cursor_shape: CursorShape,
 686    collapse_matches: bool,
 687    autoindent_mode: Option<AutoindentMode>,
 688    workspace: Option<(WeakViewHandle<Workspace>, i64)>,
 689    keymap_context_layers: BTreeMap<TypeId, KeymapContext>,
 690    input_enabled: bool,
 691    read_only: bool,
 692    leader_peer_id: Option<PeerId>,
 693    remote_id: Option<ViewId>,
 694    hover_state: HoverState,
 695    gutter_hovered: bool,
 696    link_go_to_definition_state: LinkGoToDefinitionState,
 697    copilot_state: CopilotState,
 698    inlay_hint_cache: InlayHintCache,
 699    next_inlay_id: usize,
 700    _subscriptions: Vec<Subscription>,
 701    pixel_position_of_newest_cursor: Option<Vector2F>,
 702}
 703
 704pub struct EditorSnapshot {
 705    pub mode: EditorMode,
 706    pub show_gutter: bool,
 707    pub display_snapshot: DisplaySnapshot,
 708    pub placeholder_text: Option<Arc<str>>,
 709    is_focused: bool,
 710    scroll_anchor: ScrollAnchor,
 711    ongoing_scroll: OngoingScroll,
 712}
 713
 714pub struct RemoteSelection {
 715    pub replica_id: ReplicaId,
 716    pub selection: Selection<Anchor>,
 717    pub cursor_shape: CursorShape,
 718    pub peer_id: PeerId,
 719    pub line_mode: bool,
 720    pub participant_index: Option<ParticipantIndex>,
 721}
 722
 723#[derive(Clone, Debug)]
 724struct SelectionHistoryEntry {
 725    selections: Arc<[Selection<Anchor>]>,
 726    select_next_state: Option<SelectNextState>,
 727    select_prev_state: Option<SelectNextState>,
 728    add_selections_state: Option<AddSelectionsState>,
 729}
 730
 731enum SelectionHistoryMode {
 732    Normal,
 733    Undoing,
 734    Redoing,
 735}
 736
 737impl Default for SelectionHistoryMode {
 738    fn default() -> Self {
 739        Self::Normal
 740    }
 741}
 742
 743#[derive(Default)]
 744struct SelectionHistory {
 745    #[allow(clippy::type_complexity)]
 746    selections_by_transaction:
 747        HashMap<TransactionId, (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)>,
 748    mode: SelectionHistoryMode,
 749    undo_stack: VecDeque<SelectionHistoryEntry>,
 750    redo_stack: VecDeque<SelectionHistoryEntry>,
 751}
 752
 753impl SelectionHistory {
 754    fn insert_transaction(
 755        &mut self,
 756        transaction_id: TransactionId,
 757        selections: Arc<[Selection<Anchor>]>,
 758    ) {
 759        self.selections_by_transaction
 760            .insert(transaction_id, (selections, None));
 761    }
 762
 763    #[allow(clippy::type_complexity)]
 764    fn transaction(
 765        &self,
 766        transaction_id: TransactionId,
 767    ) -> Option<&(Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
 768        self.selections_by_transaction.get(&transaction_id)
 769    }
 770
 771    #[allow(clippy::type_complexity)]
 772    fn transaction_mut(
 773        &mut self,
 774        transaction_id: TransactionId,
 775    ) -> Option<&mut (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
 776        self.selections_by_transaction.get_mut(&transaction_id)
 777    }
 778
 779    fn push(&mut self, entry: SelectionHistoryEntry) {
 780        if !entry.selections.is_empty() {
 781            match self.mode {
 782                SelectionHistoryMode::Normal => {
 783                    self.push_undo(entry);
 784                    self.redo_stack.clear();
 785                }
 786                SelectionHistoryMode::Undoing => self.push_redo(entry),
 787                SelectionHistoryMode::Redoing => self.push_undo(entry),
 788            }
 789        }
 790    }
 791
 792    fn push_undo(&mut self, entry: SelectionHistoryEntry) {
 793        if self
 794            .undo_stack
 795            .back()
 796            .map_or(true, |e| e.selections != entry.selections)
 797        {
 798            self.undo_stack.push_back(entry);
 799            if self.undo_stack.len() > MAX_SELECTION_HISTORY_LEN {
 800                self.undo_stack.pop_front();
 801            }
 802        }
 803    }
 804
 805    fn push_redo(&mut self, entry: SelectionHistoryEntry) {
 806        if self
 807            .redo_stack
 808            .back()
 809            .map_or(true, |e| e.selections != entry.selections)
 810        {
 811            self.redo_stack.push_back(entry);
 812            if self.redo_stack.len() > MAX_SELECTION_HISTORY_LEN {
 813                self.redo_stack.pop_front();
 814            }
 815        }
 816    }
 817}
 818
 819#[derive(Clone, Debug)]
 820struct AddSelectionsState {
 821    above: bool,
 822    stack: Vec<usize>,
 823}
 824
 825#[derive(Clone)]
 826struct SelectNextState {
 827    query: AhoCorasick,
 828    wordwise: bool,
 829    done: bool,
 830}
 831
 832impl std::fmt::Debug for SelectNextState {
 833    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 834        f.debug_struct(std::any::type_name::<Self>())
 835            .field("wordwise", &self.wordwise)
 836            .field("done", &self.done)
 837            .finish()
 838    }
 839}
 840
 841#[derive(Debug)]
 842struct AutocloseRegion {
 843    selection_id: usize,
 844    range: Range<Anchor>,
 845    pair: BracketPair,
 846}
 847
 848#[derive(Debug)]
 849struct SnippetState {
 850    ranges: Vec<Vec<Range<Anchor>>>,
 851    active_index: usize,
 852}
 853
 854pub struct RenameState {
 855    pub range: Range<Anchor>,
 856    pub old_name: Arc<str>,
 857    pub editor: ViewHandle<Editor>,
 858    block_id: BlockId,
 859}
 860
 861struct InvalidationStack<T>(Vec<T>);
 862
 863enum ContextMenu {
 864    Completions(CompletionsMenu),
 865    CodeActions(CodeActionsMenu),
 866}
 867
 868impl ContextMenu {
 869    fn select_first(
 870        &mut self,
 871        project: Option<&ModelHandle<Project>>,
 872        cx: &mut ViewContext<Editor>,
 873    ) -> bool {
 874        if self.visible() {
 875            match self {
 876                ContextMenu::Completions(menu) => menu.select_first(project, cx),
 877                ContextMenu::CodeActions(menu) => menu.select_first(cx),
 878            }
 879            true
 880        } else {
 881            false
 882        }
 883    }
 884
 885    fn select_prev(
 886        &mut self,
 887        project: Option<&ModelHandle<Project>>,
 888        cx: &mut ViewContext<Editor>,
 889    ) -> bool {
 890        if self.visible() {
 891            match self {
 892                ContextMenu::Completions(menu) => menu.select_prev(project, cx),
 893                ContextMenu::CodeActions(menu) => menu.select_prev(cx),
 894            }
 895            true
 896        } else {
 897            false
 898        }
 899    }
 900
 901    fn select_next(
 902        &mut self,
 903        project: Option<&ModelHandle<Project>>,
 904        cx: &mut ViewContext<Editor>,
 905    ) -> bool {
 906        if self.visible() {
 907            match self {
 908                ContextMenu::Completions(menu) => menu.select_next(project, cx),
 909                ContextMenu::CodeActions(menu) => menu.select_next(cx),
 910            }
 911            true
 912        } else {
 913            false
 914        }
 915    }
 916
 917    fn select_last(
 918        &mut self,
 919        project: Option<&ModelHandle<Project>>,
 920        cx: &mut ViewContext<Editor>,
 921    ) -> bool {
 922        if self.visible() {
 923            match self {
 924                ContextMenu::Completions(menu) => menu.select_last(project, cx),
 925                ContextMenu::CodeActions(menu) => menu.select_last(cx),
 926            }
 927            true
 928        } else {
 929            false
 930        }
 931    }
 932
 933    fn visible(&self) -> bool {
 934        match self {
 935            ContextMenu::Completions(menu) => menu.visible(),
 936            ContextMenu::CodeActions(menu) => menu.visible(),
 937        }
 938    }
 939
 940    fn render(
 941        &self,
 942        cursor_position: DisplayPoint,
 943        style: EditorStyle,
 944        cx: &mut ViewContext<Editor>,
 945    ) -> (DisplayPoint, AnyElement<Editor>) {
 946        match self {
 947            ContextMenu::Completions(menu) => (cursor_position, menu.render(style, cx)),
 948            ContextMenu::CodeActions(menu) => menu.render(cursor_position, style, cx),
 949        }
 950    }
 951}
 952
 953struct CompletionsMenu {
 954    id: CompletionId,
 955    initial_position: Anchor,
 956    buffer: ModelHandle<Buffer>,
 957    completions: Arc<RwLock<Box<[Completion]>>>,
 958    match_candidates: Vec<StringMatchCandidate>,
 959    matches: Arc<[StringMatch]>,
 960    selected_item: usize,
 961    list: UniformListState,
 962}
 963
 964impl CompletionsMenu {
 965    fn select_first(
 966        &mut self,
 967        project: Option<&ModelHandle<Project>>,
 968        cx: &mut ViewContext<Editor>,
 969    ) {
 970        self.selected_item = 0;
 971        self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 972        self.attempt_resolve_selected_completion(project, cx);
 973        cx.notify();
 974    }
 975
 976    fn select_prev(
 977        &mut self,
 978        project: Option<&ModelHandle<Project>>,
 979        cx: &mut ViewContext<Editor>,
 980    ) {
 981        if self.selected_item > 0 {
 982            self.selected_item -= 1;
 983            self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 984        }
 985        self.attempt_resolve_selected_completion(project, cx);
 986        cx.notify();
 987    }
 988
 989    fn select_next(
 990        &mut self,
 991        project: Option<&ModelHandle<Project>>,
 992        cx: &mut ViewContext<Editor>,
 993    ) {
 994        if self.selected_item + 1 < self.matches.len() {
 995            self.selected_item += 1;
 996            self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 997        }
 998        self.attempt_resolve_selected_completion(project, cx);
 999        cx.notify();
1000    }
1001
1002    fn select_last(
1003        &mut self,
1004        project: Option<&ModelHandle<Project>>,
1005        cx: &mut ViewContext<Editor>,
1006    ) {
1007        self.selected_item = self.matches.len() - 1;
1008        self.list.scroll_to(ScrollTarget::Show(self.selected_item));
1009        self.attempt_resolve_selected_completion(project, cx);
1010        cx.notify();
1011    }
1012
1013    fn attempt_resolve_selected_completion(
1014        &mut self,
1015        project: Option<&ModelHandle<Project>>,
1016        cx: &mut ViewContext<Editor>,
1017    ) {
1018        let index = self.matches[self.selected_item].candidate_id;
1019        let Some(project) = project else {
1020            return;
1021        };
1022        let language_registry = project.read(cx).languages().clone();
1023
1024        let completions = self.completions.clone();
1025        let completions_guard = completions.read();
1026        let completion = &completions_guard[index];
1027        if completion.lsp_completion.documentation.is_some() {
1028            return;
1029        }
1030
1031        let server_id = completion.server_id;
1032        let completion = completion.lsp_completion.clone();
1033        drop(completions_guard);
1034
1035        let Some(server) = project.read(cx).language_server_for_id(server_id) else {
1036            return;
1037        };
1038
1039        let can_resolve = server
1040            .capabilities()
1041            .completion_provider
1042            .as_ref()
1043            .and_then(|options| options.resolve_provider)
1044            .unwrap_or(false);
1045        if !can_resolve {
1046            return;
1047        }
1048
1049        cx.spawn(|this, mut cx| async move {
1050            let request = server.request::<lsp::request::ResolveCompletionItem>(completion);
1051            let Some(completion_item) = request.await.log_err() else {
1052                return;
1053            };
1054
1055            if let Some(lsp_documentation) = completion_item.documentation {
1056                let documentation = language::prepare_completion_documentation(
1057                    &lsp_documentation,
1058                    &language_registry,
1059                    None, // TODO: Try to reasonably work out which language the completion is for
1060                )
1061                .await;
1062
1063                let mut completions = completions.write();
1064                let completion = &mut completions[index];
1065                completion.documentation = documentation;
1066                completion.lsp_completion.documentation = Some(lsp_documentation);
1067                drop(completions);
1068
1069                _ = this.update(&mut cx, |_, cx| cx.notify());
1070            }
1071        })
1072        .detach();
1073    }
1074
1075    fn visible(&self) -> bool {
1076        !self.matches.is_empty()
1077    }
1078
1079    fn render(&self, style: EditorStyle, cx: &mut ViewContext<Editor>) -> AnyElement<Editor> {
1080        enum CompletionTag {}
1081
1082        let widest_completion_ix = self
1083            .matches
1084            .iter()
1085            .enumerate()
1086            .max_by_key(|(_, mat)| {
1087                let completions = self.completions.read();
1088                let completion = &completions[mat.candidate_id];
1089                let documentation = &completion.lsp_completion.documentation;
1090
1091                let mut len = completion.label.text.chars().count();
1092                if let Some(lsp::Documentation::String(text)) = documentation {
1093                    len += text.chars().count();
1094                }
1095
1096                len
1097            })
1098            .map(|(ix, _)| ix);
1099
1100        let completions = self.completions.clone();
1101        let matches = self.matches.clone();
1102        let selected_item = self.selected_item;
1103
1104        let list = UniformList::new(self.list.clone(), matches.len(), cx, {
1105            let style = style.clone();
1106            move |_, range, items, cx| {
1107                let start_ix = range.start;
1108                let completions_guard = completions.read();
1109
1110                for (ix, mat) in matches[range].iter().enumerate() {
1111                    let item_ix = start_ix + ix;
1112                    let candidate_id = mat.candidate_id;
1113                    let completion = &completions_guard[candidate_id];
1114                    let documentation = &completion.documentation;
1115
1116                    items.push(
1117                        MouseEventHandler::new::<CompletionTag, _>(
1118                            mat.candidate_id,
1119                            cx,
1120                            |state, _| {
1121                                let item_style = if item_ix == selected_item {
1122                                    style.autocomplete.selected_item
1123                                } else if state.hovered() {
1124                                    style.autocomplete.hovered_item
1125                                } else {
1126                                    style.autocomplete.item
1127                                };
1128
1129                                let completion_label =
1130                                    Text::new(completion.label.text.clone(), style.text.clone())
1131                                        .with_soft_wrap(false)
1132                                        .with_highlights(
1133                                            combine_syntax_and_fuzzy_match_highlights(
1134                                                &completion.label.text,
1135                                                style.text.color.into(),
1136                                                styled_runs_for_code_label(
1137                                                    &completion.label,
1138                                                    &style.syntax,
1139                                                ),
1140                                                &mat.positions,
1141                                            ),
1142                                        );
1143
1144                                if let Some(Documentation::SingleLine(text)) = documentation {
1145                                    Flex::row()
1146                                        .with_child(completion_label)
1147                                        .with_children((|| {
1148                                            let text_style = TextStyle {
1149                                                color: style.autocomplete.inline_docs_color,
1150                                                font_size: style.text.font_size
1151                                                    * style.autocomplete.inline_docs_size_percent,
1152                                                ..style.text.clone()
1153                                            };
1154
1155                                            let label = Text::new(text.clone(), text_style)
1156                                                .aligned()
1157                                                .constrained()
1158                                                .dynamically(move |constraint, _, _| {
1159                                                    gpui::SizeConstraint {
1160                                                        min: constraint.min,
1161                                                        max: vec2f(
1162                                                            constraint.max.x(),
1163                                                            constraint.min.y(),
1164                                                        ),
1165                                                    }
1166                                                });
1167
1168                                            if Some(item_ix) == widest_completion_ix {
1169                                                Some(
1170                                                    label
1171                                                        .contained()
1172                                                        .with_style(
1173                                                            style
1174                                                                .autocomplete
1175                                                                .inline_docs_container,
1176                                                        )
1177                                                        .into_any(),
1178                                                )
1179                                            } else {
1180                                                Some(label.flex_float().into_any())
1181                                            }
1182                                        })())
1183                                        .into_any()
1184                                } else {
1185                                    completion_label.into_any()
1186                                }
1187                                .contained()
1188                                .with_style(item_style)
1189                                .constrained()
1190                                .dynamically(
1191                                    move |constraint, _, _| {
1192                                        if Some(item_ix) == widest_completion_ix {
1193                                            constraint
1194                                        } else {
1195                                            gpui::SizeConstraint {
1196                                                min: constraint.min,
1197                                                max: constraint.min,
1198                                            }
1199                                        }
1200                                    },
1201                                )
1202                            },
1203                        )
1204                        .with_cursor_style(CursorStyle::PointingHand)
1205                        .on_down(MouseButton::Left, move |_, this, cx| {
1206                            this.confirm_completion(
1207                                &ConfirmCompletion {
1208                                    item_ix: Some(item_ix),
1209                                },
1210                                cx,
1211                            )
1212                            .map(|task| task.detach());
1213                        })
1214                        .into_any(),
1215                    );
1216                }
1217            }
1218        })
1219        .with_width_from_item(widest_completion_ix);
1220
1221        Flex::row()
1222            .with_child(list)
1223            .with_children({
1224                let mat = &self.matches[selected_item];
1225                let completions = self.completions.read();
1226                let completion = &completions[mat.candidate_id];
1227                let documentation = &completion.documentation;
1228
1229                match documentation {
1230                    Some(Documentation::MultiLinePlainText(text)) => {
1231                        Some(Text::new(text.clone(), style.text.clone()))
1232                    }
1233
1234                    Some(Documentation::MultiLineMarkdown(parsed)) => {
1235                        Some(render_parsed_markdown(parsed, &style, cx))
1236                    }
1237
1238                    _ => None,
1239                }
1240            })
1241            .contained()
1242            .with_style(style.autocomplete.container)
1243            .into_any()
1244    }
1245
1246    pub async fn filter(&mut self, query: Option<&str>, executor: Arc<executor::Background>) {
1247        let mut matches = if let Some(query) = query {
1248            fuzzy::match_strings(
1249                &self.match_candidates,
1250                query,
1251                query.chars().any(|c| c.is_uppercase()),
1252                100,
1253                &Default::default(),
1254                executor,
1255            )
1256            .await
1257        } else {
1258            self.match_candidates
1259                .iter()
1260                .enumerate()
1261                .map(|(candidate_id, candidate)| StringMatch {
1262                    candidate_id,
1263                    score: Default::default(),
1264                    positions: Default::default(),
1265                    string: candidate.string.clone(),
1266                })
1267                .collect()
1268        };
1269
1270        //Remove all candidates where the query's start does not match the start of any word in the candidate
1271        if let Some(query) = query {
1272            if let Some(query_start) = query.chars().next() {
1273                matches.retain(|string_match| {
1274                    split_words(&string_match.string).any(|word| {
1275                        //Check that the first codepoint of the word as lowercase matches the first
1276                        //codepoint of the query as lowercase
1277                        word.chars()
1278                            .flat_map(|codepoint| codepoint.to_lowercase())
1279                            .zip(query_start.to_lowercase())
1280                            .all(|(word_cp, query_cp)| word_cp == query_cp)
1281                    })
1282                });
1283            }
1284        }
1285
1286        let completions = self.completions.read();
1287        matches.sort_unstable_by_key(|mat| {
1288            let completion = &completions[mat.candidate_id];
1289            (
1290                completion.lsp_completion.sort_text.as_ref(),
1291                Reverse(OrderedFloat(mat.score)),
1292                completion.sort_key(),
1293            )
1294        });
1295        drop(completions);
1296
1297        for mat in &mut matches {
1298            let completions = self.completions.read();
1299            let filter_start = completions[mat.candidate_id].label.filter_range.start;
1300            for position in &mut mat.positions {
1301                *position += filter_start;
1302            }
1303        }
1304
1305        self.matches = matches.into();
1306    }
1307}
1308
1309#[derive(Clone)]
1310struct CodeActionsMenu {
1311    actions: Arc<[CodeAction]>,
1312    buffer: ModelHandle<Buffer>,
1313    selected_item: usize,
1314    list: UniformListState,
1315    deployed_from_indicator: bool,
1316}
1317
1318impl CodeActionsMenu {
1319    fn select_first(&mut self, cx: &mut ViewContext<Editor>) {
1320        self.selected_item = 0;
1321        self.list.scroll_to(ScrollTarget::Show(self.selected_item));
1322        cx.notify()
1323    }
1324
1325    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) {
1326        if self.selected_item > 0 {
1327            self.selected_item -= 1;
1328            self.list.scroll_to(ScrollTarget::Show(self.selected_item));
1329            cx.notify()
1330        }
1331    }
1332
1333    fn select_next(&mut self, cx: &mut ViewContext<Editor>) {
1334        if self.selected_item + 1 < self.actions.len() {
1335            self.selected_item += 1;
1336            self.list.scroll_to(ScrollTarget::Show(self.selected_item));
1337            cx.notify()
1338        }
1339    }
1340
1341    fn select_last(&mut self, cx: &mut ViewContext<Editor>) {
1342        self.selected_item = self.actions.len() - 1;
1343        self.list.scroll_to(ScrollTarget::Show(self.selected_item));
1344        cx.notify()
1345    }
1346
1347    fn visible(&self) -> bool {
1348        !self.actions.is_empty()
1349    }
1350
1351    fn render(
1352        &self,
1353        mut cursor_position: DisplayPoint,
1354        style: EditorStyle,
1355        cx: &mut ViewContext<Editor>,
1356    ) -> (DisplayPoint, AnyElement<Editor>) {
1357        enum ActionTag {}
1358
1359        let container_style = style.autocomplete.container;
1360        let actions = self.actions.clone();
1361        let selected_item = self.selected_item;
1362        let element = UniformList::new(
1363            self.list.clone(),
1364            actions.len(),
1365            cx,
1366            move |_, range, items, cx| {
1367                let start_ix = range.start;
1368                for (ix, action) in actions[range].iter().enumerate() {
1369                    let item_ix = start_ix + ix;
1370                    items.push(
1371                        MouseEventHandler::new::<ActionTag, _>(item_ix, cx, |state, _| {
1372                            let item_style = if item_ix == selected_item {
1373                                style.autocomplete.selected_item
1374                            } else if state.hovered() {
1375                                style.autocomplete.hovered_item
1376                            } else {
1377                                style.autocomplete.item
1378                            };
1379
1380                            Text::new(action.lsp_action.title.clone(), style.text.clone())
1381                                .with_soft_wrap(false)
1382                                .contained()
1383                                .with_style(item_style)
1384                        })
1385                        .with_cursor_style(CursorStyle::PointingHand)
1386                        .on_down(MouseButton::Left, move |_, this, cx| {
1387                            let workspace = this
1388                                .workspace
1389                                .as_ref()
1390                                .and_then(|(workspace, _)| workspace.upgrade(cx));
1391                            cx.window_context().defer(move |cx| {
1392                                if let Some(workspace) = workspace {
1393                                    workspace.update(cx, |workspace, cx| {
1394                                        if let Some(task) = Editor::confirm_code_action(
1395                                            workspace,
1396                                            &ConfirmCodeAction {
1397                                                item_ix: Some(item_ix),
1398                                            },
1399                                            cx,
1400                                        ) {
1401                                            task.detach_and_log_err(cx);
1402                                        }
1403                                    });
1404                                }
1405                            });
1406                        })
1407                        .into_any(),
1408                    );
1409                }
1410            },
1411        )
1412        .with_width_from_item(
1413            self.actions
1414                .iter()
1415                .enumerate()
1416                .max_by_key(|(_, action)| action.lsp_action.title.chars().count())
1417                .map(|(ix, _)| ix),
1418        )
1419        .contained()
1420        .with_style(container_style)
1421        .into_any();
1422
1423        if self.deployed_from_indicator {
1424            *cursor_position.column_mut() = 0;
1425        }
1426
1427        (cursor_position, element)
1428    }
1429}
1430
1431pub struct CopilotState {
1432    excerpt_id: Option<ExcerptId>,
1433    pending_refresh: Task<Option<()>>,
1434    pending_cycling_refresh: Task<Option<()>>,
1435    cycled: bool,
1436    completions: Vec<copilot::Completion>,
1437    active_completion_index: usize,
1438    suggestion: Option<Inlay>,
1439}
1440
1441impl Default for CopilotState {
1442    fn default() -> Self {
1443        Self {
1444            excerpt_id: None,
1445            pending_cycling_refresh: Task::ready(Some(())),
1446            pending_refresh: Task::ready(Some(())),
1447            completions: Default::default(),
1448            active_completion_index: 0,
1449            cycled: false,
1450            suggestion: None,
1451        }
1452    }
1453}
1454
1455impl CopilotState {
1456    fn active_completion(&self) -> Option<&copilot::Completion> {
1457        self.completions.get(self.active_completion_index)
1458    }
1459
1460    fn text_for_active_completion(
1461        &self,
1462        cursor: Anchor,
1463        buffer: &MultiBufferSnapshot,
1464    ) -> Option<&str> {
1465        use language::ToOffset as _;
1466
1467        let completion = self.active_completion()?;
1468        let excerpt_id = self.excerpt_id?;
1469        let completion_buffer = buffer.buffer_for_excerpt(excerpt_id)?;
1470        if excerpt_id != cursor.excerpt_id
1471            || !completion.range.start.is_valid(completion_buffer)
1472            || !completion.range.end.is_valid(completion_buffer)
1473        {
1474            return None;
1475        }
1476
1477        let mut completion_range = completion.range.to_offset(&completion_buffer);
1478        let prefix_len = Self::common_prefix(
1479            completion_buffer.chars_for_range(completion_range.clone()),
1480            completion.text.chars(),
1481        );
1482        completion_range.start += prefix_len;
1483        let suffix_len = Self::common_prefix(
1484            completion_buffer.reversed_chars_for_range(completion_range.clone()),
1485            completion.text[prefix_len..].chars().rev(),
1486        );
1487        completion_range.end = completion_range.end.saturating_sub(suffix_len);
1488
1489        if completion_range.is_empty()
1490            && completion_range.start == cursor.text_anchor.to_offset(&completion_buffer)
1491        {
1492            Some(&completion.text[prefix_len..completion.text.len() - suffix_len])
1493        } else {
1494            None
1495        }
1496    }
1497
1498    fn cycle_completions(&mut self, direction: Direction) {
1499        match direction {
1500            Direction::Prev => {
1501                self.active_completion_index = if self.active_completion_index == 0 {
1502                    self.completions.len().saturating_sub(1)
1503                } else {
1504                    self.active_completion_index - 1
1505                };
1506            }
1507            Direction::Next => {
1508                if self.completions.len() == 0 {
1509                    self.active_completion_index = 0
1510                } else {
1511                    self.active_completion_index =
1512                        (self.active_completion_index + 1) % self.completions.len();
1513                }
1514            }
1515        }
1516    }
1517
1518    fn push_completion(&mut self, new_completion: copilot::Completion) {
1519        for completion in &self.completions {
1520            if completion.text == new_completion.text && completion.range == new_completion.range {
1521                return;
1522            }
1523        }
1524        self.completions.push(new_completion);
1525    }
1526
1527    fn common_prefix<T1: Iterator<Item = char>, T2: Iterator<Item = char>>(a: T1, b: T2) -> usize {
1528        a.zip(b)
1529            .take_while(|(a, b)| a == b)
1530            .map(|(a, _)| a.len_utf8())
1531            .sum()
1532    }
1533}
1534
1535#[derive(Debug)]
1536struct ActiveDiagnosticGroup {
1537    primary_range: Range<Anchor>,
1538    primary_message: String,
1539    blocks: HashMap<BlockId, Diagnostic>,
1540    is_valid: bool,
1541}
1542
1543#[derive(Serialize, Deserialize)]
1544pub struct ClipboardSelection {
1545    pub len: usize,
1546    pub is_entire_line: bool,
1547    pub first_line_indent: u32,
1548}
1549
1550#[derive(Debug)]
1551pub struct NavigationData {
1552    cursor_anchor: Anchor,
1553    cursor_position: Point,
1554    scroll_anchor: ScrollAnchor,
1555    scroll_top_row: u32,
1556}
1557
1558pub struct EditorCreated(pub ViewHandle<Editor>);
1559
1560enum GotoDefinitionKind {
1561    Symbol,
1562    Type,
1563}
1564
1565#[derive(Debug, Clone)]
1566enum InlayHintRefreshReason {
1567    Toggle(bool),
1568    SettingsChange(InlayHintSettings),
1569    NewLinesShown,
1570    BufferEdited(HashSet<Arc<Language>>),
1571    RefreshRequested,
1572    ExcerptsRemoved(Vec<ExcerptId>),
1573}
1574impl InlayHintRefreshReason {
1575    fn description(&self) -> &'static str {
1576        match self {
1577            Self::Toggle(_) => "toggle",
1578            Self::SettingsChange(_) => "settings change",
1579            Self::NewLinesShown => "new lines shown",
1580            Self::BufferEdited(_) => "buffer edited",
1581            Self::RefreshRequested => "refresh requested",
1582            Self::ExcerptsRemoved(_) => "excerpts removed",
1583        }
1584    }
1585}
1586
1587impl Editor {
1588    pub fn single_line(
1589        field_editor_style: Option<Arc<GetFieldEditorTheme>>,
1590        cx: &mut ViewContext<Self>,
1591    ) -> Self {
1592        let buffer = cx.add_model(|cx| Buffer::new(0, cx.model_id() as u64, String::new()));
1593        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
1594        Self::new(EditorMode::SingleLine, buffer, None, field_editor_style, cx)
1595    }
1596
1597    pub fn multi_line(
1598        field_editor_style: Option<Arc<GetFieldEditorTheme>>,
1599        cx: &mut ViewContext<Self>,
1600    ) -> Self {
1601        let buffer = cx.add_model(|cx| Buffer::new(0, cx.model_id() as u64, String::new()));
1602        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
1603        Self::new(EditorMode::Full, buffer, None, field_editor_style, cx)
1604    }
1605
1606    pub fn auto_height(
1607        max_lines: usize,
1608        field_editor_style: Option<Arc<GetFieldEditorTheme>>,
1609        cx: &mut ViewContext<Self>,
1610    ) -> Self {
1611        let buffer = cx.add_model(|cx| Buffer::new(0, cx.model_id() as u64, String::new()));
1612        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
1613        Self::new(
1614            EditorMode::AutoHeight { max_lines },
1615            buffer,
1616            None,
1617            field_editor_style,
1618            cx,
1619        )
1620    }
1621
1622    pub fn for_buffer(
1623        buffer: ModelHandle<Buffer>,
1624        project: Option<ModelHandle<Project>>,
1625        cx: &mut ViewContext<Self>,
1626    ) -> Self {
1627        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
1628        Self::new(EditorMode::Full, buffer, project, None, cx)
1629    }
1630
1631    pub fn for_multibuffer(
1632        buffer: ModelHandle<MultiBuffer>,
1633        project: Option<ModelHandle<Project>>,
1634        cx: &mut ViewContext<Self>,
1635    ) -> Self {
1636        Self::new(EditorMode::Full, buffer, project, None, cx)
1637    }
1638
1639    pub fn clone(&self, cx: &mut ViewContext<Self>) -> Self {
1640        let mut clone = Self::new(
1641            self.mode,
1642            self.buffer.clone(),
1643            self.project.clone(),
1644            self.get_field_editor_theme.clone(),
1645            cx,
1646        );
1647        self.display_map.update(cx, |display_map, cx| {
1648            let snapshot = display_map.snapshot(cx);
1649            clone.display_map.update(cx, |display_map, cx| {
1650                display_map.set_state(&snapshot, cx);
1651            });
1652        });
1653        clone.selections.clone_state(&self.selections);
1654        clone.scroll_manager.clone_state(&self.scroll_manager);
1655        clone.searchable = self.searchable;
1656        clone
1657    }
1658
1659    fn new(
1660        mode: EditorMode,
1661        buffer: ModelHandle<MultiBuffer>,
1662        project: Option<ModelHandle<Project>>,
1663        get_field_editor_theme: Option<Arc<GetFieldEditorTheme>>,
1664        cx: &mut ViewContext<Self>,
1665    ) -> Self {
1666        let editor_view_id = cx.view_id();
1667        let display_map = cx.add_model(|cx| {
1668            let settings = settings::get::<ThemeSettings>(cx);
1669            let style = build_style(settings, get_field_editor_theme.as_deref(), None, cx);
1670            DisplayMap::new(
1671                buffer.clone(),
1672                style.text.font_id,
1673                style.text.font_size,
1674                None,
1675                2,
1676                1,
1677                cx,
1678            )
1679        });
1680
1681        let selections = SelectionsCollection::new(display_map.clone(), buffer.clone());
1682
1683        let blink_manager = cx.add_model(|cx| BlinkManager::new(CURSOR_BLINK_INTERVAL, cx));
1684
1685        let soft_wrap_mode_override =
1686            (mode == EditorMode::SingleLine).then(|| language_settings::SoftWrap::None);
1687
1688        let mut project_subscriptions = Vec::new();
1689        if mode == EditorMode::Full {
1690            if let Some(project) = project.as_ref() {
1691                if buffer.read(cx).is_singleton() {
1692                    project_subscriptions.push(cx.observe(project, |_, _, cx| {
1693                        cx.emit(Event::TitleChanged);
1694                    }));
1695                }
1696                project_subscriptions.push(cx.subscribe(project, |editor, _, event, cx| {
1697                    if let project::Event::RefreshInlayHints = event {
1698                        editor.refresh_inlay_hints(InlayHintRefreshReason::RefreshRequested, cx);
1699                    };
1700                }));
1701            }
1702        }
1703
1704        let inlay_hint_settings = inlay_hint_settings(
1705            selections.newest_anchor().head(),
1706            &buffer.read(cx).snapshot(cx),
1707            cx,
1708        );
1709
1710        let mut this = Self {
1711            handle: cx.weak_handle(),
1712            buffer: buffer.clone(),
1713            display_map: display_map.clone(),
1714            selections,
1715            scroll_manager: ScrollManager::new(),
1716            columnar_selection_tail: None,
1717            add_selections_state: None,
1718            select_next_state: None,
1719            select_prev_state: None,
1720            selection_history: Default::default(),
1721            autoclose_regions: Default::default(),
1722            snippet_stack: Default::default(),
1723            select_larger_syntax_node_stack: Vec::new(),
1724            ime_transaction: Default::default(),
1725            active_diagnostics: None,
1726            soft_wrap_mode_override,
1727            get_field_editor_theme,
1728            collaboration_hub: project.clone().map(|project| Box::new(project) as _),
1729            project,
1730            focused: false,
1731            blink_manager: blink_manager.clone(),
1732            show_local_selections: true,
1733            mode,
1734            show_gutter: mode == EditorMode::Full,
1735            show_wrap_guides: None,
1736            placeholder_text: None,
1737            highlighted_rows: None,
1738            background_highlights: Default::default(),
1739            inlay_background_highlights: Default::default(),
1740            nav_history: None,
1741            context_menu: None,
1742            mouse_context_menu: cx
1743                .add_view(|cx| context_menu::ContextMenu::new(editor_view_id, cx)),
1744            completion_tasks: Default::default(),
1745            next_completion_id: 0,
1746            next_inlay_id: 0,
1747            available_code_actions: Default::default(),
1748            code_actions_task: Default::default(),
1749            document_highlights_task: Default::default(),
1750            pending_rename: Default::default(),
1751            searchable: true,
1752            override_text_style: None,
1753            cursor_shape: Default::default(),
1754            autoindent_mode: Some(AutoindentMode::EachLine),
1755            collapse_matches: false,
1756            workspace: None,
1757            keymap_context_layers: Default::default(),
1758            input_enabled: true,
1759            read_only: false,
1760            leader_peer_id: None,
1761            remote_id: None,
1762            hover_state: Default::default(),
1763            link_go_to_definition_state: Default::default(),
1764            copilot_state: Default::default(),
1765            inlay_hint_cache: InlayHintCache::new(inlay_hint_settings),
1766            gutter_hovered: false,
1767            pixel_position_of_newest_cursor: None,
1768            _subscriptions: vec![
1769                cx.observe(&buffer, Self::on_buffer_changed),
1770                cx.subscribe(&buffer, Self::on_buffer_event),
1771                cx.observe(&display_map, Self::on_display_map_changed),
1772                cx.observe(&blink_manager, |_, _, cx| cx.notify()),
1773                cx.observe_global::<SettingsStore, _>(Self::settings_changed),
1774                cx.observe_window_activation(|editor, active, cx| {
1775                    editor.blink_manager.update(cx, |blink_manager, cx| {
1776                        if active {
1777                            blink_manager.enable(cx);
1778                        } else {
1779                            blink_manager.show_cursor(cx);
1780                            blink_manager.disable(cx);
1781                        }
1782                    });
1783                }),
1784            ],
1785        };
1786
1787        this._subscriptions.extend(project_subscriptions);
1788
1789        this.end_selection(cx);
1790        this.scroll_manager.show_scrollbar(cx);
1791
1792        let editor_created_event = EditorCreated(cx.handle());
1793        cx.emit_global(editor_created_event);
1794
1795        if mode == EditorMode::Full {
1796            let should_auto_hide_scrollbars = cx.platform().should_auto_hide_scrollbars();
1797            cx.set_global(ScrollbarAutoHide(should_auto_hide_scrollbars));
1798        }
1799
1800        this.report_editor_event("open", None, cx);
1801        this
1802    }
1803
1804    pub fn new_file(
1805        workspace: &mut Workspace,
1806        _: &workspace::NewFile,
1807        cx: &mut ViewContext<Workspace>,
1808    ) {
1809        let project = workspace.project().clone();
1810        if project.read(cx).is_remote() {
1811            cx.propagate_action();
1812        } else if let Some(buffer) = project
1813            .update(cx, |project, cx| project.create_buffer("", None, cx))
1814            .log_err()
1815        {
1816            workspace.add_item(
1817                Box::new(cx.add_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx))),
1818                cx,
1819            );
1820        }
1821    }
1822
1823    pub fn new_file_in_direction(
1824        workspace: &mut Workspace,
1825        action: &workspace::NewFileInDirection,
1826        cx: &mut ViewContext<Workspace>,
1827    ) {
1828        let project = workspace.project().clone();
1829        if project.read(cx).is_remote() {
1830            cx.propagate_action();
1831        } else if let Some(buffer) = project
1832            .update(cx, |project, cx| project.create_buffer("", None, cx))
1833            .log_err()
1834        {
1835            workspace.split_item(
1836                action.0,
1837                Box::new(cx.add_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx))),
1838                cx,
1839            );
1840        }
1841    }
1842
1843    pub fn replica_id(&self, cx: &AppContext) -> ReplicaId {
1844        self.buffer.read(cx).replica_id()
1845    }
1846
1847    pub fn leader_peer_id(&self) -> Option<PeerId> {
1848        self.leader_peer_id
1849    }
1850
1851    pub fn buffer(&self) -> &ModelHandle<MultiBuffer> {
1852        &self.buffer
1853    }
1854
1855    fn workspace(&self, cx: &AppContext) -> Option<ViewHandle<Workspace>> {
1856        self.workspace.as_ref()?.0.upgrade(cx)
1857    }
1858
1859    pub fn title<'a>(&self, cx: &'a AppContext) -> Cow<'a, str> {
1860        self.buffer().read(cx).title(cx)
1861    }
1862
1863    pub fn snapshot(&mut self, cx: &mut WindowContext) -> EditorSnapshot {
1864        EditorSnapshot {
1865            mode: self.mode,
1866            show_gutter: self.show_gutter,
1867            display_snapshot: self.display_map.update(cx, |map, cx| map.snapshot(cx)),
1868            scroll_anchor: self.scroll_manager.anchor(),
1869            ongoing_scroll: self.scroll_manager.ongoing_scroll(),
1870            placeholder_text: self.placeholder_text.clone(),
1871            is_focused: self
1872                .handle
1873                .upgrade(cx)
1874                .map_or(false, |handle| handle.is_focused(cx)),
1875        }
1876    }
1877
1878    pub fn language_at<'a, T: ToOffset>(
1879        &self,
1880        point: T,
1881        cx: &'a AppContext,
1882    ) -> Option<Arc<Language>> {
1883        self.buffer.read(cx).language_at(point, cx)
1884    }
1885
1886    pub fn file_at<'a, T: ToOffset>(&self, point: T, cx: &'a AppContext) -> Option<Arc<dyn File>> {
1887        self.buffer.read(cx).read(cx).file_at(point).cloned()
1888    }
1889
1890    pub fn active_excerpt(
1891        &self,
1892        cx: &AppContext,
1893    ) -> Option<(ExcerptId, ModelHandle<Buffer>, Range<text::Anchor>)> {
1894        self.buffer
1895            .read(cx)
1896            .excerpt_containing(self.selections.newest_anchor().head(), cx)
1897    }
1898
1899    pub fn style(&self, cx: &AppContext) -> EditorStyle {
1900        build_style(
1901            settings::get::<ThemeSettings>(cx),
1902            self.get_field_editor_theme.as_deref(),
1903            self.override_text_style.as_deref(),
1904            cx,
1905        )
1906    }
1907
1908    pub fn mode(&self) -> EditorMode {
1909        self.mode
1910    }
1911
1912    pub fn collaboration_hub(&self) -> Option<&dyn CollaborationHub> {
1913        self.collaboration_hub.as_deref()
1914    }
1915
1916    pub fn set_collaboration_hub(&mut self, hub: Box<dyn CollaborationHub>) {
1917        self.collaboration_hub = Some(hub);
1918    }
1919
1920    pub fn set_placeholder_text(
1921        &mut self,
1922        placeholder_text: impl Into<Arc<str>>,
1923        cx: &mut ViewContext<Self>,
1924    ) {
1925        self.placeholder_text = Some(placeholder_text.into());
1926        cx.notify();
1927    }
1928
1929    pub fn set_cursor_shape(&mut self, cursor_shape: CursorShape, cx: &mut ViewContext<Self>) {
1930        self.cursor_shape = cursor_shape;
1931        cx.notify();
1932    }
1933
1934    pub fn set_collapse_matches(&mut self, collapse_matches: bool) {
1935        self.collapse_matches = collapse_matches;
1936    }
1937
1938    pub fn range_for_match<T: std::marker::Copy>(&self, range: &Range<T>) -> Range<T> {
1939        if self.collapse_matches {
1940            return range.start..range.start;
1941        }
1942        range.clone()
1943    }
1944
1945    pub fn set_clip_at_line_ends(&mut self, clip: bool, cx: &mut ViewContext<Self>) {
1946        if self.display_map.read(cx).clip_at_line_ends != clip {
1947            self.display_map
1948                .update(cx, |map, _| map.clip_at_line_ends = clip);
1949        }
1950    }
1951
1952    pub fn set_keymap_context_layer<Tag: 'static>(
1953        &mut self,
1954        context: KeymapContext,
1955        cx: &mut ViewContext<Self>,
1956    ) {
1957        self.keymap_context_layers
1958            .insert(TypeId::of::<Tag>(), context);
1959        cx.notify();
1960    }
1961
1962    pub fn remove_keymap_context_layer<Tag: 'static>(&mut self, cx: &mut ViewContext<Self>) {
1963        self.keymap_context_layers.remove(&TypeId::of::<Tag>());
1964        cx.notify();
1965    }
1966
1967    pub fn set_input_enabled(&mut self, input_enabled: bool) {
1968        self.input_enabled = input_enabled;
1969    }
1970
1971    pub fn set_autoindent(&mut self, autoindent: bool) {
1972        if autoindent {
1973            self.autoindent_mode = Some(AutoindentMode::EachLine);
1974        } else {
1975            self.autoindent_mode = None;
1976        }
1977    }
1978
1979    pub fn read_only(&self) -> bool {
1980        self.read_only
1981    }
1982
1983    pub fn set_read_only(&mut self, read_only: bool) {
1984        self.read_only = read_only;
1985    }
1986
1987    pub fn set_field_editor_style(
1988        &mut self,
1989        style: Option<Arc<GetFieldEditorTheme>>,
1990        cx: &mut ViewContext<Self>,
1991    ) {
1992        self.get_field_editor_theme = style;
1993        cx.notify();
1994    }
1995
1996    fn selections_did_change(
1997        &mut self,
1998        local: bool,
1999        old_cursor_position: &Anchor,
2000        cx: &mut ViewContext<Self>,
2001    ) {
2002        if self.focused && self.leader_peer_id.is_none() {
2003            self.buffer.update(cx, |buffer, cx| {
2004                buffer.set_active_selections(
2005                    &self.selections.disjoint_anchors(),
2006                    self.selections.line_mode,
2007                    self.cursor_shape,
2008                    cx,
2009                )
2010            });
2011        }
2012
2013        let display_map = self
2014            .display_map
2015            .update(cx, |display_map, cx| display_map.snapshot(cx));
2016        let buffer = &display_map.buffer_snapshot;
2017        self.add_selections_state = None;
2018        self.select_next_state = None;
2019        self.select_prev_state = None;
2020        self.select_larger_syntax_node_stack.clear();
2021        self.invalidate_autoclose_regions(&self.selections.disjoint_anchors(), buffer);
2022        self.snippet_stack
2023            .invalidate(&self.selections.disjoint_anchors(), buffer);
2024        self.take_rename(false, cx);
2025
2026        let new_cursor_position = self.selections.newest_anchor().head();
2027
2028        self.push_to_nav_history(
2029            old_cursor_position.clone(),
2030            Some(new_cursor_position.to_point(buffer)),
2031            cx,
2032        );
2033
2034        if local {
2035            let new_cursor_position = self.selections.newest_anchor().head();
2036            let completion_menu = match self.context_menu.as_mut() {
2037                Some(ContextMenu::Completions(menu)) => Some(menu),
2038                _ => {
2039                    self.context_menu.take();
2040                    None
2041                }
2042            };
2043
2044            if let Some(completion_menu) = completion_menu {
2045                let cursor_position = new_cursor_position.to_offset(buffer);
2046                let (word_range, kind) =
2047                    buffer.surrounding_word(completion_menu.initial_position.clone());
2048                if kind == Some(CharKind::Word)
2049                    && word_range.to_inclusive().contains(&cursor_position)
2050                {
2051                    let query = Self::completion_query(buffer, cursor_position);
2052                    cx.background()
2053                        .block(completion_menu.filter(query.as_deref(), cx.background().clone()));
2054                    self.show_completions(&ShowCompletions, cx);
2055                } else {
2056                    self.hide_context_menu(cx);
2057                }
2058            }
2059
2060            hide_hover(self, cx);
2061
2062            if old_cursor_position.to_display_point(&display_map).row()
2063                != new_cursor_position.to_display_point(&display_map).row()
2064            {
2065                self.available_code_actions.take();
2066            }
2067            self.refresh_code_actions(cx);
2068            self.refresh_document_highlights(cx);
2069            refresh_matching_bracket_highlights(self, cx);
2070            self.discard_copilot_suggestion(cx);
2071        }
2072
2073        self.blink_manager.update(cx, BlinkManager::pause_blinking);
2074        cx.emit(Event::SelectionsChanged { local });
2075        cx.notify();
2076    }
2077
2078    pub fn change_selections<R>(
2079        &mut self,
2080        autoscroll: Option<Autoscroll>,
2081        cx: &mut ViewContext<Self>,
2082        change: impl FnOnce(&mut MutableSelectionsCollection<'_>) -> R,
2083    ) -> R {
2084        let old_cursor_position = self.selections.newest_anchor().head();
2085        self.push_to_selection_history();
2086
2087        let (changed, result) = self.selections.change_with(cx, change);
2088
2089        if changed {
2090            if let Some(autoscroll) = autoscroll {
2091                self.request_autoscroll(autoscroll, cx);
2092            }
2093            self.selections_did_change(true, &old_cursor_position, cx);
2094        }
2095
2096        result
2097    }
2098
2099    pub fn edit<I, S, T>(&mut self, edits: I, cx: &mut ViewContext<Self>)
2100    where
2101        I: IntoIterator<Item = (Range<S>, T)>,
2102        S: ToOffset,
2103        T: Into<Arc<str>>,
2104    {
2105        if self.read_only {
2106            return;
2107        }
2108
2109        self.buffer
2110            .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
2111    }
2112
2113    pub fn edit_with_autoindent<I, S, T>(&mut self, edits: I, cx: &mut ViewContext<Self>)
2114    where
2115        I: IntoIterator<Item = (Range<S>, T)>,
2116        S: ToOffset,
2117        T: Into<Arc<str>>,
2118    {
2119        if self.read_only {
2120            return;
2121        }
2122
2123        self.buffer.update(cx, |buffer, cx| {
2124            buffer.edit(edits, self.autoindent_mode.clone(), cx)
2125        });
2126    }
2127
2128    pub fn edit_with_block_indent<I, S, T>(
2129        &mut self,
2130        edits: I,
2131        original_indent_columns: Vec<u32>,
2132        cx: &mut ViewContext<Self>,
2133    ) where
2134        I: IntoIterator<Item = (Range<S>, T)>,
2135        S: ToOffset,
2136        T: Into<Arc<str>>,
2137    {
2138        if self.read_only {
2139            return;
2140        }
2141
2142        self.buffer.update(cx, |buffer, cx| {
2143            buffer.edit(
2144                edits,
2145                Some(AutoindentMode::Block {
2146                    original_indent_columns,
2147                }),
2148                cx,
2149            )
2150        });
2151    }
2152
2153    fn select(&mut self, phase: SelectPhase, cx: &mut ViewContext<Self>) {
2154        self.hide_context_menu(cx);
2155
2156        match phase {
2157            SelectPhase::Begin {
2158                position,
2159                add,
2160                click_count,
2161            } => self.begin_selection(position, add, click_count, cx),
2162            SelectPhase::BeginColumnar {
2163                position,
2164                goal_column,
2165            } => self.begin_columnar_selection(position, goal_column, cx),
2166            SelectPhase::Extend {
2167                position,
2168                click_count,
2169            } => self.extend_selection(position, click_count, cx),
2170            SelectPhase::Update {
2171                position,
2172                goal_column,
2173                scroll_position,
2174            } => self.update_selection(position, goal_column, scroll_position, cx),
2175            SelectPhase::End => self.end_selection(cx),
2176        }
2177    }
2178
2179    fn extend_selection(
2180        &mut self,
2181        position: DisplayPoint,
2182        click_count: usize,
2183        cx: &mut ViewContext<Self>,
2184    ) {
2185        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2186        let tail = self.selections.newest::<usize>(cx).tail();
2187        self.begin_selection(position, false, click_count, cx);
2188
2189        let position = position.to_offset(&display_map, Bias::Left);
2190        let tail_anchor = display_map.buffer_snapshot.anchor_before(tail);
2191
2192        let mut pending_selection = self
2193            .selections
2194            .pending_anchor()
2195            .expect("extend_selection not called with pending selection");
2196        if position >= tail {
2197            pending_selection.start = tail_anchor;
2198        } else {
2199            pending_selection.end = tail_anchor;
2200            pending_selection.reversed = true;
2201        }
2202
2203        let mut pending_mode = self.selections.pending_mode().unwrap();
2204        match &mut pending_mode {
2205            SelectMode::Word(range) | SelectMode::Line(range) => *range = tail_anchor..tail_anchor,
2206            _ => {}
2207        }
2208
2209        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
2210            s.set_pending(pending_selection, pending_mode)
2211        });
2212    }
2213
2214    fn begin_selection(
2215        &mut self,
2216        position: DisplayPoint,
2217        add: bool,
2218        click_count: usize,
2219        cx: &mut ViewContext<Self>,
2220    ) {
2221        if !self.focused {
2222            cx.focus_self();
2223        }
2224
2225        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2226        let buffer = &display_map.buffer_snapshot;
2227        let newest_selection = self.selections.newest_anchor().clone();
2228        let position = display_map.clip_point(position, Bias::Left);
2229
2230        let start;
2231        let end;
2232        let mode;
2233        let auto_scroll;
2234        match click_count {
2235            1 => {
2236                start = buffer.anchor_before(position.to_point(&display_map));
2237                end = start.clone();
2238                mode = SelectMode::Character;
2239                auto_scroll = true;
2240            }
2241            2 => {
2242                let range = movement::surrounding_word(&display_map, position);
2243                start = buffer.anchor_before(range.start.to_point(&display_map));
2244                end = buffer.anchor_before(range.end.to_point(&display_map));
2245                mode = SelectMode::Word(start.clone()..end.clone());
2246                auto_scroll = true;
2247            }
2248            3 => {
2249                let position = display_map
2250                    .clip_point(position, Bias::Left)
2251                    .to_point(&display_map);
2252                let line_start = display_map.prev_line_boundary(position).0;
2253                let next_line_start = buffer.clip_point(
2254                    display_map.next_line_boundary(position).0 + Point::new(1, 0),
2255                    Bias::Left,
2256                );
2257                start = buffer.anchor_before(line_start);
2258                end = buffer.anchor_before(next_line_start);
2259                mode = SelectMode::Line(start.clone()..end.clone());
2260                auto_scroll = true;
2261            }
2262            _ => {
2263                start = buffer.anchor_before(0);
2264                end = buffer.anchor_before(buffer.len());
2265                mode = SelectMode::All;
2266                auto_scroll = false;
2267            }
2268        }
2269
2270        self.change_selections(auto_scroll.then(|| Autoscroll::newest()), cx, |s| {
2271            if !add {
2272                s.clear_disjoint();
2273            } else if click_count > 1 {
2274                s.delete(newest_selection.id)
2275            }
2276
2277            s.set_pending_anchor_range(start..end, mode);
2278        });
2279    }
2280
2281    fn begin_columnar_selection(
2282        &mut self,
2283        position: DisplayPoint,
2284        goal_column: u32,
2285        cx: &mut ViewContext<Self>,
2286    ) {
2287        if !self.focused {
2288            cx.focus_self();
2289        }
2290
2291        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2292        let tail = self.selections.newest::<Point>(cx).tail();
2293        self.columnar_selection_tail = Some(display_map.buffer_snapshot.anchor_before(tail));
2294
2295        self.select_columns(
2296            tail.to_display_point(&display_map),
2297            position,
2298            goal_column,
2299            &display_map,
2300            cx,
2301        );
2302    }
2303
2304    fn update_selection(
2305        &mut self,
2306        position: DisplayPoint,
2307        goal_column: u32,
2308        scroll_position: Vector2F,
2309        cx: &mut ViewContext<Self>,
2310    ) {
2311        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2312
2313        if let Some(tail) = self.columnar_selection_tail.as_ref() {
2314            let tail = tail.to_display_point(&display_map);
2315            self.select_columns(tail, position, goal_column, &display_map, cx);
2316        } else if let Some(mut pending) = self.selections.pending_anchor() {
2317            let buffer = self.buffer.read(cx).snapshot(cx);
2318            let head;
2319            let tail;
2320            let mode = self.selections.pending_mode().unwrap();
2321            match &mode {
2322                SelectMode::Character => {
2323                    head = position.to_point(&display_map);
2324                    tail = pending.tail().to_point(&buffer);
2325                }
2326                SelectMode::Word(original_range) => {
2327                    let original_display_range = original_range.start.to_display_point(&display_map)
2328                        ..original_range.end.to_display_point(&display_map);
2329                    let original_buffer_range = original_display_range.start.to_point(&display_map)
2330                        ..original_display_range.end.to_point(&display_map);
2331                    if movement::is_inside_word(&display_map, position)
2332                        || original_display_range.contains(&position)
2333                    {
2334                        let word_range = movement::surrounding_word(&display_map, position);
2335                        if word_range.start < original_display_range.start {
2336                            head = word_range.start.to_point(&display_map);
2337                        } else {
2338                            head = word_range.end.to_point(&display_map);
2339                        }
2340                    } else {
2341                        head = position.to_point(&display_map);
2342                    }
2343
2344                    if head <= original_buffer_range.start {
2345                        tail = original_buffer_range.end;
2346                    } else {
2347                        tail = original_buffer_range.start;
2348                    }
2349                }
2350                SelectMode::Line(original_range) => {
2351                    let original_range = original_range.to_point(&display_map.buffer_snapshot);
2352
2353                    let position = display_map
2354                        .clip_point(position, Bias::Left)
2355                        .to_point(&display_map);
2356                    let line_start = display_map.prev_line_boundary(position).0;
2357                    let next_line_start = buffer.clip_point(
2358                        display_map.next_line_boundary(position).0 + Point::new(1, 0),
2359                        Bias::Left,
2360                    );
2361
2362                    if line_start < original_range.start {
2363                        head = line_start
2364                    } else {
2365                        head = next_line_start
2366                    }
2367
2368                    if head <= original_range.start {
2369                        tail = original_range.end;
2370                    } else {
2371                        tail = original_range.start;
2372                    }
2373                }
2374                SelectMode::All => {
2375                    return;
2376                }
2377            };
2378
2379            if head < tail {
2380                pending.start = buffer.anchor_before(head);
2381                pending.end = buffer.anchor_before(tail);
2382                pending.reversed = true;
2383            } else {
2384                pending.start = buffer.anchor_before(tail);
2385                pending.end = buffer.anchor_before(head);
2386                pending.reversed = false;
2387            }
2388
2389            self.change_selections(None, cx, |s| {
2390                s.set_pending(pending, mode);
2391            });
2392        } else {
2393            error!("update_selection dispatched with no pending selection");
2394            return;
2395        }
2396
2397        self.set_scroll_position(scroll_position, cx);
2398        cx.notify();
2399    }
2400
2401    fn end_selection(&mut self, cx: &mut ViewContext<Self>) {
2402        self.columnar_selection_tail.take();
2403        if self.selections.pending_anchor().is_some() {
2404            let selections = self.selections.all::<usize>(cx);
2405            self.change_selections(None, cx, |s| {
2406                s.select(selections);
2407                s.clear_pending();
2408            });
2409        }
2410    }
2411
2412    fn select_columns(
2413        &mut self,
2414        tail: DisplayPoint,
2415        head: DisplayPoint,
2416        goal_column: u32,
2417        display_map: &DisplaySnapshot,
2418        cx: &mut ViewContext<Self>,
2419    ) {
2420        let start_row = cmp::min(tail.row(), head.row());
2421        let end_row = cmp::max(tail.row(), head.row());
2422        let start_column = cmp::min(tail.column(), goal_column);
2423        let end_column = cmp::max(tail.column(), goal_column);
2424        let reversed = start_column < tail.column();
2425
2426        let selection_ranges = (start_row..=end_row)
2427            .filter_map(|row| {
2428                if start_column <= display_map.line_len(row) && !display_map.is_block_line(row) {
2429                    let start = display_map
2430                        .clip_point(DisplayPoint::new(row, start_column), Bias::Left)
2431                        .to_point(display_map);
2432                    let end = display_map
2433                        .clip_point(DisplayPoint::new(row, end_column), Bias::Right)
2434                        .to_point(display_map);
2435                    if reversed {
2436                        Some(end..start)
2437                    } else {
2438                        Some(start..end)
2439                    }
2440                } else {
2441                    None
2442                }
2443            })
2444            .collect::<Vec<_>>();
2445
2446        self.change_selections(None, cx, |s| {
2447            s.select_ranges(selection_ranges);
2448        });
2449        cx.notify();
2450    }
2451
2452    pub fn has_pending_nonempty_selection(&self) -> bool {
2453        let pending_nonempty_selection = match self.selections.pending_anchor() {
2454            Some(Selection { start, end, .. }) => start != end,
2455            None => false,
2456        };
2457        pending_nonempty_selection || self.columnar_selection_tail.is_some()
2458    }
2459
2460    pub fn has_pending_selection(&self) -> bool {
2461        self.selections.pending_anchor().is_some() || self.columnar_selection_tail.is_some()
2462    }
2463
2464    pub fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {
2465        if self.take_rename(false, cx).is_some() {
2466            return;
2467        }
2468
2469        if hide_hover(self, cx) {
2470            return;
2471        }
2472
2473        if self.hide_context_menu(cx).is_some() {
2474            return;
2475        }
2476
2477        if self.discard_copilot_suggestion(cx) {
2478            return;
2479        }
2480
2481        if self.snippet_stack.pop().is_some() {
2482            return;
2483        }
2484
2485        if self.mode == EditorMode::Full {
2486            if self.active_diagnostics.is_some() {
2487                self.dismiss_diagnostics(cx);
2488                return;
2489            }
2490
2491            if self.change_selections(Some(Autoscroll::fit()), cx, |s| s.try_cancel()) {
2492                return;
2493            }
2494        }
2495
2496        cx.propagate_action();
2497    }
2498
2499    pub fn handle_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
2500        let text: Arc<str> = text.into();
2501
2502        if self.read_only {
2503            return;
2504        }
2505
2506        let selections = self.selections.all_adjusted(cx);
2507        let mut brace_inserted = false;
2508        let mut edits = Vec::new();
2509        let mut new_selections = Vec::with_capacity(selections.len());
2510        let mut new_autoclose_regions = Vec::new();
2511        let snapshot = self.buffer.read(cx).read(cx);
2512
2513        for (selection, autoclose_region) in
2514            self.selections_with_autoclose_regions(selections, &snapshot)
2515        {
2516            if let Some(scope) = snapshot.language_scope_at(selection.head()) {
2517                // Determine if the inserted text matches the opening or closing
2518                // bracket of any of this language's bracket pairs.
2519                let mut bracket_pair = None;
2520                let mut is_bracket_pair_start = false;
2521                if !text.is_empty() {
2522                    // `text` can be empty when an user is using IME (e.g. Chinese Wubi Simplified)
2523                    //  and they are removing the character that triggered IME popup.
2524                    for (pair, enabled) in scope.brackets() {
2525                        if enabled && pair.close && pair.start.ends_with(text.as_ref()) {
2526                            bracket_pair = Some(pair.clone());
2527                            is_bracket_pair_start = true;
2528                            break;
2529                        } else if pair.end.as_str() == text.as_ref() {
2530                            bracket_pair = Some(pair.clone());
2531                            break;
2532                        }
2533                    }
2534                }
2535
2536                if let Some(bracket_pair) = bracket_pair {
2537                    if selection.is_empty() {
2538                        if is_bracket_pair_start {
2539                            let prefix_len = bracket_pair.start.len() - text.len();
2540
2541                            // If the inserted text is a suffix of an opening bracket and the
2542                            // selection is preceded by the rest of the opening bracket, then
2543                            // insert the closing bracket.
2544                            let following_text_allows_autoclose = snapshot
2545                                .chars_at(selection.start)
2546                                .next()
2547                                .map_or(true, |c| scope.should_autoclose_before(c));
2548                            let preceding_text_matches_prefix = prefix_len == 0
2549                                || (selection.start.column >= (prefix_len as u32)
2550                                    && snapshot.contains_str_at(
2551                                        Point::new(
2552                                            selection.start.row,
2553                                            selection.start.column - (prefix_len as u32),
2554                                        ),
2555                                        &bracket_pair.start[..prefix_len],
2556                                    ));
2557                            if following_text_allows_autoclose && preceding_text_matches_prefix {
2558                                let anchor = snapshot.anchor_before(selection.end);
2559                                new_selections.push((selection.map(|_| anchor), text.len()));
2560                                new_autoclose_regions.push((
2561                                    anchor,
2562                                    text.len(),
2563                                    selection.id,
2564                                    bracket_pair.clone(),
2565                                ));
2566                                edits.push((
2567                                    selection.range(),
2568                                    format!("{}{}", text, bracket_pair.end).into(),
2569                                ));
2570                                brace_inserted = true;
2571                                continue;
2572                            }
2573                        }
2574
2575                        if let Some(region) = autoclose_region {
2576                            // If the selection is followed by an auto-inserted closing bracket,
2577                            // then don't insert that closing bracket again; just move the selection
2578                            // past the closing bracket.
2579                            let should_skip = selection.end == region.range.end.to_point(&snapshot)
2580                                && text.as_ref() == region.pair.end.as_str();
2581                            if should_skip {
2582                                let anchor = snapshot.anchor_after(selection.end);
2583                                new_selections
2584                                    .push((selection.map(|_| anchor), region.pair.end.len()));
2585                                continue;
2586                            }
2587                        }
2588                    }
2589                    // If an opening bracket is 1 character long and is typed while
2590                    // text is selected, then surround that text with the bracket pair.
2591                    else if is_bracket_pair_start && bracket_pair.start.chars().count() == 1 {
2592                        edits.push((selection.start..selection.start, text.clone()));
2593                        edits.push((
2594                            selection.end..selection.end,
2595                            bracket_pair.end.as_str().into(),
2596                        ));
2597                        brace_inserted = true;
2598                        new_selections.push((
2599                            Selection {
2600                                id: selection.id,
2601                                start: snapshot.anchor_after(selection.start),
2602                                end: snapshot.anchor_before(selection.end),
2603                                reversed: selection.reversed,
2604                                goal: selection.goal,
2605                            },
2606                            0,
2607                        ));
2608                        continue;
2609                    }
2610                }
2611            }
2612
2613            // If not handling any auto-close operation, then just replace the selected
2614            // text with the given input and move the selection to the end of the
2615            // newly inserted text.
2616            let anchor = snapshot.anchor_after(selection.end);
2617            new_selections.push((selection.map(|_| anchor), 0));
2618            edits.push((selection.start..selection.end, text.clone()));
2619        }
2620
2621        drop(snapshot);
2622        self.transact(cx, |this, cx| {
2623            this.buffer.update(cx, |buffer, cx| {
2624                buffer.edit(edits, this.autoindent_mode.clone(), cx);
2625            });
2626
2627            let new_anchor_selections = new_selections.iter().map(|e| &e.0);
2628            let new_selection_deltas = new_selections.iter().map(|e| e.1);
2629            let snapshot = this.buffer.read(cx).read(cx);
2630            let new_selections = resolve_multiple::<usize, _>(new_anchor_selections, &snapshot)
2631                .zip(new_selection_deltas)
2632                .map(|(selection, delta)| Selection {
2633                    id: selection.id,
2634                    start: selection.start + delta,
2635                    end: selection.end + delta,
2636                    reversed: selection.reversed,
2637                    goal: SelectionGoal::None,
2638                })
2639                .collect::<Vec<_>>();
2640
2641            let mut i = 0;
2642            for (position, delta, selection_id, pair) in new_autoclose_regions {
2643                let position = position.to_offset(&snapshot) + delta;
2644                let start = snapshot.anchor_before(position);
2645                let end = snapshot.anchor_after(position);
2646                while let Some(existing_state) = this.autoclose_regions.get(i) {
2647                    match existing_state.range.start.cmp(&start, &snapshot) {
2648                        Ordering::Less => i += 1,
2649                        Ordering::Greater => break,
2650                        Ordering::Equal => match end.cmp(&existing_state.range.end, &snapshot) {
2651                            Ordering::Less => i += 1,
2652                            Ordering::Equal => break,
2653                            Ordering::Greater => break,
2654                        },
2655                    }
2656                }
2657                this.autoclose_regions.insert(
2658                    i,
2659                    AutocloseRegion {
2660                        selection_id,
2661                        range: start..end,
2662                        pair,
2663                    },
2664                );
2665            }
2666
2667            drop(snapshot);
2668            let had_active_copilot_suggestion = this.has_active_copilot_suggestion(cx);
2669            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
2670
2671            if !brace_inserted && settings::get::<EditorSettings>(cx).use_on_type_format {
2672                if let Some(on_type_format_task) =
2673                    this.trigger_on_type_formatting(text.to_string(), cx)
2674                {
2675                    on_type_format_task.detach_and_log_err(cx);
2676                }
2677            }
2678
2679            if had_active_copilot_suggestion {
2680                this.refresh_copilot_suggestions(true, cx);
2681                if !this.has_active_copilot_suggestion(cx) {
2682                    this.trigger_completion_on_input(&text, cx);
2683                }
2684            } else {
2685                this.trigger_completion_on_input(&text, cx);
2686                this.refresh_copilot_suggestions(true, cx);
2687            }
2688        });
2689    }
2690
2691    pub fn newline(&mut self, _: &Newline, cx: &mut ViewContext<Self>) {
2692        self.transact(cx, |this, cx| {
2693            let (edits, selection_fixup_info): (Vec<_>, Vec<_>) = {
2694                let selections = this.selections.all::<usize>(cx);
2695                let multi_buffer = this.buffer.read(cx);
2696                let buffer = multi_buffer.snapshot(cx);
2697                selections
2698                    .iter()
2699                    .map(|selection| {
2700                        let start_point = selection.start.to_point(&buffer);
2701                        let mut indent = buffer.indent_size_for_line(start_point.row);
2702                        indent.len = cmp::min(indent.len, start_point.column);
2703                        let start = selection.start;
2704                        let end = selection.end;
2705                        let is_cursor = start == end;
2706                        let language_scope = buffer.language_scope_at(start);
2707                        let (comment_delimiter, insert_extra_newline) = if let Some(language) =
2708                            &language_scope
2709                        {
2710                            let leading_whitespace_len = buffer
2711                                .reversed_chars_at(start)
2712                                .take_while(|c| c.is_whitespace() && *c != '\n')
2713                                .map(|c| c.len_utf8())
2714                                .sum::<usize>();
2715
2716                            let trailing_whitespace_len = buffer
2717                                .chars_at(end)
2718                                .take_while(|c| c.is_whitespace() && *c != '\n')
2719                                .map(|c| c.len_utf8())
2720                                .sum::<usize>();
2721
2722                            let insert_extra_newline =
2723                                language.brackets().any(|(pair, enabled)| {
2724                                    let pair_start = pair.start.trim_end();
2725                                    let pair_end = pair.end.trim_start();
2726
2727                                    enabled
2728                                        && pair.newline
2729                                        && buffer.contains_str_at(
2730                                            end + trailing_whitespace_len,
2731                                            pair_end,
2732                                        )
2733                                        && buffer.contains_str_at(
2734                                            (start - leading_whitespace_len)
2735                                                .saturating_sub(pair_start.len()),
2736                                            pair_start,
2737                                        )
2738                                });
2739                            // Comment extension on newline is allowed only for cursor selections
2740                            let comment_delimiter = language.line_comment_prefix().filter(|_| {
2741                                let is_comment_extension_enabled =
2742                                    multi_buffer.settings_at(0, cx).extend_comment_on_newline;
2743                                is_cursor && is_comment_extension_enabled
2744                            });
2745                            let comment_delimiter = if let Some(delimiter) = comment_delimiter {
2746                                buffer
2747                                    .buffer_line_for_row(start_point.row)
2748                                    .is_some_and(|(snapshot, range)| {
2749                                        let mut index_of_first_non_whitespace = 0;
2750                                        let line_starts_with_comment = snapshot
2751                                            .chars_for_range(range)
2752                                            .skip_while(|c| {
2753                                                let should_skip = c.is_whitespace();
2754                                                if should_skip {
2755                                                    index_of_first_non_whitespace += 1;
2756                                                }
2757                                                should_skip
2758                                            })
2759                                            .take(delimiter.len())
2760                                            .eq(delimiter.chars());
2761                                        let cursor_is_placed_after_comment_marker =
2762                                            index_of_first_non_whitespace + delimiter.len()
2763                                                <= start_point.column as usize;
2764                                        line_starts_with_comment
2765                                            && cursor_is_placed_after_comment_marker
2766                                    })
2767                                    .then(|| delimiter.clone())
2768                            } else {
2769                                None
2770                            };
2771                            (comment_delimiter, insert_extra_newline)
2772                        } else {
2773                            (None, false)
2774                        };
2775
2776                        let capacity_for_delimiter = comment_delimiter
2777                            .as_deref()
2778                            .map(str::len)
2779                            .unwrap_or_default();
2780                        let mut new_text =
2781                            String::with_capacity(1 + capacity_for_delimiter + indent.len as usize);
2782                        new_text.push_str("\n");
2783                        new_text.extend(indent.chars());
2784                        if let Some(delimiter) = &comment_delimiter {
2785                            new_text.push_str(&delimiter);
2786                        }
2787                        if insert_extra_newline {
2788                            new_text = new_text.repeat(2);
2789                        }
2790
2791                        let anchor = buffer.anchor_after(end);
2792                        let new_selection = selection.map(|_| anchor);
2793                        (
2794                            (start..end, new_text),
2795                            (insert_extra_newline, new_selection),
2796                        )
2797                    })
2798                    .unzip()
2799            };
2800
2801            this.edit_with_autoindent(edits, cx);
2802            let buffer = this.buffer.read(cx).snapshot(cx);
2803            let new_selections = selection_fixup_info
2804                .into_iter()
2805                .map(|(extra_newline_inserted, new_selection)| {
2806                    let mut cursor = new_selection.end.to_point(&buffer);
2807                    if extra_newline_inserted {
2808                        cursor.row -= 1;
2809                        cursor.column = buffer.line_len(cursor.row);
2810                    }
2811                    new_selection.map(|_| cursor)
2812                })
2813                .collect();
2814
2815            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
2816            this.refresh_copilot_suggestions(true, cx);
2817        });
2818    }
2819
2820    pub fn newline_above(&mut self, _: &NewlineAbove, cx: &mut ViewContext<Self>) {
2821        let buffer = self.buffer.read(cx);
2822        let snapshot = buffer.snapshot(cx);
2823
2824        let mut edits = Vec::new();
2825        let mut rows = Vec::new();
2826        let mut rows_inserted = 0;
2827
2828        for selection in self.selections.all_adjusted(cx) {
2829            let cursor = selection.head();
2830            let row = cursor.row;
2831
2832            let start_of_line = snapshot.clip_point(Point::new(row, 0), Bias::Left);
2833
2834            let newline = "\n".to_string();
2835            edits.push((start_of_line..start_of_line, newline));
2836
2837            rows.push(row + rows_inserted);
2838            rows_inserted += 1;
2839        }
2840
2841        self.transact(cx, |editor, cx| {
2842            editor.edit(edits, cx);
2843
2844            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
2845                let mut index = 0;
2846                s.move_cursors_with(|map, _, _| {
2847                    let row = rows[index];
2848                    index += 1;
2849
2850                    let point = Point::new(row, 0);
2851                    let boundary = map.next_line_boundary(point).1;
2852                    let clipped = map.clip_point(boundary, Bias::Left);
2853
2854                    (clipped, SelectionGoal::None)
2855                });
2856            });
2857
2858            let mut indent_edits = Vec::new();
2859            let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
2860            for row in rows {
2861                let indents = multibuffer_snapshot.suggested_indents(row..row + 1, cx);
2862                for (row, indent) in indents {
2863                    if indent.len == 0 {
2864                        continue;
2865                    }
2866
2867                    let text = match indent.kind {
2868                        IndentKind::Space => " ".repeat(indent.len as usize),
2869                        IndentKind::Tab => "\t".repeat(indent.len as usize),
2870                    };
2871                    let point = Point::new(row, 0);
2872                    indent_edits.push((point..point, text));
2873                }
2874            }
2875            editor.edit(indent_edits, cx);
2876        });
2877    }
2878
2879    pub fn newline_below(&mut self, _: &NewlineBelow, cx: &mut ViewContext<Self>) {
2880        let buffer = self.buffer.read(cx);
2881        let snapshot = buffer.snapshot(cx);
2882
2883        let mut edits = Vec::new();
2884        let mut rows = Vec::new();
2885        let mut rows_inserted = 0;
2886
2887        for selection in self.selections.all_adjusted(cx) {
2888            let cursor = selection.head();
2889            let row = cursor.row;
2890
2891            let point = Point::new(row + 1, 0);
2892            let start_of_line = snapshot.clip_point(point, Bias::Left);
2893
2894            let newline = "\n".to_string();
2895            edits.push((start_of_line..start_of_line, newline));
2896
2897            rows_inserted += 1;
2898            rows.push(row + rows_inserted);
2899        }
2900
2901        self.transact(cx, |editor, cx| {
2902            editor.edit(edits, cx);
2903
2904            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
2905                let mut index = 0;
2906                s.move_cursors_with(|map, _, _| {
2907                    let row = rows[index];
2908                    index += 1;
2909
2910                    let point = Point::new(row, 0);
2911                    let boundary = map.next_line_boundary(point).1;
2912                    let clipped = map.clip_point(boundary, Bias::Left);
2913
2914                    (clipped, SelectionGoal::None)
2915                });
2916            });
2917
2918            let mut indent_edits = Vec::new();
2919            let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
2920            for row in rows {
2921                let indents = multibuffer_snapshot.suggested_indents(row..row + 1, cx);
2922                for (row, indent) in indents {
2923                    if indent.len == 0 {
2924                        continue;
2925                    }
2926
2927                    let text = match indent.kind {
2928                        IndentKind::Space => " ".repeat(indent.len as usize),
2929                        IndentKind::Tab => "\t".repeat(indent.len as usize),
2930                    };
2931                    let point = Point::new(row, 0);
2932                    indent_edits.push((point..point, text));
2933                }
2934            }
2935            editor.edit(indent_edits, cx);
2936        });
2937    }
2938
2939    pub fn insert(&mut self, text: &str, cx: &mut ViewContext<Self>) {
2940        self.insert_with_autoindent_mode(
2941            text,
2942            Some(AutoindentMode::Block {
2943                original_indent_columns: Vec::new(),
2944            }),
2945            cx,
2946        );
2947    }
2948
2949    fn insert_with_autoindent_mode(
2950        &mut self,
2951        text: &str,
2952        autoindent_mode: Option<AutoindentMode>,
2953        cx: &mut ViewContext<Self>,
2954    ) {
2955        if self.read_only {
2956            return;
2957        }
2958
2959        let text: Arc<str> = text.into();
2960        self.transact(cx, |this, cx| {
2961            let old_selections = this.selections.all_adjusted(cx);
2962            let selection_anchors = this.buffer.update(cx, |buffer, cx| {
2963                let anchors = {
2964                    let snapshot = buffer.read(cx);
2965                    old_selections
2966                        .iter()
2967                        .map(|s| {
2968                            let anchor = snapshot.anchor_after(s.head());
2969                            s.map(|_| anchor)
2970                        })
2971                        .collect::<Vec<_>>()
2972                };
2973                buffer.edit(
2974                    old_selections
2975                        .iter()
2976                        .map(|s| (s.start..s.end, text.clone())),
2977                    autoindent_mode,
2978                    cx,
2979                );
2980                anchors
2981            });
2982
2983            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
2984                s.select_anchors(selection_anchors);
2985            })
2986        });
2987    }
2988
2989    fn trigger_completion_on_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
2990        if !settings::get::<EditorSettings>(cx).show_completions_on_input {
2991            return;
2992        }
2993
2994        let selection = self.selections.newest_anchor();
2995        if self
2996            .buffer
2997            .read(cx)
2998            .is_completion_trigger(selection.head(), text, cx)
2999        {
3000            self.show_completions(&ShowCompletions, cx);
3001        } else {
3002            self.hide_context_menu(cx);
3003        }
3004    }
3005
3006    /// If any empty selections is touching the start of its innermost containing autoclose
3007    /// region, expand it to select the brackets.
3008    fn select_autoclose_pair(&mut self, cx: &mut ViewContext<Self>) {
3009        let selections = self.selections.all::<usize>(cx);
3010        let buffer = self.buffer.read(cx).read(cx);
3011        let mut new_selections = Vec::new();
3012        for (mut selection, region) in self.selections_with_autoclose_regions(selections, &buffer) {
3013            if let (Some(region), true) = (region, selection.is_empty()) {
3014                let mut range = region.range.to_offset(&buffer);
3015                if selection.start == range.start {
3016                    if range.start >= region.pair.start.len() {
3017                        range.start -= region.pair.start.len();
3018                        if buffer.contains_str_at(range.start, &region.pair.start) {
3019                            if buffer.contains_str_at(range.end, &region.pair.end) {
3020                                range.end += region.pair.end.len();
3021                                selection.start = range.start;
3022                                selection.end = range.end;
3023                            }
3024                        }
3025                    }
3026                }
3027            }
3028            new_selections.push(selection);
3029        }
3030
3031        drop(buffer);
3032        self.change_selections(None, cx, |selections| selections.select(new_selections));
3033    }
3034
3035    /// Iterate the given selections, and for each one, find the smallest surrounding
3036    /// autoclose region. This uses the ordering of the selections and the autoclose
3037    /// regions to avoid repeated comparisons.
3038    fn selections_with_autoclose_regions<'a, D: ToOffset + Clone>(
3039        &'a self,
3040        selections: impl IntoIterator<Item = Selection<D>>,
3041        buffer: &'a MultiBufferSnapshot,
3042    ) -> impl Iterator<Item = (Selection<D>, Option<&'a AutocloseRegion>)> {
3043        let mut i = 0;
3044        let mut regions = self.autoclose_regions.as_slice();
3045        selections.into_iter().map(move |selection| {
3046            let range = selection.start.to_offset(buffer)..selection.end.to_offset(buffer);
3047
3048            let mut enclosing = None;
3049            while let Some(pair_state) = regions.get(i) {
3050                if pair_state.range.end.to_offset(buffer) < range.start {
3051                    regions = &regions[i + 1..];
3052                    i = 0;
3053                } else if pair_state.range.start.to_offset(buffer) > range.end {
3054                    break;
3055                } else if pair_state.selection_id == selection.id {
3056                    enclosing = Some(pair_state);
3057                    i += 1;
3058                }
3059            }
3060
3061            (selection.clone(), enclosing)
3062        })
3063    }
3064
3065    /// Remove any autoclose regions that no longer contain their selection.
3066    fn invalidate_autoclose_regions(
3067        &mut self,
3068        mut selections: &[Selection<Anchor>],
3069        buffer: &MultiBufferSnapshot,
3070    ) {
3071        self.autoclose_regions.retain(|state| {
3072            let mut i = 0;
3073            while let Some(selection) = selections.get(i) {
3074                if selection.end.cmp(&state.range.start, buffer).is_lt() {
3075                    selections = &selections[1..];
3076                    continue;
3077                }
3078                if selection.start.cmp(&state.range.end, buffer).is_gt() {
3079                    break;
3080                }
3081                if selection.id == state.selection_id {
3082                    return true;
3083                } else {
3084                    i += 1;
3085                }
3086            }
3087            false
3088        });
3089    }
3090    fn completion_query(buffer: &MultiBufferSnapshot, position: impl ToOffset) -> Option<String> {
3091        let offset = position.to_offset(buffer);
3092        let (word_range, kind) = buffer.surrounding_word(offset);
3093        if offset > word_range.start && kind == Some(CharKind::Word) {
3094            Some(
3095                buffer
3096                    .text_for_range(word_range.start..offset)
3097                    .collect::<String>(),
3098            )
3099        } else {
3100            None
3101        }
3102    }
3103
3104    pub fn toggle_inlay_hints(&mut self, _: &ToggleInlayHints, cx: &mut ViewContext<Self>) {
3105        self.refresh_inlay_hints(
3106            InlayHintRefreshReason::Toggle(!self.inlay_hint_cache.enabled),
3107            cx,
3108        );
3109    }
3110
3111    pub fn inlay_hints_enabled(&self) -> bool {
3112        self.inlay_hint_cache.enabled
3113    }
3114
3115    fn refresh_inlay_hints(&mut self, reason: InlayHintRefreshReason, cx: &mut ViewContext<Self>) {
3116        if self.project.is_none() || self.mode != EditorMode::Full {
3117            return;
3118        }
3119
3120        let reason_description = reason.description();
3121        let (invalidate_cache, required_languages) = match reason {
3122            InlayHintRefreshReason::Toggle(enabled) => {
3123                self.inlay_hint_cache.enabled = enabled;
3124                if enabled {
3125                    (InvalidationStrategy::RefreshRequested, None)
3126                } else {
3127                    self.inlay_hint_cache.clear();
3128                    self.splice_inlay_hints(
3129                        self.visible_inlay_hints(cx)
3130                            .iter()
3131                            .map(|inlay| inlay.id)
3132                            .collect(),
3133                        Vec::new(),
3134                        cx,
3135                    );
3136                    return;
3137                }
3138            }
3139            InlayHintRefreshReason::SettingsChange(new_settings) => {
3140                match self.inlay_hint_cache.update_settings(
3141                    &self.buffer,
3142                    new_settings,
3143                    self.visible_inlay_hints(cx),
3144                    cx,
3145                ) {
3146                    ControlFlow::Break(Some(InlaySplice {
3147                        to_remove,
3148                        to_insert,
3149                    })) => {
3150                        self.splice_inlay_hints(to_remove, to_insert, cx);
3151                        return;
3152                    }
3153                    ControlFlow::Break(None) => return,
3154                    ControlFlow::Continue(()) => (InvalidationStrategy::RefreshRequested, None),
3155                }
3156            }
3157            InlayHintRefreshReason::ExcerptsRemoved(excerpts_removed) => {
3158                if let Some(InlaySplice {
3159                    to_remove,
3160                    to_insert,
3161                }) = self.inlay_hint_cache.remove_excerpts(excerpts_removed)
3162                {
3163                    self.splice_inlay_hints(to_remove, to_insert, cx);
3164                }
3165                return;
3166            }
3167            InlayHintRefreshReason::NewLinesShown => (InvalidationStrategy::None, None),
3168            InlayHintRefreshReason::BufferEdited(buffer_languages) => {
3169                (InvalidationStrategy::BufferEdited, Some(buffer_languages))
3170            }
3171            InlayHintRefreshReason::RefreshRequested => {
3172                (InvalidationStrategy::RefreshRequested, None)
3173            }
3174        };
3175
3176        if let Some(InlaySplice {
3177            to_remove,
3178            to_insert,
3179        }) = self.inlay_hint_cache.spawn_hint_refresh(
3180            reason_description,
3181            self.excerpt_visible_offsets(required_languages.as_ref(), cx),
3182            invalidate_cache,
3183            cx,
3184        ) {
3185            self.splice_inlay_hints(to_remove, to_insert, cx);
3186        }
3187    }
3188
3189    fn visible_inlay_hints(&self, cx: &ViewContext<'_, '_, Editor>) -> Vec<Inlay> {
3190        self.display_map
3191            .read(cx)
3192            .current_inlays()
3193            .filter(move |inlay| {
3194                Some(inlay.id) != self.copilot_state.suggestion.as_ref().map(|h| h.id)
3195            })
3196            .cloned()
3197            .collect()
3198    }
3199
3200    pub fn excerpt_visible_offsets(
3201        &self,
3202        restrict_to_languages: Option<&HashSet<Arc<Language>>>,
3203        cx: &mut ViewContext<'_, '_, Editor>,
3204    ) -> HashMap<ExcerptId, (ModelHandle<Buffer>, Global, Range<usize>)> {
3205        let multi_buffer = self.buffer().read(cx);
3206        let multi_buffer_snapshot = multi_buffer.snapshot(cx);
3207        let multi_buffer_visible_start = self
3208            .scroll_manager
3209            .anchor()
3210            .anchor
3211            .to_point(&multi_buffer_snapshot);
3212        let multi_buffer_visible_end = multi_buffer_snapshot.clip_point(
3213            multi_buffer_visible_start
3214                + Point::new(self.visible_line_count().unwrap_or(0.).ceil() as u32, 0),
3215            Bias::Left,
3216        );
3217        let multi_buffer_visible_range = multi_buffer_visible_start..multi_buffer_visible_end;
3218        multi_buffer
3219            .range_to_buffer_ranges(multi_buffer_visible_range, cx)
3220            .into_iter()
3221            .filter(|(_, excerpt_visible_range, _)| !excerpt_visible_range.is_empty())
3222            .filter_map(|(buffer_handle, excerpt_visible_range, excerpt_id)| {
3223                let buffer = buffer_handle.read(cx);
3224                let language = buffer.language()?;
3225                if let Some(restrict_to_languages) = restrict_to_languages {
3226                    if !restrict_to_languages.contains(language) {
3227                        return None;
3228                    }
3229                }
3230                Some((
3231                    excerpt_id,
3232                    (
3233                        buffer_handle,
3234                        buffer.version().clone(),
3235                        excerpt_visible_range,
3236                    ),
3237                ))
3238            })
3239            .collect()
3240    }
3241
3242    fn splice_inlay_hints(
3243        &self,
3244        to_remove: Vec<InlayId>,
3245        to_insert: Vec<Inlay>,
3246        cx: &mut ViewContext<Self>,
3247    ) {
3248        self.display_map.update(cx, |display_map, cx| {
3249            display_map.splice_inlays(to_remove, to_insert, cx);
3250        });
3251        cx.notify();
3252    }
3253
3254    fn trigger_on_type_formatting(
3255        &self,
3256        input: String,
3257        cx: &mut ViewContext<Self>,
3258    ) -> Option<Task<Result<()>>> {
3259        if input.len() != 1 {
3260            return None;
3261        }
3262
3263        let project = self.project.as_ref()?;
3264        let position = self.selections.newest_anchor().head();
3265        let (buffer, buffer_position) = self
3266            .buffer
3267            .read(cx)
3268            .text_anchor_for_position(position.clone(), cx)?;
3269
3270        // OnTypeFormatting returns a list of edits, no need to pass them between Zed instances,
3271        // hence we do LSP request & edit on host side only — add formats to host's history.
3272        let push_to_lsp_host_history = true;
3273        // If this is not the host, append its history with new edits.
3274        let push_to_client_history = project.read(cx).is_remote();
3275
3276        let on_type_formatting = project.update(cx, |project, cx| {
3277            project.on_type_format(
3278                buffer.clone(),
3279                buffer_position,
3280                input,
3281                push_to_lsp_host_history,
3282                cx,
3283            )
3284        });
3285        Some(cx.spawn(|editor, mut cx| async move {
3286            if let Some(transaction) = on_type_formatting.await? {
3287                if push_to_client_history {
3288                    buffer.update(&mut cx, |buffer, _| {
3289                        buffer.push_transaction(transaction, Instant::now());
3290                    });
3291                }
3292                editor.update(&mut cx, |editor, cx| {
3293                    editor.refresh_document_highlights(cx);
3294                })?;
3295            }
3296            Ok(())
3297        }))
3298    }
3299
3300    fn show_completions(&mut self, _: &ShowCompletions, cx: &mut ViewContext<Self>) {
3301        if self.pending_rename.is_some() {
3302            return;
3303        }
3304
3305        let project = if let Some(project) = self.project.clone() {
3306            project
3307        } else {
3308            return;
3309        };
3310
3311        let position = self.selections.newest_anchor().head();
3312        let (buffer, buffer_position) = if let Some(output) = self
3313            .buffer
3314            .read(cx)
3315            .text_anchor_for_position(position.clone(), cx)
3316        {
3317            output
3318        } else {
3319            return;
3320        };
3321
3322        let query = Self::completion_query(&self.buffer.read(cx).read(cx), position.clone());
3323        let completions = project.update(cx, |project, cx| {
3324            project.completions(&buffer, buffer_position, cx)
3325        });
3326
3327        let id = post_inc(&mut self.next_completion_id);
3328        let task = cx.spawn(|this, mut cx| {
3329            async move {
3330                let menu = if let Some(completions) = completions.await.log_err() {
3331                    let mut menu = CompletionsMenu {
3332                        id,
3333                        initial_position: position,
3334                        match_candidates: completions
3335                            .iter()
3336                            .enumerate()
3337                            .map(|(id, completion)| {
3338                                StringMatchCandidate::new(
3339                                    id,
3340                                    completion.label.text[completion.label.filter_range.clone()]
3341                                        .into(),
3342                                )
3343                            })
3344                            .collect(),
3345                        buffer,
3346                        completions: Arc::new(RwLock::new(completions.into())),
3347                        matches: Vec::new().into(),
3348                        selected_item: 0,
3349                        list: Default::default(),
3350                    };
3351                    menu.filter(query.as_deref(), cx.background()).await;
3352                    if menu.matches.is_empty() {
3353                        None
3354                    } else {
3355                        _ = this.update(&mut cx, |editor, cx| {
3356                            menu.attempt_resolve_selected_completion(editor.project.as_ref(), cx);
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, 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
5533            .context_menu
5534            .as_mut()
5535            .map(|menu| menu.select_last(self.project.as_ref(), cx))
5536            .unwrap_or(false)
5537        {
5538            return;
5539        }
5540
5541        if matches!(self.mode, EditorMode::SingleLine) {
5542            cx.propagate_action();
5543            return;
5544        }
5545
5546        let row_count = if let Some(row_count) = self.visible_line_count() {
5547            row_count as u32 - 1
5548        } else {
5549            return;
5550        };
5551
5552        let autoscroll = if action.center_cursor {
5553            Autoscroll::center()
5554        } else {
5555            Autoscroll::fit()
5556        };
5557
5558        self.change_selections(Some(autoscroll), cx, |s| {
5559            let line_mode = s.line_mode;
5560            s.move_with(|map, selection| {
5561                if !selection.is_empty() && !line_mode {
5562                    selection.goal = SelectionGoal::None;
5563                }
5564                let (cursor, goal) =
5565                    movement::down_by_rows(map, selection.end, row_count, selection.goal, false);
5566                selection.collapse_to(cursor, goal);
5567            });
5568        });
5569    }
5570
5571    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
5572        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5573            s.move_heads_with(|map, head, goal| movement::down(map, head, goal, false))
5574        });
5575    }
5576
5577    pub fn context_menu_first(&mut self, _: &ContextMenuFirst, cx: &mut ViewContext<Self>) {
5578        if let Some(context_menu) = self.context_menu.as_mut() {
5579            context_menu.select_first(self.project.as_ref(), cx);
5580        }
5581    }
5582
5583    pub fn context_menu_prev(&mut self, _: &ContextMenuPrev, cx: &mut ViewContext<Self>) {
5584        if let Some(context_menu) = self.context_menu.as_mut() {
5585            context_menu.select_prev(self.project.as_ref(), cx);
5586        }
5587    }
5588
5589    pub fn context_menu_next(&mut self, _: &ContextMenuNext, cx: &mut ViewContext<Self>) {
5590        if let Some(context_menu) = self.context_menu.as_mut() {
5591            context_menu.select_next(self.project.as_ref(), cx);
5592        }
5593    }
5594
5595    pub fn context_menu_last(&mut self, _: &ContextMenuLast, cx: &mut ViewContext<Self>) {
5596        if let Some(context_menu) = self.context_menu.as_mut() {
5597            context_menu.select_last(self.project.as_ref(), cx);
5598        }
5599    }
5600
5601    pub fn move_to_previous_word_start(
5602        &mut self,
5603        _: &MoveToPreviousWordStart,
5604        cx: &mut ViewContext<Self>,
5605    ) {
5606        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5607            s.move_cursors_with(|map, head, _| {
5608                (
5609                    movement::previous_word_start(map, head),
5610                    SelectionGoal::None,
5611                )
5612            });
5613        })
5614    }
5615
5616    pub fn move_to_previous_subword_start(
5617        &mut self,
5618        _: &MoveToPreviousSubwordStart,
5619        cx: &mut ViewContext<Self>,
5620    ) {
5621        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5622            s.move_cursors_with(|map, head, _| {
5623                (
5624                    movement::previous_subword_start(map, head),
5625                    SelectionGoal::None,
5626                )
5627            });
5628        })
5629    }
5630
5631    pub fn select_to_previous_word_start(
5632        &mut self,
5633        _: &SelectToPreviousWordStart,
5634        cx: &mut ViewContext<Self>,
5635    ) {
5636        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5637            s.move_heads_with(|map, head, _| {
5638                (
5639                    movement::previous_word_start(map, head),
5640                    SelectionGoal::None,
5641                )
5642            });
5643        })
5644    }
5645
5646    pub fn select_to_previous_subword_start(
5647        &mut self,
5648        _: &SelectToPreviousSubwordStart,
5649        cx: &mut ViewContext<Self>,
5650    ) {
5651        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5652            s.move_heads_with(|map, head, _| {
5653                (
5654                    movement::previous_subword_start(map, head),
5655                    SelectionGoal::None,
5656                )
5657            });
5658        })
5659    }
5660
5661    pub fn delete_to_previous_word_start(
5662        &mut self,
5663        _: &DeleteToPreviousWordStart,
5664        cx: &mut ViewContext<Self>,
5665    ) {
5666        self.transact(cx, |this, cx| {
5667            this.select_autoclose_pair(cx);
5668            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5669                let line_mode = s.line_mode;
5670                s.move_with(|map, selection| {
5671                    if selection.is_empty() && !line_mode {
5672                        let cursor = movement::previous_word_start(map, selection.head());
5673                        selection.set_head(cursor, SelectionGoal::None);
5674                    }
5675                });
5676            });
5677            this.insert("", cx);
5678        });
5679    }
5680
5681    pub fn delete_to_previous_subword_start(
5682        &mut self,
5683        _: &DeleteToPreviousSubwordStart,
5684        cx: &mut ViewContext<Self>,
5685    ) {
5686        self.transact(cx, |this, cx| {
5687            this.select_autoclose_pair(cx);
5688            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5689                let line_mode = s.line_mode;
5690                s.move_with(|map, selection| {
5691                    if selection.is_empty() && !line_mode {
5692                        let cursor = movement::previous_subword_start(map, selection.head());
5693                        selection.set_head(cursor, SelectionGoal::None);
5694                    }
5695                });
5696            });
5697            this.insert("", cx);
5698        });
5699    }
5700
5701    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
5702        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5703            s.move_cursors_with(|map, head, _| {
5704                (movement::next_word_end(map, head), SelectionGoal::None)
5705            });
5706        })
5707    }
5708
5709    pub fn move_to_next_subword_end(
5710        &mut self,
5711        _: &MoveToNextSubwordEnd,
5712        cx: &mut ViewContext<Self>,
5713    ) {
5714        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5715            s.move_cursors_with(|map, head, _| {
5716                (movement::next_subword_end(map, head), SelectionGoal::None)
5717            });
5718        })
5719    }
5720
5721    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
5722        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5723            s.move_heads_with(|map, head, _| {
5724                (movement::next_word_end(map, head), SelectionGoal::None)
5725            });
5726        })
5727    }
5728
5729    pub fn select_to_next_subword_end(
5730        &mut self,
5731        _: &SelectToNextSubwordEnd,
5732        cx: &mut ViewContext<Self>,
5733    ) {
5734        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5735            s.move_heads_with(|map, head, _| {
5736                (movement::next_subword_end(map, head), SelectionGoal::None)
5737            });
5738        })
5739    }
5740
5741    pub fn delete_to_next_word_end(&mut self, _: &DeleteToNextWordEnd, cx: &mut ViewContext<Self>) {
5742        self.transact(cx, |this, cx| {
5743            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5744                let line_mode = s.line_mode;
5745                s.move_with(|map, selection| {
5746                    if selection.is_empty() && !line_mode {
5747                        let cursor = movement::next_word_end(map, selection.head());
5748                        selection.set_head(cursor, SelectionGoal::None);
5749                    }
5750                });
5751            });
5752            this.insert("", cx);
5753        });
5754    }
5755
5756    pub fn delete_to_next_subword_end(
5757        &mut self,
5758        _: &DeleteToNextSubwordEnd,
5759        cx: &mut ViewContext<Self>,
5760    ) {
5761        self.transact(cx, |this, cx| {
5762            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5763                s.move_with(|map, selection| {
5764                    if selection.is_empty() {
5765                        let cursor = movement::next_subword_end(map, selection.head());
5766                        selection.set_head(cursor, SelectionGoal::None);
5767                    }
5768                });
5769            });
5770            this.insert("", cx);
5771        });
5772    }
5773
5774    pub fn move_to_beginning_of_line(
5775        &mut self,
5776        _: &MoveToBeginningOfLine,
5777        cx: &mut ViewContext<Self>,
5778    ) {
5779        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5780            s.move_cursors_with(|map, head, _| {
5781                (
5782                    movement::indented_line_beginning(map, head, true),
5783                    SelectionGoal::None,
5784                )
5785            });
5786        })
5787    }
5788
5789    pub fn select_to_beginning_of_line(
5790        &mut self,
5791        action: &SelectToBeginningOfLine,
5792        cx: &mut ViewContext<Self>,
5793    ) {
5794        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5795            s.move_heads_with(|map, head, _| {
5796                (
5797                    movement::indented_line_beginning(map, head, action.stop_at_soft_wraps),
5798                    SelectionGoal::None,
5799                )
5800            });
5801        });
5802    }
5803
5804    pub fn delete_to_beginning_of_line(
5805        &mut self,
5806        _: &DeleteToBeginningOfLine,
5807        cx: &mut ViewContext<Self>,
5808    ) {
5809        self.transact(cx, |this, cx| {
5810            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5811                s.move_with(|_, selection| {
5812                    selection.reversed = true;
5813                });
5814            });
5815
5816            this.select_to_beginning_of_line(
5817                &SelectToBeginningOfLine {
5818                    stop_at_soft_wraps: false,
5819                },
5820                cx,
5821            );
5822            this.backspace(&Backspace, cx);
5823        });
5824    }
5825
5826    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
5827        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5828            s.move_cursors_with(|map, head, _| {
5829                (movement::line_end(map, head, true), SelectionGoal::None)
5830            });
5831        })
5832    }
5833
5834    pub fn select_to_end_of_line(
5835        &mut self,
5836        action: &SelectToEndOfLine,
5837        cx: &mut ViewContext<Self>,
5838    ) {
5839        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5840            s.move_heads_with(|map, head, _| {
5841                (
5842                    movement::line_end(map, head, action.stop_at_soft_wraps),
5843                    SelectionGoal::None,
5844                )
5845            });
5846        })
5847    }
5848
5849    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
5850        self.transact(cx, |this, cx| {
5851            this.select_to_end_of_line(
5852                &SelectToEndOfLine {
5853                    stop_at_soft_wraps: false,
5854                },
5855                cx,
5856            );
5857            this.delete(&Delete, cx);
5858        });
5859    }
5860
5861    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
5862        self.transact(cx, |this, cx| {
5863            this.select_to_end_of_line(
5864                &SelectToEndOfLine {
5865                    stop_at_soft_wraps: false,
5866                },
5867                cx,
5868            );
5869            this.cut(&Cut, cx);
5870        });
5871    }
5872
5873    pub fn move_to_start_of_paragraph(
5874        &mut self,
5875        _: &MoveToStartOfParagraph,
5876        cx: &mut ViewContext<Self>,
5877    ) {
5878        if matches!(self.mode, EditorMode::SingleLine) {
5879            cx.propagate_action();
5880            return;
5881        }
5882
5883        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5884            s.move_with(|map, selection| {
5885                selection.collapse_to(
5886                    movement::start_of_paragraph(map, selection.head(), 1),
5887                    SelectionGoal::None,
5888                )
5889            });
5890        })
5891    }
5892
5893    pub fn move_to_end_of_paragraph(
5894        &mut self,
5895        _: &MoveToEndOfParagraph,
5896        cx: &mut ViewContext<Self>,
5897    ) {
5898        if matches!(self.mode, EditorMode::SingleLine) {
5899            cx.propagate_action();
5900            return;
5901        }
5902
5903        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5904            s.move_with(|map, selection| {
5905                selection.collapse_to(
5906                    movement::end_of_paragraph(map, selection.head(), 1),
5907                    SelectionGoal::None,
5908                )
5909            });
5910        })
5911    }
5912
5913    pub fn select_to_start_of_paragraph(
5914        &mut self,
5915        _: &SelectToStartOfParagraph,
5916        cx: &mut ViewContext<Self>,
5917    ) {
5918        if matches!(self.mode, EditorMode::SingleLine) {
5919            cx.propagate_action();
5920            return;
5921        }
5922
5923        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5924            s.move_heads_with(|map, head, _| {
5925                (
5926                    movement::start_of_paragraph(map, head, 1),
5927                    SelectionGoal::None,
5928                )
5929            });
5930        })
5931    }
5932
5933    pub fn select_to_end_of_paragraph(
5934        &mut self,
5935        _: &SelectToEndOfParagraph,
5936        cx: &mut ViewContext<Self>,
5937    ) {
5938        if matches!(self.mode, EditorMode::SingleLine) {
5939            cx.propagate_action();
5940            return;
5941        }
5942
5943        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5944            s.move_heads_with(|map, head, _| {
5945                (
5946                    movement::end_of_paragraph(map, head, 1),
5947                    SelectionGoal::None,
5948                )
5949            });
5950        })
5951    }
5952
5953    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
5954        if matches!(self.mode, EditorMode::SingleLine) {
5955            cx.propagate_action();
5956            return;
5957        }
5958
5959        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5960            s.select_ranges(vec![0..0]);
5961        });
5962    }
5963
5964    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
5965        let mut selection = self.selections.last::<Point>(cx);
5966        selection.set_head(Point::zero(), SelectionGoal::None);
5967
5968        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5969            s.select(vec![selection]);
5970        });
5971    }
5972
5973    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
5974        if matches!(self.mode, EditorMode::SingleLine) {
5975            cx.propagate_action();
5976            return;
5977        }
5978
5979        let cursor = self.buffer.read(cx).read(cx).len();
5980        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5981            s.select_ranges(vec![cursor..cursor])
5982        });
5983    }
5984
5985    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
5986        self.nav_history = nav_history;
5987    }
5988
5989    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
5990        self.nav_history.as_ref()
5991    }
5992
5993    fn push_to_nav_history(
5994        &mut self,
5995        cursor_anchor: Anchor,
5996        new_position: Option<Point>,
5997        cx: &mut ViewContext<Self>,
5998    ) {
5999        if let Some(nav_history) = self.nav_history.as_mut() {
6000            let buffer = self.buffer.read(cx).read(cx);
6001            let cursor_position = cursor_anchor.to_point(&buffer);
6002            let scroll_state = self.scroll_manager.anchor();
6003            let scroll_top_row = scroll_state.top_row(&buffer);
6004            drop(buffer);
6005
6006            if let Some(new_position) = new_position {
6007                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
6008                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
6009                    return;
6010                }
6011            }
6012
6013            nav_history.push(
6014                Some(NavigationData {
6015                    cursor_anchor,
6016                    cursor_position,
6017                    scroll_anchor: scroll_state,
6018                    scroll_top_row,
6019                }),
6020                cx,
6021            );
6022        }
6023    }
6024
6025    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
6026        let buffer = self.buffer.read(cx).snapshot(cx);
6027        let mut selection = self.selections.first::<usize>(cx);
6028        selection.set_head(buffer.len(), SelectionGoal::None);
6029        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6030            s.select(vec![selection]);
6031        });
6032    }
6033
6034    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
6035        let end = self.buffer.read(cx).read(cx).len();
6036        self.change_selections(None, cx, |s| {
6037            s.select_ranges(vec![0..end]);
6038        });
6039    }
6040
6041    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
6042        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6043        let mut selections = self.selections.all::<Point>(cx);
6044        let max_point = display_map.buffer_snapshot.max_point();
6045        for selection in &mut selections {
6046            let rows = selection.spanned_rows(true, &display_map);
6047            selection.start = Point::new(rows.start, 0);
6048            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
6049            selection.reversed = false;
6050        }
6051        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6052            s.select(selections);
6053        });
6054    }
6055
6056    pub fn split_selection_into_lines(
6057        &mut self,
6058        _: &SplitSelectionIntoLines,
6059        cx: &mut ViewContext<Self>,
6060    ) {
6061        let mut to_unfold = Vec::new();
6062        let mut new_selection_ranges = Vec::new();
6063        {
6064            let selections = self.selections.all::<Point>(cx);
6065            let buffer = self.buffer.read(cx).read(cx);
6066            for selection in selections {
6067                for row in selection.start.row..selection.end.row {
6068                    let cursor = Point::new(row, buffer.line_len(row));
6069                    new_selection_ranges.push(cursor..cursor);
6070                }
6071                new_selection_ranges.push(selection.end..selection.end);
6072                to_unfold.push(selection.start..selection.end);
6073            }
6074        }
6075        self.unfold_ranges(to_unfold, true, true, cx);
6076        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6077            s.select_ranges(new_selection_ranges);
6078        });
6079    }
6080
6081    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
6082        self.add_selection(true, cx);
6083    }
6084
6085    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
6086        self.add_selection(false, cx);
6087    }
6088
6089    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
6090        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6091        let mut selections = self.selections.all::<Point>(cx);
6092        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
6093            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
6094            let range = oldest_selection.display_range(&display_map).sorted();
6095            let columns = cmp::min(range.start.column(), range.end.column())
6096                ..cmp::max(range.start.column(), range.end.column());
6097
6098            selections.clear();
6099            let mut stack = Vec::new();
6100            for row in range.start.row()..=range.end.row() {
6101                if let Some(selection) = self.selections.build_columnar_selection(
6102                    &display_map,
6103                    row,
6104                    &columns,
6105                    oldest_selection.reversed,
6106                ) {
6107                    stack.push(selection.id);
6108                    selections.push(selection);
6109                }
6110            }
6111
6112            if above {
6113                stack.reverse();
6114            }
6115
6116            AddSelectionsState { above, stack }
6117        });
6118
6119        let last_added_selection = *state.stack.last().unwrap();
6120        let mut new_selections = Vec::new();
6121        if above == state.above {
6122            let end_row = if above {
6123                0
6124            } else {
6125                display_map.max_point().row()
6126            };
6127
6128            'outer: for selection in selections {
6129                if selection.id == last_added_selection {
6130                    let range = selection.display_range(&display_map).sorted();
6131                    debug_assert_eq!(range.start.row(), range.end.row());
6132                    let mut row = range.start.row();
6133                    let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
6134                    {
6135                        start..end
6136                    } else {
6137                        cmp::min(range.start.column(), range.end.column())
6138                            ..cmp::max(range.start.column(), range.end.column())
6139                    };
6140
6141                    while row != end_row {
6142                        if above {
6143                            row -= 1;
6144                        } else {
6145                            row += 1;
6146                        }
6147
6148                        if let Some(new_selection) = self.selections.build_columnar_selection(
6149                            &display_map,
6150                            row,
6151                            &columns,
6152                            selection.reversed,
6153                        ) {
6154                            state.stack.push(new_selection.id);
6155                            if above {
6156                                new_selections.push(new_selection);
6157                                new_selections.push(selection);
6158                            } else {
6159                                new_selections.push(selection);
6160                                new_selections.push(new_selection);
6161                            }
6162
6163                            continue 'outer;
6164                        }
6165                    }
6166                }
6167
6168                new_selections.push(selection);
6169            }
6170        } else {
6171            new_selections = selections;
6172            new_selections.retain(|s| s.id != last_added_selection);
6173            state.stack.pop();
6174        }
6175
6176        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6177            s.select(new_selections);
6178        });
6179        if state.stack.len() > 1 {
6180            self.add_selections_state = Some(state);
6181        }
6182    }
6183
6184    pub fn select_next_match_internal(
6185        &mut self,
6186        display_map: &DisplaySnapshot,
6187        replace_newest: bool,
6188        autoscroll: Option<Autoscroll>,
6189        cx: &mut ViewContext<Self>,
6190    ) -> Result<()> {
6191        fn select_next_match_ranges(
6192            this: &mut Editor,
6193            range: Range<usize>,
6194            replace_newest: bool,
6195            auto_scroll: Option<Autoscroll>,
6196            cx: &mut ViewContext<Editor>,
6197        ) {
6198            this.unfold_ranges([range.clone()], false, true, cx);
6199            this.change_selections(auto_scroll, cx, |s| {
6200                if replace_newest {
6201                    s.delete(s.newest_anchor().id);
6202                }
6203                s.insert_range(range.clone());
6204            });
6205        }
6206
6207        let buffer = &display_map.buffer_snapshot;
6208        let mut selections = self.selections.all::<usize>(cx);
6209        if let Some(mut select_next_state) = self.select_next_state.take() {
6210            let query = &select_next_state.query;
6211            if !select_next_state.done {
6212                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
6213                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
6214                let mut next_selected_range = None;
6215
6216                let bytes_after_last_selection =
6217                    buffer.bytes_in_range(last_selection.end..buffer.len());
6218                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
6219                let query_matches = query
6220                    .stream_find_iter(bytes_after_last_selection)
6221                    .map(|result| (last_selection.end, result))
6222                    .chain(
6223                        query
6224                            .stream_find_iter(bytes_before_first_selection)
6225                            .map(|result| (0, result)),
6226                    );
6227
6228                for (start_offset, query_match) in query_matches {
6229                    let query_match = query_match.unwrap(); // can only fail due to I/O
6230                    let offset_range =
6231                        start_offset + query_match.start()..start_offset + query_match.end();
6232                    let display_range = offset_range.start.to_display_point(&display_map)
6233                        ..offset_range.end.to_display_point(&display_map);
6234
6235                    if !select_next_state.wordwise
6236                        || (!movement::is_inside_word(&display_map, display_range.start)
6237                            && !movement::is_inside_word(&display_map, display_range.end))
6238                    {
6239                        if selections
6240                            .iter()
6241                            .find(|selection| selection.equals(&offset_range))
6242                            .is_none()
6243                        {
6244                            next_selected_range = Some(offset_range);
6245                            break;
6246                        }
6247                    }
6248                }
6249
6250                if let Some(next_selected_range) = next_selected_range {
6251                    select_next_match_ranges(
6252                        self,
6253                        next_selected_range,
6254                        replace_newest,
6255                        autoscroll,
6256                        cx,
6257                    );
6258                } else {
6259                    select_next_state.done = true;
6260                }
6261            }
6262
6263            self.select_next_state = Some(select_next_state);
6264        } else if selections.len() == 1 {
6265            let selection = selections.last_mut().unwrap();
6266            if selection.start == selection.end {
6267                let word_range = movement::surrounding_word(
6268                    &display_map,
6269                    selection.start.to_display_point(&display_map),
6270                );
6271                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
6272                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
6273                selection.goal = SelectionGoal::None;
6274                selection.reversed = false;
6275
6276                let query = buffer
6277                    .text_for_range(selection.start..selection.end)
6278                    .collect::<String>();
6279
6280                let is_empty = query.is_empty();
6281                let select_state = SelectNextState {
6282                    query: AhoCorasick::new(&[query])?,
6283                    wordwise: true,
6284                    done: is_empty,
6285                };
6286                select_next_match_ranges(
6287                    self,
6288                    selection.start..selection.end,
6289                    replace_newest,
6290                    autoscroll,
6291                    cx,
6292                );
6293                self.select_next_state = Some(select_state);
6294            } else {
6295                let query = buffer
6296                    .text_for_range(selection.start..selection.end)
6297                    .collect::<String>();
6298                self.select_next_state = Some(SelectNextState {
6299                    query: AhoCorasick::new(&[query])?,
6300                    wordwise: false,
6301                    done: false,
6302                });
6303                self.select_next_match_internal(display_map, replace_newest, autoscroll, cx)?;
6304            }
6305        }
6306        Ok(())
6307    }
6308
6309    pub fn select_all_matches(
6310        &mut self,
6311        action: &SelectAllMatches,
6312        cx: &mut ViewContext<Self>,
6313    ) -> Result<()> {
6314        self.push_to_selection_history();
6315        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6316
6317        loop {
6318            self.select_next_match_internal(&display_map, action.replace_newest, None, cx)?;
6319
6320            if self
6321                .select_next_state
6322                .as_ref()
6323                .map(|selection_state| selection_state.done)
6324                .unwrap_or(true)
6325            {
6326                break;
6327            }
6328        }
6329
6330        Ok(())
6331    }
6332
6333    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) -> Result<()> {
6334        self.push_to_selection_history();
6335        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6336        self.select_next_match_internal(
6337            &display_map,
6338            action.replace_newest,
6339            Some(Autoscroll::newest()),
6340            cx,
6341        )?;
6342        Ok(())
6343    }
6344
6345    pub fn select_previous(
6346        &mut self,
6347        action: &SelectPrevious,
6348        cx: &mut ViewContext<Self>,
6349    ) -> Result<()> {
6350        self.push_to_selection_history();
6351        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6352        let buffer = &display_map.buffer_snapshot;
6353        let mut selections = self.selections.all::<usize>(cx);
6354        if let Some(mut select_prev_state) = self.select_prev_state.take() {
6355            let query = &select_prev_state.query;
6356            if !select_prev_state.done {
6357                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
6358                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
6359                let mut next_selected_range = None;
6360                // When we're iterating matches backwards, the oldest match will actually be the furthest one in the buffer.
6361                let bytes_before_last_selection =
6362                    buffer.reversed_bytes_in_range(0..last_selection.start);
6363                let bytes_after_first_selection =
6364                    buffer.reversed_bytes_in_range(first_selection.end..buffer.len());
6365                let query_matches = query
6366                    .stream_find_iter(bytes_before_last_selection)
6367                    .map(|result| (last_selection.start, result))
6368                    .chain(
6369                        query
6370                            .stream_find_iter(bytes_after_first_selection)
6371                            .map(|result| (buffer.len(), result)),
6372                    );
6373                for (end_offset, query_match) in query_matches {
6374                    let query_match = query_match.unwrap(); // can only fail due to I/O
6375                    let offset_range =
6376                        end_offset - query_match.end()..end_offset - query_match.start();
6377                    let display_range = offset_range.start.to_display_point(&display_map)
6378                        ..offset_range.end.to_display_point(&display_map);
6379
6380                    if !select_prev_state.wordwise
6381                        || (!movement::is_inside_word(&display_map, display_range.start)
6382                            && !movement::is_inside_word(&display_map, display_range.end))
6383                    {
6384                        next_selected_range = Some(offset_range);
6385                        break;
6386                    }
6387                }
6388
6389                if let Some(next_selected_range) = next_selected_range {
6390                    self.unfold_ranges([next_selected_range.clone()], false, true, cx);
6391                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
6392                        if action.replace_newest {
6393                            s.delete(s.newest_anchor().id);
6394                        }
6395                        s.insert_range(next_selected_range);
6396                    });
6397                } else {
6398                    select_prev_state.done = true;
6399                }
6400            }
6401
6402            self.select_prev_state = Some(select_prev_state);
6403        } else if selections.len() == 1 {
6404            let selection = selections.last_mut().unwrap();
6405            if selection.start == selection.end {
6406                let word_range = movement::surrounding_word(
6407                    &display_map,
6408                    selection.start.to_display_point(&display_map),
6409                );
6410                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
6411                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
6412                selection.goal = SelectionGoal::None;
6413                selection.reversed = false;
6414
6415                let query = buffer
6416                    .text_for_range(selection.start..selection.end)
6417                    .collect::<String>();
6418                let query = query.chars().rev().collect::<String>();
6419                let select_state = SelectNextState {
6420                    query: AhoCorasick::new(&[query])?,
6421                    wordwise: true,
6422                    done: false,
6423                };
6424                self.unfold_ranges([selection.start..selection.end], false, true, cx);
6425                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
6426                    s.select(selections);
6427                });
6428                self.select_prev_state = Some(select_state);
6429            } else {
6430                let query = buffer
6431                    .text_for_range(selection.start..selection.end)
6432                    .collect::<String>();
6433                let query = query.chars().rev().collect::<String>();
6434                self.select_prev_state = Some(SelectNextState {
6435                    query: AhoCorasick::new(&[query])?,
6436                    wordwise: false,
6437                    done: false,
6438                });
6439                self.select_previous(action, cx)?;
6440            }
6441        }
6442        Ok(())
6443    }
6444
6445    pub fn toggle_comments(&mut self, action: &ToggleComments, cx: &mut ViewContext<Self>) {
6446        self.transact(cx, |this, cx| {
6447            let mut selections = this.selections.all::<Point>(cx);
6448            let mut edits = Vec::new();
6449            let mut selection_edit_ranges = Vec::new();
6450            let mut last_toggled_row = None;
6451            let snapshot = this.buffer.read(cx).read(cx);
6452            let empty_str: Arc<str> = "".into();
6453            let mut suffixes_inserted = Vec::new();
6454
6455            fn comment_prefix_range(
6456                snapshot: &MultiBufferSnapshot,
6457                row: u32,
6458                comment_prefix: &str,
6459                comment_prefix_whitespace: &str,
6460            ) -> Range<Point> {
6461                let start = Point::new(row, snapshot.indent_size_for_line(row).len);
6462
6463                let mut line_bytes = snapshot
6464                    .bytes_in_range(start..snapshot.max_point())
6465                    .flatten()
6466                    .copied();
6467
6468                // If this line currently begins with the line comment prefix, then record
6469                // the range containing the prefix.
6470                if line_bytes
6471                    .by_ref()
6472                    .take(comment_prefix.len())
6473                    .eq(comment_prefix.bytes())
6474                {
6475                    // Include any whitespace that matches the comment prefix.
6476                    let matching_whitespace_len = line_bytes
6477                        .zip(comment_prefix_whitespace.bytes())
6478                        .take_while(|(a, b)| a == b)
6479                        .count() as u32;
6480                    let end = Point::new(
6481                        start.row,
6482                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
6483                    );
6484                    start..end
6485                } else {
6486                    start..start
6487                }
6488            }
6489
6490            fn comment_suffix_range(
6491                snapshot: &MultiBufferSnapshot,
6492                row: u32,
6493                comment_suffix: &str,
6494                comment_suffix_has_leading_space: bool,
6495            ) -> Range<Point> {
6496                let end = Point::new(row, snapshot.line_len(row));
6497                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
6498
6499                let mut line_end_bytes = snapshot
6500                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
6501                    .flatten()
6502                    .copied();
6503
6504                let leading_space_len = if suffix_start_column > 0
6505                    && line_end_bytes.next() == Some(b' ')
6506                    && comment_suffix_has_leading_space
6507                {
6508                    1
6509                } else {
6510                    0
6511                };
6512
6513                // If this line currently begins with the line comment prefix, then record
6514                // the range containing the prefix.
6515                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
6516                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
6517                    start..end
6518                } else {
6519                    end..end
6520                }
6521            }
6522
6523            // TODO: Handle selections that cross excerpts
6524            for selection in &mut selections {
6525                let start_column = snapshot.indent_size_for_line(selection.start.row).len;
6526                let language = if let Some(language) =
6527                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
6528                {
6529                    language
6530                } else {
6531                    continue;
6532                };
6533
6534                selection_edit_ranges.clear();
6535
6536                // If multiple selections contain a given row, avoid processing that
6537                // row more than once.
6538                let mut start_row = selection.start.row;
6539                if last_toggled_row == Some(start_row) {
6540                    start_row += 1;
6541                }
6542                let end_row =
6543                    if selection.end.row > selection.start.row && selection.end.column == 0 {
6544                        selection.end.row - 1
6545                    } else {
6546                        selection.end.row
6547                    };
6548                last_toggled_row = Some(end_row);
6549
6550                if start_row > end_row {
6551                    continue;
6552                }
6553
6554                // If the language has line comments, toggle those.
6555                if let Some(full_comment_prefix) = language.line_comment_prefix() {
6556                    // Split the comment prefix's trailing whitespace into a separate string,
6557                    // as that portion won't be used for detecting if a line is a comment.
6558                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
6559                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
6560                    let mut all_selection_lines_are_comments = true;
6561
6562                    for row in start_row..=end_row {
6563                        if snapshot.is_line_blank(row) && start_row < end_row {
6564                            continue;
6565                        }
6566
6567                        let prefix_range = comment_prefix_range(
6568                            snapshot.deref(),
6569                            row,
6570                            comment_prefix,
6571                            comment_prefix_whitespace,
6572                        );
6573                        if prefix_range.is_empty() {
6574                            all_selection_lines_are_comments = false;
6575                        }
6576                        selection_edit_ranges.push(prefix_range);
6577                    }
6578
6579                    if all_selection_lines_are_comments {
6580                        edits.extend(
6581                            selection_edit_ranges
6582                                .iter()
6583                                .cloned()
6584                                .map(|range| (range, empty_str.clone())),
6585                        );
6586                    } else {
6587                        let min_column = selection_edit_ranges
6588                            .iter()
6589                            .map(|r| r.start.column)
6590                            .min()
6591                            .unwrap_or(0);
6592                        edits.extend(selection_edit_ranges.iter().map(|range| {
6593                            let position = Point::new(range.start.row, min_column);
6594                            (position..position, full_comment_prefix.clone())
6595                        }));
6596                    }
6597                } else if let Some((full_comment_prefix, comment_suffix)) =
6598                    language.block_comment_delimiters()
6599                {
6600                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
6601                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
6602                    let prefix_range = comment_prefix_range(
6603                        snapshot.deref(),
6604                        start_row,
6605                        comment_prefix,
6606                        comment_prefix_whitespace,
6607                    );
6608                    let suffix_range = comment_suffix_range(
6609                        snapshot.deref(),
6610                        end_row,
6611                        comment_suffix.trim_start_matches(' '),
6612                        comment_suffix.starts_with(' '),
6613                    );
6614
6615                    if prefix_range.is_empty() || suffix_range.is_empty() {
6616                        edits.push((
6617                            prefix_range.start..prefix_range.start,
6618                            full_comment_prefix.clone(),
6619                        ));
6620                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
6621                        suffixes_inserted.push((end_row, comment_suffix.len()));
6622                    } else {
6623                        edits.push((prefix_range, empty_str.clone()));
6624                        edits.push((suffix_range, empty_str.clone()));
6625                    }
6626                } else {
6627                    continue;
6628                }
6629            }
6630
6631            drop(snapshot);
6632            this.buffer.update(cx, |buffer, cx| {
6633                buffer.edit(edits, None, cx);
6634            });
6635
6636            // Adjust selections so that they end before any comment suffixes that
6637            // were inserted.
6638            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
6639            let mut selections = this.selections.all::<Point>(cx);
6640            let snapshot = this.buffer.read(cx).read(cx);
6641            for selection in &mut selections {
6642                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
6643                    match row.cmp(&selection.end.row) {
6644                        Ordering::Less => {
6645                            suffixes_inserted.next();
6646                            continue;
6647                        }
6648                        Ordering::Greater => break,
6649                        Ordering::Equal => {
6650                            if selection.end.column == snapshot.line_len(row) {
6651                                if selection.is_empty() {
6652                                    selection.start.column -= suffix_len as u32;
6653                                }
6654                                selection.end.column -= suffix_len as u32;
6655                            }
6656                            break;
6657                        }
6658                    }
6659                }
6660            }
6661
6662            drop(snapshot);
6663            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
6664
6665            let selections = this.selections.all::<Point>(cx);
6666            let selections_on_single_row = selections.windows(2).all(|selections| {
6667                selections[0].start.row == selections[1].start.row
6668                    && selections[0].end.row == selections[1].end.row
6669                    && selections[0].start.row == selections[0].end.row
6670            });
6671            let selections_selecting = selections
6672                .iter()
6673                .any(|selection| selection.start != selection.end);
6674            let advance_downwards = action.advance_downwards
6675                && selections_on_single_row
6676                && !selections_selecting
6677                && this.mode != EditorMode::SingleLine;
6678
6679            if advance_downwards {
6680                let snapshot = this.buffer.read(cx).snapshot(cx);
6681
6682                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
6683                    s.move_cursors_with(|display_snapshot, display_point, _| {
6684                        let mut point = display_point.to_point(display_snapshot);
6685                        point.row += 1;
6686                        point = snapshot.clip_point(point, Bias::Left);
6687                        let display_point = point.to_display_point(display_snapshot);
6688                        (display_point, SelectionGoal::Column(display_point.column()))
6689                    })
6690                });
6691            }
6692        });
6693    }
6694
6695    pub fn select_larger_syntax_node(
6696        &mut self,
6697        _: &SelectLargerSyntaxNode,
6698        cx: &mut ViewContext<Self>,
6699    ) {
6700        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6701        let buffer = self.buffer.read(cx).snapshot(cx);
6702        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
6703
6704        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
6705        let mut selected_larger_node = false;
6706        let new_selections = old_selections
6707            .iter()
6708            .map(|selection| {
6709                let old_range = selection.start..selection.end;
6710                let mut new_range = old_range.clone();
6711                while let Some(containing_range) =
6712                    buffer.range_for_syntax_ancestor(new_range.clone())
6713                {
6714                    new_range = containing_range;
6715                    if !display_map.intersects_fold(new_range.start)
6716                        && !display_map.intersects_fold(new_range.end)
6717                    {
6718                        break;
6719                    }
6720                }
6721
6722                selected_larger_node |= new_range != old_range;
6723                Selection {
6724                    id: selection.id,
6725                    start: new_range.start,
6726                    end: new_range.end,
6727                    goal: SelectionGoal::None,
6728                    reversed: selection.reversed,
6729                }
6730            })
6731            .collect::<Vec<_>>();
6732
6733        if selected_larger_node {
6734            stack.push(old_selections);
6735            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6736                s.select(new_selections);
6737            });
6738        }
6739        self.select_larger_syntax_node_stack = stack;
6740    }
6741
6742    pub fn select_smaller_syntax_node(
6743        &mut self,
6744        _: &SelectSmallerSyntaxNode,
6745        cx: &mut ViewContext<Self>,
6746    ) {
6747        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
6748        if let Some(selections) = stack.pop() {
6749            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6750                s.select(selections.to_vec());
6751            });
6752        }
6753        self.select_larger_syntax_node_stack = stack;
6754    }
6755
6756    pub fn move_to_enclosing_bracket(
6757        &mut self,
6758        _: &MoveToEnclosingBracket,
6759        cx: &mut ViewContext<Self>,
6760    ) {
6761        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6762            s.move_offsets_with(|snapshot, selection| {
6763                let Some(enclosing_bracket_ranges) =
6764                    snapshot.enclosing_bracket_ranges(selection.start..selection.end)
6765                else {
6766                    return;
6767                };
6768
6769                let mut best_length = usize::MAX;
6770                let mut best_inside = false;
6771                let mut best_in_bracket_range = false;
6772                let mut best_destination = None;
6773                for (open, close) in enclosing_bracket_ranges {
6774                    let close = close.to_inclusive();
6775                    let length = close.end() - open.start;
6776                    let inside = selection.start >= open.end && selection.end <= *close.start();
6777                    let in_bracket_range = open.to_inclusive().contains(&selection.head())
6778                        || close.contains(&selection.head());
6779
6780                    // If best is next to a bracket and current isn't, skip
6781                    if !in_bracket_range && best_in_bracket_range {
6782                        continue;
6783                    }
6784
6785                    // Prefer smaller lengths unless best is inside and current isn't
6786                    if length > best_length && (best_inside || !inside) {
6787                        continue;
6788                    }
6789
6790                    best_length = length;
6791                    best_inside = inside;
6792                    best_in_bracket_range = in_bracket_range;
6793                    best_destination = Some(
6794                        if close.contains(&selection.start) && close.contains(&selection.end) {
6795                            if inside {
6796                                open.end
6797                            } else {
6798                                open.start
6799                            }
6800                        } else {
6801                            if inside {
6802                                *close.start()
6803                            } else {
6804                                *close.end()
6805                            }
6806                        },
6807                    );
6808                }
6809
6810                if let Some(destination) = best_destination {
6811                    selection.collapse_to(destination, SelectionGoal::None);
6812                }
6813            })
6814        });
6815    }
6816
6817    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
6818        self.end_selection(cx);
6819        self.selection_history.mode = SelectionHistoryMode::Undoing;
6820        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
6821            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
6822            self.select_next_state = entry.select_next_state;
6823            self.select_prev_state = entry.select_prev_state;
6824            self.add_selections_state = entry.add_selections_state;
6825            self.request_autoscroll(Autoscroll::newest(), cx);
6826        }
6827        self.selection_history.mode = SelectionHistoryMode::Normal;
6828    }
6829
6830    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
6831        self.end_selection(cx);
6832        self.selection_history.mode = SelectionHistoryMode::Redoing;
6833        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
6834            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
6835            self.select_next_state = entry.select_next_state;
6836            self.select_prev_state = entry.select_prev_state;
6837            self.add_selections_state = entry.add_selections_state;
6838            self.request_autoscroll(Autoscroll::newest(), cx);
6839        }
6840        self.selection_history.mode = SelectionHistoryMode::Normal;
6841    }
6842
6843    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
6844        self.go_to_diagnostic_impl(Direction::Next, cx)
6845    }
6846
6847    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
6848        self.go_to_diagnostic_impl(Direction::Prev, cx)
6849    }
6850
6851    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
6852        let buffer = self.buffer.read(cx).snapshot(cx);
6853        let selection = self.selections.newest::<usize>(cx);
6854
6855        // If there is an active Diagnostic Popover. Jump to it's diagnostic instead.
6856        if direction == Direction::Next {
6857            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
6858                let (group_id, jump_to) = popover.activation_info();
6859                if self.activate_diagnostics(group_id, cx) {
6860                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6861                        let mut new_selection = s.newest_anchor().clone();
6862                        new_selection.collapse_to(jump_to, SelectionGoal::None);
6863                        s.select_anchors(vec![new_selection.clone()]);
6864                    });
6865                }
6866                return;
6867            }
6868        }
6869
6870        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
6871            active_diagnostics
6872                .primary_range
6873                .to_offset(&buffer)
6874                .to_inclusive()
6875        });
6876        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
6877            if active_primary_range.contains(&selection.head()) {
6878                *active_primary_range.end()
6879            } else {
6880                selection.head()
6881            }
6882        } else {
6883            selection.head()
6884        };
6885
6886        loop {
6887            let mut diagnostics = if direction == Direction::Prev {
6888                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
6889            } else {
6890                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
6891            };
6892            let group = diagnostics.find_map(|entry| {
6893                if entry.diagnostic.is_primary
6894                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
6895                    && !entry.range.is_empty()
6896                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
6897                {
6898                    Some((entry.range, entry.diagnostic.group_id))
6899                } else {
6900                    None
6901                }
6902            });
6903
6904            if let Some((primary_range, group_id)) = group {
6905                if self.activate_diagnostics(group_id, cx) {
6906                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6907                        s.select(vec![Selection {
6908                            id: selection.id,
6909                            start: primary_range.start,
6910                            end: primary_range.start,
6911                            reversed: false,
6912                            goal: SelectionGoal::None,
6913                        }]);
6914                    });
6915                }
6916                break;
6917            } else {
6918                // Cycle around to the start of the buffer, potentially moving back to the start of
6919                // the currently active diagnostic.
6920                active_primary_range.take();
6921                if direction == Direction::Prev {
6922                    if search_start == buffer.len() {
6923                        break;
6924                    } else {
6925                        search_start = buffer.len();
6926                    }
6927                } else if search_start == 0 {
6928                    break;
6929                } else {
6930                    search_start = 0;
6931                }
6932            }
6933        }
6934    }
6935
6936    fn go_to_hunk(&mut self, _: &GoToHunk, cx: &mut ViewContext<Self>) {
6937        let snapshot = self
6938            .display_map
6939            .update(cx, |display_map, cx| display_map.snapshot(cx));
6940        let selection = self.selections.newest::<Point>(cx);
6941
6942        if !self.seek_in_direction(
6943            &snapshot,
6944            selection.head(),
6945            false,
6946            snapshot
6947                .buffer_snapshot
6948                .git_diff_hunks_in_range((selection.head().row + 1)..u32::MAX),
6949            cx,
6950        ) {
6951            let wrapped_point = Point::zero();
6952            self.seek_in_direction(
6953                &snapshot,
6954                wrapped_point,
6955                true,
6956                snapshot
6957                    .buffer_snapshot
6958                    .git_diff_hunks_in_range((wrapped_point.row + 1)..u32::MAX),
6959                cx,
6960            );
6961        }
6962    }
6963
6964    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
6965        let snapshot = self
6966            .display_map
6967            .update(cx, |display_map, cx| display_map.snapshot(cx));
6968        let selection = self.selections.newest::<Point>(cx);
6969
6970        if !self.seek_in_direction(
6971            &snapshot,
6972            selection.head(),
6973            false,
6974            snapshot
6975                .buffer_snapshot
6976                .git_diff_hunks_in_range_rev(0..selection.head().row),
6977            cx,
6978        ) {
6979            let wrapped_point = snapshot.buffer_snapshot.max_point();
6980            self.seek_in_direction(
6981                &snapshot,
6982                wrapped_point,
6983                true,
6984                snapshot
6985                    .buffer_snapshot
6986                    .git_diff_hunks_in_range_rev(0..wrapped_point.row),
6987                cx,
6988            );
6989        }
6990    }
6991
6992    fn seek_in_direction(
6993        &mut self,
6994        snapshot: &DisplaySnapshot,
6995        initial_point: Point,
6996        is_wrapped: bool,
6997        hunks: impl Iterator<Item = DiffHunk<u32>>,
6998        cx: &mut ViewContext<Editor>,
6999    ) -> bool {
7000        let display_point = initial_point.to_display_point(snapshot);
7001        let mut hunks = hunks
7002            .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
7003            .skip_while(|hunk| {
7004                if is_wrapped {
7005                    false
7006                } else {
7007                    hunk.contains_display_row(display_point.row())
7008                }
7009            })
7010            .dedup();
7011
7012        if let Some(hunk) = hunks.next() {
7013            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
7014                let row = hunk.start_display_row();
7015                let point = DisplayPoint::new(row, 0);
7016                s.select_display_ranges([point..point]);
7017            });
7018
7019            true
7020        } else {
7021            false
7022        }
7023    }
7024
7025    pub fn go_to_definition(&mut self, _: &GoToDefinition, cx: &mut ViewContext<Self>) {
7026        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, false, cx);
7027    }
7028
7029    pub fn go_to_type_definition(&mut self, _: &GoToTypeDefinition, cx: &mut ViewContext<Self>) {
7030        self.go_to_definition_of_kind(GotoDefinitionKind::Type, false, cx);
7031    }
7032
7033    pub fn go_to_definition_split(&mut self, _: &GoToDefinitionSplit, cx: &mut ViewContext<Self>) {
7034        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, true, cx);
7035    }
7036
7037    pub fn go_to_type_definition_split(
7038        &mut self,
7039        _: &GoToTypeDefinitionSplit,
7040        cx: &mut ViewContext<Self>,
7041    ) {
7042        self.go_to_definition_of_kind(GotoDefinitionKind::Type, true, cx);
7043    }
7044
7045    fn go_to_definition_of_kind(
7046        &mut self,
7047        kind: GotoDefinitionKind,
7048        split: bool,
7049        cx: &mut ViewContext<Self>,
7050    ) {
7051        let Some(workspace) = self.workspace(cx) else {
7052            return;
7053        };
7054        let buffer = self.buffer.read(cx);
7055        let head = self.selections.newest::<usize>(cx).head();
7056        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
7057            text_anchor
7058        } else {
7059            return;
7060        };
7061
7062        let project = workspace.read(cx).project().clone();
7063        let definitions = project.update(cx, |project, cx| match kind {
7064            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
7065            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
7066        });
7067
7068        cx.spawn_labeled("Fetching Definition...", |editor, mut cx| async move {
7069            let definitions = definitions.await?;
7070            editor.update(&mut cx, |editor, cx| {
7071                editor.navigate_to_definitions(
7072                    definitions
7073                        .into_iter()
7074                        .map(GoToDefinitionLink::Text)
7075                        .collect(),
7076                    split,
7077                    cx,
7078                );
7079            })?;
7080            Ok::<(), anyhow::Error>(())
7081        })
7082        .detach_and_log_err(cx);
7083    }
7084
7085    pub fn navigate_to_definitions(
7086        &mut self,
7087        mut definitions: Vec<GoToDefinitionLink>,
7088        split: bool,
7089        cx: &mut ViewContext<Editor>,
7090    ) {
7091        let Some(workspace) = self.workspace(cx) else {
7092            return;
7093        };
7094        let pane = workspace.read(cx).active_pane().clone();
7095        // If there is one definition, just open it directly
7096        if definitions.len() == 1 {
7097            let definition = definitions.pop().unwrap();
7098            let target_task = match definition {
7099                GoToDefinitionLink::Text(link) => Task::Ready(Some(Ok(Some(link.target)))),
7100                GoToDefinitionLink::InlayHint(lsp_location, server_id) => {
7101                    self.compute_target_location(lsp_location, server_id, cx)
7102                }
7103            };
7104            cx.spawn(|editor, mut cx| async move {
7105                let target = target_task.await.context("target resolution task")?;
7106                if let Some(target) = target {
7107                    editor.update(&mut cx, |editor, cx| {
7108                        let range = target.range.to_offset(target.buffer.read(cx));
7109                        let range = editor.range_for_match(&range);
7110                        if Some(&target.buffer) == editor.buffer.read(cx).as_singleton().as_ref() {
7111                            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
7112                                s.select_ranges([range]);
7113                            });
7114                        } else {
7115                            cx.window_context().defer(move |cx| {
7116                                let target_editor: ViewHandle<Self> =
7117                                    workspace.update(cx, |workspace, cx| {
7118                                        if split {
7119                                            workspace.split_project_item(target.buffer.clone(), cx)
7120                                        } else {
7121                                            workspace.open_project_item(target.buffer.clone(), cx)
7122                                        }
7123                                    });
7124                                target_editor.update(cx, |target_editor, cx| {
7125                                    // When selecting a definition in a different buffer, disable the nav history
7126                                    // to avoid creating a history entry at the previous cursor location.
7127                                    pane.update(cx, |pane, _| pane.disable_history());
7128                                    target_editor.change_selections(
7129                                        Some(Autoscroll::fit()),
7130                                        cx,
7131                                        |s| {
7132                                            s.select_ranges([range]);
7133                                        },
7134                                    );
7135                                    pane.update(cx, |pane, _| pane.enable_history());
7136                                });
7137                            });
7138                        }
7139                    })
7140                } else {
7141                    Ok(())
7142                }
7143            })
7144            .detach_and_log_err(cx);
7145        } else if !definitions.is_empty() {
7146            let replica_id = self.replica_id(cx);
7147            cx.spawn(|editor, mut cx| async move {
7148                let (title, location_tasks) = editor
7149                    .update(&mut cx, |editor, cx| {
7150                        let title = definitions
7151                            .iter()
7152                            .find_map(|definition| match definition {
7153                                GoToDefinitionLink::Text(link) => {
7154                                    link.origin.as_ref().map(|origin| {
7155                                        let buffer = origin.buffer.read(cx);
7156                                        format!(
7157                                            "Definitions for {}",
7158                                            buffer
7159                                                .text_for_range(origin.range.clone())
7160                                                .collect::<String>()
7161                                        )
7162                                    })
7163                                }
7164                                GoToDefinitionLink::InlayHint(_, _) => None,
7165                            })
7166                            .unwrap_or("Definitions".to_string());
7167                        let location_tasks = definitions
7168                            .into_iter()
7169                            .map(|definition| match definition {
7170                                GoToDefinitionLink::Text(link) => {
7171                                    Task::Ready(Some(Ok(Some(link.target))))
7172                                }
7173                                GoToDefinitionLink::InlayHint(lsp_location, server_id) => {
7174                                    editor.compute_target_location(lsp_location, server_id, cx)
7175                                }
7176                            })
7177                            .collect::<Vec<_>>();
7178                        (title, location_tasks)
7179                    })
7180                    .context("location tasks preparation")?;
7181
7182                let locations = futures::future::join_all(location_tasks)
7183                    .await
7184                    .into_iter()
7185                    .filter_map(|location| location.transpose())
7186                    .collect::<Result<_>>()
7187                    .context("location tasks")?;
7188                workspace.update(&mut cx, |workspace, cx| {
7189                    Self::open_locations_in_multibuffer(
7190                        workspace, locations, replica_id, title, split, cx,
7191                    )
7192                });
7193
7194                anyhow::Ok(())
7195            })
7196            .detach_and_log_err(cx);
7197        }
7198    }
7199
7200    fn compute_target_location(
7201        &self,
7202        lsp_location: lsp::Location,
7203        server_id: LanguageServerId,
7204        cx: &mut ViewContext<Editor>,
7205    ) -> Task<anyhow::Result<Option<Location>>> {
7206        let Some(project) = self.project.clone() else {
7207            return Task::Ready(Some(Ok(None)));
7208        };
7209
7210        cx.spawn(move |editor, mut cx| async move {
7211            let location_task = editor.update(&mut cx, |editor, cx| {
7212                project.update(cx, |project, cx| {
7213                    let language_server_name =
7214                        editor.buffer.read(cx).as_singleton().and_then(|buffer| {
7215                            project
7216                                .language_server_for_buffer(buffer.read(cx), server_id, cx)
7217                                .map(|(_, lsp_adapter)| {
7218                                    LanguageServerName(Arc::from(lsp_adapter.name()))
7219                                })
7220                        });
7221                    language_server_name.map(|language_server_name| {
7222                        project.open_local_buffer_via_lsp(
7223                            lsp_location.uri.clone(),
7224                            server_id,
7225                            language_server_name,
7226                            cx,
7227                        )
7228                    })
7229                })
7230            })?;
7231            let location = match location_task {
7232                Some(task) => Some({
7233                    let target_buffer_handle = task.await.context("open local buffer")?;
7234                    let range = {
7235                        target_buffer_handle.update(&mut cx, |target_buffer, _| {
7236                            let target_start = target_buffer.clip_point_utf16(
7237                                point_from_lsp(lsp_location.range.start),
7238                                Bias::Left,
7239                            );
7240                            let target_end = target_buffer.clip_point_utf16(
7241                                point_from_lsp(lsp_location.range.end),
7242                                Bias::Left,
7243                            );
7244                            target_buffer.anchor_after(target_start)
7245                                ..target_buffer.anchor_before(target_end)
7246                        })
7247                    };
7248                    Location {
7249                        buffer: target_buffer_handle,
7250                        range,
7251                    }
7252                }),
7253                None => None,
7254            };
7255            Ok(location)
7256        })
7257    }
7258
7259    pub fn find_all_references(
7260        workspace: &mut Workspace,
7261        _: &FindAllReferences,
7262        cx: &mut ViewContext<Workspace>,
7263    ) -> Option<Task<Result<()>>> {
7264        let active_item = workspace.active_item(cx)?;
7265        let editor_handle = active_item.act_as::<Self>(cx)?;
7266
7267        let editor = editor_handle.read(cx);
7268        let buffer = editor.buffer.read(cx);
7269        let head = editor.selections.newest::<usize>(cx).head();
7270        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
7271        let replica_id = editor.replica_id(cx);
7272
7273        let project = workspace.project().clone();
7274        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
7275        Some(cx.spawn_labeled(
7276            "Finding All References...",
7277            |workspace, mut cx| async move {
7278                let locations = references.await?;
7279                if locations.is_empty() {
7280                    return Ok(());
7281                }
7282
7283                workspace.update(&mut cx, |workspace, cx| {
7284                    let title = locations
7285                        .first()
7286                        .as_ref()
7287                        .map(|location| {
7288                            let buffer = location.buffer.read(cx);
7289                            format!(
7290                                "References to `{}`",
7291                                buffer
7292                                    .text_for_range(location.range.clone())
7293                                    .collect::<String>()
7294                            )
7295                        })
7296                        .unwrap();
7297                    Self::open_locations_in_multibuffer(
7298                        workspace, locations, replica_id, title, false, cx,
7299                    );
7300                })?;
7301
7302                Ok(())
7303            },
7304        ))
7305    }
7306
7307    /// Opens a multibuffer with the given project locations in it
7308    pub fn open_locations_in_multibuffer(
7309        workspace: &mut Workspace,
7310        mut locations: Vec<Location>,
7311        replica_id: ReplicaId,
7312        title: String,
7313        split: bool,
7314        cx: &mut ViewContext<Workspace>,
7315    ) {
7316        // If there are multiple definitions, open them in a multibuffer
7317        locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
7318        let mut locations = locations.into_iter().peekable();
7319        let mut ranges_to_highlight = Vec::new();
7320
7321        let excerpt_buffer = cx.add_model(|cx| {
7322            let mut multibuffer = MultiBuffer::new(replica_id);
7323            while let Some(location) = locations.next() {
7324                let buffer = location.buffer.read(cx);
7325                let mut ranges_for_buffer = Vec::new();
7326                let range = location.range.to_offset(buffer);
7327                ranges_for_buffer.push(range.clone());
7328
7329                while let Some(next_location) = locations.peek() {
7330                    if next_location.buffer == location.buffer {
7331                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
7332                        locations.next();
7333                    } else {
7334                        break;
7335                    }
7336                }
7337
7338                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
7339                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
7340                    location.buffer.clone(),
7341                    ranges_for_buffer,
7342                    1,
7343                    cx,
7344                ))
7345            }
7346
7347            multibuffer.with_title(title)
7348        });
7349
7350        let editor = cx.add_view(|cx| {
7351            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx)
7352        });
7353        editor.update(cx, |editor, cx| {
7354            editor.highlight_background::<Self>(
7355                ranges_to_highlight,
7356                |theme| theme.editor.highlighted_line_background,
7357                cx,
7358            );
7359        });
7360        if split {
7361            workspace.split_item(SplitDirection::Right, Box::new(editor), cx);
7362        } else {
7363            workspace.add_item(Box::new(editor), cx);
7364        }
7365    }
7366
7367    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
7368        use language::ToOffset as _;
7369
7370        let project = self.project.clone()?;
7371        let selection = self.selections.newest_anchor().clone();
7372        let (cursor_buffer, cursor_buffer_position) = self
7373            .buffer
7374            .read(cx)
7375            .text_anchor_for_position(selection.head(), cx)?;
7376        let (tail_buffer, _) = self
7377            .buffer
7378            .read(cx)
7379            .text_anchor_for_position(selection.tail(), cx)?;
7380        if tail_buffer != cursor_buffer {
7381            return None;
7382        }
7383
7384        let snapshot = cursor_buffer.read(cx).snapshot();
7385        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
7386        let prepare_rename = project.update(cx, |project, cx| {
7387            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
7388        });
7389
7390        Some(cx.spawn(|this, mut cx| async move {
7391            let rename_range = if let Some(range) = prepare_rename.await? {
7392                Some(range)
7393            } else {
7394                this.update(&mut cx, |this, cx| {
7395                    let buffer = this.buffer.read(cx).snapshot(cx);
7396                    let mut buffer_highlights = this
7397                        .document_highlights_for_position(selection.head(), &buffer)
7398                        .filter(|highlight| {
7399                            highlight.start.excerpt_id() == selection.head().excerpt_id()
7400                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
7401                        });
7402                    buffer_highlights
7403                        .next()
7404                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
7405                })?
7406            };
7407            if let Some(rename_range) = rename_range {
7408                let rename_buffer_range = rename_range.to_offset(&snapshot);
7409                let cursor_offset_in_rename_range =
7410                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
7411
7412                this.update(&mut cx, |this, cx| {
7413                    this.take_rename(false, cx);
7414                    let style = this.style(cx);
7415                    let buffer = this.buffer.read(cx).read(cx);
7416                    let cursor_offset = selection.head().to_offset(&buffer);
7417                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
7418                    let rename_end = rename_start + rename_buffer_range.len();
7419                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
7420                    let mut old_highlight_id = None;
7421                    let old_name: Arc<str> = buffer
7422                        .chunks(rename_start..rename_end, true)
7423                        .map(|chunk| {
7424                            if old_highlight_id.is_none() {
7425                                old_highlight_id = chunk.syntax_highlight_id;
7426                            }
7427                            chunk.text
7428                        })
7429                        .collect::<String>()
7430                        .into();
7431
7432                    drop(buffer);
7433
7434                    // Position the selection in the rename editor so that it matches the current selection.
7435                    this.show_local_selections = false;
7436                    let rename_editor = cx.add_view(|cx| {
7437                        let mut editor = Editor::single_line(None, cx);
7438                        if let Some(old_highlight_id) = old_highlight_id {
7439                            editor.override_text_style =
7440                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
7441                        }
7442                        editor.buffer.update(cx, |buffer, cx| {
7443                            buffer.edit([(0..0, old_name.clone())], None, cx)
7444                        });
7445                        editor.select_all(&SelectAll, cx);
7446                        editor
7447                    });
7448
7449                    let ranges = this
7450                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
7451                        .into_iter()
7452                        .flat_map(|(_, ranges)| ranges.into_iter())
7453                        .chain(
7454                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
7455                                .into_iter()
7456                                .flat_map(|(_, ranges)| ranges.into_iter()),
7457                        )
7458                        .collect();
7459
7460                    this.highlight_text::<Rename>(
7461                        ranges,
7462                        HighlightStyle {
7463                            fade_out: Some(style.rename_fade),
7464                            ..Default::default()
7465                        },
7466                        cx,
7467                    );
7468                    cx.focus(&rename_editor);
7469                    let block_id = this.insert_blocks(
7470                        [BlockProperties {
7471                            style: BlockStyle::Flex,
7472                            position: range.start.clone(),
7473                            height: 1,
7474                            render: Arc::new({
7475                                let editor = rename_editor.clone();
7476                                move |cx: &mut BlockContext| {
7477                                    ChildView::new(&editor, cx)
7478                                        .contained()
7479                                        .with_padding_left(cx.anchor_x)
7480                                        .into_any()
7481                                }
7482                            }),
7483                            disposition: BlockDisposition::Below,
7484                        }],
7485                        Some(Autoscroll::fit()),
7486                        cx,
7487                    )[0];
7488                    this.pending_rename = Some(RenameState {
7489                        range,
7490                        old_name,
7491                        editor: rename_editor,
7492                        block_id,
7493                    });
7494                })?;
7495            }
7496
7497            Ok(())
7498        }))
7499    }
7500
7501    pub fn confirm_rename(
7502        workspace: &mut Workspace,
7503        _: &ConfirmRename,
7504        cx: &mut ViewContext<Workspace>,
7505    ) -> Option<Task<Result<()>>> {
7506        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
7507
7508        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
7509            let rename = editor.take_rename(false, cx)?;
7510            let buffer = editor.buffer.read(cx);
7511            let (start_buffer, start) =
7512                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
7513            let (end_buffer, end) =
7514                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
7515            if start_buffer == end_buffer {
7516                let new_name = rename.editor.read(cx).text(cx);
7517                Some((start_buffer, start..end, rename.old_name, new_name))
7518            } else {
7519                None
7520            }
7521        })?;
7522
7523        let rename = workspace.project().clone().update(cx, |project, cx| {
7524            project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
7525        });
7526
7527        let editor = editor.downgrade();
7528        Some(cx.spawn(|workspace, mut cx| async move {
7529            let project_transaction = rename.await?;
7530            Self::open_project_transaction(
7531                &editor,
7532                workspace,
7533                project_transaction,
7534                format!("Rename: {}{}", old_name, new_name),
7535                cx.clone(),
7536            )
7537            .await?;
7538
7539            editor.update(&mut cx, |editor, cx| {
7540                editor.refresh_document_highlights(cx);
7541            })?;
7542            Ok(())
7543        }))
7544    }
7545
7546    fn take_rename(
7547        &mut self,
7548        moving_cursor: bool,
7549        cx: &mut ViewContext<Self>,
7550    ) -> Option<RenameState> {
7551        let rename = self.pending_rename.take()?;
7552        self.remove_blocks(
7553            [rename.block_id].into_iter().collect(),
7554            Some(Autoscroll::fit()),
7555            cx,
7556        );
7557        self.clear_highlights::<Rename>(cx);
7558        self.show_local_selections = true;
7559
7560        if moving_cursor {
7561            let rename_editor = rename.editor.read(cx);
7562            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
7563
7564            // Update the selection to match the position of the selection inside
7565            // the rename editor.
7566            let snapshot = self.buffer.read(cx).read(cx);
7567            let rename_range = rename.range.to_offset(&snapshot);
7568            let cursor_in_editor = snapshot
7569                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
7570                .min(rename_range.end);
7571            drop(snapshot);
7572
7573            self.change_selections(None, cx, |s| {
7574                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
7575            });
7576        } else {
7577            self.refresh_document_highlights(cx);
7578        }
7579
7580        Some(rename)
7581    }
7582
7583    #[cfg(any(test, feature = "test-support"))]
7584    pub fn pending_rename(&self) -> Option<&RenameState> {
7585        self.pending_rename.as_ref()
7586    }
7587
7588    fn format(&mut self, _: &Format, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
7589        let project = match &self.project {
7590            Some(project) => project.clone(),
7591            None => return None,
7592        };
7593
7594        Some(self.perform_format(project, FormatTrigger::Manual, cx))
7595    }
7596
7597    fn perform_format(
7598        &mut self,
7599        project: ModelHandle<Project>,
7600        trigger: FormatTrigger,
7601        cx: &mut ViewContext<Self>,
7602    ) -> Task<Result<()>> {
7603        let buffer = self.buffer().clone();
7604        let buffers = buffer.read(cx).all_buffers();
7605
7606        let mut timeout = cx.background().timer(FORMAT_TIMEOUT).fuse();
7607        let format = project.update(cx, |project, cx| project.format(buffers, true, trigger, cx));
7608
7609        cx.spawn(|_, mut cx| async move {
7610            let transaction = futures::select_biased! {
7611                _ = timeout => {
7612                    log::warn!("timed out waiting for formatting");
7613                    None
7614                }
7615                transaction = format.log_err().fuse() => transaction,
7616            };
7617
7618            buffer.update(&mut cx, |buffer, cx| {
7619                if let Some(transaction) = transaction {
7620                    if !buffer.is_singleton() {
7621                        buffer.push_transaction(&transaction.0, cx);
7622                    }
7623                }
7624
7625                cx.notify();
7626            });
7627
7628            Ok(())
7629        })
7630    }
7631
7632    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
7633        if let Some(project) = self.project.clone() {
7634            self.buffer.update(cx, |multi_buffer, cx| {
7635                project.update(cx, |project, cx| {
7636                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
7637                });
7638            })
7639        }
7640    }
7641
7642    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
7643        cx.show_character_palette();
7644    }
7645
7646    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
7647        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
7648            let buffer = self.buffer.read(cx).snapshot(cx);
7649            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
7650            let is_valid = buffer
7651                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
7652                .any(|entry| {
7653                    entry.diagnostic.is_primary
7654                        && !entry.range.is_empty()
7655                        && entry.range.start == primary_range_start
7656                        && entry.diagnostic.message == active_diagnostics.primary_message
7657                });
7658
7659            if is_valid != active_diagnostics.is_valid {
7660                active_diagnostics.is_valid = is_valid;
7661                let mut new_styles = HashMap::default();
7662                for (block_id, diagnostic) in &active_diagnostics.blocks {
7663                    new_styles.insert(
7664                        *block_id,
7665                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
7666                    );
7667                }
7668                self.display_map
7669                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
7670            }
7671        }
7672    }
7673
7674    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
7675        self.dismiss_diagnostics(cx);
7676        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
7677            let buffer = self.buffer.read(cx).snapshot(cx);
7678
7679            let mut primary_range = None;
7680            let mut primary_message = None;
7681            let mut group_end = Point::zero();
7682            let diagnostic_group = buffer
7683                .diagnostic_group::<Point>(group_id)
7684                .map(|entry| {
7685                    if entry.range.end > group_end {
7686                        group_end = entry.range.end;
7687                    }
7688                    if entry.diagnostic.is_primary {
7689                        primary_range = Some(entry.range.clone());
7690                        primary_message = Some(entry.diagnostic.message.clone());
7691                    }
7692                    entry
7693                })
7694                .collect::<Vec<_>>();
7695            let primary_range = primary_range?;
7696            let primary_message = primary_message?;
7697            let primary_range =
7698                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
7699
7700            let blocks = display_map
7701                .insert_blocks(
7702                    diagnostic_group.iter().map(|entry| {
7703                        let diagnostic = entry.diagnostic.clone();
7704                        let message_height = diagnostic.message.lines().count() as u8;
7705                        BlockProperties {
7706                            style: BlockStyle::Fixed,
7707                            position: buffer.anchor_after(entry.range.start),
7708                            height: message_height,
7709                            render: diagnostic_block_renderer(diagnostic, true),
7710                            disposition: BlockDisposition::Below,
7711                        }
7712                    }),
7713                    cx,
7714                )
7715                .into_iter()
7716                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
7717                .collect();
7718
7719            Some(ActiveDiagnosticGroup {
7720                primary_range,
7721                primary_message,
7722                blocks,
7723                is_valid: true,
7724            })
7725        });
7726        self.active_diagnostics.is_some()
7727    }
7728
7729    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
7730        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
7731            self.display_map.update(cx, |display_map, cx| {
7732                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
7733            });
7734            cx.notify();
7735        }
7736    }
7737
7738    pub fn set_selections_from_remote(
7739        &mut self,
7740        selections: Vec<Selection<Anchor>>,
7741        pending_selection: Option<Selection<Anchor>>,
7742        cx: &mut ViewContext<Self>,
7743    ) {
7744        let old_cursor_position = self.selections.newest_anchor().head();
7745        self.selections.change_with(cx, |s| {
7746            s.select_anchors(selections);
7747            if let Some(pending_selection) = pending_selection {
7748                s.set_pending(pending_selection, SelectMode::Character);
7749            } else {
7750                s.clear_pending();
7751            }
7752        });
7753        self.selections_did_change(false, &old_cursor_position, cx);
7754    }
7755
7756    fn push_to_selection_history(&mut self) {
7757        self.selection_history.push(SelectionHistoryEntry {
7758            selections: self.selections.disjoint_anchors(),
7759            select_next_state: self.select_next_state.clone(),
7760            select_prev_state: self.select_prev_state.clone(),
7761            add_selections_state: self.add_selections_state.clone(),
7762        });
7763    }
7764
7765    pub fn transact(
7766        &mut self,
7767        cx: &mut ViewContext<Self>,
7768        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
7769    ) -> Option<TransactionId> {
7770        self.start_transaction_at(Instant::now(), cx);
7771        update(self, cx);
7772        self.end_transaction_at(Instant::now(), cx)
7773    }
7774
7775    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
7776        self.end_selection(cx);
7777        if let Some(tx_id) = self
7778            .buffer
7779            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
7780        {
7781            self.selection_history
7782                .insert_transaction(tx_id, self.selections.disjoint_anchors());
7783        }
7784    }
7785
7786    fn end_transaction_at(
7787        &mut self,
7788        now: Instant,
7789        cx: &mut ViewContext<Self>,
7790    ) -> Option<TransactionId> {
7791        if let Some(tx_id) = self
7792            .buffer
7793            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
7794        {
7795            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
7796                *end_selections = Some(self.selections.disjoint_anchors());
7797            } else {
7798                error!("unexpectedly ended a transaction that wasn't started by this editor");
7799            }
7800
7801            cx.emit(Event::Edited);
7802            Some(tx_id)
7803        } else {
7804            None
7805        }
7806    }
7807
7808    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
7809        let mut fold_ranges = Vec::new();
7810
7811        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
7812
7813        let selections = self.selections.all_adjusted(cx);
7814        for selection in selections {
7815            let range = selection.range().sorted();
7816            let buffer_start_row = range.start.row;
7817
7818            for row in (0..=range.end.row).rev() {
7819                let fold_range = display_map.foldable_range(row);
7820
7821                if let Some(fold_range) = fold_range {
7822                    if fold_range.end.row >= buffer_start_row {
7823                        fold_ranges.push(fold_range);
7824                        if row <= range.start.row {
7825                            break;
7826                        }
7827                    }
7828                }
7829            }
7830        }
7831
7832        self.fold_ranges(fold_ranges, true, cx);
7833    }
7834
7835    pub fn fold_at(&mut self, fold_at: &FoldAt, cx: &mut ViewContext<Self>) {
7836        let buffer_row = fold_at.buffer_row;
7837        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
7838
7839        if let Some(fold_range) = display_map.foldable_range(buffer_row) {
7840            let autoscroll = self
7841                .selections
7842                .all::<Point>(cx)
7843                .iter()
7844                .any(|selection| fold_range.overlaps(&selection.range()));
7845
7846            self.fold_ranges(std::iter::once(fold_range), autoscroll, cx);
7847        }
7848    }
7849
7850    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
7851        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
7852        let buffer = &display_map.buffer_snapshot;
7853        let selections = self.selections.all::<Point>(cx);
7854        let ranges = selections
7855            .iter()
7856            .map(|s| {
7857                let range = s.display_range(&display_map).sorted();
7858                let mut start = range.start.to_point(&display_map);
7859                let mut end = range.end.to_point(&display_map);
7860                start.column = 0;
7861                end.column = buffer.line_len(end.row);
7862                start..end
7863            })
7864            .collect::<Vec<_>>();
7865
7866        self.unfold_ranges(ranges, true, true, cx);
7867    }
7868
7869    pub fn unfold_at(&mut self, unfold_at: &UnfoldAt, cx: &mut ViewContext<Self>) {
7870        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
7871
7872        let intersection_range = Point::new(unfold_at.buffer_row, 0)
7873            ..Point::new(
7874                unfold_at.buffer_row,
7875                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
7876            );
7877
7878        let autoscroll = self
7879            .selections
7880            .all::<Point>(cx)
7881            .iter()
7882            .any(|selection| selection.range().overlaps(&intersection_range));
7883
7884        self.unfold_ranges(std::iter::once(intersection_range), true, autoscroll, cx)
7885    }
7886
7887    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
7888        let selections = self.selections.all::<Point>(cx);
7889        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
7890        let line_mode = self.selections.line_mode;
7891        let ranges = selections.into_iter().map(|s| {
7892            if line_mode {
7893                let start = Point::new(s.start.row, 0);
7894                let end = Point::new(s.end.row, display_map.buffer_snapshot.line_len(s.end.row));
7895                start..end
7896            } else {
7897                s.start..s.end
7898            }
7899        });
7900        self.fold_ranges(ranges, true, cx);
7901    }
7902
7903    pub fn fold_ranges<T: ToOffset + Clone>(
7904        &mut self,
7905        ranges: impl IntoIterator<Item = Range<T>>,
7906        auto_scroll: bool,
7907        cx: &mut ViewContext<Self>,
7908    ) {
7909        let mut ranges = ranges.into_iter().peekable();
7910        if ranges.peek().is_some() {
7911            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
7912
7913            if auto_scroll {
7914                self.request_autoscroll(Autoscroll::fit(), cx);
7915            }
7916
7917            cx.notify();
7918        }
7919    }
7920
7921    pub fn unfold_ranges<T: ToOffset + Clone>(
7922        &mut self,
7923        ranges: impl IntoIterator<Item = Range<T>>,
7924        inclusive: bool,
7925        auto_scroll: bool,
7926        cx: &mut ViewContext<Self>,
7927    ) {
7928        let mut ranges = ranges.into_iter().peekable();
7929        if ranges.peek().is_some() {
7930            self.display_map
7931                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
7932            if auto_scroll {
7933                self.request_autoscroll(Autoscroll::fit(), cx);
7934            }
7935
7936            cx.notify();
7937        }
7938    }
7939
7940    pub fn gutter_hover(
7941        &mut self,
7942        GutterHover { hovered }: &GutterHover,
7943        cx: &mut ViewContext<Self>,
7944    ) {
7945        self.gutter_hovered = *hovered;
7946        cx.notify();
7947    }
7948
7949    pub fn insert_blocks(
7950        &mut self,
7951        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
7952        autoscroll: Option<Autoscroll>,
7953        cx: &mut ViewContext<Self>,
7954    ) -> Vec<BlockId> {
7955        let blocks = self
7956            .display_map
7957            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
7958        if let Some(autoscroll) = autoscroll {
7959            self.request_autoscroll(autoscroll, cx);
7960        }
7961        blocks
7962    }
7963
7964    pub fn replace_blocks(
7965        &mut self,
7966        blocks: HashMap<BlockId, RenderBlock>,
7967        autoscroll: Option<Autoscroll>,
7968        cx: &mut ViewContext<Self>,
7969    ) {
7970        self.display_map
7971            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
7972        if let Some(autoscroll) = autoscroll {
7973            self.request_autoscroll(autoscroll, cx);
7974        }
7975    }
7976
7977    pub fn remove_blocks(
7978        &mut self,
7979        block_ids: HashSet<BlockId>,
7980        autoscroll: Option<Autoscroll>,
7981        cx: &mut ViewContext<Self>,
7982    ) {
7983        self.display_map.update(cx, |display_map, cx| {
7984            display_map.remove_blocks(block_ids, cx)
7985        });
7986        if let Some(autoscroll) = autoscroll {
7987            self.request_autoscroll(autoscroll, cx);
7988        }
7989    }
7990
7991    pub fn longest_row(&self, cx: &mut AppContext) -> u32 {
7992        self.display_map
7993            .update(cx, |map, cx| map.snapshot(cx))
7994            .longest_row()
7995    }
7996
7997    pub fn max_point(&self, cx: &mut AppContext) -> DisplayPoint {
7998        self.display_map
7999            .update(cx, |map, cx| map.snapshot(cx))
8000            .max_point()
8001    }
8002
8003    pub fn text(&self, cx: &AppContext) -> String {
8004        self.buffer.read(cx).read(cx).text()
8005    }
8006
8007    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
8008        self.transact(cx, |this, cx| {
8009            this.buffer
8010                .read(cx)
8011                .as_singleton()
8012                .expect("you can only call set_text on editors for singleton buffers")
8013                .update(cx, |buffer, cx| buffer.set_text(text, cx));
8014        });
8015    }
8016
8017    pub fn display_text(&self, cx: &mut AppContext) -> String {
8018        self.display_map
8019            .update(cx, |map, cx| map.snapshot(cx))
8020            .text()
8021    }
8022
8023    pub fn wrap_guides(&self, cx: &AppContext) -> SmallVec<[(usize, bool); 2]> {
8024        let mut wrap_guides = smallvec::smallvec![];
8025
8026        if self.show_wrap_guides == Some(false) {
8027            return wrap_guides;
8028        }
8029
8030        let settings = self.buffer.read(cx).settings_at(0, cx);
8031        if settings.show_wrap_guides {
8032            if let SoftWrap::Column(soft_wrap) = self.soft_wrap_mode(cx) {
8033                wrap_guides.push((soft_wrap as usize, true));
8034            }
8035            wrap_guides.extend(settings.wrap_guides.iter().map(|guide| (*guide, false)))
8036        }
8037
8038        wrap_guides
8039    }
8040
8041    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
8042        let settings = self.buffer.read(cx).settings_at(0, cx);
8043        let mode = self
8044            .soft_wrap_mode_override
8045            .unwrap_or_else(|| settings.soft_wrap);
8046        match mode {
8047            language_settings::SoftWrap::None => SoftWrap::None,
8048            language_settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
8049            language_settings::SoftWrap::PreferredLineLength => {
8050                SoftWrap::Column(settings.preferred_line_length)
8051            }
8052        }
8053    }
8054
8055    pub fn set_soft_wrap_mode(
8056        &mut self,
8057        mode: language_settings::SoftWrap,
8058        cx: &mut ViewContext<Self>,
8059    ) {
8060        self.soft_wrap_mode_override = Some(mode);
8061        cx.notify();
8062    }
8063
8064    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut AppContext) -> bool {
8065        self.display_map
8066            .update(cx, |map, cx| map.set_wrap_width(width, cx))
8067    }
8068
8069    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
8070        if self.soft_wrap_mode_override.is_some() {
8071            self.soft_wrap_mode_override.take();
8072        } else {
8073            let soft_wrap = match self.soft_wrap_mode(cx) {
8074                SoftWrap::None => language_settings::SoftWrap::EditorWidth,
8075                SoftWrap::EditorWidth | SoftWrap::Column(_) => language_settings::SoftWrap::None,
8076            };
8077            self.soft_wrap_mode_override = Some(soft_wrap);
8078        }
8079        cx.notify();
8080    }
8081
8082    pub fn set_show_gutter(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
8083        self.show_gutter = show_gutter;
8084        cx.notify();
8085    }
8086
8087    pub fn set_show_wrap_guides(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
8088        self.show_wrap_guides = Some(show_gutter);
8089        cx.notify();
8090    }
8091
8092    pub fn reveal_in_finder(&mut self, _: &RevealInFinder, cx: &mut ViewContext<Self>) {
8093        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
8094            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
8095                cx.reveal_path(&file.abs_path(cx));
8096            }
8097        }
8098    }
8099
8100    pub fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
8101        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
8102            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
8103                if let Some(path) = file.abs_path(cx).to_str() {
8104                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
8105                }
8106            }
8107        }
8108    }
8109
8110    pub fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
8111        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
8112            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
8113                if let Some(path) = file.path().to_str() {
8114                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
8115                }
8116            }
8117        }
8118    }
8119
8120    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
8121        self.highlighted_rows = rows;
8122    }
8123
8124    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
8125        self.highlighted_rows.clone()
8126    }
8127
8128    pub fn highlight_background<T: 'static>(
8129        &mut self,
8130        ranges: Vec<Range<Anchor>>,
8131        color_fetcher: fn(&Theme) -> Color,
8132        cx: &mut ViewContext<Self>,
8133    ) {
8134        self.background_highlights
8135            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
8136        cx.notify();
8137    }
8138
8139    pub fn highlight_inlay_background<T: 'static>(
8140        &mut self,
8141        ranges: Vec<InlayHighlight>,
8142        color_fetcher: fn(&Theme) -> Color,
8143        cx: &mut ViewContext<Self>,
8144    ) {
8145        // TODO: no actual highlights happen for inlays currently, find a way to do that
8146        self.inlay_background_highlights
8147            .insert(Some(TypeId::of::<T>()), (color_fetcher, ranges));
8148        cx.notify();
8149    }
8150
8151    pub fn clear_background_highlights<T: 'static>(
8152        &mut self,
8153        cx: &mut ViewContext<Self>,
8154    ) -> Option<BackgroundHighlight> {
8155        let text_highlights = self.background_highlights.remove(&TypeId::of::<T>());
8156        let inlay_highlights = self
8157            .inlay_background_highlights
8158            .remove(&Some(TypeId::of::<T>()));
8159        if text_highlights.is_some() || inlay_highlights.is_some() {
8160            cx.notify();
8161        }
8162        text_highlights
8163    }
8164
8165    #[cfg(feature = "test-support")]
8166    pub fn all_text_background_highlights(
8167        &mut self,
8168        cx: &mut ViewContext<Self>,
8169    ) -> Vec<(Range<DisplayPoint>, Color)> {
8170        let snapshot = self.snapshot(cx);
8171        let buffer = &snapshot.buffer_snapshot;
8172        let start = buffer.anchor_before(0);
8173        let end = buffer.anchor_after(buffer.len());
8174        let theme = theme::current(cx);
8175        self.background_highlights_in_range(start..end, &snapshot, theme.as_ref())
8176    }
8177
8178    fn document_highlights_for_position<'a>(
8179        &'a self,
8180        position: Anchor,
8181        buffer: &'a MultiBufferSnapshot,
8182    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
8183        let read_highlights = self
8184            .background_highlights
8185            .get(&TypeId::of::<DocumentHighlightRead>())
8186            .map(|h| &h.1);
8187        let write_highlights = self
8188            .background_highlights
8189            .get(&TypeId::of::<DocumentHighlightWrite>())
8190            .map(|h| &h.1);
8191        let left_position = position.bias_left(buffer);
8192        let right_position = position.bias_right(buffer);
8193        read_highlights
8194            .into_iter()
8195            .chain(write_highlights)
8196            .flat_map(move |ranges| {
8197                let start_ix = match ranges.binary_search_by(|probe| {
8198                    let cmp = probe.end.cmp(&left_position, buffer);
8199                    if cmp.is_ge() {
8200                        Ordering::Greater
8201                    } else {
8202                        Ordering::Less
8203                    }
8204                }) {
8205                    Ok(i) | Err(i) => i,
8206                };
8207
8208                let right_position = right_position.clone();
8209                ranges[start_ix..]
8210                    .iter()
8211                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
8212            })
8213    }
8214
8215    pub fn background_highlights_in_range(
8216        &self,
8217        search_range: Range<Anchor>,
8218        display_snapshot: &DisplaySnapshot,
8219        theme: &Theme,
8220    ) -> Vec<(Range<DisplayPoint>, Color)> {
8221        let mut results = Vec::new();
8222        for (color_fetcher, ranges) in self.background_highlights.values() {
8223            let color = color_fetcher(theme);
8224            let start_ix = match ranges.binary_search_by(|probe| {
8225                let cmp = probe
8226                    .end
8227                    .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
8228                if cmp.is_gt() {
8229                    Ordering::Greater
8230                } else {
8231                    Ordering::Less
8232                }
8233            }) {
8234                Ok(i) | Err(i) => i,
8235            };
8236            for range in &ranges[start_ix..] {
8237                if range
8238                    .start
8239                    .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
8240                    .is_ge()
8241                {
8242                    break;
8243                }
8244
8245                let start = range.start.to_display_point(&display_snapshot);
8246                let end = range.end.to_display_point(&display_snapshot);
8247                results.push((start..end, color))
8248            }
8249        }
8250        results
8251    }
8252
8253    pub fn background_highlight_row_ranges<T: 'static>(
8254        &self,
8255        search_range: Range<Anchor>,
8256        display_snapshot: &DisplaySnapshot,
8257        count: usize,
8258    ) -> Vec<RangeInclusive<DisplayPoint>> {
8259        let mut results = Vec::new();
8260        let Some((_, ranges)) = self.background_highlights.get(&TypeId::of::<T>()) else {
8261            return vec![];
8262        };
8263
8264        let start_ix = match ranges.binary_search_by(|probe| {
8265            let cmp = probe
8266                .end
8267                .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
8268            if cmp.is_gt() {
8269                Ordering::Greater
8270            } else {
8271                Ordering::Less
8272            }
8273        }) {
8274            Ok(i) | Err(i) => i,
8275        };
8276        let mut push_region = |start: Option<Point>, end: Option<Point>| {
8277            if let (Some(start_display), Some(end_display)) = (start, end) {
8278                results.push(
8279                    start_display.to_display_point(display_snapshot)
8280                        ..=end_display.to_display_point(display_snapshot),
8281                );
8282            }
8283        };
8284        let mut start_row: Option<Point> = None;
8285        let mut end_row: Option<Point> = None;
8286        if ranges.len() > count {
8287            return Vec::new();
8288        }
8289        for range in &ranges[start_ix..] {
8290            if range
8291                .start
8292                .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
8293                .is_ge()
8294            {
8295                break;
8296            }
8297            let end = range.end.to_point(&display_snapshot.buffer_snapshot);
8298            if let Some(current_row) = &end_row {
8299                if end.row == current_row.row {
8300                    continue;
8301                }
8302            }
8303            let start = range.start.to_point(&display_snapshot.buffer_snapshot);
8304            if start_row.is_none() {
8305                assert_eq!(end_row, None);
8306                start_row = Some(start);
8307                end_row = Some(end);
8308                continue;
8309            }
8310            if let Some(current_end) = end_row.as_mut() {
8311                if start.row > current_end.row + 1 {
8312                    push_region(start_row, end_row);
8313                    start_row = Some(start);
8314                    end_row = Some(end);
8315                } else {
8316                    // Merge two hunks.
8317                    *current_end = end;
8318                }
8319            } else {
8320                unreachable!();
8321            }
8322        }
8323        // We might still have a hunk that was not rendered (if there was a search hit on the last line)
8324        push_region(start_row, end_row);
8325        results
8326    }
8327
8328    pub fn highlight_text<T: 'static>(
8329        &mut self,
8330        ranges: Vec<Range<Anchor>>,
8331        style: HighlightStyle,
8332        cx: &mut ViewContext<Self>,
8333    ) {
8334        self.display_map.update(cx, |map, _| {
8335            map.highlight_text(TypeId::of::<T>(), ranges, style)
8336        });
8337        cx.notify();
8338    }
8339
8340    pub fn highlight_inlays<T: 'static>(
8341        &mut self,
8342        highlights: Vec<InlayHighlight>,
8343        style: HighlightStyle,
8344        cx: &mut ViewContext<Self>,
8345    ) {
8346        self.display_map.update(cx, |map, _| {
8347            map.highlight_inlays(TypeId::of::<T>(), highlights, style)
8348        });
8349        cx.notify();
8350    }
8351
8352    pub fn text_highlights<'a, T: 'static>(
8353        &'a self,
8354        cx: &'a AppContext,
8355    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
8356        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
8357    }
8358
8359    pub fn clear_highlights<T: 'static>(&mut self, cx: &mut ViewContext<Self>) {
8360        let cleared = self
8361            .display_map
8362            .update(cx, |map, _| map.clear_highlights(TypeId::of::<T>()));
8363        if cleared {
8364            cx.notify();
8365        }
8366    }
8367
8368    pub fn show_local_cursors(&self, cx: &AppContext) -> bool {
8369        self.blink_manager.read(cx).visible() && self.focused
8370    }
8371
8372    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
8373        cx.notify();
8374    }
8375
8376    fn on_buffer_event(
8377        &mut self,
8378        multibuffer: ModelHandle<MultiBuffer>,
8379        event: &multi_buffer::Event,
8380        cx: &mut ViewContext<Self>,
8381    ) {
8382        match event {
8383            multi_buffer::Event::Edited {
8384                sigleton_buffer_edited,
8385            } => {
8386                self.refresh_active_diagnostics(cx);
8387                self.refresh_code_actions(cx);
8388                if self.has_active_copilot_suggestion(cx) {
8389                    self.update_visible_copilot_suggestion(cx);
8390                }
8391                cx.emit(Event::BufferEdited);
8392
8393                if *sigleton_buffer_edited {
8394                    if let Some(project) = &self.project {
8395                        let project = project.read(cx);
8396                        let languages_affected = multibuffer
8397                            .read(cx)
8398                            .all_buffers()
8399                            .into_iter()
8400                            .filter_map(|buffer| {
8401                                let buffer = buffer.read(cx);
8402                                let language = buffer.language()?;
8403                                if project.is_local()
8404                                    && project.language_servers_for_buffer(buffer, cx).count() == 0
8405                                {
8406                                    None
8407                                } else {
8408                                    Some(language)
8409                                }
8410                            })
8411                            .cloned()
8412                            .collect::<HashSet<_>>();
8413                        if !languages_affected.is_empty() {
8414                            self.refresh_inlay_hints(
8415                                InlayHintRefreshReason::BufferEdited(languages_affected),
8416                                cx,
8417                            );
8418                        }
8419                    }
8420                }
8421            }
8422            multi_buffer::Event::ExcerptsAdded {
8423                buffer,
8424                predecessor,
8425                excerpts,
8426            } => {
8427                cx.emit(Event::ExcerptsAdded {
8428                    buffer: buffer.clone(),
8429                    predecessor: *predecessor,
8430                    excerpts: excerpts.clone(),
8431                });
8432                self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
8433            }
8434            multi_buffer::Event::ExcerptsRemoved { ids } => {
8435                self.refresh_inlay_hints(InlayHintRefreshReason::ExcerptsRemoved(ids.clone()), cx);
8436                cx.emit(Event::ExcerptsRemoved { ids: ids.clone() })
8437            }
8438            multi_buffer::Event::Reparsed => cx.emit(Event::Reparsed),
8439            multi_buffer::Event::DirtyChanged => cx.emit(Event::DirtyChanged),
8440            multi_buffer::Event::Saved => cx.emit(Event::Saved),
8441            multi_buffer::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
8442            multi_buffer::Event::Reloaded => cx.emit(Event::TitleChanged),
8443            multi_buffer::Event::DiffBaseChanged => cx.emit(Event::DiffBaseChanged),
8444            multi_buffer::Event::Closed => cx.emit(Event::Closed),
8445            multi_buffer::Event::DiagnosticsUpdated => {
8446                self.refresh_active_diagnostics(cx);
8447            }
8448            _ => {}
8449        };
8450    }
8451
8452    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
8453        cx.notify();
8454    }
8455
8456    fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
8457        self.refresh_copilot_suggestions(true, cx);
8458        self.refresh_inlay_hints(
8459            InlayHintRefreshReason::SettingsChange(inlay_hint_settings(
8460                self.selections.newest_anchor().head(),
8461                &self.buffer.read(cx).snapshot(cx),
8462                cx,
8463            )),
8464            cx,
8465        );
8466    }
8467
8468    pub fn set_searchable(&mut self, searchable: bool) {
8469        self.searchable = searchable;
8470    }
8471
8472    pub fn searchable(&self) -> bool {
8473        self.searchable
8474    }
8475
8476    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
8477        let active_item = workspace.active_item(cx);
8478        let editor_handle = if let Some(editor) = active_item
8479            .as_ref()
8480            .and_then(|item| item.act_as::<Self>(cx))
8481        {
8482            editor
8483        } else {
8484            cx.propagate_action();
8485            return;
8486        };
8487
8488        let editor = editor_handle.read(cx);
8489        let buffer = editor.buffer.read(cx);
8490        if buffer.is_singleton() {
8491            cx.propagate_action();
8492            return;
8493        }
8494
8495        let mut new_selections_by_buffer = HashMap::default();
8496        for selection in editor.selections.all::<usize>(cx) {
8497            for (buffer, mut range, _) in
8498                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
8499            {
8500                if selection.reversed {
8501                    mem::swap(&mut range.start, &mut range.end);
8502                }
8503                new_selections_by_buffer
8504                    .entry(buffer)
8505                    .or_insert(Vec::new())
8506                    .push(range)
8507            }
8508        }
8509
8510        editor_handle.update(cx, |editor, cx| {
8511            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
8512        });
8513        let pane = workspace.active_pane().clone();
8514        pane.update(cx, |pane, _| pane.disable_history());
8515
8516        // We defer the pane interaction because we ourselves are a workspace item
8517        // and activating a new item causes the pane to call a method on us reentrantly,
8518        // which panics if we're on the stack.
8519        cx.defer(move |workspace, cx| {
8520            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
8521                let editor = workspace.open_project_item::<Self>(buffer, cx);
8522                editor.update(cx, |editor, cx| {
8523                    editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
8524                        s.select_ranges(ranges);
8525                    });
8526                });
8527            }
8528
8529            pane.update(cx, |pane, _| pane.enable_history());
8530        });
8531    }
8532
8533    fn jump(
8534        workspace: &mut Workspace,
8535        path: ProjectPath,
8536        position: Point,
8537        anchor: language::Anchor,
8538        cx: &mut ViewContext<Workspace>,
8539    ) {
8540        let editor = workspace.open_path(path, None, true, cx);
8541        cx.spawn(|_, mut cx| async move {
8542            let editor = editor
8543                .await?
8544                .downcast::<Editor>()
8545                .ok_or_else(|| anyhow!("opened item was not an editor"))?
8546                .downgrade();
8547            editor.update(&mut cx, |editor, cx| {
8548                let buffer = editor
8549                    .buffer()
8550                    .read(cx)
8551                    .as_singleton()
8552                    .ok_or_else(|| anyhow!("cannot jump in a multi-buffer"))?;
8553                let buffer = buffer.read(cx);
8554                let cursor = if buffer.can_resolve(&anchor) {
8555                    language::ToPoint::to_point(&anchor, buffer)
8556                } else {
8557                    buffer.clip_point(position, Bias::Left)
8558                };
8559
8560                let nav_history = editor.nav_history.take();
8561                editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
8562                    s.select_ranges([cursor..cursor]);
8563                });
8564                editor.nav_history = nav_history;
8565
8566                anyhow::Ok(())
8567            })??;
8568
8569            anyhow::Ok(())
8570        })
8571        .detach_and_log_err(cx);
8572    }
8573
8574    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
8575        let snapshot = self.buffer.read(cx).read(cx);
8576        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
8577        Some(
8578            ranges
8579                .iter()
8580                .map(move |range| {
8581                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
8582                })
8583                .collect(),
8584        )
8585    }
8586
8587    fn selection_replacement_ranges(
8588        &self,
8589        range: Range<OffsetUtf16>,
8590        cx: &AppContext,
8591    ) -> Vec<Range<OffsetUtf16>> {
8592        let selections = self.selections.all::<OffsetUtf16>(cx);
8593        let newest_selection = selections
8594            .iter()
8595            .max_by_key(|selection| selection.id)
8596            .unwrap();
8597        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
8598        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
8599        let snapshot = self.buffer.read(cx).read(cx);
8600        selections
8601            .into_iter()
8602            .map(|mut selection| {
8603                selection.start.0 =
8604                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
8605                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
8606                snapshot.clip_offset_utf16(selection.start, Bias::Left)
8607                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
8608            })
8609            .collect()
8610    }
8611
8612    fn report_copilot_event(
8613        &self,
8614        suggestion_id: Option<String>,
8615        suggestion_accepted: bool,
8616        cx: &AppContext,
8617    ) {
8618        let Some(project) = &self.project else { return };
8619
8620        // If None, we are either getting suggestions in a new, unsaved file, or in a file without an extension
8621        let file_extension = self
8622            .buffer
8623            .read(cx)
8624            .as_singleton()
8625            .and_then(|b| b.read(cx).file())
8626            .and_then(|file| Path::new(file.file_name(cx)).extension())
8627            .and_then(|e| e.to_str())
8628            .map(|a| a.to_string());
8629
8630        let telemetry = project.read(cx).client().telemetry().clone();
8631        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
8632
8633        let event = ClickhouseEvent::Copilot {
8634            suggestion_id,
8635            suggestion_accepted,
8636            file_extension,
8637        };
8638        telemetry.report_clickhouse_event(event, telemetry_settings);
8639    }
8640
8641    fn report_editor_event(
8642        &self,
8643        operation: &'static str,
8644        file_extension: Option<String>,
8645        cx: &AppContext,
8646    ) {
8647        let Some(project) = &self.project else { return };
8648
8649        // If None, we are in a file without an extension
8650        let file = self
8651            .buffer
8652            .read(cx)
8653            .as_singleton()
8654            .and_then(|b| b.read(cx).file());
8655        let file_extension = file_extension.or(file
8656            .as_ref()
8657            .and_then(|file| Path::new(file.file_name(cx)).extension())
8658            .and_then(|e| e.to_str())
8659            .map(|a| a.to_string()));
8660
8661        let vim_mode = cx
8662            .global::<SettingsStore>()
8663            .raw_user_settings()
8664            .get("vim_mode")
8665            == Some(&serde_json::Value::Bool(true));
8666        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
8667        let copilot_enabled = all_language_settings(file, cx).copilot_enabled(None, None);
8668        let copilot_enabled_for_language = self
8669            .buffer
8670            .read(cx)
8671            .settings_at(0, cx)
8672            .show_copilot_suggestions;
8673
8674        let telemetry = project.read(cx).client().telemetry().clone();
8675        let event = ClickhouseEvent::Editor {
8676            file_extension,
8677            vim_mode,
8678            operation,
8679            copilot_enabled,
8680            copilot_enabled_for_language,
8681        };
8682        telemetry.report_clickhouse_event(event, telemetry_settings)
8683    }
8684
8685    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
8686    /// with each line being an array of {text, highlight} objects.
8687    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
8688        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
8689            return;
8690        };
8691
8692        #[derive(Serialize)]
8693        struct Chunk<'a> {
8694            text: String,
8695            highlight: Option<&'a str>,
8696        }
8697
8698        let snapshot = buffer.read(cx).snapshot();
8699        let range = self
8700            .selected_text_range(cx)
8701            .and_then(|selected_range| {
8702                if selected_range.is_empty() {
8703                    None
8704                } else {
8705                    Some(selected_range)
8706                }
8707            })
8708            .unwrap_or_else(|| 0..snapshot.len());
8709
8710        let chunks = snapshot.chunks(range, true);
8711        let mut lines = Vec::new();
8712        let mut line: VecDeque<Chunk> = VecDeque::new();
8713
8714        let theme = &theme::current(cx).editor.syntax;
8715
8716        for chunk in chunks {
8717            let highlight = chunk.syntax_highlight_id.and_then(|id| id.name(theme));
8718            let mut chunk_lines = chunk.text.split("\n").peekable();
8719            while let Some(text) = chunk_lines.next() {
8720                let mut merged_with_last_token = false;
8721                if let Some(last_token) = line.back_mut() {
8722                    if last_token.highlight == highlight {
8723                        last_token.text.push_str(text);
8724                        merged_with_last_token = true;
8725                    }
8726                }
8727
8728                if !merged_with_last_token {
8729                    line.push_back(Chunk {
8730                        text: text.into(),
8731                        highlight,
8732                    });
8733                }
8734
8735                if chunk_lines.peek().is_some() {
8736                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
8737                        line.pop_front();
8738                    }
8739                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
8740                        line.pop_back();
8741                    }
8742
8743                    lines.push(mem::take(&mut line));
8744                }
8745            }
8746        }
8747
8748        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else {
8749            return;
8750        };
8751        cx.write_to_clipboard(ClipboardItem::new(lines));
8752    }
8753
8754    pub fn inlay_hint_cache(&self) -> &InlayHintCache {
8755        &self.inlay_hint_cache
8756    }
8757
8758    pub fn replay_insert_event(
8759        &mut self,
8760        text: &str,
8761        relative_utf16_range: Option<Range<isize>>,
8762        cx: &mut ViewContext<Self>,
8763    ) {
8764        if !self.input_enabled {
8765            cx.emit(Event::InputIgnored { text: text.into() });
8766            return;
8767        }
8768        if let Some(relative_utf16_range) = relative_utf16_range {
8769            let selections = self.selections.all::<OffsetUtf16>(cx);
8770            self.change_selections(None, cx, |s| {
8771                let new_ranges = selections.into_iter().map(|range| {
8772                    let start = OffsetUtf16(
8773                        range
8774                            .head()
8775                            .0
8776                            .saturating_add_signed(relative_utf16_range.start),
8777                    );
8778                    let end = OffsetUtf16(
8779                        range
8780                            .head()
8781                            .0
8782                            .saturating_add_signed(relative_utf16_range.end),
8783                    );
8784                    start..end
8785                });
8786                s.select_ranges(new_ranges);
8787            });
8788        }
8789
8790        self.handle_input(text, cx);
8791    }
8792
8793    pub fn supports_inlay_hints(&self, cx: &AppContext) -> bool {
8794        let Some(project) = self.project.as_ref() else {
8795            return false;
8796        };
8797        let project = project.read(cx);
8798
8799        let mut supports = false;
8800        self.buffer().read(cx).for_each_buffer(|buffer| {
8801            if !supports {
8802                supports = project
8803                    .language_servers_for_buffer(buffer.read(cx), cx)
8804                    .any(
8805                        |(_, server)| match server.capabilities().inlay_hint_provider {
8806                            Some(lsp::OneOf::Left(enabled)) => enabled,
8807                            Some(lsp::OneOf::Right(_)) => true,
8808                            None => false,
8809                        },
8810                    )
8811            }
8812        });
8813        supports
8814    }
8815}
8816
8817pub trait CollaborationHub {
8818    fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator>;
8819    fn user_participant_indices<'a>(
8820        &self,
8821        cx: &'a AppContext,
8822    ) -> &'a HashMap<u64, ParticipantIndex>;
8823}
8824
8825impl CollaborationHub for ModelHandle<Project> {
8826    fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator> {
8827        self.read(cx).collaborators()
8828    }
8829
8830    fn user_participant_indices<'a>(
8831        &self,
8832        cx: &'a AppContext,
8833    ) -> &'a HashMap<u64, ParticipantIndex> {
8834        self.read(cx).user_store().read(cx).participant_indices()
8835    }
8836}
8837
8838fn inlay_hint_settings(
8839    location: Anchor,
8840    snapshot: &MultiBufferSnapshot,
8841    cx: &mut ViewContext<'_, '_, Editor>,
8842) -> InlayHintSettings {
8843    let file = snapshot.file_at(location);
8844    let language = snapshot.language_at(location);
8845    let settings = all_language_settings(file, cx);
8846    settings
8847        .language(language.map(|l| l.name()).as_deref())
8848        .inlay_hints
8849}
8850
8851fn consume_contiguous_rows(
8852    contiguous_row_selections: &mut Vec<Selection<Point>>,
8853    selection: &Selection<Point>,
8854    display_map: &DisplaySnapshot,
8855    selections: &mut std::iter::Peekable<std::slice::Iter<Selection<Point>>>,
8856) -> (u32, u32) {
8857    contiguous_row_selections.push(selection.clone());
8858    let start_row = selection.start.row;
8859    let mut end_row = ending_row(selection, display_map);
8860
8861    while let Some(next_selection) = selections.peek() {
8862        if next_selection.start.row <= end_row {
8863            end_row = ending_row(next_selection, display_map);
8864            contiguous_row_selections.push(selections.next().unwrap().clone());
8865        } else {
8866            break;
8867        }
8868    }
8869    (start_row, end_row)
8870}
8871
8872fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> u32 {
8873    if next_selection.end.column > 0 || next_selection.is_empty() {
8874        display_map.next_line_boundary(next_selection.end).0.row + 1
8875    } else {
8876        next_selection.end.row
8877    }
8878}
8879
8880impl EditorSnapshot {
8881    pub fn remote_selections_in_range<'a>(
8882        &'a self,
8883        range: &'a Range<Anchor>,
8884        collaboration_hub: &dyn CollaborationHub,
8885        cx: &'a AppContext,
8886    ) -> impl 'a + Iterator<Item = RemoteSelection> {
8887        let participant_indices = collaboration_hub.user_participant_indices(cx);
8888        let collaborators_by_peer_id = collaboration_hub.collaborators(cx);
8889        let collaborators_by_replica_id = collaborators_by_peer_id
8890            .iter()
8891            .map(|(_, collaborator)| (collaborator.replica_id, collaborator))
8892            .collect::<HashMap<_, _>>();
8893        self.buffer_snapshot
8894            .remote_selections_in_range(range)
8895            .filter_map(move |(replica_id, line_mode, cursor_shape, selection)| {
8896                let collaborator = collaborators_by_replica_id.get(&replica_id)?;
8897                let participant_index = participant_indices.get(&collaborator.user_id).copied();
8898                Some(RemoteSelection {
8899                    replica_id,
8900                    selection,
8901                    cursor_shape,
8902                    line_mode,
8903                    participant_index,
8904                    peer_id: collaborator.peer_id,
8905                })
8906            })
8907    }
8908
8909    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
8910        self.display_snapshot.buffer_snapshot.language_at(position)
8911    }
8912
8913    pub fn is_focused(&self) -> bool {
8914        self.is_focused
8915    }
8916
8917    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
8918        self.placeholder_text.as_ref()
8919    }
8920
8921    pub fn scroll_position(&self) -> Vector2F {
8922        self.scroll_anchor.scroll_position(&self.display_snapshot)
8923    }
8924}
8925
8926impl Deref for EditorSnapshot {
8927    type Target = DisplaySnapshot;
8928
8929    fn deref(&self) -> &Self::Target {
8930        &self.display_snapshot
8931    }
8932}
8933
8934#[derive(Clone, Debug, PartialEq, Eq)]
8935pub enum Event {
8936    InputIgnored {
8937        text: Arc<str>,
8938    },
8939    InputHandled {
8940        utf16_range_to_replace: Option<Range<isize>>,
8941        text: Arc<str>,
8942    },
8943    ExcerptsAdded {
8944        buffer: ModelHandle<Buffer>,
8945        predecessor: ExcerptId,
8946        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
8947    },
8948    ExcerptsRemoved {
8949        ids: Vec<ExcerptId>,
8950    },
8951    BufferEdited,
8952    Edited,
8953    Reparsed,
8954    Focused,
8955    Blurred,
8956    DirtyChanged,
8957    Saved,
8958    TitleChanged,
8959    DiffBaseChanged,
8960    SelectionsChanged {
8961        local: bool,
8962    },
8963    ScrollPositionChanged {
8964        local: bool,
8965        autoscroll: bool,
8966    },
8967    Closed,
8968}
8969
8970pub struct EditorFocused(pub ViewHandle<Editor>);
8971pub struct EditorBlurred(pub ViewHandle<Editor>);
8972pub struct EditorReleased(pub WeakViewHandle<Editor>);
8973
8974impl Entity for Editor {
8975    type Event = Event;
8976
8977    fn release(&mut self, cx: &mut AppContext) {
8978        cx.emit_global(EditorReleased(self.handle.clone()));
8979    }
8980}
8981
8982impl View for Editor {
8983    fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
8984        let style = self.style(cx);
8985        let font_changed = self.display_map.update(cx, |map, cx| {
8986            map.set_fold_ellipses_color(style.folds.ellipses.text_color);
8987            map.set_font(style.text.font_id, style.text.font_size, cx)
8988        });
8989
8990        if font_changed {
8991            cx.defer(move |editor, cx: &mut ViewContext<Editor>| {
8992                hide_hover(editor, cx);
8993                hide_link_definition(editor, cx);
8994            });
8995        }
8996
8997        Stack::new()
8998            .with_child(EditorElement::new(style.clone()))
8999            .with_child(ChildView::new(&self.mouse_context_menu, cx))
9000            .into_any()
9001    }
9002
9003    fn ui_name() -> &'static str {
9004        "Editor"
9005    }
9006
9007    fn focus_in(&mut self, focused: AnyViewHandle, cx: &mut ViewContext<Self>) {
9008        if cx.is_self_focused() {
9009            let focused_event = EditorFocused(cx.handle());
9010            cx.emit(Event::Focused);
9011            cx.emit_global(focused_event);
9012        }
9013        if let Some(rename) = self.pending_rename.as_ref() {
9014            cx.focus(&rename.editor);
9015        } else if cx.is_self_focused() || !focused.is::<Editor>() {
9016            if !self.focused {
9017                self.blink_manager.update(cx, BlinkManager::enable);
9018            }
9019            self.focused = true;
9020            self.buffer.update(cx, |buffer, cx| {
9021                buffer.finalize_last_transaction(cx);
9022                if self.leader_peer_id.is_none() {
9023                    buffer.set_active_selections(
9024                        &self.selections.disjoint_anchors(),
9025                        self.selections.line_mode,
9026                        self.cursor_shape,
9027                        cx,
9028                    );
9029                }
9030            });
9031        }
9032    }
9033
9034    fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
9035        let blurred_event = EditorBlurred(cx.handle());
9036        cx.emit_global(blurred_event);
9037        self.focused = false;
9038        self.blink_manager.update(cx, BlinkManager::disable);
9039        self.buffer
9040            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
9041        self.hide_context_menu(cx);
9042        hide_hover(self, cx);
9043        cx.emit(Event::Blurred);
9044        cx.notify();
9045    }
9046
9047    fn modifiers_changed(
9048        &mut self,
9049        event: &gpui::platform::ModifiersChangedEvent,
9050        cx: &mut ViewContext<Self>,
9051    ) -> bool {
9052        let pending_selection = self.has_pending_selection();
9053
9054        if let Some(point) = &self.link_go_to_definition_state.last_trigger_point {
9055            if event.cmd && !pending_selection {
9056                let point = point.clone();
9057                let snapshot = self.snapshot(cx);
9058                let kind = point.definition_kind(event.shift);
9059
9060                show_link_definition(kind, self, point, snapshot, cx);
9061                return false;
9062            }
9063        }
9064
9065        {
9066            if self.link_go_to_definition_state.symbol_range.is_some()
9067                || !self.link_go_to_definition_state.definitions.is_empty()
9068            {
9069                self.link_go_to_definition_state.symbol_range.take();
9070                self.link_go_to_definition_state.definitions.clear();
9071                cx.notify();
9072            }
9073
9074            self.link_go_to_definition_state.task = None;
9075
9076            self.clear_highlights::<LinkGoToDefinitionState>(cx);
9077        }
9078
9079        false
9080    }
9081
9082    fn update_keymap_context(&self, keymap: &mut KeymapContext, cx: &AppContext) {
9083        Self::reset_to_default_keymap_context(keymap);
9084        let mode = match self.mode {
9085            EditorMode::SingleLine => "single_line",
9086            EditorMode::AutoHeight { .. } => "auto_height",
9087            EditorMode::Full => "full",
9088        };
9089        keymap.add_key("mode", mode);
9090        if self.pending_rename.is_some() {
9091            keymap.add_identifier("renaming");
9092        }
9093        if self.context_menu_visible() {
9094            match self.context_menu.as_ref() {
9095                Some(ContextMenu::Completions(_)) => {
9096                    keymap.add_identifier("menu");
9097                    keymap.add_identifier("showing_completions")
9098                }
9099                Some(ContextMenu::CodeActions(_)) => {
9100                    keymap.add_identifier("menu");
9101                    keymap.add_identifier("showing_code_actions")
9102                }
9103                None => {}
9104            }
9105        }
9106
9107        for layer in self.keymap_context_layers.values() {
9108            keymap.extend(layer);
9109        }
9110
9111        if let Some(extension) = self
9112            .buffer
9113            .read(cx)
9114            .as_singleton()
9115            .and_then(|buffer| buffer.read(cx).file()?.path().extension()?.to_str())
9116        {
9117            keymap.add_key("extension", extension.to_string());
9118        }
9119    }
9120
9121    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
9122        Some(
9123            self.buffer
9124                .read(cx)
9125                .read(cx)
9126                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
9127                .collect(),
9128        )
9129    }
9130
9131    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
9132        // Prevent the IME menu from appearing when holding down an alphabetic key
9133        // while input is disabled.
9134        if !self.input_enabled {
9135            return None;
9136        }
9137
9138        let range = self.selections.newest::<OffsetUtf16>(cx).range();
9139        Some(range.start.0..range.end.0)
9140    }
9141
9142    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
9143        let snapshot = self.buffer.read(cx).read(cx);
9144        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
9145        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
9146    }
9147
9148    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
9149        self.clear_highlights::<InputComposition>(cx);
9150        self.ime_transaction.take();
9151    }
9152
9153    fn replace_text_in_range(
9154        &mut self,
9155        range_utf16: Option<Range<usize>>,
9156        text: &str,
9157        cx: &mut ViewContext<Self>,
9158    ) {
9159        if !self.input_enabled {
9160            cx.emit(Event::InputIgnored { text: text.into() });
9161            return;
9162        }
9163
9164        self.transact(cx, |this, cx| {
9165            let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
9166                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
9167                Some(this.selection_replacement_ranges(range_utf16, cx))
9168            } else {
9169                this.marked_text_ranges(cx)
9170            };
9171
9172            let range_to_replace = new_selected_ranges.as_ref().and_then(|ranges_to_replace| {
9173                let newest_selection_id = this.selections.newest_anchor().id;
9174                this.selections
9175                    .all::<OffsetUtf16>(cx)
9176                    .iter()
9177                    .zip(ranges_to_replace.iter())
9178                    .find_map(|(selection, range)| {
9179                        if selection.id == newest_selection_id {
9180                            Some(
9181                                (range.start.0 as isize - selection.head().0 as isize)
9182                                    ..(range.end.0 as isize - selection.head().0 as isize),
9183                            )
9184                        } else {
9185                            None
9186                        }
9187                    })
9188            });
9189
9190            cx.emit(Event::InputHandled {
9191                utf16_range_to_replace: range_to_replace,
9192                text: text.into(),
9193            });
9194
9195            if let Some(new_selected_ranges) = new_selected_ranges {
9196                this.change_selections(None, cx, |selections| {
9197                    selections.select_ranges(new_selected_ranges)
9198                });
9199            }
9200
9201            this.handle_input(text, cx);
9202        });
9203
9204        if let Some(transaction) = self.ime_transaction {
9205            self.buffer.update(cx, |buffer, cx| {
9206                buffer.group_until_transaction(transaction, cx);
9207            });
9208        }
9209
9210        self.unmark_text(cx);
9211    }
9212
9213    fn replace_and_mark_text_in_range(
9214        &mut self,
9215        range_utf16: Option<Range<usize>>,
9216        text: &str,
9217        new_selected_range_utf16: Option<Range<usize>>,
9218        cx: &mut ViewContext<Self>,
9219    ) {
9220        if !self.input_enabled {
9221            cx.emit(Event::InputIgnored { text: text.into() });
9222            return;
9223        }
9224
9225        let transaction = self.transact(cx, |this, cx| {
9226            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
9227                let snapshot = this.buffer.read(cx).read(cx);
9228                if let Some(relative_range_utf16) = range_utf16.as_ref() {
9229                    for marked_range in &mut marked_ranges {
9230                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
9231                        marked_range.start.0 += relative_range_utf16.start;
9232                        marked_range.start =
9233                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
9234                        marked_range.end =
9235                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
9236                    }
9237                }
9238                Some(marked_ranges)
9239            } else if let Some(range_utf16) = range_utf16 {
9240                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
9241                Some(this.selection_replacement_ranges(range_utf16, cx))
9242            } else {
9243                None
9244            };
9245
9246            let range_to_replace = ranges_to_replace.as_ref().and_then(|ranges_to_replace| {
9247                let newest_selection_id = this.selections.newest_anchor().id;
9248                this.selections
9249                    .all::<OffsetUtf16>(cx)
9250                    .iter()
9251                    .zip(ranges_to_replace.iter())
9252                    .find_map(|(selection, range)| {
9253                        if selection.id == newest_selection_id {
9254                            Some(
9255                                (range.start.0 as isize - selection.head().0 as isize)
9256                                    ..(range.end.0 as isize - selection.head().0 as isize),
9257                            )
9258                        } else {
9259                            None
9260                        }
9261                    })
9262            });
9263
9264            cx.emit(Event::InputHandled {
9265                utf16_range_to_replace: range_to_replace,
9266                text: text.into(),
9267            });
9268
9269            if let Some(ranges) = ranges_to_replace {
9270                this.change_selections(None, cx, |s| s.select_ranges(ranges));
9271            }
9272
9273            let marked_ranges = {
9274                let snapshot = this.buffer.read(cx).read(cx);
9275                this.selections
9276                    .disjoint_anchors()
9277                    .iter()
9278                    .map(|selection| {
9279                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
9280                    })
9281                    .collect::<Vec<_>>()
9282            };
9283
9284            if text.is_empty() {
9285                this.unmark_text(cx);
9286            } else {
9287                this.highlight_text::<InputComposition>(
9288                    marked_ranges.clone(),
9289                    this.style(cx).composition_mark,
9290                    cx,
9291                );
9292            }
9293
9294            this.handle_input(text, cx);
9295
9296            if let Some(new_selected_range) = new_selected_range_utf16 {
9297                let snapshot = this.buffer.read(cx).read(cx);
9298                let new_selected_ranges = marked_ranges
9299                    .into_iter()
9300                    .map(|marked_range| {
9301                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
9302                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
9303                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
9304                        snapshot.clip_offset_utf16(new_start, Bias::Left)
9305                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
9306                    })
9307                    .collect::<Vec<_>>();
9308
9309                drop(snapshot);
9310                this.change_selections(None, cx, |selections| {
9311                    selections.select_ranges(new_selected_ranges)
9312                });
9313            }
9314        });
9315
9316        self.ime_transaction = self.ime_transaction.or(transaction);
9317        if let Some(transaction) = self.ime_transaction {
9318            self.buffer.update(cx, |buffer, cx| {
9319                buffer.group_until_transaction(transaction, cx);
9320            });
9321        }
9322
9323        if self.text_highlights::<InputComposition>(cx).is_none() {
9324            self.ime_transaction.take();
9325        }
9326    }
9327}
9328
9329fn build_style(
9330    settings: &ThemeSettings,
9331    get_field_editor_theme: Option<&GetFieldEditorTheme>,
9332    override_text_style: Option<&OverrideTextStyle>,
9333    cx: &AppContext,
9334) -> EditorStyle {
9335    let font_cache = cx.font_cache();
9336    let line_height_scalar = settings.line_height();
9337    let theme_id = settings.theme.meta.id;
9338    let mut theme = settings.theme.editor.clone();
9339    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
9340        let field_editor_theme = get_field_editor_theme(&settings.theme);
9341        theme.text_color = field_editor_theme.text.color;
9342        theme.selection = field_editor_theme.selection;
9343        theme.background = field_editor_theme
9344            .container
9345            .background_color
9346            .unwrap_or_default();
9347        EditorStyle {
9348            text: field_editor_theme.text,
9349            placeholder_text: field_editor_theme.placeholder_text,
9350            line_height_scalar,
9351            theme,
9352            theme_id,
9353        }
9354    } else {
9355        let font_family_id = settings.buffer_font_family;
9356        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
9357        let font_properties = Default::default();
9358        let font_id = font_cache
9359            .select_font(font_family_id, &font_properties)
9360            .unwrap();
9361        let font_size = settings.buffer_font_size(cx);
9362        EditorStyle {
9363            text: TextStyle {
9364                color: settings.theme.editor.text_color,
9365                font_family_name,
9366                font_family_id,
9367                font_id,
9368                font_size,
9369                font_properties,
9370                underline: Default::default(),
9371                soft_wrap: false,
9372            },
9373            placeholder_text: None,
9374            line_height_scalar,
9375            theme,
9376            theme_id,
9377        }
9378    };
9379
9380    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
9381        if let Some(highlighted) = style
9382            .text
9383            .clone()
9384            .highlight(highlight_style, font_cache)
9385            .log_err()
9386        {
9387            style.text = highlighted;
9388        }
9389    }
9390
9391    style
9392}
9393
9394trait SelectionExt {
9395    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
9396    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
9397    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
9398    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
9399        -> Range<u32>;
9400}
9401
9402impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
9403    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
9404        let start = self.start.to_point(buffer);
9405        let end = self.end.to_point(buffer);
9406        if self.reversed {
9407            end..start
9408        } else {
9409            start..end
9410        }
9411    }
9412
9413    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
9414        let start = self.start.to_offset(buffer);
9415        let end = self.end.to_offset(buffer);
9416        if self.reversed {
9417            end..start
9418        } else {
9419            start..end
9420        }
9421    }
9422
9423    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
9424        let start = self
9425            .start
9426            .to_point(&map.buffer_snapshot)
9427            .to_display_point(map);
9428        let end = self
9429            .end
9430            .to_point(&map.buffer_snapshot)
9431            .to_display_point(map);
9432        if self.reversed {
9433            end..start
9434        } else {
9435            start..end
9436        }
9437    }
9438
9439    fn spanned_rows(
9440        &self,
9441        include_end_if_at_line_start: bool,
9442        map: &DisplaySnapshot,
9443    ) -> Range<u32> {
9444        let start = self.start.to_point(&map.buffer_snapshot);
9445        let mut end = self.end.to_point(&map.buffer_snapshot);
9446        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
9447            end.row -= 1;
9448        }
9449
9450        let buffer_start = map.prev_line_boundary(start).0;
9451        let buffer_end = map.next_line_boundary(end).0;
9452        buffer_start.row..buffer_end.row + 1
9453    }
9454}
9455
9456impl<T: InvalidationRegion> InvalidationStack<T> {
9457    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
9458    where
9459        S: Clone + ToOffset,
9460    {
9461        while let Some(region) = self.last() {
9462            let all_selections_inside_invalidation_ranges =
9463                if selections.len() == region.ranges().len() {
9464                    selections
9465                        .iter()
9466                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
9467                        .all(|(selection, invalidation_range)| {
9468                            let head = selection.head().to_offset(buffer);
9469                            invalidation_range.start <= head && invalidation_range.end >= head
9470                        })
9471                } else {
9472                    false
9473                };
9474
9475            if all_selections_inside_invalidation_ranges {
9476                break;
9477            } else {
9478                self.pop();
9479            }
9480        }
9481    }
9482}
9483
9484impl<T> Default for InvalidationStack<T> {
9485    fn default() -> Self {
9486        Self(Default::default())
9487    }
9488}
9489
9490impl<T> Deref for InvalidationStack<T> {
9491    type Target = Vec<T>;
9492
9493    fn deref(&self) -> &Self::Target {
9494        &self.0
9495    }
9496}
9497
9498impl<T> DerefMut for InvalidationStack<T> {
9499    fn deref_mut(&mut self) -> &mut Self::Target {
9500        &mut self.0
9501    }
9502}
9503
9504impl InvalidationRegion for SnippetState {
9505    fn ranges(&self) -> &[Range<Anchor>] {
9506        &self.ranges[self.active_index]
9507    }
9508}
9509
9510impl Deref for EditorStyle {
9511    type Target = theme::Editor;
9512
9513    fn deref(&self) -> &Self::Target {
9514        &self.theme
9515    }
9516}
9517
9518pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
9519    let mut highlighted_lines = Vec::new();
9520
9521    for (index, line) in diagnostic.message.lines().enumerate() {
9522        let line = match &diagnostic.source {
9523            Some(source) if index == 0 => {
9524                let source_highlight = Vec::from_iter(0..source.len());
9525                highlight_diagnostic_message(source_highlight, &format!("{source}: {line}"))
9526            }
9527
9528            _ => highlight_diagnostic_message(Vec::new(), line),
9529        };
9530        highlighted_lines.push(line);
9531    }
9532    let message = diagnostic.message;
9533    Arc::new(move |cx: &mut BlockContext| {
9534        let message = message.clone();
9535        let settings = settings::get::<ThemeSettings>(cx);
9536        let tooltip_style = settings.theme.tooltip.clone();
9537        let theme = &settings.theme.editor;
9538        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
9539        let font_size = (style.text_scale_factor * settings.buffer_font_size(cx)).round();
9540        let anchor_x = cx.anchor_x;
9541        enum BlockContextToolip {}
9542        MouseEventHandler::new::<BlockContext, _>(cx.block_id, cx, |_, _| {
9543            Flex::column()
9544                .with_children(highlighted_lines.iter().map(|(line, highlights)| {
9545                    Label::new(
9546                        line.clone(),
9547                        style.message.clone().with_font_size(font_size),
9548                    )
9549                    .with_highlights(highlights.clone())
9550                    .contained()
9551                    .with_margin_left(anchor_x)
9552                }))
9553                .aligned()
9554                .left()
9555                .into_any()
9556        })
9557        .with_cursor_style(CursorStyle::PointingHand)
9558        .on_click(MouseButton::Left, move |_, _, cx| {
9559            cx.write_to_clipboard(ClipboardItem::new(message.clone()));
9560        })
9561        // We really need to rethink this ID system...
9562        .with_tooltip::<BlockContextToolip>(
9563            cx.block_id,
9564            "Copy diagnostic message",
9565            None,
9566            tooltip_style,
9567            cx,
9568        )
9569        .into_any()
9570    })
9571}
9572
9573pub fn highlight_diagnostic_message(
9574    initial_highlights: Vec<usize>,
9575    message: &str,
9576) -> (String, Vec<usize>) {
9577    let mut message_without_backticks = String::new();
9578    let mut prev_offset = 0;
9579    let mut inside_block = false;
9580    let mut highlights = initial_highlights;
9581    for (match_ix, (offset, _)) in message
9582        .match_indices('`')
9583        .chain([(message.len(), "")])
9584        .enumerate()
9585    {
9586        message_without_backticks.push_str(&message[prev_offset..offset]);
9587        if inside_block {
9588            highlights.extend(prev_offset - match_ix..offset - match_ix);
9589        }
9590
9591        inside_block = !inside_block;
9592        prev_offset = offset + 1;
9593    }
9594
9595    (message_without_backticks, highlights)
9596}
9597
9598pub fn diagnostic_style(
9599    severity: DiagnosticSeverity,
9600    valid: bool,
9601    theme: &theme::Editor,
9602) -> DiagnosticStyle {
9603    match (severity, valid) {
9604        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
9605        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
9606        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
9607        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
9608        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
9609        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
9610        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
9611        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
9612        _ => theme.invalid_hint_diagnostic.clone(),
9613    }
9614}
9615
9616pub fn combine_syntax_and_fuzzy_match_highlights(
9617    text: &str,
9618    default_style: HighlightStyle,
9619    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
9620    match_indices: &[usize],
9621) -> Vec<(Range<usize>, HighlightStyle)> {
9622    let mut result = Vec::new();
9623    let mut match_indices = match_indices.iter().copied().peekable();
9624
9625    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
9626    {
9627        syntax_highlight.weight = None;
9628
9629        // Add highlights for any fuzzy match characters before the next
9630        // syntax highlight range.
9631        while let Some(&match_index) = match_indices.peek() {
9632            if match_index >= range.start {
9633                break;
9634            }
9635            match_indices.next();
9636            let end_index = char_ix_after(match_index, text);
9637            let mut match_style = default_style;
9638            match_style.weight = Some(fonts::Weight::BOLD);
9639            result.push((match_index..end_index, match_style));
9640        }
9641
9642        if range.start == usize::MAX {
9643            break;
9644        }
9645
9646        // Add highlights for any fuzzy match characters within the
9647        // syntax highlight range.
9648        let mut offset = range.start;
9649        while let Some(&match_index) = match_indices.peek() {
9650            if match_index >= range.end {
9651                break;
9652            }
9653
9654            match_indices.next();
9655            if match_index > offset {
9656                result.push((offset..match_index, syntax_highlight));
9657            }
9658
9659            let mut end_index = char_ix_after(match_index, text);
9660            while let Some(&next_match_index) = match_indices.peek() {
9661                if next_match_index == end_index && next_match_index < range.end {
9662                    end_index = char_ix_after(next_match_index, text);
9663                    match_indices.next();
9664                } else {
9665                    break;
9666                }
9667            }
9668
9669            let mut match_style = syntax_highlight;
9670            match_style.weight = Some(fonts::Weight::BOLD);
9671            result.push((match_index..end_index, match_style));
9672            offset = end_index;
9673        }
9674
9675        if offset < range.end {
9676            result.push((offset..range.end, syntax_highlight));
9677        }
9678    }
9679
9680    fn char_ix_after(ix: usize, text: &str) -> usize {
9681        ix + text[ix..].chars().next().unwrap().len_utf8()
9682    }
9683
9684    result
9685}
9686
9687pub fn styled_runs_for_code_label<'a>(
9688    label: &'a CodeLabel,
9689    syntax_theme: &'a theme::SyntaxTheme,
9690) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
9691    let fade_out = HighlightStyle {
9692        fade_out: Some(0.35),
9693        ..Default::default()
9694    };
9695
9696    let mut prev_end = label.filter_range.end;
9697    label
9698        .runs
9699        .iter()
9700        .enumerate()
9701        .flat_map(move |(ix, (range, highlight_id))| {
9702            let style = if let Some(style) = highlight_id.style(syntax_theme) {
9703                style
9704            } else {
9705                return Default::default();
9706            };
9707            let mut muted_style = style;
9708            muted_style.highlight(fade_out);
9709
9710            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
9711            if range.start >= label.filter_range.end {
9712                if range.start > prev_end {
9713                    runs.push((prev_end..range.start, fade_out));
9714                }
9715                runs.push((range.clone(), muted_style));
9716            } else if range.end <= label.filter_range.end {
9717                runs.push((range.clone(), style));
9718            } else {
9719                runs.push((range.start..label.filter_range.end, style));
9720                runs.push((label.filter_range.end..range.end, muted_style));
9721            }
9722            prev_end = cmp::max(prev_end, range.end);
9723
9724            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
9725                runs.push((prev_end..label.text.len(), fade_out));
9726            }
9727
9728            runs
9729        })
9730}
9731
9732pub fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
9733    let mut index = 0;
9734    let mut codepoints = text.char_indices().peekable();
9735
9736    std::iter::from_fn(move || {
9737        let start_index = index;
9738        while let Some((new_index, codepoint)) = codepoints.next() {
9739            index = new_index + codepoint.len_utf8();
9740            let current_upper = codepoint.is_uppercase();
9741            let next_upper = codepoints
9742                .peek()
9743                .map(|(_, c)| c.is_uppercase())
9744                .unwrap_or(false);
9745
9746            if !current_upper && next_upper {
9747                return Some(&text[start_index..index]);
9748            }
9749        }
9750
9751        index = text.len();
9752        if start_index < text.len() {
9753            return Some(&text[start_index..]);
9754        }
9755        None
9756    })
9757    .flat_map(|word| word.split_inclusive('_'))
9758    .flat_map(|word| word.split_inclusive('-'))
9759}
9760
9761trait RangeToAnchorExt {
9762    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
9763}
9764
9765impl<T: ToOffset> RangeToAnchorExt for Range<T> {
9766    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
9767        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
9768    }
9769}