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