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