Introduce InlineCompletionProvider (#9777)

This pull request introduces a new `InlineCompletionProvider` trait,
which enables making `Editor` copilot-agnostic and lets us push all the
copilot functionality into the `copilot_ui` module. Long-term, I would
like to merge `copilot` and `copilot_ui`, but right now `project`
depends on `copilot`, which makes this impossible.

The reason for adding this new trait is so that we can experiment with
other inline completion providers and swap them at runtime using config
settings.

Please, note also that we renamed some of the existing copilot actions
to be more agnostic (see release notes below). We still kept the old
actions bound for backwards-compatibility, but we should probably remove
them at some later version.

Also, as a drive-by, we added new methods to the `Global` trait that let
you read or mutate a global directly, e.g.:

```rs
MyGlobal::update(cx, |global, cx| {
});
```

Release Notes:

- Renamed the `copilot::Suggest` action to
`editor::ShowInlineCompletion`
- Renamed the `copilot::NextSuggestion` action to
`editor::NextInlineCompletion`
- Renamed the `copilot::PreviousSuggestion` action to
`editor::PreviousInlineCompletion`
- Renamed the `editor::AcceptPartialCopilotSuggestion` action to
`editor::AcceptPartialInlineCompletion`

---------

Co-authored-by: Nathan <nathan@zed.dev>
Co-authored-by: Kyle <kylek@zed.dev>
Co-authored-by: Kyle Kelley <rgbkrk@gmail.com>
This commit is contained in:
Antonio Scandurra 2024-03-26 13:28:06 +01:00 committed by GitHub
parent b8663e56a9
commit fb6cff89d7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
45 changed files with 1472 additions and 1138 deletions

View file

@ -897,17 +897,6 @@ impl AppContext {
.unwrap()
}
/// Updates the global of the given type with a closure. Unlike `global_mut`, this method provides
/// your closure with mutable access to the `AppContext` and the global simultaneously.
pub fn update_global<G: Global, R>(&mut self, f: impl FnOnce(&mut G, &mut Self) -> R) -> R {
self.update(|cx| {
let mut global = cx.lease_global::<G>();
let result = f(&mut global, cx);
cx.end_global_lease(global);
result
})
}
/// Register a callback to be invoked when a global of the given type is updated.
pub fn observe_global<G: Global>(
&mut self,

View file

@ -1,7 +1,7 @@
use crate::{
AnyView, AnyWindowHandle, AppCell, AppContext, BackgroundExecutor, Context, DismissEvent,
FocusableView, ForegroundExecutor, Global, Model, ModelContext, Render, Result, Task, View,
ViewContext, VisualContext, WindowContext, WindowHandle,
AnyView, AnyWindowHandle, AppCell, AppContext, BackgroundExecutor, BorrowAppContext, Context,
DismissEvent, FocusableView, ForegroundExecutor, Global, Model, ModelContext, Render, Result,
Task, View, ViewContext, VisualContext, WindowContext, WindowHandle,
};
use anyhow::{anyhow, Context as _};
use derive_more::{Deref, DerefMut};
@ -192,7 +192,7 @@ impl AsyncAppContext {
.upgrade()
.ok_or_else(|| anyhow!("app was released"))?;
let mut app = app.borrow_mut();
Ok(app.update_global(update))
Ok(app.update(|cx| cx.update_global(update)))
}
}

View file

@ -1,6 +1,6 @@
use crate::{
AnyView, AnyWindowHandle, AppContext, AsyncAppContext, Context, Effect, Entity, EntityId,
EventEmitter, Global, Model, Subscription, Task, View, WeakModel, WindowContext, WindowHandle,
EventEmitter, Model, Subscription, Task, View, WeakModel, WindowContext, WindowHandle,
};
use anyhow::Result;
use derive_more::{Deref, DerefMut};
@ -190,17 +190,6 @@ impl<'a, T: 'static> ModelContext<'a, T> {
}
}
/// Updates the given global
pub fn update_global<G, R>(&mut self, f: impl FnOnce(&mut G, &mut Self) -> R) -> R
where
G: Global,
{
let mut global = self.app.lease_global::<G>();
let result = f(&mut global, self);
self.app.end_global_lease(global);
result
}
/// Spawn the future returned by the given function.
/// The function is provided a weak handle to the model owned by this context and a context that can be held across await points.
/// The returned task must be held or detached.

View file

