inline_completion.rs

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