Cargo.lock 🔗
@@ -9640,6 +9640,7 @@ dependencies = [
"editor",
"fuzzy",
"gpui",
+ "itertools 0.11.0",
"language",
"menu",
"picker",
Piotr Osiewicz created
Previously it expanded to a label, which was correct for oneshots, but
wrong for everything else.
Release Notes:
- Improved UseSelectedQuery (shift-enter) action for tasks modal by
making it substitute a full command and not the task label.
- Fixed one-shot tasks having duplicates in tasks modal.
Cargo.lock | 1
crates/task/src/oneshot_source.rs | 11 +++++++--
crates/tasks_ui/Cargo.toml | 1
crates/tasks_ui/src/modal.rs | 35 ++++++++++++++++++++++----------
4 files changed, 34 insertions(+), 14 deletions(-)
@@ -9640,6 +9640,7 @@ dependencies = [
"editor",
"fuzzy",
"gpui",
+ "itertools 0.11.0",
"language",
"menu",
"picker",
@@ -66,9 +66,14 @@ impl OneshotSource {
/// 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
+ 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
+ }
}
}
@@ -22,6 +22,7 @@ ui.workspace = true
util.workspace = true
workspace.workspace = true
language.workspace = true
+itertools.workspace = true
[dev-dependencies]
editor = { workspace = true, features = ["test-support"] }
@@ -310,7 +310,20 @@ impl PickerDelegate for TasksModalDelegate {
}
fn selected_as_query(&self) -> Option<String> {
- Some(self.matches.get(self.selected_index())?.string.clone())
+ use itertools::intersperse;
+ let task_index = self.matches.get(self.selected_index())?.candidate_id;
+ let tasks = self.candidates.as_ref()?;
+ let (_, task) = tasks.get(task_index)?;
+ // .exec doesn't actually spawn anything; it merely prepares a spawning command,
+ // which we can use for substitution.
+ let mut spawn_prompt = task.exec(self.task_context.clone())?;
+ if !spawn_prompt.args.is_empty() {
+ spawn_prompt.command.push(' ');
+ spawn_prompt
+ .command
+ .extend(intersperse(spawn_prompt.args, " ".to_string()));
+ }
+ Some(spawn_prompt.command)
}
}
@@ -381,15 +394,15 @@ mod tests {
cx.dispatch_action(menu::UseSelectedQuery);
assert_eq!(
query(&tasks_picker, cx),
- "example task",
- "Query should be set to the selected task's name"
+ "echo 4",
+ "Query should be set to the selected task's command"
);
assert_eq!(
task_names(&tasks_picker, cx),
- vec!["example task"],
- "No other tasks should be listed"
+ Vec::<String>::new(),
+ "No task should be listed"
);
- cx.dispatch_action(menu::Confirm);
+ cx.dispatch_action(menu::SecondaryConfirm);
let tasks_picker = open_spawn_tasks(&workspace, cx);
assert_eq!(
@@ -399,8 +412,8 @@ mod tests {
);
assert_eq!(
task_names(&tasks_picker, cx),
- vec!["example task", "another one"],
- "Last recently used task should be listed first"
+ vec!["echo 4", "another one", "example task"],
+ "New oneshot task should be listed first"
);
let query_str = "echo 4";
@@ -408,8 +421,8 @@ mod tests {
assert_eq!(query(&tasks_picker, cx), query_str);
assert_eq!(
task_names(&tasks_picker, cx),
- Vec::<String>::new(),
- "No tasks should match custom command query"
+ vec!["echo 4"],
+ "New oneshot should match custom command query"
);
cx.dispatch_action(menu::SecondaryConfirm);
@@ -421,7 +434,7 @@ mod tests {
);
assert_eq!(
task_names(&tasks_picker, cx),
- vec![query_str, "example task", "another one"],
+ vec![query_str, "another one", "example task"],
"Last recently used one show task should be listed first"
);