Skip to content

Commit

Permalink
accept vec of tasks when spawning terminal tasks
Browse files Browse the repository at this point in the history
  • Loading branch information
cartercanedy committed Jan 19, 2025
1 parent daf1524 commit 05908b0
Show file tree
Hide file tree
Showing 12 changed files with 269 additions and 98 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 29 additions & 2 deletions crates/editor/src/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4208,9 +4208,10 @@ impl Editor {
match action {
CodeActionsItem::Task(task_source_kind, resolved_task) => {
workspace.update(cx, |workspace, cx| {
workspace::tasks::schedule_resolved_task(
workspace::tasks::schedule_resolved_tasks(
workspace,
task_source_kind,
vec![],
resolved_task,
false,
cx,
Expand Down Expand Up @@ -5087,9 +5088,35 @@ impl Editor {

workspace
.update(&mut cx, |workspace, cx| {
workspace::tasks::schedule_resolved_task(
let worktree = match task_source_kind {
TaskSourceKind::Worktree { id, .. } => Some(id),
_ => None
};

let pre_tasks = workspace
.project()
.read(cx)
.task_store()
.read(cx)
.task_inventory()
.map_or(vec![], |inventory| {
inventory
.read(cx)
.build_pre_task_list(
&resolved_task,
worktree,
&context
)
.unwrap_or(vec![])
.into_iter()
.map(|(_, task)| task)
.collect_vec()
});

workspace::tasks::schedule_resolved_tasks(
workspace,
task_source_kind,
pre_tasks,
resolved_task,
false,
cx,
Expand Down
42 changes: 23 additions & 19 deletions crates/project/src/task_inventory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,37 +123,42 @@ impl Inventory {
}

/// Topological sort of the dependency graph of `task`
pub fn build_pre_task_list(&self, task: &TaskTemplate) -> anyhow::Result<Vec<(TaskSourceKind, TaskTemplate)>> {
// collect all tasks from all available worktrees
let tasks = self
.templates_from_settings
.worktree
.iter()
.flat_map(|leaf| {
self.worktree_templates_from_settings(Some(*leaf.0))
.chain(self.global_templates_from_settings())
.collect_vec()
pub fn build_pre_task_list(
&self,
base_task: &ResolvedTask,
worktree: Option<WorktreeId>,
task_context: &TaskContext,
) -> anyhow::Result<Vec<(TaskSourceKind, ResolvedTask)>> {
let tasks_in_scope = self
.worktree_templates_from_settings(worktree)
.chain(self.global_templates_from_settings())
.filter_map(|(kind, task)| {
let base_id = kind.to_id_base();
task
.resolve_task(&base_id, task_context)
.map(|task| (kind, task))
})
.unique_by(|(_, task)| task.label.clone())
.unique_by(|(_, task)| task.resolved_label.clone())
.collect_vec();

if let None = tasks
if let None = tasks_in_scope
.iter()
.find(|(_, TaskTemplate { label, .. })| task.label.as_str() == label.as_str())
.find(|(_, task)| task.resolved_label == base_task.resolved_label)
{
return Err(anyhow::anyhow!("couldn't find with label {} in available tasks", &task.label));
return Err(anyhow::anyhow!("couldn't find with label {} in available tasks", base_task.resolved_label));
}

// map task labels to their dep graph node idx, source, and dependencies
let nodes = tasks
let nodes = tasks_in_scope
.iter()
.enumerate()
.map(|(idx, (source, task))| (
task.label.as_str(),
task.resolved_label,
(
idx as u32,
source,
task.pre
task
.resolved_pre_labels
.iter()
.map(|s| s.as_str())
.unique()
Expand Down Expand Up @@ -181,9 +186,8 @@ impl Inventory {
}
}


dep_graph
.subgraph(nodes.get(task.label.as_str()).unwrap().0)
.subgraph(nodes.get(base_task.resolved_label.as_str()).unwrap().0)
.topo_sort()
.map(|tasks| {
tasks
Expand Down
1 change: 1 addition & 0 deletions crates/task/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ sha2.workspace = true
shellexpand.workspace = true
util.workspace = true
zed_actions.workspace = true
itertools.workspace = true

[dev-dependencies]
gpui = { workspace = true, features = ["test-support"] }
2 changes: 2 additions & 0 deletions crates/task/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ pub struct ResolvedTask {
/// Further actions that need to take place after the resolved task is spawned,
/// with all task variables resolved.
pub resolved: Option<SpawnInTerminal>,
/// Pretasks with their variables expanded
pub resolved_pre_labels: Vec<String>
}

impl ResolvedTask {
Expand Down
17 changes: 17 additions & 0 deletions crates/task/src/task_template.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::path::PathBuf;
use itertools::Itertools as _;
use util::serde::default_true;

use anyhow::{bail, Context};
Expand Down Expand Up @@ -160,6 +161,7 @@ impl TaskTemplate {
None => None,
}
.or(cx.cwd.clone());

let human_readable_label = substitute_all_template_variables_in_str(
&self.label,
&truncated_variables,
Expand All @@ -176,18 +178,32 @@ impl TaskTemplate {
}
string
});

let full_label = substitute_all_template_variables_in_str(
&self.label,
&task_variables,
&variable_names,
&mut substituted_variables,
)?;

let pre_labels = self
.pre
.iter()
.filter_map(|pre_label| substitute_all_template_variables_in_str(
pre_label,
&truncated_variables,
&variable_names,
&mut substituted_variables
))
.collect_vec();

let command = substitute_all_template_variables_in_str(
&self.command,
&task_variables,
&variable_names,
&mut substituted_variables,
)?;

let args_with_substitutions = substitute_all_template_variables_in_vec(
&self.args,
&task_variables,
Expand Down Expand Up @@ -228,6 +244,7 @@ impl TaskTemplate {
substituted_variables,
original_task: self.clone(),
resolved_label: full_label.clone(),
resolved_pre_labels: pre_labels,
resolved: Some(SpawnInTerminal {
id,
cwd,
Expand Down
61 changes: 52 additions & 9 deletions crates/tasks_ui/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
use itertools::Itertools;
use ::settings::Settings;
use editor::{tasks::task_context, Editor};
use gpui::{AppContext, Task as AsyncTask, ViewContext, WindowContext};
use modal::{TaskOverrides, TasksModal};
use project::{Location, WorktreeId};
use project::{Location, TaskSourceKind, WorktreeId};
use task::{RevealTarget, TaskId};
use ui::VisualContext;
use util::ResultExt;
use workspace::tasks::schedule_task;
use workspace::{tasks::schedule_resolved_task, Workspace};
use workspace::{tasks::schedule_resolved_tasks, Workspace};

mod modal;
mod settings;
Expand Down Expand Up @@ -37,12 +40,15 @@ pub fn init(cx: &mut AppContext) {
{
if action.reevaluate_context {
let mut original_task = last_scheduled_task.original_task().clone();

if let Some(allow_concurrent_runs) = action.allow_concurrent_runs {
original_task.allow_concurrent_runs = allow_concurrent_runs;
}

if let Some(use_new_terminal) = action.use_new_terminal {
original_task.use_new_terminal = use_new_terminal;
}

let context_task = task_context(workspace, cx);
cx.spawn(|workspace, mut cx| async move {
let task_context = context_task.await;
Expand Down Expand Up @@ -70,13 +76,50 @@ pub fn init(cx: &mut AppContext) {
}
}

schedule_resolved_task(
workspace,
task_source_kind,
last_scheduled_task,
false,
cx,
);
let worktree = match task_source_kind {
TaskSourceKind::Worktree { id, .. } => Some(id),
_ => None
};

let task_context = task_context(workspace, cx);

let _ = cx.spawn(|workspace, mut cx| async move {
let task_context = task_context.await;
let Some(workspace) = workspace.upgrade() else { return; };

cx.update_view(&workspace, |workspace, cx| {
let pre_tasks = workspace
.project()
.read(cx)
.task_store()
.read(cx)
.task_inventory()
.map_or(vec![], |inventory| {
inventory
.read(cx)
.build_pre_task_list(
&last_scheduled_task,
worktree,
&task_context
)
.unwrap_or(vec![])
.into_iter()
.map(|(_, task)| task)
.collect_vec()
});

schedule_resolved_tasks(
workspace,
task_source_kind,
pre_tasks,
last_scheduled_task,
false,
cx,
);
}).log_err();

});

}
} else {
toggle_modal(workspace, None, cx).detach();
Expand Down
50 changes: 44 additions & 6 deletions crates/tasks_ui/src/modal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@ use std::sync::Arc;
use crate::active_item_selection_properties;
use fuzzy::{StringMatch, StringMatchCandidate};
use gpui::{
rems, Action, AnyElement, AppContext, DismissEvent, EventEmitter, FocusableView,
InteractiveElement, Model, ParentElement, Render, SharedString, Styled, Subscription, Task,
View, ViewContext, VisualContext, WeakView,
rems, Action, AnyElement, AppContext, DismissEvent, EventEmitter, FocusableView, InteractiveElement, Model, ParentElement, Render, SharedString, Styled, Subscription, Task, View, ViewContext, VisualContext, WeakView
};
use itertools::Itertools;
use picker::{highlighted_match_with_paths::HighlightedText, Picker, PickerDelegate};
use project::{task_store::TaskStore, TaskSourceKind};
use task::{ResolvedTask, RevealTarget, TaskContext, TaskTemplate};
Expand All @@ -17,7 +16,7 @@ use ui::{
WindowContext,
};
use util::ResultExt;
use workspace::{tasks::schedule_resolved_task, ModalView, Workspace};
use workspace::{tasks::schedule_resolved_tasks, ModalView, Workspace};
pub use zed_actions::{Rerun, Spawn};

/// A modal used to spawn new tasks.
Expand Down Expand Up @@ -296,7 +295,39 @@ impl PickerDelegate for TasksModalDelegate {

self.workspace
.update(cx, |workspace, cx| {
schedule_resolved_task(workspace, task_source_kind, task, omit_history_entry, cx);
let worktree = match task_source_kind {
TaskSourceKind::Worktree { id, .. } => Some(id),
_ => None
};

let pre_tasks = workspace
.project()
.read(cx)
.task_store()
.read(cx)
.task_inventory()
.map_or(vec![], |inventory| {
inventory
.read(cx)
.build_pre_task_list(
&task,
worktree,
&self.task_context
)
.unwrap_or(vec![])
.into_iter()
.map(|(_, task)| task)
.collect_vec()
});

schedule_resolved_tasks(
workspace,
task_source_kind,
pre_tasks,
task,
omit_history_entry,
cx
);
})
.ok();
cx.emit(DismissEvent);
Expand Down Expand Up @@ -443,7 +474,14 @@ impl PickerDelegate for TasksModalDelegate {
}
self.workspace
.update(cx, |workspace, cx| {
schedule_resolved_task(workspace, task_source_kind, task, omit_history_entry, cx);
schedule_resolved_tasks(
workspace,
task_source_kind,
vec![],
task,
omit_history_entry,
cx
);
})
.ok();
cx.emit(DismissEvent);
Expand Down
Loading

0 comments on commit 05908b0

Please sign in to comment.