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