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