Allow listing recipes in submodules with --list-submodules
(#2113)
This commit is contained in:
parent
d2b10e04d3
commit
d38c1add13
@ -30,7 +30,7 @@ _just() {
|
||||
|
||||
case "${cmd}" in
|
||||
just)
|
||||
opts="-n -f -q -u -v -d -c -e -l -s -E -g -h -V --check --chooser --color --command-color --yes --dry-run --dump-format --highlight --list-heading --list-prefix --no-aliases --no-deps --no-dotenv --no-highlight --justfile --quiet --set --shell --shell-arg --shell-command --clear-shell-args --unsorted --unstable --verbose --working-directory --changelog --choose --command --completions --dump --edit --evaluate --fmt --init --list --groups --man --show --summary --variables --dotenv-filename --dotenv-path --global-justfile --timestamp --timestamp-format --help --version [ARGUMENTS]..."
|
||||
opts="-n -f -q -u -v -d -c -e -l -s -E -g -h -V --check --chooser --color --command-color --yes --dry-run --dump-format --highlight --list-heading --list-prefix --list-submodules --no-aliases --no-deps --no-dotenv --no-highlight --justfile --quiet --set --shell --shell-arg --shell-command --clear-shell-args --unsorted --unstable --verbose --working-directory --changelog --choose --command --completions --dump --edit --evaluate --fmt --init --list --groups --man --show --summary --variables --dotenv-filename --dotenv-path --global-justfile --timestamp --timestamp-format --help --version [ARGUMENTS]..."
|
||||
if [[ ${cur} == -* ]] ; then
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
||||
return 0
|
||||
|
@ -46,6 +46,7 @@ set edit:completion:arg-completer[just] = {|@words|
|
||||
cand -n 'Print what just would do without doing it'
|
||||
cand --dry-run 'Print what just would do without doing it'
|
||||
cand --highlight 'Highlight echoed recipe lines in bold'
|
||||
cand --list-submodules 'List recipes in submodules'
|
||||
cand --no-aliases 'Don''t show aliases in list'
|
||||
cand --no-deps 'Don''t run recipe dependencies'
|
||||
cand --no-dotenv 'Don''t load `.env` file'
|
||||
|
@ -57,6 +57,7 @@ complete -c just -l check -d 'Run `--fmt` in \'check\' mode. Exits with 0 if jus
|
||||
complete -c just -l yes -d 'Automatically confirm all recipes.'
|
||||
complete -c just -s n -l dry-run -d 'Print what just would do without doing it'
|
||||
complete -c just -l highlight -d 'Highlight echoed recipe lines in bold'
|
||||
complete -c just -l list-submodules -d 'List recipes in submodules'
|
||||
complete -c just -l no-aliases -d 'Don\'t show aliases in list'
|
||||
complete -c just -l no-deps -d 'Don\'t run recipe dependencies'
|
||||
complete -c just -l no-dotenv -d 'Don\'t load `.env` file'
|
||||
|
@ -49,6 +49,7 @@ Register-ArgumentCompleter -Native -CommandName 'just' -ScriptBlock {
|
||||
[CompletionResult]::new('-n', 'n', [CompletionResultType]::ParameterName, 'Print what just would do without doing it')
|
||||
[CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'Print what just would do without doing it')
|
||||
[CompletionResult]::new('--highlight', 'highlight', [CompletionResultType]::ParameterName, 'Highlight echoed recipe lines in bold')
|
||||
[CompletionResult]::new('--list-submodules', 'list-submodules', [CompletionResultType]::ParameterName, 'List recipes in submodules')
|
||||
[CompletionResult]::new('--no-aliases', 'no-aliases', [CompletionResultType]::ParameterName, 'Don''t show aliases in list')
|
||||
[CompletionResult]::new('--no-deps', 'no-deps', [CompletionResultType]::ParameterName, 'Don''t run recipe dependencies')
|
||||
[CompletionResult]::new('--no-dotenv', 'no-dotenv', [CompletionResultType]::ParameterName, 'Don''t load `.env` file')
|
||||
|
@ -44,6 +44,7 @@ _just() {
|
||||
'(-q --quiet)-n[Print what just would do without doing it]' \
|
||||
'(-q --quiet)--dry-run[Print what just would do without doing it]' \
|
||||
'--highlight[Highlight echoed recipe lines in bold]' \
|
||||
'--list-submodules[List recipes in submodules]' \
|
||||
'--no-aliases[Don'\''t show aliases in list]' \
|
||||
'--no-deps[Don'\''t run recipe dependencies]' \
|
||||
'--no-dotenv[Don'\''t load \`.env\` file]' \
|
||||
|
@ -32,6 +32,7 @@ pub(crate) struct Config {
|
||||
pub(crate) invocation_directory: PathBuf,
|
||||
pub(crate) list_heading: String,
|
||||
pub(crate) list_prefix: String,
|
||||
pub(crate) list_submodules: bool,
|
||||
pub(crate) load_dotenv: bool,
|
||||
pub(crate) no_aliases: bool,
|
||||
pub(crate) no_dependencies: bool,
|
||||
@ -97,11 +98,12 @@ mod arg {
|
||||
pub(crate) const DOTENV_PATH: &str = "DOTENV-PATH";
|
||||
pub(crate) const DRY_RUN: &str = "DRY-RUN";
|
||||
pub(crate) const DUMP_FORMAT: &str = "DUMP-FORMAT";
|
||||
pub(crate) const GLOBAL_JUSTFILE: &str = "GLOBAL_JUSTFILE";
|
||||
pub(crate) const GLOBAL_JUSTFILE: &str = "GLOBAL-JUSTFILE";
|
||||
pub(crate) const HIGHLIGHT: &str = "HIGHLIGHT";
|
||||
pub(crate) const JUSTFILE: &str = "JUSTFILE";
|
||||
pub(crate) const LIST_HEADING: &str = "LIST-HEADING";
|
||||
pub(crate) const LIST_PREFIX: &str = "LIST-PREFIX";
|
||||
pub(crate) const LIST_SUBMODULES: &str = "LIST-SUBMODULES";
|
||||
pub(crate) const NO_ALIASES: &str = "NO-ALIASES";
|
||||
pub(crate) const NO_DEPS: &str = "NO-DEPS";
|
||||
pub(crate) const NO_DOTENV: &str = "NO-DOTENV";
|
||||
@ -112,7 +114,7 @@ mod arg {
|
||||
pub(crate) const SHELL_ARG: &str = "SHELL-ARG";
|
||||
pub(crate) const SHELL_COMMAND: &str = "SHELL-COMMAND";
|
||||
pub(crate) const TIMESTAMP: &str = "TIMESTAMP";
|
||||
pub(crate) const TIMESTAMP_FORMAT: &str = "TIMESTAMP_FORMAT";
|
||||
pub(crate) const TIMESTAMP_FORMAT: &str = "TIMESTAMP-FORMAT";
|
||||
pub(crate) const UNSORTED: &str = "UNSORTED";
|
||||
pub(crate) const UNSTABLE: &str = "UNSTABLE";
|
||||
pub(crate) const VERBOSE: &str = "VERBOSE";
|
||||
@ -236,6 +238,13 @@ impl Config {
|
||||
.value_name("TEXT")
|
||||
.action(ArgAction::Set),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(arg::LIST_SUBMODULES)
|
||||
.long("list-submodules")
|
||||
.help("List recipes in submodules")
|
||||
.action(ArgAction::SetTrue)
|
||||
.env("JUST_LIST_SUBMODULES"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(arg::NO_ALIASES)
|
||||
.long("no-aliases")
|
||||
@ -754,6 +763,7 @@ impl Config {
|
||||
list_prefix: matches
|
||||
.get_one::<String>(arg::LIST_PREFIX)
|
||||
.map_or_else(|| " ".into(), Into::into),
|
||||
list_submodules: matches.get_flag(arg::LIST_SUBMODULES),
|
||||
load_dotenv: !matches.get_flag(arg::NO_DOTENV),
|
||||
no_aliases: matches.get_flag(arg::NO_ALIASES),
|
||||
no_dependencies: matches.get_flag(arg::NO_DEPS),
|
||||
|
@ -488,6 +488,12 @@ impl Subcommand {
|
||||
.ok_or_else(|| Error::UnknownSubmodule { path: path.clone() })?;
|
||||
}
|
||||
|
||||
Self::list_module(config, module, 0);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn list_module(config: &Config, module: &Justfile, depth: usize) {
|
||||
let aliases = if config.no_aliases {
|
||||
BTreeMap::new()
|
||||
} else {
|
||||
@ -532,7 +538,11 @@ impl Subcommand {
|
||||
.max()
|
||||
.unwrap_or(0);
|
||||
|
||||
print!("{}", config.list_heading);
|
||||
let list_prefix = config.list_prefix.repeat(depth + 1);
|
||||
|
||||
if depth == 0 {
|
||||
print!("{}", config.list_heading);
|
||||
}
|
||||
|
||||
let groups = {
|
||||
let mut groups = BTreeMap::<Option<String>, Vec<&Recipe>>::new();
|
||||
@ -557,7 +567,7 @@ impl Subcommand {
|
||||
let no_groups = groups.contains_key(&None) && groups.len() == 1;
|
||||
|
||||
if !no_groups {
|
||||
print!("{}", config.list_prefix);
|
||||
print!("{list_prefix}");
|
||||
if let Some(group_name) = group {
|
||||
println!("[{group_name}]");
|
||||
} else {
|
||||
@ -580,8 +590,7 @@ impl Subcommand {
|
||||
if doc.lines().count() > 1 {
|
||||
for line in doc.lines() {
|
||||
println!(
|
||||
"{}{} {}",
|
||||
config.list_prefix,
|
||||
"{list_prefix}{} {}",
|
||||
config.color.stdout().doc().paint("#"),
|
||||
config.color.stdout().doc().paint(line),
|
||||
);
|
||||
@ -590,8 +599,7 @@ impl Subcommand {
|
||||
}
|
||||
|
||||
print!(
|
||||
"{}{}",
|
||||
config.list_prefix,
|
||||
"{list_prefix}{}",
|
||||
RecipeSignature { name, recipe }.color_display(config.color.stdout())
|
||||
);
|
||||
|
||||
@ -611,11 +619,21 @@ impl Subcommand {
|
||||
}
|
||||
}
|
||||
|
||||
for submodule in module.modules(config) {
|
||||
println!("{}{} ...", config.list_prefix, submodule.name(),);
|
||||
}
|
||||
if config.list_submodules {
|
||||
for (i, submodule) in module.modules(config).into_iter().enumerate() {
|
||||
if i + groups.len() > 0 {
|
||||
println!();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
println!("{list_prefix}{}:", submodule.name());
|
||||
|
||||
Self::list_module(config, submodule, depth + 1);
|
||||
}
|
||||
} else {
|
||||
for submodule in module.modules(config) {
|
||||
println!("{list_prefix}{} ...", submodule.name(),);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn show<'src>(
|
||||
|
130
tests/list.rs
130
tests/list.rs
@ -223,3 +223,133 @@ fn list_unknown_submodule() {
|
||||
.status(1)
|
||||
.run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_with_groups_in_modules() {
|
||||
Test::new()
|
||||
.justfile(
|
||||
"
|
||||
[group('FOO')]
|
||||
foo:
|
||||
|
||||
mod bar
|
||||
",
|
||||
)
|
||||
.write("bar.just", "[group('BAZ')]\nbaz:")
|
||||
.test_round_trip(false)
|
||||
.args(["--unstable", "--list", "--list-submodules"])
|
||||
.stdout(
|
||||
"
|
||||
Available recipes:
|
||||
[FOO]
|
||||
foo
|
||||
|
||||
bar:
|
||||
[BAZ]
|
||||
baz
|
||||
",
|
||||
)
|
||||
.run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_displays_recipes_in_submodules() {
|
||||
Test::new()
|
||||
.write("foo.just", "bar:\n @echo FOO")
|
||||
.justfile(
|
||||
"
|
||||
mod foo
|
||||
",
|
||||
)
|
||||
.test_round_trip(false)
|
||||
.args(["--unstable", "--list", "--list-submodules"])
|
||||
.stdout(
|
||||
"
|
||||
Available recipes:
|
||||
foo:
|
||||
bar
|
||||
",
|
||||
)
|
||||
.run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn modules_are_space_separated_in_output() {
|
||||
Test::new()
|
||||
.write("foo.just", "foo:")
|
||||
.write("bar.just", "bar:")
|
||||
.justfile(
|
||||
"
|
||||
mod foo
|
||||
|
||||
mod bar
|
||||
",
|
||||
)
|
||||
.test_round_trip(false)
|
||||
.args(["--unstable", "--list", "--list-submodules"])
|
||||
.stdout(
|
||||
"
|
||||
Available recipes:
|
||||
bar:
|
||||
bar
|
||||
|
||||
foo:
|
||||
foo
|
||||
",
|
||||
)
|
||||
.run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn module_recipe_list_alignment_ignores_private_recipes() {
|
||||
Test::new()
|
||||
.write(
|
||||
"foo.just",
|
||||
"
|
||||
# foos
|
||||
foo:
|
||||
@echo FOO
|
||||
|
||||
[private]
|
||||
barbarbar:
|
||||
@echo BAR
|
||||
|
||||
@_bazbazbaz:
|
||||
@echo BAZ
|
||||
",
|
||||
)
|
||||
.justfile("mod foo")
|
||||
.test_round_trip(false)
|
||||
.args(["--unstable", "--list", "--list-submodules"])
|
||||
.stdout(
|
||||
"
|
||||
Available recipes:
|
||||
foo:
|
||||
foo # foos
|
||||
",
|
||||
)
|
||||
.run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn nested_modules_are_properly_indented() {
|
||||
Test::new()
|
||||
.write("foo.just", "mod bar")
|
||||
.write("bar.just", "baz:\n @echo FOO")
|
||||
.justfile(
|
||||
"
|
||||
mod foo
|
||||
",
|
||||
)
|
||||
.test_round_trip(false)
|
||||
.args(["--unstable", "--list", "--list-submodules"])
|
||||
.stdout(
|
||||
"
|
||||
Available recipes:
|
||||
foo:
|
||||
bar:
|
||||
baz
|
||||
",
|
||||
)
|
||||
.run();
|
||||
}
|
||||
|
@ -258,7 +258,7 @@ impl Test {
|
||||
}
|
||||
}
|
||||
|
||||
if !compare("status", output.status.code().unwrap(), self.status)
|
||||
if !compare("status", output.status.code(), Some(self.status))
|
||||
| (self.stdout_regex.is_none() && !compare("stdout", output_stdout, &stdout))
|
||||
| (self.stderr_regex.is_none() && !compare("stderr", output_stderr, &stderr))
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user