
This PR supplements tasks with additional environment variables; ideally we'll be able to write a task like: `cargo test -p $ZED_CURRENT_PACKAGE -- $ZED_CURRENT_FUNCTION` - [x] Flesh out multibuffer interactions - [x] Add ZED_SYMBOL detection based on tree-sitter queries - [ ] Add release note and demo - [x] Figure out a solution for rerun dilemma - should `task: rerun` reevaluate contexts for tasks? This PR introduced the following variables: - ZED_COLUMN - current line column - ZED_ROW - current line row and the following, which are available for buffers with associated files: - ZED_WORKTREE_ROOT - absolute path to the root of the current worktree. - ZED_FILE - absolute path to the file - ZED_SYMBOL - currently selected symbol; should match the last symbol shown in a symbol breadcrumb (e.g. `mod tests > fn test_task_contexts` should be equal to ZED_SYMBOL of `test_task_contexts`). Note that this isn't necessarily a test function or a function at all. Also, you can use them in `cwd` field of definitions (note though that we're using https://docs.rs/subst/latest/subst/#features for that, so don't expect a full shell functionality to work); the syntax should match up with your typical Unix shell. Release Notes: - Added task contexts, which are additional environment variables set by Zed for task execution; task content is dependent on the state of the editor at the time the task is spawned. --------- Co-authored-by: Anthony <anthonyeid7@protonmail.com>
81 lines
2 KiB
Rust
81 lines
2 KiB
Rust
//! A source of tasks, based on ad-hoc user command prompt input.
|
|
|
|
use std::sync::Arc;
|
|
|
|
use crate::{SpawnInTerminal, Task, TaskContext, TaskId, TaskSource};
|
|
use gpui::{AppContext, Context, Model};
|
|
|
|
/// A storage and source of tasks generated out of user command prompt inputs.
|
|
pub struct OneshotSource {
|
|
tasks: Vec<Arc<dyn Task>>,
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
struct OneshotTask {
|
|
id: TaskId,
|
|
}
|
|
|
|
impl OneshotTask {
|
|
fn new(prompt: String) -> Self {
|
|
Self { id: TaskId(prompt) }
|
|
}
|
|
}
|
|
|
|
impl Task for OneshotTask {
|
|
fn id(&self) -> &TaskId {
|
|
&self.id
|
|
}
|
|
|
|
fn name(&self) -> &str {
|
|
&self.id.0
|
|
}
|
|
|
|
fn cwd(&self) -> Option<&str> {
|
|
None
|
|
}
|
|
|
|
fn exec(&self, cx: TaskContext) -> Option<SpawnInTerminal> {
|
|
if self.id().0.is_empty() {
|
|
return None;
|
|
}
|
|
let TaskContext { cwd, env } = cx;
|
|
Some(SpawnInTerminal {
|
|
id: self.id().clone(),
|
|
label: self.name().to_owned(),
|
|
command: self.id().0.clone(),
|
|
args: vec![],
|
|
cwd,
|
|
env,
|
|
use_new_terminal: Default::default(),
|
|
allow_concurrent_runs: Default::default(),
|
|
})
|
|
}
|
|
}
|
|
|
|
impl OneshotSource {
|
|
/// Initializes the oneshot source, preparing to store user prompts.
|
|
pub fn new(cx: &mut AppContext) -> Model<Box<dyn TaskSource>> {
|
|
cx.new_model(|_| Box::new(Self { tasks: Vec::new() }) as Box<dyn TaskSource>)
|
|
}
|
|
|
|
/// Spawns a certain task based on the user prompt.
|
|
pub fn spawn(&mut self, prompt: String) -> Arc<dyn Task> {
|
|
let ret = Arc::new(OneshotTask::new(prompt));
|
|
self.tasks.push(ret.clone());
|
|
ret
|
|
}
|
|
}
|
|
|
|
impl TaskSource for OneshotSource {
|
|
fn as_any(&mut self) -> &mut dyn std::any::Any {
|
|
self
|
|
}
|
|
|
|
fn tasks_for_path(
|
|
&mut self,
|
|
_path: Option<&std::path::Path>,
|
|
_cx: &mut gpui::ModelContext<Box<dyn TaskSource>>,
|
|
) -> Vec<Arc<dyn Task>> {
|
|
self.tasks.clone()
|
|
}
|
|
}
|