use std::sync::Arc;
use eyre::{Result, bail};
use itertools::Itertools;
use serde_json::json;
use crate::config::Config;
use crate::file::display_path;
use crate::task::Task;
use crate::task::task_fetcher::TaskFetcher;
use crate::task::task_source_checker::task_cwd;
use crate::ui::info;
#[derive(Debug, clap::Args)]
#[clap(verbatim_doc_comment, after_long_help = AFTER_LONG_HELP)]
pub struct TasksInfo {
#[clap(verbatim_doc_comment)]
pub task: String,
#[clap(short = 'J', long, verbatim_doc_comment)]
pub json: bool,
}
impl TasksInfo {
pub async fn run(self) -> Result<()> {
let config = Config::get().await?;
let task_name = crate::task::expand_colon_task_syntax(&self.task, &config)?;
let tasks = if task_name.starts_with("//") {
let ctx = crate::task::TaskLoadContext::from_pattern(&task_name);
config.tasks_with_context(Some(&ctx)).await?
} else {
config.tasks().await?
};
let tasks_with_aliases = crate::task::build_task_ref_map(tasks.iter());
use crate::task::GetMatchingExt;
let matching = tasks_with_aliases.get_matching(&task_name).ok();
let task = matching.and_then(|m| m.first().cloned().cloned());
if let Some(task) = task {
let mut tasks = vec![task.clone()];
TaskFetcher::new(false).fetch_tasks(&mut tasks).await?;
let task = &tasks[0];
if self.json {
self.display_json(&config, task).await?;
} else {
self.display(&config, task).await?;
}
} else {
bail!(
"Task not found: {}, use `mise tasks ls --all --hidden` to list all tasks",
self.task
);
}
Ok(())
}
async fn display(&self, config: &Arc<Config>, task: &Task) -> Result<()> {
info::inline_section("Task", &task.display_name)?;
if !task.aliases.is_empty() {
info::inline_section("Aliases", task.aliases.join(", "))?;
}
info::inline_section("Description", &task.description)?;
info::inline_section("Source", display_path(&task.config_source))?;
let mut properties = vec![];
if task.hide {
properties.push("hide");
}
if task.raw {
properties.push("raw");
}
if !properties.is_empty() {
info::inline_section("Properties", properties.join(", "))?;
}
if !task.depends.is_empty() {
info::inline_section("Depends on", task.depends.iter().join(", "))?;
}
if !task.depends_post.is_empty() {
info::inline_section("Depends post", task.depends_post.iter().join(", "))?;
}
if let Some(dir) = &task.dir {
info::inline_section("Directory", display_path(dir))?;
}
if !task.sources.is_empty() {
info::inline_section("Sources", task.sources.join(", "))?;
}
let root = task_cwd(task, config).await?;
let outputs = task.outputs.paths(task, &root);
if !outputs.is_empty() {
info::inline_section("Outputs", outputs.join(", "))?;
}
if let Some(file) = &task.file {
info::inline_section("File", display_path(file))?;
}
let run = task.run();
if !run.is_empty() {
info::section("Run", run.iter().map(|e| e.to_string()).join("\n"))?;
}
if !task.env.is_empty() {
let env_display = task
.env
.0
.iter()
.map(|directive| directive.to_string())
.collect::<Vec<_>>()
.join("\n");
info::section("Environment Variables", env_display)?;
}
let spec = task.parse_usage_spec_for_display(config).await?;
if !spec.is_empty() {
info::section("Usage Spec", &spec)?;
}
Ok(())
}
async fn display_json(&self, config: &Arc<Config>, task: &Task) -> Result<()> {
let spec = task.parse_usage_spec_for_display(config).await?;
let o = json!({
"name": task.display_name,
"aliases": task.aliases,
"description": task.description,
"source": task.config_source,
"depends": task.depends,
"depends_post": task.depends_post,
"wait_for": task.wait_for,
"env": task.env.0.iter().map(|d| d.to_string()).collect::<Vec<_>>(),
"dir": task.dir,
"hide": task.hide,
"raw": task.raw,
"sources": task.sources,
"outputs": task.outputs,
"shell": task.shell,
"quiet": task.quiet,
"silent": task.silent,
"tools": task.tools,
"run": task.run(),
"file": task.file,
"usage_spec": spec,
});
miseprintln!("{}", serde_json::to_string_pretty(&o)?);
Ok(())
}
}
static AFTER_LONG_HELP: &str = color_print::cstr!(
r#"<bold><underline>Examples:</underline></bold>
$ <bold>mise tasks info</bold>
Name: test
Aliases: t
Description: Test the application
Source: ~/src/myproj/mise.toml
$ <bold>mise tasks info test --json</bold>
{
"name": "test",
"aliases": "t",
"description": "Test the application",
"source": "~/src/myproj/mise.toml",
"depends": [],
"env": {},
"dir": null,
"hide": false,
"raw": false,
"sources": [],
"outputs": [],
"run": [
"echo \"testing!\""
],
"file": null,
"usage_spec": {}
}
"#
);