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