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