Eliminate GPUI View, ViewContext, and WindowContext types (#22632)

There's still a bit more work to do on this, but this PR is compiling
(with warnings) after eliminating the key types. When the tasks below
are complete, this will be the new narrative for GPUI:

- `Entity<T>` - This replaces `View<T>`/`Model<T>`. It represents a unit
of state, and if `T` implements `Render`, then `Entity<T>` implements
`Element`.
- `&mut App` This replaces `AppContext` and represents the app.
- `&mut Context<T>` This replaces `ModelContext` and derefs to `App`. It
is provided by the framework when updating an entity.
- `&mut Window` Broken out of `&mut WindowContext` which no longer
exists. Every method that once took `&mut WindowContext` now takes `&mut
Window, &mut App` and every method that took `&mut ViewContext<T>` now
takes `&mut Window, &mut Context<T>`

Not pictured here are the two other failed attempts. It's been quite a
month!

Tasks:

- [x] Remove `View`, `ViewContext`, `WindowContext` and thread through
`Window`
- [x] [@cole-miller @mikayla-maki] Redraw window when entities change
- [x] [@cole-miller @mikayla-maki] Get examples and Zed running
- [x] [@cole-miller @mikayla-maki] Fix Zed rendering
- [x] [@mikayla-maki] Fix todo! macros and comments
- [x] Fix a bug where the editor would not be redrawn because of view
caching
- [x] remove publicness window.notify() and replace with
`AppContext::notify`
- [x] remove `observe_new_window_models`, replace with
`observe_new_models` with an optional window
- [x] Fix a bug where the project panel would not be redrawn because of
the wrong refresh() call being used
- [x] Fix the tests
- [x] Fix warnings by eliminating `Window` params or using `_`
- [x] Fix conflicts
- [x] Simplify generic code where possible
- [x] Rename types
- [ ] Update docs

### issues post merge

- [x] Issues switching between normal and insert mode
- [x] Assistant re-rendering failure
- [x] Vim test failures
- [x] Mac build issue



Release Notes:

- N/A

---------

Co-authored-by: Antonio Scandurra <me@as-cii.com>
Co-authored-by: Cole Miller <cole@zed.dev>
Co-authored-by: Mikayla <mikayla@zed.dev>
Co-authored-by: Joseph <joseph@zed.dev>
Co-authored-by: max <max@zed.dev>
Co-authored-by: Michael Sloan <michael@zed.dev>
Co-authored-by: Mikayla Maki <mikaylamaki@Mikaylas-MacBook-Pro.local>
Co-authored-by: Mikayla <mikayla.c.maki@gmail.com>
Co-authored-by: joão <joao@zed.dev>
This commit is contained in:
Nathan Sobo 2025-01-25 20:02:45 -07:00 committed by GitHub
parent 21b4a0d50e
commit 6fca1d2b0b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
648 changed files with 36248 additions and 28208 deletions

View file

@ -17,7 +17,7 @@ mod symbols_command;
mod tab_command;
mod terminal_command;
use gpui::AppContext;
use gpui::App;
use language::{CodeLabel, HighlightId};
use ui::ActiveTheme as _;
@ -40,11 +40,7 @@ pub use crate::symbols_command::*;
pub use crate::tab_command::*;
pub use crate::terminal_command::*;
pub fn create_label_for_command(
command_name: &str,
arguments: &[&str],
cx: &AppContext,
) -> CodeLabel {
pub fn create_label_for_command(command_name: &str, arguments: &[&str], cx: &App) -> CodeLabel {
let mut label = CodeLabel::default();
label.push_str(command_name, None);
label.push_str(" ", None);

View file

@ -5,7 +5,7 @@ use assistant_slash_command::{
};
use feature_flags::FeatureFlag;
use futures::StreamExt;
use gpui::{AppContext, AsyncAppContext, AsyncWindowContext, Task, WeakView, WindowContext};
use gpui::{App, AsyncAppContext, Task, WeakEntity, Window};
use language::{CodeLabel, LspAdapterDelegate};
use language_model::{
LanguageModelCompletionEvent, LanguageModelRegistry, LanguageModelRequest,
@ -45,7 +45,7 @@ impl SlashCommand for AutoCommand {
self.description()
}
fn label(&self, cx: &AppContext) -> CodeLabel {
fn label(&self, cx: &App) -> CodeLabel {
create_label_for_command("auto", &["--prompt"], cx)
}
@ -53,8 +53,9 @@ impl SlashCommand for AutoCommand {
self: Arc<Self>,
_arguments: &[String],
_cancel: Arc<AtomicBool>,
workspace: Option<WeakView<Workspace>>,
cx: &mut WindowContext,
workspace: Option<WeakEntity<Workspace>>,
_window: &mut Window,
cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
// There's no autocomplete for a prompt, since it's arbitrary text.
// However, we can use this opportunity to kick off a drain of the backlog.
@ -74,7 +75,7 @@ impl SlashCommand for AutoCommand {
return Task::ready(Err(anyhow!("No project indexer, cannot use /auto")));
};
let cx: &mut AppContext = cx;
let cx: &mut App = cx;
cx.spawn(|cx: gpui::AsyncAppContext| async move {
let task = project_index.read_with(&cx, |project_index, cx| {
@ -96,9 +97,10 @@ impl SlashCommand for AutoCommand {
arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: language::BufferSnapshot,
workspace: WeakView<Workspace>,
workspace: WeakEntity<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>,
cx: &mut WindowContext,
window: &mut Window,
cx: &mut App,
) -> Task<SlashCommandResult> {
let Some(workspace) = workspace.upgrade() else {
return Task::ready(Err(anyhow::anyhow!("workspace was dropped")));
@ -115,7 +117,7 @@ impl SlashCommand for AutoCommand {
return Task::ready(Err(anyhow!("no project indexer")));
};
let task = cx.spawn(|cx: AsyncWindowContext| async move {
let task = window.spawn(cx, |cx| async move {
let summaries = project_index
.read_with(&cx, |project_index, cx| project_index.all_summaries(cx))?
.await?;

View file

@ -1,10 +1,10 @@
use anyhow::{anyhow, Context, Result};
use anyhow::{anyhow, Context as _, Result};
use assistant_slash_command::{
ArgumentCompletion, SlashCommand, SlashCommandOutput, SlashCommandOutputSection,
SlashCommandResult,
};
use fs::Fs;
use gpui::{AppContext, Model, Task, WeakView};
use gpui::{App, Entity, Task, WeakEntity};
use language::{BufferSnapshot, LspAdapterDelegate};
use project::{Project, ProjectPath};
use std::{
@ -76,7 +76,7 @@ impl CargoWorkspaceSlashCommand {
Ok(message)
}
fn path_to_cargo_toml(project: Model<Project>, cx: &mut AppContext) -> Option<Arc<Path>> {
fn path_to_cargo_toml(project: Entity<Project>, cx: &mut App) -> Option<Arc<Path>> {
let worktree = project.read(cx).worktrees(cx).next()?;
let worktree = worktree.read(cx);
let entry = worktree.entry_for_path("Cargo.toml")?;
@ -107,8 +107,9 @@ impl SlashCommand for CargoWorkspaceSlashCommand {
self: Arc<Self>,
_arguments: &[String],
_cancel: Arc<AtomicBool>,
_workspace: Option<WeakView<Workspace>>,
_cx: &mut WindowContext,
_workspace: Option<WeakEntity<Workspace>>,
_window: &mut Window,
_cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
Task::ready(Err(anyhow!("this command does not require argument")))
}
@ -122,9 +123,10 @@ impl SlashCommand for CargoWorkspaceSlashCommand {
_arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: BufferSnapshot,
workspace: WeakView<Workspace>,
workspace: WeakEntity<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>,
cx: &mut WindowContext,
_window: &mut Window,
cx: &mut App,
) -> Task<SlashCommandResult> {
let output = workspace.update(cx, |workspace, cx| {
let project = workspace.project().clone();

View file

@ -8,7 +8,7 @@ use context_server::{
manager::{ContextServer, ContextServerManager},
types::Prompt,
};
use gpui::{AppContext, Model, Task, WeakView, WindowContext};
use gpui::{App, Entity, Task, WeakEntity, Window};
use language::{BufferSnapshot, CodeLabel, LspAdapterDelegate};
use std::sync::atomic::AtomicBool;
use std::sync::Arc;
@ -19,14 +19,14 @@ use workspace::Workspace;
use crate::create_label_for_command;
pub struct ContextServerSlashCommand {
server_manager: Model<ContextServerManager>,
server_manager: Entity<ContextServerManager>,
server_id: Arc<str>,
prompt: Prompt,
}
impl ContextServerSlashCommand {
pub fn new(
server_manager: Model<ContextServerManager>,
server_manager: Entity<ContextServerManager>,
server: &Arc<ContextServer>,
prompt: Prompt,
) -> Self {
@ -43,7 +43,7 @@ impl SlashCommand for ContextServerSlashCommand {
self.prompt.name.clone()
}
fn label(&self, cx: &AppContext) -> language::CodeLabel {
fn label(&self, cx: &App) -> language::CodeLabel {
let mut parts = vec![self.prompt.name.as_str()];
if let Some(args) = &self.prompt.arguments {
if let Some(arg) = args.first() {
@ -77,8 +77,9 @@ impl SlashCommand for ContextServerSlashCommand {
self: Arc<Self>,
arguments: &[String],
_cancel: Arc<AtomicBool>,
_workspace: Option<WeakView<Workspace>>,
cx: &mut WindowContext,
_workspace: Option<WeakEntity<Workspace>>,
_window: &mut Window,
cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
let Ok((arg_name, arg_value)) = completion_argument(&self.prompt, arguments) else {
return Task::ready(Err(anyhow!("Failed to complete argument")));
@ -128,9 +129,10 @@ impl SlashCommand for ContextServerSlashCommand {
arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: BufferSnapshot,
_workspace: WeakView<Workspace>,
_workspace: WeakEntity<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>,
cx: &mut WindowContext,
_window: &mut Window,
cx: &mut App,
) -> Task<SlashCommandResult> {
let server_id = self.server_id.clone();
let prompt_name = self.prompt.name.clone();

View file

@ -3,7 +3,7 @@ use assistant_slash_command::{
ArgumentCompletion, SlashCommand, SlashCommandOutput, SlashCommandOutputSection,
SlashCommandResult,
};
use gpui::{Task, WeakView};
use gpui::{Task, WeakEntity};
use language::{BufferSnapshot, LspAdapterDelegate};
use prompt_library::PromptStore;
use std::{
@ -36,8 +36,9 @@ impl SlashCommand for DefaultSlashCommand {
self: Arc<Self>,
_arguments: &[String],
_cancellation_flag: Arc<AtomicBool>,
_workspace: Option<WeakView<Workspace>>,
_cx: &mut WindowContext,
_workspace: Option<WeakEntity<Workspace>>,
_window: &mut Window,
_cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
Task::ready(Err(anyhow!("this command does not require argument")))
}
@ -47,9 +48,10 @@ impl SlashCommand for DefaultSlashCommand {
_arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: BufferSnapshot,
_workspace: WeakView<Workspace>,
_workspace: WeakEntity<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>,
cx: &mut WindowContext,
_window: &mut Window,
cx: &mut App,
) -> Task<SlashCommandResult> {
let store = PromptStore::global(cx);
cx.background_executor().spawn(async move {

View file

@ -6,7 +6,7 @@ use assistant_slash_command::{
};
use collections::HashSet;
use futures::future;
use gpui::{Task, WeakView, WindowContext};
use gpui::{App, Task, WeakEntity, Window};
use language::{BufferSnapshot, LspAdapterDelegate};
use std::sync::{atomic::AtomicBool, Arc};
use text::OffsetRangeExt;
@ -40,8 +40,9 @@ impl SlashCommand for DeltaSlashCommand {
self: Arc<Self>,
_arguments: &[String],
_cancellation_flag: Arc<AtomicBool>,
_workspace: Option<WeakView<Workspace>>,
_cx: &mut WindowContext,
_workspace: Option<WeakEntity<Workspace>>,
_window: &mut Window,
_cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
Task::ready(Err(anyhow!("this command does not require argument")))
}
@ -51,9 +52,10 @@ impl SlashCommand for DeltaSlashCommand {
_arguments: &[String],
context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
context_buffer: BufferSnapshot,
workspace: WeakView<Workspace>,
workspace: WeakEntity<Workspace>,
delegate: Option<Arc<dyn LspAdapterDelegate>>,
cx: &mut WindowContext,
window: &mut Window,
cx: &mut App,
) -> Task<SlashCommandResult> {
let mut paths = HashSet::default();
let mut file_command_old_outputs = Vec::new();
@ -77,6 +79,7 @@ impl SlashCommand for DeltaSlashCommand {
context_buffer.clone(),
workspace.clone(),
delegate.clone(),
window,
cx,
));
}

View file

@ -4,7 +4,7 @@ use assistant_slash_command::{
SlashCommandResult,
};
use fuzzy::{PathMatch, StringMatchCandidate};
use gpui::{AppContext, Model, Task, View, WeakView};
use gpui::{App, Entity, Task, WeakEntity};
use language::{
Anchor, BufferSnapshot, DiagnosticEntry, DiagnosticSeverity, LspAdapterDelegate,
OffsetRangeExt, ToOffset,
@ -30,8 +30,8 @@ impl DiagnosticsSlashCommand {
&self,
query: String,
cancellation_flag: Arc<AtomicBool>,
workspace: &View<Workspace>,
cx: &mut AppContext,
workspace: &Entity<Workspace>,
cx: &mut App,
) -> Task<Vec<PathMatch>> {
if query.is_empty() {
let workspace = workspace.read(cx);
@ -90,7 +90,7 @@ impl SlashCommand for DiagnosticsSlashCommand {
"diagnostics".into()
}
fn label(&self, cx: &AppContext) -> language::CodeLabel {
fn label(&self, cx: &App) -> language::CodeLabel {
create_label_for_command("diagnostics", &[INCLUDE_WARNINGS_ARGUMENT], cx)
}
@ -118,8 +118,9 @@ impl SlashCommand for DiagnosticsSlashCommand {
self: Arc<Self>,
arguments: &[String],
cancellation_flag: Arc<AtomicBool>,
workspace: Option<WeakView<Workspace>>,
cx: &mut WindowContext,
workspace: Option<WeakEntity<Workspace>>,
_: &mut Window,
cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
let Some(workspace) = workspace.and_then(|workspace| workspace.upgrade()) else {
return Task::ready(Err(anyhow!("workspace was dropped")));
@ -172,9 +173,10 @@ impl SlashCommand for DiagnosticsSlashCommand {
arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: BufferSnapshot,
workspace: WeakView<Workspace>,
workspace: WeakEntity<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>,
cx: &mut WindowContext,
window: &mut Window,
cx: &mut App,
) -> Task<SlashCommandResult> {
let Some(workspace) = workspace.upgrade() else {
return Task::ready(Err(anyhow!("workspace was dropped")));
@ -184,7 +186,7 @@ impl SlashCommand for DiagnosticsSlashCommand {
let task = collect_diagnostics(workspace.read(cx).project().clone(), options, cx);
cx.spawn(move |_| async move {
window.spawn(cx, move |_| async move {
task.await?
.map(|output| output.to_event_stream())
.ok_or_else(|| anyhow!("No diagnostics found"))
@ -223,9 +225,9 @@ impl Options {
}
fn collect_diagnostics(
project: Model<Project>,
project: Entity<Project>,
options: Options,
cx: &mut AppContext,
cx: &mut App,
) -> Task<Result<Option<SlashCommandOutput>>> {
let error_source = if let Some(path_matcher) = &options.path_matcher {
debug_assert_eq!(path_matcher.sources().len(), 1);

View file

@ -8,7 +8,7 @@ use assistant_slash_command::{
ArgumentCompletion, SlashCommand, SlashCommandOutput, SlashCommandOutputSection,
SlashCommandResult,
};
use gpui::{AppContext, BackgroundExecutor, Model, Task, WeakView};
use gpui::{App, BackgroundExecutor, Entity, Task, WeakEntity};
use indexed_docs::{
DocsDotRsProvider, IndexedDocsRegistry, IndexedDocsStore, LocalRustdocProvider, PackageName,
ProviderId,
@ -24,7 +24,7 @@ pub struct DocsSlashCommand;
impl DocsSlashCommand {
pub const NAME: &'static str = "docs";
fn path_to_cargo_toml(project: Model<Project>, cx: &mut AppContext) -> Option<Arc<Path>> {
fn path_to_cargo_toml(project: Entity<Project>, cx: &mut App) -> Option<Arc<Path>> {
let worktree = project.read(cx).worktrees(cx).next()?;
let worktree = worktree.read(cx);
let entry = worktree.entry_for_path("Cargo.toml")?;
@ -43,8 +43,8 @@ impl DocsSlashCommand {
/// access the workspace so we can read the project.
fn ensure_rust_doc_providers_are_registered(
&self,
workspace: Option<WeakView<Workspace>>,
cx: &mut AppContext,
workspace: Option<WeakEntity<Workspace>>,
cx: &mut App,
) {
let indexed_docs_registry = IndexedDocsRegistry::global(cx);
if indexed_docs_registry
@ -164,8 +164,9 @@ impl SlashCommand for DocsSlashCommand {
self: Arc<Self>,
arguments: &[String],
_cancel: Arc<AtomicBool>,
workspace: Option<WeakView<Workspace>>,
cx: &mut WindowContext,
workspace: Option<WeakEntity<Workspace>>,
_: &mut Window,
cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
self.ensure_rust_doc_providers_are_registered(workspace, cx);
@ -272,9 +273,10 @@ impl SlashCommand for DocsSlashCommand {
arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: BufferSnapshot,
_workspace: WeakView<Workspace>,
_workspace: WeakEntity<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>,
cx: &mut WindowContext,
_: &mut Window,
cx: &mut App,
) -> Task<SlashCommandResult> {
if arguments.is_empty() {
return Task::ready(Err(anyhow!("missing an argument")));

View file

@ -9,7 +9,7 @@ use assistant_slash_command::{
SlashCommandResult,
};
use futures::AsyncReadExt;
use gpui::{Task, WeakView};
use gpui::{Task, WeakEntity};
use html_to_markdown::{convert_html_to_markdown, markdown, TagHandler};
use http_client::{AsyncBody, HttpClient, HttpClientWithUrl};
use language::{BufferSnapshot, LspAdapterDelegate};
@ -124,8 +124,9 @@ impl SlashCommand for FetchSlashCommand {
self: Arc<Self>,
_arguments: &[String],
_cancel: Arc<AtomicBool>,
_workspace: Option<WeakView<Workspace>>,
_cx: &mut WindowContext,
_workspace: Option<WeakEntity<Workspace>>,
_window: &mut Window,
_cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
Task::ready(Ok(Vec::new()))
}
@ -135,9 +136,10 @@ impl SlashCommand for FetchSlashCommand {
arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: BufferSnapshot,
workspace: WeakView<Workspace>,
workspace: WeakEntity<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>,
cx: &mut WindowContext,
_: &mut Window,
cx: &mut App,
) -> Task<SlashCommandResult> {
let Some(argument) = arguments.first() else {
return Task::ready(Err(anyhow!("missing URL")));

View file

@ -6,7 +6,7 @@ use assistant_slash_command::{
use futures::channel::mpsc;
use futures::Stream;
use fuzzy::PathMatch;
use gpui::{AppContext, Model, Task, View, WeakView};
use gpui::{App, Entity, Task, WeakEntity};
use language::{BufferSnapshot, CodeLabel, HighlightId, LineEnding, LspAdapterDelegate};
use project::{PathMatchCandidateSet, Project};
use serde::{Deserialize, Serialize};
@ -28,8 +28,8 @@ impl FileSlashCommand {
&self,
query: String,
cancellation_flag: Arc<AtomicBool>,
workspace: &View<Workspace>,
cx: &mut AppContext,
workspace: &Entity<Workspace>,
cx: &mut App,
) -> Task<Vec<PathMatch>> {
if query.is_empty() {
let workspace = workspace.read(cx);
@ -134,8 +134,9 @@ impl SlashCommand for FileSlashCommand {
self: Arc<Self>,
arguments: &[String],
cancellation_flag: Arc<AtomicBool>,
workspace: Option<WeakView<Workspace>>,
cx: &mut WindowContext,
workspace: Option<WeakEntity<Workspace>>,
_: &mut Window,
cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
let Some(workspace) = workspace.and_then(|workspace| workspace.upgrade()) else {
return Task::ready(Err(anyhow!("workspace was dropped")));
@ -187,9 +188,10 @@ impl SlashCommand for FileSlashCommand {
arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: BufferSnapshot,
workspace: WeakView<Workspace>,
workspace: WeakEntity<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>,
cx: &mut WindowContext,
_: &mut Window,
cx: &mut App,
) -> Task<SlashCommandResult> {
let Some(workspace) = workspace.upgrade() else {
return Task::ready(Err(anyhow!("workspace was dropped")));
@ -209,9 +211,9 @@ impl SlashCommand for FileSlashCommand {
}
fn collect_files(
project: Model<Project>,
project: Entity<Project>,
glob_inputs: &[String],
cx: &mut AppContext,
cx: &mut App,
) -> impl Stream<Item = Result<SlashCommandEvent>> {
let Ok(matchers) = glob_inputs
.into_iter()

View file

@ -7,7 +7,7 @@ use assistant_slash_command::{
SlashCommandResult,
};
use chrono::Local;
use gpui::{Task, WeakView};
use gpui::{Task, WeakEntity};
use language::{BufferSnapshot, LspAdapterDelegate};
use ui::prelude::*;
use workspace::Workspace;
@ -35,8 +35,9 @@ impl SlashCommand for NowSlashCommand {
self: Arc<Self>,
_arguments: &[String],
_cancel: Arc<AtomicBool>,
_workspace: Option<WeakView<Workspace>>,
_cx: &mut WindowContext,
_workspace: Option<WeakEntity<Workspace>>,
_window: &mut Window,
_cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
Task::ready(Ok(Vec::new()))
}
@ -46,9 +47,10 @@ impl SlashCommand for NowSlashCommand {
_arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: BufferSnapshot,
_workspace: WeakView<Workspace>,
_workspace: WeakEntity<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>,
_cx: &mut WindowContext,
_window: &mut Window,
_cx: &mut App,
) -> Task<SlashCommandResult> {
let now = Local::now();
let text = format!("Today is {now}.", now = now.to_rfc2822());

View file

@ -10,7 +10,7 @@ use assistant_slash_command::{
SlashCommandResult,
};
use feature_flags::FeatureFlag;
use gpui::{AppContext, Task, WeakView, WindowContext};
use gpui::{App, Task, WeakEntity};
use language::{Anchor, CodeLabel, LspAdapterDelegate};
use language_model::{LanguageModelRegistry, LanguageModelTool};
use prompt_library::PromptBuilder;
@ -43,7 +43,7 @@ impl SlashCommand for ProjectSlashCommand {
"project".into()
}
fn label(&self, cx: &AppContext) -> CodeLabel {
fn label(&self, cx: &App) -> CodeLabel {
create_label_for_command("project", &[], cx)
}
@ -67,8 +67,9 @@ impl SlashCommand for ProjectSlashCommand {
self: Arc<Self>,
_arguments: &[String],
_cancel: Arc<AtomicBool>,
_workspace: Option<WeakView<Workspace>>,
_cx: &mut WindowContext,
_workspace: Option<WeakEntity<Workspace>>,
_window: &mut Window,
_cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
Task::ready(Ok(Vec::new()))
}
@ -78,9 +79,10 @@ impl SlashCommand for ProjectSlashCommand {
_arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<Anchor>],
context_buffer: language::BufferSnapshot,
workspace: WeakView<Workspace>,
workspace: WeakEntity<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>,
cx: &mut WindowContext,
window: &mut Window,
cx: &mut App,
) -> Task<SlashCommandResult> {
let model_registry = LanguageModelRegistry::read_global(cx);
let current_model = model_registry.active_model();
@ -97,7 +99,7 @@ impl SlashCommand for ProjectSlashCommand {
return Task::ready(Err(anyhow::anyhow!("no project indexer")));
};
cx.spawn(|mut cx| async move {
window.spawn(cx, |mut cx| async move {
let current_model = current_model.ok_or_else(|| anyhow!("no model selected"))?;
let prompt =

View file

@ -1,9 +1,9 @@
use anyhow::{anyhow, Context, Result};
use anyhow::{anyhow, Context as _, Result};
use assistant_slash_command::{
ArgumentCompletion, SlashCommand, SlashCommandOutput, SlashCommandOutputSection,
SlashCommandResult,
};
use gpui::{Task, WeakView};
use gpui::{Task, WeakEntity};
use language::{BufferSnapshot, LspAdapterDelegate};
use prompt_library::PromptStore;
use std::sync::{atomic::AtomicBool, Arc};
@ -37,8 +37,9 @@ impl SlashCommand for PromptSlashCommand {
self: Arc<Self>,
arguments: &[String],
_cancellation_flag: Arc<AtomicBool>,
_workspace: Option<WeakView<Workspace>>,
cx: &mut WindowContext,
_workspace: Option<WeakEntity<Workspace>>,
_: &mut Window,
cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
let store = PromptStore::global(cx);
let query = arguments.to_owned().join(" ");
@ -64,9 +65,10 @@ impl SlashCommand for PromptSlashCommand {
arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: BufferSnapshot,
_workspace: WeakView<Workspace>,
_workspace: WeakEntity<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>,
cx: &mut WindowContext,
_: &mut Window,
cx: &mut App,
) -> Task<SlashCommandResult> {
let title = arguments.to_owned().join(" ");
if title.trim().is_empty() {

View file

@ -4,7 +4,7 @@ use assistant_slash_command::{
SlashCommandResult,
};
use feature_flags::FeatureFlag;
use gpui::{AppContext, Task, WeakView};
use gpui::{App, Task, WeakEntity};
use language::{CodeLabel, LspAdapterDelegate};
use semantic_index::{LoadedSearchResult, SemanticDb};
use std::{
@ -34,7 +34,7 @@ impl SlashCommand for SearchSlashCommand {
"search".into()
}
fn label(&self, cx: &AppContext) -> CodeLabel {
fn label(&self, cx: &App) -> CodeLabel {
create_label_for_command("search", &["--n"], cx)
}
@ -58,8 +58,9 @@ impl SlashCommand for SearchSlashCommand {
self: Arc<Self>,
_arguments: &[String],
_cancel: Arc<AtomicBool>,
_workspace: Option<WeakView<Workspace>>,
_cx: &mut WindowContext,
_workspace: Option<WeakEntity<Workspace>>,
_window: &mut Window,
_cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
Task::ready(Ok(Vec::new()))
}
@ -69,9 +70,10 @@ impl SlashCommand for SearchSlashCommand {
arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: language::BufferSnapshot,
workspace: WeakView<Workspace>,
workspace: WeakEntity<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>,
cx: &mut WindowContext,
window: &mut Window,
cx: &mut App,
) -> Task<SlashCommandResult> {
let Some(workspace) = workspace.upgrade() else {
return Task::ready(Err(anyhow::anyhow!("workspace was dropped")));
@ -107,7 +109,7 @@ impl SlashCommand for SearchSlashCommand {
return Task::ready(Err(anyhow::anyhow!("no project indexer")));
};
cx.spawn(|cx| async move {
window.spawn(cx, |cx| async move {
let results = project_index
.read_with(&cx, |project_index, cx| {
project_index.search(vec![query.clone()], limit.unwrap_or(5), cx)

View file

@ -5,8 +5,7 @@ use assistant_slash_command::{
};
use editor::Editor;
use futures::StreamExt;
use gpui::{AppContext, Task, WeakView};
use gpui::{SharedString, ViewContext, WindowContext};
use gpui::{App, Context, SharedString, Task, WeakEntity, Window};
use language::{BufferSnapshot, CodeLabel, LspAdapterDelegate};
use std::sync::atomic::AtomicBool;
use std::sync::Arc;
@ -22,7 +21,7 @@ impl SlashCommand for SelectionCommand {
"selection".into()
}
fn label(&self, _cx: &AppContext) -> CodeLabel {
fn label(&self, _cx: &App) -> CodeLabel {
CodeLabel::plain(self.name(), None)
}
@ -50,8 +49,9 @@ impl SlashCommand for SelectionCommand {
self: Arc<Self>,
_arguments: &[String],
_cancel: Arc<AtomicBool>,
_workspace: Option<WeakView<Workspace>>,
_cx: &mut WindowContext,
_workspace: Option<WeakEntity<Workspace>>,
_window: &mut Window,
_cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
Task::ready(Err(anyhow!("this command does not require argument")))
}
@ -61,9 +61,10 @@ impl SlashCommand for SelectionCommand {
_arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: BufferSnapshot,
workspace: WeakView<Workspace>,
workspace: WeakEntity<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>,
cx: &mut WindowContext,
_window: &mut Window,
cx: &mut App,
) -> Task<SlashCommandResult> {
let mut events = vec![];
@ -102,7 +103,7 @@ impl SlashCommand for SelectionCommand {
pub fn selections_creases(
workspace: &mut workspace::Workspace,
cx: &mut ViewContext<Workspace>,
cx: &mut Context<Workspace>,
) -> Option<Vec<(String, String)>> {
let editor = workspace
.active_item(cx)

View file

@ -9,7 +9,7 @@ use assistant_slash_command::{
};
use feature_flags::FeatureFlag;
use futures::channel::mpsc;
use gpui::{Task, WeakView};
use gpui::{Task, WeakEntity};
use language::{BufferSnapshot, LspAdapterDelegate};
use smol::stream::StreamExt;
use smol::Timer;
@ -45,8 +45,9 @@ impl SlashCommand for StreamingExampleSlashCommand {
self: Arc<Self>,
_arguments: &[String],
_cancel: Arc<AtomicBool>,
_workspace: Option<WeakView<Workspace>>,
_cx: &mut WindowContext,
_workspace: Option<WeakEntity<Workspace>>,
_window: &mut Window,
_cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
Task::ready(Ok(Vec::new()))
}
@ -56,9 +57,10 @@ impl SlashCommand for StreamingExampleSlashCommand {
_arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: BufferSnapshot,
_workspace: WeakView<Workspace>,
_workspace: WeakEntity<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>,
cx: &mut WindowContext,
_: &mut Window,
cx: &mut App,
) -> Task<SlashCommandResult> {
let (events_tx, events_rx) = mpsc::unbounded();
cx.background_executor()

View file

@ -4,11 +4,11 @@ use assistant_slash_command::{
SlashCommandResult,
};
use editor::Editor;
use gpui::{Task, WeakView};
use gpui::{Task, WeakEntity};
use language::{BufferSnapshot, LspAdapterDelegate};
use std::sync::Arc;
use std::{path::Path, sync::atomic::AtomicBool};
use ui::{IconName, WindowContext};
use ui::{App, IconName, Window};
use workspace::Workspace;
pub struct OutlineSlashCommand;
@ -34,8 +34,9 @@ impl SlashCommand for OutlineSlashCommand {
self: Arc<Self>,
_arguments: &[String],
_cancel: Arc<AtomicBool>,
_workspace: Option<WeakView<Workspace>>,
_cx: &mut WindowContext,
_workspace: Option<WeakEntity<Workspace>>,
_window: &mut Window,
_cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
Task::ready(Err(anyhow!("this command does not require argument")))
}
@ -49,9 +50,10 @@ impl SlashCommand for OutlineSlashCommand {
_arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: BufferSnapshot,
workspace: WeakView<Workspace>,
workspace: WeakEntity<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>,
cx: &mut WindowContext,
_: &mut Window,
cx: &mut App,
) -> Task<SlashCommandResult> {
let output = workspace.update(cx, |workspace, cx| {
let Some(active_item) = workspace.active_item(cx) else {

View file

@ -1,4 +1,4 @@
use anyhow::{Context, Result};
use anyhow::{Context as _, Result};
use assistant_slash_command::{
ArgumentCompletion, SlashCommand, SlashCommandOutput, SlashCommandOutputSection,
SlashCommandResult,
@ -6,13 +6,13 @@ use assistant_slash_command::{
use collections::{HashMap, HashSet};
use editor::Editor;
use futures::future::join_all;
use gpui::{Entity, Task, WeakView};
use gpui::{Task, WeakEntity};
use language::{BufferSnapshot, CodeLabel, HighlightId, LspAdapterDelegate};
use std::{
path::PathBuf,
sync::{atomic::AtomicBool, Arc},
};
use ui::{prelude::*, ActiveTheme, WindowContext};
use ui::{prelude::*, ActiveTheme, App, Window};
use util::ResultExt;
use workspace::Workspace;
@ -51,8 +51,9 @@ impl SlashCommand for TabSlashCommand {
self: Arc<Self>,
arguments: &[String],
cancel: Arc<AtomicBool>,
workspace: Option<WeakView<Workspace>>,
cx: &mut WindowContext,
workspace: Option<WeakEntity<Workspace>>,
window: &mut Window,
cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
let mut has_all_tabs_completion_item = false;
let argument_set = arguments
@ -82,10 +83,10 @@ impl SlashCommand for TabSlashCommand {
});
let current_query = arguments.last().cloned().unwrap_or_default();
let tab_items_search =
tab_items_for_queries(workspace, &[current_query], cancel, false, cx);
tab_items_for_queries(workspace, &[current_query], cancel, false, window, cx);
let comment_id = cx.theme().syntax().highlight_id("comment").map(HighlightId);
cx.spawn(|_| async move {
window.spawn(cx, |_| async move {
let tab_items = tab_items_search.await?;
let run_command = tab_items.len() == 1;
let tab_completion_items = tab_items.into_iter().filter_map(|(path, ..)| {
@ -137,15 +138,17 @@ impl SlashCommand for TabSlashCommand {
arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: BufferSnapshot,
workspace: WeakView<Workspace>,
workspace: WeakEntity<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>,
cx: &mut WindowContext,
window: &mut Window,
cx: &mut App,
) -> Task<SlashCommandResult> {
let tab_items_search = tab_items_for_queries(
Some(workspace),
arguments,
Arc::new(AtomicBool::new(false)),
true,
window,
cx,
);
@ -160,15 +163,16 @@ impl SlashCommand for TabSlashCommand {
}
fn tab_items_for_queries(
workspace: Option<WeakView<Workspace>>,
workspace: Option<WeakEntity<Workspace>>,
queries: &[String],
cancel: Arc<AtomicBool>,
strict_match: bool,
cx: &mut WindowContext,
window: &mut Window,
cx: &mut App,
) -> Task<anyhow::Result<Vec<(Option<PathBuf>, BufferSnapshot, usize)>>> {
let empty_query = queries.is_empty() || queries.iter().all(|query| query.trim().is_empty());
let queries = queries.to_owned();
cx.spawn(|mut cx| async move {
window.spawn(cx, |mut cx| async move {
let mut open_buffers =
workspace
.context("no workspace")?
@ -281,7 +285,7 @@ fn tab_items_for_queries(
fn active_item_buffer(
workspace: &mut Workspace,
cx: &mut ViewContext<Workspace>,
cx: &mut Context<Workspace>,
) -> anyhow::Result<BufferSnapshot> {
let active_editor = workspace
.active_item(cx)

View file

@ -6,7 +6,7 @@ use assistant_slash_command::{
ArgumentCompletion, SlashCommand, SlashCommandOutput, SlashCommandOutputSection,
SlashCommandResult,
};
use gpui::{AppContext, Task, View, WeakView};
use gpui::{App, Entity, Task, WeakEntity};
use language::{BufferSnapshot, CodeLabel, LspAdapterDelegate};
use terminal_view::{terminal_panel::TerminalPanel, TerminalView};
use ui::prelude::*;
@ -25,7 +25,7 @@ impl SlashCommand for TerminalSlashCommand {
"terminal".into()
}
fn label(&self, cx: &AppContext) -> CodeLabel {
fn label(&self, cx: &App) -> CodeLabel {
create_label_for_command("terminal", &[LINE_COUNT_ARG], cx)
}
@ -53,8 +53,9 @@ impl SlashCommand for TerminalSlashCommand {
self: Arc<Self>,
_arguments: &[String],
_cancel: Arc<AtomicBool>,
_workspace: Option<WeakView<Workspace>>,
_cx: &mut WindowContext,
_workspace: Option<WeakEntity<Workspace>>,
_window: &mut Window,
_cx: &mut App,
) -> Task<Result<Vec<ArgumentCompletion>>> {
Task::ready(Ok(Vec::new()))
}
@ -64,9 +65,10 @@ impl SlashCommand for TerminalSlashCommand {
arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: BufferSnapshot,
workspace: WeakView<Workspace>,
workspace: WeakEntity<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>,
cx: &mut WindowContext,
_: &mut Window,
cx: &mut App,
) -> Task<SlashCommandResult> {
let Some(workspace) = workspace.upgrade() else {
return Task::ready(Err(anyhow::anyhow!("workspace was dropped")));
@ -107,9 +109,9 @@ impl SlashCommand for TerminalSlashCommand {
}
fn resolve_active_terminal(
workspace: &View<Workspace>,
cx: &WindowContext,
) -> Option<View<TerminalView>> {
workspace: &Entity<Workspace>,
cx: &mut App,
) -> Option<Entity<TerminalView>> {
if let Some(terminal_view) = workspace
.read(cx)
.active_item(cx)