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