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