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