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