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}
19
20pub trait InlineCompletionProvider: 'static + Sized {
21 fn name() -> &'static str;
22 fn display_name() -> &'static str;
23 fn show_completions_in_menu() -> bool;
24 fn show_completions_in_normal_mode() -> bool;
25 fn show_tab_accept_marker() -> bool {
26 false
27 }
28 fn is_enabled(
29 &self,
30 buffer: &Entity<Buffer>,
31 cursor_position: language::Anchor,
32 cx: &App,
33 ) -> bool;
34 fn is_refreshing(&self) -> bool;
35 fn refresh(
36 &mut self,
37 buffer: Entity<Buffer>,
38 cursor_position: language::Anchor,
39 debounce: bool,
40 cx: &mut Context<Self>,
41 );
42 fn needs_terms_acceptance(&self, _cx: &App) -> bool {
43 false
44 }
45 fn cycle(
46 &mut self,
47 buffer: Entity<Buffer>,
48 cursor_position: language::Anchor,
49 direction: Direction,
50 cx: &mut Context<Self>,
51 );
52 fn accept(&mut self, cx: &mut Context<Self>);
53 fn discard(&mut self, cx: &mut Context<Self>);
54 fn suggest(
55 &mut self,
56 buffer: &Entity<Buffer>,
57 cursor_position: language::Anchor,
58 cx: &mut Context<Self>,
59 ) -> Option<InlineCompletion>;
60}
61
62pub trait InlineCompletionProviderHandle {
63 fn name(&self) -> &'static str;
64 fn display_name(&self) -> &'static str;
65 fn is_enabled(
66 &self,
67 buffer: &Entity<Buffer>,
68 cursor_position: language::Anchor,
69 cx: &App,
70 ) -> bool;
71 fn show_completions_in_menu(&self) -> bool;
72 fn show_completions_in_normal_mode(&self) -> bool;
73 fn show_tab_accept_marker(&self) -> bool;
74 fn needs_terms_acceptance(&self, cx: &App) -> bool;
75 fn is_refreshing(&self, cx: &App) -> bool;
76 fn refresh(
77 &self,
78 buffer: Entity<Buffer>,
79 cursor_position: language::Anchor,
80 debounce: bool,
81 cx: &mut App,
82 );
83 fn cycle(
84 &self,
85 buffer: Entity<Buffer>,
86 cursor_position: language::Anchor,
87 direction: Direction,
88 cx: &mut App,
89 );
90 fn accept(&self, cx: &mut App);
91 fn discard(&self, cx: &mut App);
92 fn suggest(
93 &self,
94 buffer: &Entity<Buffer>,
95 cursor_position: language::Anchor,
96 cx: &mut App,
97 ) -> Option<InlineCompletion>;
98}
99
100impl<T> InlineCompletionProviderHandle for Entity<T>
101where
102 T: InlineCompletionProvider,
103{
104 fn name(&self) -> &'static str {
105 T::name()
106 }
107
108 fn display_name(&self) -> &'static str {
109 T::display_name()
110 }
111
112 fn show_completions_in_menu(&self) -> bool {
113 T::show_completions_in_menu()
114 }
115
116 fn show_completions_in_normal_mode(&self) -> bool {
117 T::show_completions_in_normal_mode()
118 }
119
120 fn show_tab_accept_marker(&self) -> bool {
121 T::show_tab_accept_marker()
122 }
123
124 fn is_enabled(
125 &self,
126 buffer: &Entity<Buffer>,
127 cursor_position: language::Anchor,
128 cx: &App,
129 ) -> bool {
130 self.read(cx).is_enabled(buffer, cursor_position, cx)
131 }
132
133 fn needs_terms_acceptance(&self, cx: &App) -> bool {
134 self.read(cx).needs_terms_acceptance(cx)
135 }
136
137 fn is_refreshing(&self, cx: &App) -> bool {
138 self.read(cx).is_refreshing()
139 }
140
141 fn refresh(
142 &self,
143 buffer: Entity<Buffer>,
144 cursor_position: language::Anchor,
145 debounce: bool,
146 cx: &mut App,
147 ) {
148 self.update(cx, |this, cx| {
149 this.refresh(buffer, cursor_position, debounce, cx)
150 })
151 }
152
153 fn cycle(
154 &self,
155 buffer: Entity<Buffer>,
156 cursor_position: language::Anchor,
157 direction: Direction,
158 cx: &mut App,
159 ) {
160 self.update(cx, |this, cx| {
161 this.cycle(buffer, cursor_position, direction, cx)
162 })
163 }
164
165 fn accept(&self, cx: &mut App) {
166 self.update(cx, |this, cx| this.accept(cx))
167 }
168
169 fn discard(&self, cx: &mut App) {
170 self.update(cx, |this, cx| this.discard(cx))
171 }
172
173 fn suggest(
174 &self,
175 buffer: &Entity<Buffer>,
176 cursor_position: language::Anchor,
177 cx: &mut App,
178 ) -> Option<InlineCompletion> {
179 self.update(cx, |this, cx| this.suggest(buffer, cursor_position, cx))
180 }
181}