1use gpui::{AppContext, Model, ModelContext};
2use language::Buffer;
3use std::ops::Range;
4use text::{Anchor, Rope};
5
6// TODO: Find a better home for `Direction`.
7//
8// This should live in an ancestor crate of `editor` and `inline_completion`,
9// but at time of writing there isn't an obvious spot.
10#[derive(Copy, Clone, PartialEq, Eq)]
11pub enum Direction {
12 Prev,
13 Next,
14}
15
16pub enum InlayProposal {
17 Hint(Anchor, project::InlayHint),
18 Suggestion(Anchor, Rope),
19}
20
21pub struct CompletionProposal {
22 pub inlays: Vec<InlayProposal>,
23 pub text: Rope,
24 pub delete_range: Option<Range<Anchor>>,
25}
26
27pub trait InlineCompletionProvider: 'static + Sized {
28 fn name() -> &'static str;
29 fn is_enabled(
30 &self,
31 buffer: &Model<Buffer>,
32 cursor_position: language::Anchor,
33 cx: &AppContext,
34 ) -> bool;
35 fn refresh(
36 &mut self,
37 buffer: Model<Buffer>,
38 cursor_position: language::Anchor,
39 debounce: bool,
40 cx: &mut ModelContext<Self>,
41 );
42 fn cycle(
43 &mut self,
44 buffer: Model<Buffer>,
45 cursor_position: language::Anchor,
46 direction: Direction,
47 cx: &mut ModelContext<Self>,
48 );
49 fn accept(&mut self, cx: &mut ModelContext<Self>);
50 fn discard(&mut self, should_report_inline_completion_event: bool, cx: &mut ModelContext<Self>);
51 fn active_completion_text<'a>(
52 &'a self,
53 buffer: &Model<Buffer>,
54 cursor_position: language::Anchor,
55 cx: &'a AppContext,
56 ) -> Option<CompletionProposal>;
57}
58
59pub trait InlineCompletionProviderHandle {
60 fn is_enabled(
61 &self,
62 buffer: &Model<Buffer>,
63 cursor_position: language::Anchor,
64 cx: &AppContext,
65 ) -> 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, should_report_inline_completion_event: bool, cx: &mut AppContext);
82 fn active_completion_text<'a>(
83 &'a self,
84 buffer: &Model<Buffer>,
85 cursor_position: language::Anchor,
86 cx: &'a AppContext,
87 ) -> Option<CompletionProposal>;
88}
89
90impl<T> InlineCompletionProviderHandle for Model<T>
91where
92 T: InlineCompletionProvider,
93{
94 fn is_enabled(
95 &self,
96 buffer: &Model<Buffer>,
97 cursor_position: language::Anchor,
98 cx: &AppContext,
99 ) -> bool {
100 self.read(cx).is_enabled(buffer, cursor_position, cx)
101 }
102
103 fn refresh(
104 &self,
105 buffer: Model<Buffer>,
106 cursor_position: language::Anchor,
107 debounce: bool,
108 cx: &mut AppContext,
109 ) {
110 self.update(cx, |this, cx| {
111 this.refresh(buffer, cursor_position, debounce, cx)
112 })
113 }
114
115 fn cycle(
116 &self,
117 buffer: Model<Buffer>,
118 cursor_position: language::Anchor,
119 direction: Direction,
120 cx: &mut AppContext,
121 ) {
122 self.update(cx, |this, cx| {
123 this.cycle(buffer, cursor_position, direction, cx)
124 })
125 }
126
127 fn accept(&self, cx: &mut AppContext) {
128 self.update(cx, |this, cx| this.accept(cx))
129 }
130
131 fn discard(&self, should_report_inline_completion_event: bool, cx: &mut AppContext) {
132 self.update(cx, |this, cx| {
133 this.discard(should_report_inline_completion_event, cx)
134 })
135 }
136
137 fn active_completion_text<'a>(
138 &'a self,
139 buffer: &Model<Buffer>,
140 cursor_position: language::Anchor,
141 cx: &'a AppContext,
142 ) -> Option<CompletionProposal> {
143 self.read(cx)
144 .active_completion_text(buffer, cursor_position, cx)
145 }
146}