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