//! A source of tasks, based on ad-hoc user command prompt input. use std::sync::Arc; use crate::{ static_source::RevealStrategy, 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>, } #[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 prepare_exec(&self, cx: TaskContext) -> Option { if self.id().0.is_empty() { return None; } let TaskContext { cwd, task_variables, } = cx; Some(SpawnInTerminal { id: self.id().clone(), label: self.name().to_owned(), command: self.id().0.clone(), args: vec![], cwd, env: task_variables.into_env_variables(), use_new_terminal: Default::default(), allow_concurrent_runs: Default::default(), reveal: RevealStrategy::default(), }) } } impl OneshotSource { /// Initializes the oneshot source, preparing to store user prompts. pub fn new(cx: &mut AppContext) -> Model> { cx.new_model(|_| Box::new(Self { tasks: Vec::new() }) as Box) } /// Spawns a certain task based on the user prompt. pub fn spawn(&mut self, prompt: String) -> Arc { if let Some(task) = self.tasks.iter().find(|task| task.id().0 == prompt) { // If we already have an oneshot task with that command, let's just reuse it. task.clone() } else { let new_oneshot = Arc::new(OneshotTask::new(prompt)); self.tasks.push(new_oneshot.clone()); new_oneshot } } /// Removes a task with a given ID from this source. pub fn remove(&mut self, id: &TaskId) { let position = self.tasks.iter().position(|task| task.id() == id); if let Some(position) = position { self.tasks.remove(position); } } } impl TaskSource for OneshotSource { fn as_any(&mut self) -> &mut dyn std::any::Any { self } fn tasks_to_schedule( &mut self, _cx: &mut gpui::ModelContext>, ) -> Vec> { self.tasks.clone() } }