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