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