1//! A source of tasks, based on ad-hoc user command prompt input.
2
3use std::sync::Arc;
4
5use crate::{SpawnInTerminal, Task, TaskId, TaskSource};
6use gpui::{AppContext, Context, Model};
7
8/// A storage and source of tasks generated out of user command prompt inputs.
9pub struct OneshotSource {
10 tasks: Vec<Arc<dyn Task>>,
11}
12
13#[derive(Clone)]
14struct OneshotTask {
15 id: TaskId,
16}
17
18impl OneshotTask {
19 fn new(prompt: String) -> Self {
20 Self { id: TaskId(prompt) }
21 }
22}
23
24impl Task for OneshotTask {
25 fn id(&self) -> &TaskId {
26 &self.id
27 }
28
29 fn name(&self) -> &str {
30 &self.id.0
31 }
32
33 fn cwd(&self) -> Option<&std::path::Path> {
34 None
35 }
36
37 fn exec(&self, cwd: Option<std::path::PathBuf>) -> Option<SpawnInTerminal> {
38 if self.id().0.is_empty() {
39 return None;
40 }
41 Some(SpawnInTerminal {
42 id: self.id().clone(),
43 label: self.name().to_owned(),
44 command: self.id().0.clone(),
45 args: vec![],
46 cwd,
47 env: Default::default(),
48 use_new_terminal: Default::default(),
49 allow_concurrent_runs: Default::default(),
50 })
51 }
52}
53
54impl OneshotSource {
55 /// Initializes the oneshot source, preparing to store user prompts.
56 pub fn new(cx: &mut AppContext) -> Model<Box<dyn TaskSource>> {
57 cx.new_model(|_| Box::new(Self { tasks: Vec::new() }) as Box<dyn TaskSource>)
58 }
59
60 /// Spawns a certain task based on the user prompt.
61 pub fn spawn(&mut self, prompt: String) -> Arc<dyn Task> {
62 let ret = Arc::new(OneshotTask::new(prompt));
63 self.tasks.push(ret.clone());
64 ret
65 }
66}
67
68impl TaskSource for OneshotSource {
69 fn as_any(&mut self) -> &mut dyn std::any::Any {
70 self
71 }
72
73 fn tasks_for_path(
74 &mut self,
75 _path: Option<&std::path::Path>,
76 _cx: &mut gpui::ModelContext<Box<dyn TaskSource>>,
77 ) -> Vec<Arc<dyn Task>> {
78 self.tasks.clone()
79 }
80}