1use gpui::{App, Context, Entity};
2use language::Buffer;
3use std::ops::Range;
4
5// TODO: Find a better home for `Direction`.
6//
7// This should live in an ancestor crate of `editor` and `inline_completion`,
8// but at time of writing there isn't an obvious spot.
9#[derive(Copy, Clone, PartialEq, Eq)]
10pub enum Direction {
11 Prev,
12 Next,
13}
14
15#[derive(Clone)]
16pub struct InlineCompletion {
17 pub edits: Vec<(Range<language::Anchor>, String)>,
18 pub edit_preview: Option<language::EditPreview>,
19}
20
21pub trait InlineCompletionProvider: 'static + Sized {
22 fn name() -> &'static str;
23 fn display_name() -> &'static str;
24 fn show_completions_in_menu() -> bool;
25 fn show_completions_in_normal_mode() -> bool;
26 fn show_tab_accept_marker() -> bool {
27 false
28 }
29 fn is_enabled(
30 &self,
31 buffer: &Entity<Buffer>,
32 cursor_position: language::Anchor,
33 cx: &App,
34 ) -> bool;
35 fn is_refreshing(&self) -> bool;
36 fn refresh(
37 &mut self,
38 buffer: Entity<Buffer>,
39 cursor_position: language::Anchor,
40 debounce: bool,
41 cx: &mut Context<Self>,
42 );
43 fn needs_terms_acceptance(&self, _cx: &App) -> bool {
44 false
45 }
46 fn cycle(
47 &mut self,
48 buffer: Entity<Buffer>,
49 cursor_position: language::Anchor,
50 direction: Direction,
51 cx: &mut Context<Self>,
52 );
53 fn accept(&mut self, cx: &mut Context<Self>);
54 fn discard(&mut self, cx: &mut Context<Self>);
55 fn suggest(
56 &mut self,
57 buffer: &Entity<Buffer>,
58 cursor_position: language::Anchor,
59 cx: &mut Context<Self>,
60 ) -> Option<InlineCompletion>;
61}
62
63pub trait InlineCompletionProviderHandle {
64 fn name(&self) -> &'static str;
65 fn display_name(&self) -> &'static str;
66 fn is_enabled(
67 &self,
68 buffer: &Entity<Buffer>,
69 cursor_position: language::Anchor,
70 cx: &App,
71 ) -> bool;
72 fn show_completions_in_menu(&self) -> bool;
73 fn show_completions_in_normal_mode(&self) -> bool;
74 fn show_tab_accept_marker(&self) -> bool;
75 fn needs_terms_acceptance(&self, cx: &App) -> bool;
76 fn is_refreshing(&self, cx: &App) -> bool;
77 fn refresh(
78 &self,
79 buffer: Entity<Buffer>,
80 cursor_position: language::Anchor,
81 debounce: bool,
82 cx: &mut App,
83 );
84 fn cycle(
85 &self,
86 buffer: Entity<Buffer>,
87 cursor_position: language::Anchor,
88 direction: Direction,
89 cx: &mut App,
90 );
91 fn accept(&self, cx: &mut App);
92 fn discard(&self, cx: &mut App);
93 fn suggest(
94 &self,
95 buffer: &Entity<Buffer>,
96 cursor_position: language::Anchor,
97 cx: &mut App,
98 ) -> Option<InlineCompletion>;
99}
100
101impl<T> InlineCompletionProviderHandle for Entity<T>
102where
103 T: InlineCompletionProvider,
104{
105 fn name(&self) -> &'static str {
106 T::name()
107 }
108
109 fn display_name(&self) -> &'static str {
110 T::display_name()
111 }
112
113 fn show_completions_in_menu(&self) -> bool {
114 T::show_completions_in_menu()
115 }
116
117 fn show_completions_in_normal_mode(&self) -> bool {
118 T::show_completions_in_normal_mode()
119 }
120
121 fn show_tab_accept_marker(&self) -> bool {
122 T::show_tab_accept_marker()
123 }
124
125 fn is_enabled(
126 &self,
127 buffer: &Entity<Buffer>,
128 cursor_position: language::Anchor,
129 cx: &App,
130 ) -> bool {
131 self.read(cx).is_enabled(buffer, cursor_position, cx)
132 }
133
134 fn needs_terms_acceptance(&self, cx: &App) -> bool {
135 self.read(cx).needs_terms_acceptance(cx)
136 }
137
138 fn is_refreshing(&self, cx: &App) -> bool {
139 self.read(cx).is_refreshing()
140 }
141
142 fn refresh(
143 &self,
144 buffer: Entity<Buffer>,
145 cursor_position: language::Anchor,
146 debounce: bool,
147 cx: &mut App,
148 ) {
149 self.update(cx, |this, cx| {
150 this.refresh(buffer, cursor_position, debounce, cx)
151 })
152 }
153
154 fn cycle(
155 &self,
156 buffer: Entity<Buffer>,
157 cursor_position: language::Anchor,
158 direction: Direction,
159 cx: &mut App,
160 ) {
161 self.update(cx, |this, cx| {
162 this.cycle(buffer, cursor_position, direction, cx)
163 })
164 }
165
166 fn accept(&self, cx: &mut App) {
167 self.update(cx, |this, cx| this.accept(cx))
168 }
169
170 fn discard(&self, cx: &mut App) {
171 self.update(cx, |this, cx| this.discard(cx))
172 }
173
174 fn suggest(
175 &self,
176 buffer: &Entity<Buffer>,
177 cursor_position: language::Anchor,
178 cx: &mut App,
179 ) -> Option<InlineCompletion> {
180 self.update(cx, |this, cx| this.suggest(buffer, cursor_position, cx))
181 }
182}