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 EditPredictionProvider: 'static + Sized {
 42    fn name() -> &'static str;
 43    fn display_name() -> &'static str;
 44    fn show_completions_in_menu() -> 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        project: Option<Entity<Project>>,
 62        buffer: Entity<Buffer>,
 63        cursor_position: language::Anchor,
 64        debounce: bool,
 65        cx: &mut Context<Self>,
 66    );
 67    fn needs_terms_acceptance(&self, _cx: &App) -> bool {
 68        false
 69    }
 70    fn cycle(
 71        &mut self,
 72        buffer: Entity<Buffer>,
 73        cursor_position: language::Anchor,
 74        direction: Direction,
 75        cx: &mut Context<Self>,
 76    );
 77    fn accept(&mut self, cx: &mut Context<Self>);
 78    fn discard(&mut self, cx: &mut Context<Self>);
 79    fn suggest(
 80        &mut self,
 81        buffer: &Entity<Buffer>,
 82        cursor_position: language::Anchor,
 83        cx: &mut Context<Self>,
 84    ) -> Option<InlineCompletion>;
 85}
 86
 87pub trait InlineCompletionProviderHandle {
 88    fn name(&self) -> &'static str;
 89    fn display_name(&self) -> &'static str;
 90    fn is_enabled(
 91        &self,
 92        buffer: &Entity<Buffer>,
 93        cursor_position: language::Anchor,
 94        cx: &App,
 95    ) -> bool;
 96    fn show_completions_in_menu(&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        project: Option<Entity<Project>>,
105        buffer: Entity<Buffer>,
106        cursor_position: language::Anchor,
107        debounce: bool,
108        cx: &mut App,
109    );
110    fn cycle(
111        &self,
112        buffer: Entity<Buffer>,
113        cursor_position: language::Anchor,
114        direction: Direction,
115        cx: &mut App,
116    );
117    fn accept(&self, cx: &mut App);
118    fn discard(&self, cx: &mut App);
119    fn suggest(
120        &self,
121        buffer: &Entity<Buffer>,
122        cursor_position: language::Anchor,
123        cx: &mut App,
124    ) -> Option<InlineCompletion>;
125}
126
127impl<T> InlineCompletionProviderHandle for Entity<T>
128where
129    T: EditPredictionProvider,
130{
131    fn name(&self) -> &'static str {
132        T::name()
133    }
134
135    fn display_name(&self) -> &'static str {
136        T::display_name()
137    }
138
139    fn show_completions_in_menu(&self) -> bool {
140        T::show_completions_in_menu()
141    }
142
143    fn show_tab_accept_marker(&self) -> bool {
144        T::show_tab_accept_marker()
145    }
146
147    fn data_collection_state(&self, cx: &App) -> DataCollectionState {
148        self.read(cx).data_collection_state(cx)
149    }
150
151    fn toggle_data_collection(&self, cx: &mut App) {
152        self.update(cx, |this, cx| this.toggle_data_collection(cx))
153    }
154
155    fn is_enabled(
156        &self,
157        buffer: &Entity<Buffer>,
158        cursor_position: language::Anchor,
159        cx: &App,
160    ) -> bool {
161        self.read(cx).is_enabled(buffer, cursor_position, cx)
162    }
163
164    fn needs_terms_acceptance(&self, cx: &App) -> bool {
165        self.read(cx).needs_terms_acceptance(cx)
166    }
167
168    fn is_refreshing(&self, cx: &App) -> bool {
169        self.read(cx).is_refreshing()
170    }
171
172    fn refresh(
173        &self,
174        project: Option<Entity<Project>>,
175        buffer: Entity<Buffer>,
176        cursor_position: language::Anchor,
177        debounce: bool,
178        cx: &mut App,
179    ) {
180        self.update(cx, |this, cx| {
181            this.refresh(project, buffer, cursor_position, debounce, cx)
182        })
183    }
184
185    fn cycle(
186        &self,
187        buffer: Entity<Buffer>,
188        cursor_position: language::Anchor,
189        direction: Direction,
190        cx: &mut App,
191    ) {
192        self.update(cx, |this, cx| {
193            this.cycle(buffer, cursor_position, direction, cx)
194        })
195    }
196
197    fn accept(&self, cx: &mut App) {
198        self.update(cx, |this, cx| this.accept(cx))
199    }
200
201    fn discard(&self, cx: &mut App) {
202        self.update(cx, |this, cx| this.discard(cx))
203    }
204
205    fn suggest(
206        &self,
207        buffer: &Entity<Buffer>,
208        cursor_position: language::Anchor,
209        cx: &mut App,
210    ) -> Option<InlineCompletion> {
211        self.update(cx, |this, cx| this.suggest(buffer, cursor_position, cx))
212    }
213}