@ -1,7 +1,7 @@
use crate::{
Action, AnyElement, AnyView, AnyWindowHandle, AppCell, AppContext, AsyncAppContext,
AvailableSpace, BackgroundExecutor, Bounds, ClipboardItem, Context, Empty, Entity,
EventEmitter, ForegroundExecutor, Global, InputEvent, Keystroke, Model, ModelContext,
AvailableSpace, BackgroundExecutor, BorrowAppContext, Bounds, ClipboardItem, Context, Empty,
Entity, EventEmitter, ForegroundExecutor, Global, InputEvent, Keystroke, Model, ModelContext,
Modifiers, ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent,
Pixels, Platform, Point, Render, Result, Size, Task, TestDispatcher, TestPlatform, TestWindow,
TextSystem, View, ViewContext, VisualContext, WindowContext, WindowHandle, WindowOptions,
@ -51,14 +51,6 @@ impl Context for TestAppContext {
app.update_model(handle, update)
}
fn update_window<T, F>(&mut self, window: AnyWindowHandle, f: F) -> Result<T>
where
F: FnOnce(AnyView, &mut WindowContext<'_>) -> T,
{
let mut lock = self.app.borrow_mut();
lock.update_window(window, f)
}
fn read_model<T, R>(
&self,
handle: &Model<T>,
@ -71,6 +63,14 @@ impl Context for TestAppContext {
app.read_model(handle, read)
}
fn update_window<T, F>(&mut self, window: AnyWindowHandle, f: F) -> Result<T>
where
F: FnOnce(AnyView, &mut WindowContext<'_>) -> T,
{
let mut lock = self.app.borrow_mut();
lock.update_window(window, f)
}
fn read_window<T, R>(
&self,
window: &WindowHandle<T>,
@ -309,7 +309,7 @@ impl TestAppContext {
/// sets the global in this context.
pub fn set_global<G: Global>(&mut self, global: G) {
let mut lock = self.app.borrow_mut();
lock.set_global(global);
lock.update(|cx| cx.set_global(global))
}
/// updates the global in this context. (panics if `has_global` would return false)
@ -318,7 +318,7 @@ impl TestAppContext {
update: impl FnOnce(&mut G, &mut AppContext) -> R,
) -> R {
let mut lock = self.app.borrow_mut();
lock.update_global(update)
lock.update(|cx| cx.update_global(update))
}
/// Returns an `AsyncAppContext` which can be used to run tasks that expect to be on a background

View file

@ -261,6 +261,10 @@ pub trait EventEmitter<E: Any>: 'static {}
pub trait BorrowAppContext {
/// Set a global value on the context.
fn set_global<T: Global>(&mut self, global: T);
/// Updates the global state of the given type.
fn update_global<G, R>(&mut self, f: impl FnOnce(&mut G, &mut Self) -> R) -> R
where
G: Global;
}
impl<C> BorrowAppContext for C
@ -270,6 +274,16 @@ where
fn set_global<G: Global>(&mut self, global: G) {
self.borrow_mut().set_global(global)
}
fn update_global<G, R>(&mut self, f: impl FnOnce(&mut G, &mut Self) -> R) -> R
where
G: Global,
{
let mut global = self.borrow_mut().lease_global::<G>();
let result = f(&mut global, self);
self.borrow_mut().end_global_lease(global);
result
}
}
/// A flatten equivalent for anyhow `Result`s.
@ -293,4 +307,18 @@ impl<T> Flatten<T> for Result<T> {
/// A marker trait for types that can be stored in GPUI's global state.
///
/// Implement this on types you want to store in the context as a global.
pub trait Global: 'static {}
pub trait Global: 'static + Sized {
/// Access the global of the implementing type. Panics if a global for that type has not been assigned.
fn get(cx: &AppContext) -> &Self {
cx.global()
}
/// Updates the global of the implementing type with a closure. Unlike `global_mut`, this method provides
/// your closure with mutable access to the `AppContext` and the global simultaneously.
fn update<C, R>(cx: &mut C, f: impl FnOnce(&mut Self, &mut C) -> R) -> R
where
C: BorrowAppContext,
{
cx.update_global(f)
}
}

View file

@ -854,18 +854,6 @@ impl<'a> WindowContext<'a> {
.spawn(|app| f(AsyncWindowContext::new(app, self.window.handle)))
}
/// Updates the global of the given type. The given closure is given simultaneous mutable
/// access both to the global and the context.
pub fn update_global<G, R>(&mut self, f: impl FnOnce(&mut G, &mut Self) -> R) -> R
where
G: Global,
{
let mut global = self.app.lease_global::<G>();
let result = f(&mut global, self);
self.app.end_global_lease(global);
result
}
fn window_bounds_changed(&mut self) {
self.window.scale_factor = self.window.platform_window.scale_factor();
self.window.viewport_size = self.window.platform_window.content_size();
@ -2388,17 +2376,6 @@ impl<'a, V: 'static> ViewContext<'a, V> {
self.window_cx.spawn(|cx| f(view, cx))
}
/// Updates the global state of the given type.
pub fn update_global<G, R>(&mut self, f: impl FnOnce(&mut G, &mut Self) -> R) -> R
where
G: Global,
{
let mut global = self.app.lease_global::<G>();
let result = f(&mut global, self);
self.app.end_global_lease(global);
result
}
/// Register a callback to be invoked when the given global state changes.
pub fn observe_global<G: Global>(
&mut self,