inline_completion.rs

  1use gpui::{App, Context, Entity};
  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    pub edit_preview: Option<language::EditPreview>,
 19}
 20
 21pub enum DataCollectionState {
 22    /// The provider doesn't support data collection.
 23    Unsupported,
 24    /// When there's a file not saved yet. In this case, we can't tell to which project it belongs.
 25    Unknown,
 26    /// Data collection is enabled
 27    Enabled,
 28    /// Data collection is disabled or unanswered.
 29    Disabled,
 30}
 31
 32impl DataCollectionState {
 33    pub fn is_supported(&self) -> bool {
 34        !matches!(self, DataCollectionState::Unsupported)
 35    }
 36
 37    pub fn is_unknown(&self) -> bool {
 38        matches!(self, DataCollectionState::Unknown)
 39    }
 40
 41    pub fn is_enabled(&self) -> bool {
 42        matches!(self, DataCollectionState::Enabled)
 43    }
 44}
 45
 46pub trait InlineCompletionProvider: 'static + Sized {
 47    fn name() -> &'static str;
 48    fn display_name() -> &'static str;
 49    fn show_completions_in_menu() -> bool;
 50    fn show_completions_in_normal_mode() -> bool;
 51    fn show_tab_accept_marker() -> bool {
 52        false
 53    }
 54    fn data_collection_state(&self, _cx: &App) -> DataCollectionState {
 55        DataCollectionState::Unsupported
 56    }
 57    fn toggle_data_collection(&mut self, _cx: &mut App) {}
 58    fn is_enabled(
 59        &self,
 60        buffer: &Entity<Buffer>,
 61        cursor_position: language::Anchor,
 62        cx: &App,
 63    ) -> bool;
 64    fn is_refreshing(&self) -> bool;
 65    fn refresh(
 66        &mut self,
 67        buffer: Entity<Buffer>,
 68        cursor_position: language::Anchor,
 69        debounce: bool,
 70        cx: &mut Context<Self>,
 71    );
 72    fn needs_terms_acceptance(&self, _cx: &App) -> bool {
 73        false
 74    }
 75    fn cycle(
 76        &mut self,
 77        buffer: Entity<Buffer>,
 78        cursor_position: language::Anchor,
 79        direction: Direction,
 80        cx: &mut Context<Self>,
 81    );
 82    fn accept(&mut self, cx: &mut Context<Self>);
 83    fn discard(&mut self, cx: &mut Context<Self>);
 84    fn suggest(
 85        &mut self,
 86        buffer: &Entity<Buffer>,
 87        cursor_position: language::Anchor,
 88        cx: &mut Context<Self>,
 89    ) -> Option<InlineCompletion>;
 90}
 91
 92pub trait InlineCompletionProviderHandle {
 93    fn name(&self) -> &'static str;
 94    fn display_name(&self) -> &'static str;
 95    fn is_enabled(
 96        &self,
 97        buffer: &Entity<Buffer>,
 98        cursor_position: language::Anchor,
 99        cx: &App,
100    ) -> bool;
101    fn show_completions_in_menu(&self) -> bool;
102    fn show_completions_in_normal_mode(&self) -> bool;
103    fn show_tab_accept_marker(&self) -> bool;
104    fn data_collection_state(&self, cx: &App) -> DataCollectionState;
105    fn toggle_data_collection(&self, cx: &mut App);
106    fn needs_terms_acceptance(&self, cx: &App) -> bool;
107    fn is_refreshing(&self, cx: &App) -> bool;
108    fn refresh(
109        &self,
110        buffer: Entity<Buffer>,
111        cursor_position: language::Anchor,
112        debounce: bool,
113        cx: &mut App,
114    );
115    fn cycle(
116        &self,
117        buffer: Entity<Buffer>,
118        cursor_position: language::Anchor,
119        direction: Direction,
120        cx: &mut App,
121    );
122    fn accept(&self, cx: &mut App);
123    fn discard(&self, cx: &mut App);
124    fn suggest(
125        &self,
126        buffer: &Entity<Buffer>,
127        cursor_position: language::Anchor,
128        cx: &mut App,
129    ) -> Option<InlineCompletion>;
130}
131
132impl<T> InlineCompletionProviderHandle for Entity<T>
133where
134    T: InlineCompletionProvider,
135{
136    fn name(&self) -> &'static str {
137        T::name()
138    }
139
140    fn display_name(&self) -> &'static str {
141        T::display_name()
142    }
143
144    fn show_completions_in_menu(&self) -> bool {
145        T::show_completions_in_menu()
146    }
147
148    fn show_completions_in_normal_mode(&self) -> bool {
149        T::show_completions_in_normal_mode()
150    }
151
152    fn show_tab_accept_marker(&self) -> bool {
153        T::show_tab_accept_marker()
154    }
155
156    fn data_collection_state(&self, cx: &App) -> DataCollectionState {
157        self.read(cx).data_collection_state(cx)
158    }
159
160    fn toggle_data_collection(&self, cx: &mut App) {
161        self.update(cx, |this, cx| this.toggle_data_collection(cx))
162    }
163
164    fn is_enabled(
165        &self,
166        buffer: &Entity<Buffer>,
167        cursor_position: language::Anchor,
168        cx: &App,
169    ) -> bool {
170        self.read(cx).is_enabled(buffer, cursor_position, cx)
171    }
172
173    fn needs_terms_acceptance(&self, cx: &App) -> bool {
174        self.read(cx).needs_terms_acceptance(cx)
175    }
176
177    fn is_refreshing(&self, cx: &App) -> bool {
178        self.read(cx).is_refreshing()
179    }
180
181    fn refresh(
182        &self,
183        buffer: Entity<Buffer>,
184        cursor_position: language::Anchor,
185        debounce: bool,
186        cx: &mut App,
187    ) {
188        self.update(cx, |this, cx| {
189            this.refresh(buffer, cursor_position, debounce, cx)
190        })
191    }
192
193    fn cycle(
194        &self,
195        buffer: Entity<Buffer>,
196        cursor_position: language::Anchor,
197        direction: Direction,
198        cx: &mut App,
199    ) {
200        self.update(cx, |this, cx| {
201            this.cycle(buffer, cursor_position, direction, cx)
202        })
203    }
204
205    fn accept(&self, cx: &mut App) {
206        self.update(cx, |this, cx| this.accept(cx))
207    }
208
209    fn discard(&self, cx: &mut App) {
210        self.update(cx, |this, cx| this.discard(cx))
211    }
212
213    fn suggest(
214        &self,
215        buffer: &Entity<Buffer>,
216        cursor_position: language::Anchor,
217        cx: &mut App,
218    ) -> Option<InlineCompletion> {
219        self.update(cx, |this, cx| this.suggest(buffer, cursor_position, cx))
220    }
221}