mirror of https://github.com/jdx/mise
feat: added basic task markdown generation (#2677)
This commit is contained in:
parent
398c3ff75e
commit
9e64dd02a6
|
@ -3,3 +3,4 @@ target/
|
|||
CHANGELOG.md
|
||||
docs/node_modules/
|
||||
node_modules/
|
||||
test/
|
||||
|
|
|
@ -4106,9 +4106,9 @@ checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
|
|||
|
||||
[[package]]
|
||||
name = "usage-lib"
|
||||
version = "0.7.4"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef8f6a44b06866b37810400ecc3ee80dd0354448c870a60d424d6ab364c7e50b"
|
||||
checksum = "4d2f461138354b775e96629ce474dad0f7b9996dd902db85665de06b8a2aaeda"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"heck 0.5.0",
|
||||
|
@ -4120,6 +4120,7 @@ dependencies = [
|
|||
"once_cell",
|
||||
"serde",
|
||||
"strum",
|
||||
"tera",
|
||||
"thiserror",
|
||||
"xx",
|
||||
]
|
||||
|
|
|
@ -116,7 +116,7 @@ toml = { version = "0.8", features = ["parse"] }
|
|||
toml_edit = { version = "0.22", features = ["parse"] }
|
||||
url = "2.5.0"
|
||||
#usage-lib = { path = "../usage/lib" }
|
||||
usage-lib = { version = "0.7.0", features = ["clap"] }
|
||||
usage-lib = { version = "0.8.0", features = ["clap", "docs"] }
|
||||
versions = { version = "6.2.0", features = ["serde"] }
|
||||
vfox = "0.1"
|
||||
walkdir = "2.5.0"
|
||||
|
|
|
@ -111,6 +111,9 @@ export const commands: { [key: string]: Command } = {
|
|||
"github-action": {
|
||||
hide: false,
|
||||
},
|
||||
"task-docs": {
|
||||
hide: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
"global": {
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
## `mise generate task-docs [OPTIONS]` <Badge type="warning" text="experimental" />
|
||||
|
||||
```text
|
||||
[experimental] Generate documentation for tasks in a project
|
||||
|
||||
Usage: generate task-docs [OPTIONS]
|
||||
|
||||
Options:
|
||||
-m, --multi
|
||||
render each task as a separate document, requires `--output` to be a directory
|
||||
|
||||
-i, --inject
|
||||
inserts the documentation into an existing file
|
||||
|
||||
This will look for a special comment, <!-- mise-tasks -->, and replace it with the generated documentation.
|
||||
It will replace everything between the comment and the next comment, <!-- /mise-tasks --> so it can be
|
||||
run multiple times on the same file to update the documentation.
|
||||
|
||||
-I, --index
|
||||
write only an index of tasks, intended for use with `--multi`
|
||||
|
||||
-o, --output <OUTPUT>
|
||||
writes the generated docs to a file/directory
|
||||
|
||||
Examples:
|
||||
|
||||
$ mise generate task-docs
|
||||
```
|
|
@ -550,6 +550,35 @@ Examples:
|
|||
$ git push # runs `mise run ci` on GitHub
|
||||
```
|
||||
|
||||
## `mise generate task-docs [OPTIONS]` <Badge type="warning" text="experimental" />
|
||||
|
||||
```text
|
||||
[experimental] Generate documentation for tasks in a project
|
||||
|
||||
Usage: generate task-docs [OPTIONS]
|
||||
|
||||
Options:
|
||||
-m, --multi
|
||||
render each task as a separate document, requires `--output` to be a directory
|
||||
|
||||
-i, --inject
|
||||
inserts the documentation into an existing file
|
||||
|
||||
This will look for a special comment, <!-- mise-tasks -->, and replace it with the generated documentation.
|
||||
It will replace everything between the comment and the next comment, <!-- /mise-tasks --> so it can be
|
||||
run multiple times on the same file to update the documentation.
|
||||
|
||||
-I, --index
|
||||
write only an index of tasks, intended for use with `--multi`
|
||||
|
||||
-o, --output <OUTPUT>
|
||||
writes the generated docs to a file/directory
|
||||
|
||||
Examples:
|
||||
|
||||
$ mise generate task-docs
|
||||
```
|
||||
|
||||
## `mise implode [OPTIONS]`
|
||||
|
||||
```text
|
||||
|
|
|
@ -28,8 +28,12 @@ If there are multiple commands, the args are only passed to the last command.
|
|||
:::tip
|
||||
You can define arguments/flags for tasks which will provide validation, parsing, autocomplete, and documentation.
|
||||
|
||||
* [Arguments in File Tasks](/tasks/file-tasks.html#arguments)
|
||||
* [Arguments in TOML Tasks](/tasks/toml-tasks.html#arguments)
|
||||
* [Arguments in File Tasks](/tasks/file-tasks#arguments)
|
||||
* [Arguments in TOML Tasks](/tasks/toml-tasks#arguments)
|
||||
|
||||
Autocomplete will work automatically for tasks if the `usage` CLI is installed and mise completions are working.
|
||||
|
||||
Markdown documentation can be generated with [`mise generate task-docs`](/cli/generate/task-docs).
|
||||
:::
|
||||
|
||||
Multiple tasks/arguments can be separated with this `:::` delimiter:
|
||||
|
|
|
@ -348,7 +348,7 @@ The "--" separates runtimes from the commands to pass along to the subprocess."#
|
|||
arg "[COMMAND]..." help="Command string to execute (same as --command)" var=true
|
||||
}
|
||||
cmd "generate" subcommand_required=true help="[experimental] Generate files for various tools/services" {
|
||||
alias "gen"
|
||||
alias "g"
|
||||
cmd "git-pre-commit" help="[experimental] Generate a git pre-commit hook" {
|
||||
alias "pre-commit"
|
||||
long_help r"[experimental] Generate a git pre-commit hook
|
||||
|
@ -387,9 +387,22 @@ when you push changes to your repository."
|
|||
}
|
||||
flag "-w --write" help="write to .github/workflows/$name.yml"
|
||||
}
|
||||
cmd "task-docs" help="[experimental] Generate documentation for tasks in a project" {
|
||||
after_long_help r"Examples:
|
||||
|
||||
$ mise generate task-docs
|
||||
"
|
||||
flag "-m --multi" help="render each task as a separate document, requires `--output` to be a directory"
|
||||
flag "-i --inject" help="inserts the documentation into an existing file" {
|
||||
long_help "inserts the documentation into an existing file\n\nThis will look for a special comment, <!-- mise-tasks -->, and replace it with the generated documentation.\nIt will replace everything between the comment and the next comment, <!-- /mise-tasks --> so it can be\nrun multiple times on the same file to update the documentation."
|
||||
}
|
||||
flag "-I --index" help="write only an index of tasks, intended for use with `--multi`"
|
||||
flag "-o --output" help="writes the generated docs to a file/directory" {
|
||||
arg "<OUTPUT>"
|
||||
}
|
||||
}
|
||||
}
|
||||
cmd "global" hide=true help="Sets/gets the global tool version(s)" {
|
||||
alias "g" hide=true
|
||||
long_help r"Sets/gets the global tool version(s)
|
||||
|
||||
Displays the contents of global config after writing.
|
||||
|
|
|
@ -2,10 +2,11 @@ use clap::Subcommand;
|
|||
|
||||
mod git_pre_commit;
|
||||
mod github_action;
|
||||
mod task_docs;
|
||||
|
||||
/// [experimental] Generate files for various tools/services
|
||||
#[derive(Debug, clap::Args)]
|
||||
#[clap(visible_alias = "gen")]
|
||||
#[clap(visible_alias = "g")]
|
||||
pub struct Generate {
|
||||
#[clap(subcommand)]
|
||||
command: Commands,
|
||||
|
@ -15,6 +16,7 @@ pub struct Generate {
|
|||
enum Commands {
|
||||
GitPreCommit(git_pre_commit::GitPreCommit),
|
||||
GithubAction(github_action::GithubAction),
|
||||
TaskDocs(task_docs::TaskDocs),
|
||||
}
|
||||
|
||||
impl Commands {
|
||||
|
@ -22,6 +24,7 @@ impl Commands {
|
|||
match self {
|
||||
Self::GitPreCommit(cmd) => cmd.run(),
|
||||
Self::GithubAction(cmd) => cmd.run(),
|
||||
Self::TaskDocs(cmd) => cmd.run(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
source: src/cli/generate/task_docs.rs
|
||||
expression: output
|
||||
---
|
||||
# `filetask`
|
||||
|
||||
## Flag `--user <user>`
|
||||
|
||||
The user to run as
|
|
@ -0,0 +1,95 @@
|
|||
use crate::config::settings::SETTINGS;
|
||||
use crate::config::CONFIG;
|
||||
use crate::{dirs, file};
|
||||
use std::path::PathBuf;
|
||||
|
||||
/// [experimental] Generate documentation for tasks in a project
|
||||
#[derive(Debug, clap::Args)]
|
||||
#[clap(verbatim_doc_comment, after_long_help = AFTER_LONG_HELP)]
|
||||
pub struct TaskDocs {
|
||||
/// render each task as a separate document, requires `--output` to be a directory
|
||||
#[clap(long, short, verbatim_doc_comment)]
|
||||
multi: bool,
|
||||
/// inserts the documentation into an existing file
|
||||
///
|
||||
/// This will look for a special comment, <!-- mise-tasks -->, and replace it with the generated documentation.
|
||||
/// It will replace everything between the comment and the next comment, <!-- /mise-tasks --> so it can be
|
||||
/// run multiple times on the same file to update the documentation.
|
||||
#[clap(long, short, verbatim_doc_comment)]
|
||||
inject: bool,
|
||||
/// write only an index of tasks, intended for use with `--multi`
|
||||
#[clap(long, short = 'I', verbatim_doc_comment)]
|
||||
index: bool,
|
||||
/// writes the generated docs to a file/directory
|
||||
#[clap(long, short, verbatim_doc_comment)]
|
||||
output: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl TaskDocs {
|
||||
pub fn run(self) -> eyre::Result<()> {
|
||||
SETTINGS.ensure_experimental("generate task-docs")?;
|
||||
let tasks = CONFIG.load_tasks_in_dir(dirs::CWD.as_ref().unwrap())?;
|
||||
let mut out = vec![];
|
||||
for task in &tasks {
|
||||
out.push(task.render_markdown()?);
|
||||
}
|
||||
if let Some(output) = &self.output {
|
||||
if self.multi {
|
||||
if output.is_dir() {
|
||||
for (i, task) in tasks.iter().enumerate() {
|
||||
let path = output.join(format!("task-{}.md", i));
|
||||
file::write(&path, &task.render_markdown()?)?;
|
||||
}
|
||||
} else {
|
||||
return Err(eyre::eyre!(
|
||||
"`--output` must be a directory when `--multi` is set"
|
||||
));
|
||||
}
|
||||
} else {
|
||||
let mut doc = String::new();
|
||||
for task in out {
|
||||
doc.push_str(&task);
|
||||
doc.push_str("\n\n");
|
||||
}
|
||||
if self.inject {
|
||||
let mut contents = file::read_to_string(output)?;
|
||||
let start = contents.find("<!-- mise-tasks -->").unwrap_or(0);
|
||||
let end = contents[start..]
|
||||
.find("<!-- /mise-tasks -->")
|
||||
.unwrap_or(contents.len());
|
||||
contents.replace_range(start..end, &doc);
|
||||
file::write(output, &contents)?;
|
||||
} else {
|
||||
file::write(output, &doc)?;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for task in out {
|
||||
miseprintln!("{}", task);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
static AFTER_LONG_HELP: &str = color_print::cstr!(
|
||||
r#"<bold><underline>Examples:</underline></bold>
|
||||
|
||||
$ <bold>mise generate task-docs</bold>
|
||||
"#
|
||||
);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use test_log::test;
|
||||
|
||||
use crate::test::{cleanup, reset, setup_git_repo};
|
||||
|
||||
#[test]
|
||||
fn test_task_docs() {
|
||||
reset();
|
||||
setup_git_repo();
|
||||
assert_cli_snapshot!("generate", "task-docs");
|
||||
cleanup();
|
||||
}
|
||||
}
|
|
@ -15,7 +15,7 @@ use crate::config::Settings;
|
|||
///
|
||||
/// Use `mise local` to set a tool version locally in the current directory.
|
||||
#[derive(Debug, clap::Args)]
|
||||
#[clap(verbatim_doc_comment, hide = true, alias = "g", after_long_help = AFTER_LONG_HELP)]
|
||||
#[clap(verbatim_doc_comment, hide = true, after_long_help = AFTER_LONG_HELP)]
|
||||
pub struct Global {
|
||||
/// Tool(s) to add to .tool-versions
|
||||
/// e.g.: node@20
|
||||
|
|
|
@ -255,7 +255,7 @@ impl Config {
|
|||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
fn load_tasks_in_dir(&self, dir: &Path) -> Result<Vec<Task>> {
|
||||
pub fn load_tasks_in_dir(&self, dir: &Path) -> Result<Vec<Task>> {
|
||||
let configs = self.configs_at_root(dir);
|
||||
let config_tasks = configs
|
||||
.par_iter()
|
||||
|
|
|
@ -220,6 +220,11 @@ impl Task {
|
|||
.collect())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_markdown(&self) -> Result<String> {
|
||||
let (spec, _) = self.parse_usage_spec(None)?;
|
||||
Ok(spec.render_markdown()?)
|
||||
}
|
||||
}
|
||||
|
||||
fn name_from_path(root: impl AsRef<Path>, path: impl AsRef<Path>) -> Result<String> {
|
||||
|
|
Loading…
Reference in New Issue