Fix submodule recipe listing indentation (#2063)

This commit is contained in:
Casey Rodarmor 2024-05-20 00:25:18 -07:00 committed by GitHub
parent 9e658fba39
commit d6b2e6bad2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 135 additions and 88 deletions

View File

@ -29,13 +29,14 @@ pub(crate) use {
output::output, output_error::OutputError, parameter::Parameter, parameter_kind::ParameterKind,
parser::Parser, platform::Platform, platform_interface::PlatformInterface, position::Position,
positional::Positional, ran::Ran, range_ext::RangeExt, recipe::Recipe,
recipe_context::RecipeContext, recipe_resolver::RecipeResolver, scope::Scope, search::Search,
search_config::SearchConfig, search_error::SearchError, set::Set, setting::Setting,
settings::Settings, shebang::Shebang, shell::Shell, show_whitespace::ShowWhitespace,
source::Source, string_kind::StringKind, string_literal::StringLiteral, subcommand::Subcommand,
suggestion::Suggestion, table::Table, thunk::Thunk, token::Token, token_kind::TokenKind,
unresolved_dependency::UnresolvedDependency, unresolved_recipe::UnresolvedRecipe,
use_color::UseColor, variables::Variables, verbosity::Verbosity, warning::Warning,
recipe_context::RecipeContext, recipe_resolver::RecipeResolver,
recipe_signature::RecipeSignature, scope::Scope, search::Search, search_config::SearchConfig,
search_error::SearchError, set::Set, setting::Setting, settings::Settings, shebang::Shebang,
shell::Shell, show_whitespace::ShowWhitespace, source::Source, string_kind::StringKind,
string_literal::StringLiteral, subcommand::Subcommand, suggestion::Suggestion, table::Table,
thunk::Thunk, token::Token, token_kind::TokenKind, unresolved_dependency::UnresolvedDependency,
unresolved_recipe::UnresolvedRecipe, use_color::UseColor, variables::Variables,
verbosity::Verbosity, warning::Warning,
},
std::{
borrow::Cow,
@ -168,6 +169,7 @@ mod range_ext;
mod recipe;
mod recipe_context;
mod recipe_resolver;
mod recipe_signature;
mod run;
mod scope;
mod search;

16
src/recipe_signature.rs Normal file
View File

@ -0,0 +1,16 @@
use super::*;
pub(crate) struct RecipeSignature<'a> {
pub(crate) name: &'a str,
pub(crate) recipe: &'a Recipe<'a>,
}
impl<'a> ColorDisplay for RecipeSignature<'a> {
fn fmt(&self, f: &mut Formatter, color: Color) -> fmt::Result {
write!(f, "{}", self.name)?;
for parameter in &self.recipe.parameters {
write!(f, " {}", parameter.color_display(color))?;
}
Ok(())
}
}

View File

@ -466,8 +466,12 @@ impl Subcommand {
fn list(config: &Config, level: usize, justfile: &Justfile) {
const MAX_WIDTH: usize = 50;
if level == 0 {
print!("{}", config.list_heading);
}
// Construct a target to alias map.
let mut recipe_aliases: BTreeMap<&str, Vec<&str>> = BTreeMap::new();
let mut recipe_aliases = BTreeMap::<&str, Vec<&str>>::new();
if !config.no_aliases {
for alias in justfile.aliases.values() {
if alias.is_private() {
@ -483,7 +487,7 @@ impl Subcommand {
}
}
let mut line_widths: BTreeMap<&str, usize> = BTreeMap::new();
let mut line_widths = BTreeMap::<&str, usize>::new();
for (name, recipe) in &justfile.recipes {
if !recipe.is_public() {
@ -491,26 +495,24 @@ impl Subcommand {
}
for name in iter::once(name).chain(recipe_aliases.get(name).unwrap_or(&Vec::new())) {
let mut line_width = UnicodeWidthStr::width(*name);
for parameter in &recipe.parameters {
line_width += UnicodeWidthStr::width(
format!(" {}", parameter.color_display(Color::never())).as_str(),
);
}
if line_width <= MAX_WIDTH {
line_widths.insert(name, line_width);
}
line_widths.insert(
name,
UnicodeWidthStr::width(
RecipeSignature { name, recipe }
.color_display(Color::never())
.to_string()
.as_str(),
),
);
}
}
let max_line_width = line_widths.values().copied().max().unwrap_or_default();
let doc_color = config.color.stdout().doc();
if level == 0 {
print!("{}", config.list_heading);
}
let max_line_width = line_widths
.values()
.filter(|line_width| **line_width <= MAX_WIDTH)
.copied()
.max()
.unwrap_or_default();
for recipe in justfile.public_recipes(config.unsorted) {
let name = recipe.name();
@ -519,10 +521,11 @@ impl Subcommand {
.chain(recipe_aliases.get(name).unwrap_or(&Vec::new()))
.enumerate()
{
print!("{}{name}", config.list_prefix.repeat(level + 1));
for parameter in &recipe.parameters {
print!(" {}", parameter.color_display(config.color.stdout()));
}
print!(
"{}{}",
config.list_prefix.repeat(level + 1),
RecipeSignature { name, recipe }.color_display(config.color.stdout())
);
let doc = match (i, recipe.doc) {
(0, Some(doc)) => Some(Cow::Borrowed(doc)),
@ -534,10 +537,9 @@ impl Subcommand {
print!(
" {:padding$}{} {}",
"",
doc_color.paint("#"),
doc_color.paint(&doc),
padding = max_line_width
.saturating_sub(line_widths.get(name).copied().unwrap_or(max_line_width))
config.color.stdout().doc().paint("#"),
config.color.stdout().doc().paint(&doc),
padding = max_line_width.saturating_sub(line_widths[name]),
);
}
@ -546,7 +548,7 @@ impl Subcommand {
}
for (name, module) in &justfile.modules {
println!(" {name}:");
println!("{}{name}:", config.list_prefix.repeat(level + 1));
Self::list(config, level + 1, module);
}
}

View File

@ -69,6 +69,7 @@ mod interrupts;
mod invocation_directory;
mod json;
mod line_prefixes;
mod list;
mod man;
mod misc;
mod modules;

79
tests/list.rs Normal file
View File

@ -0,0 +1,79 @@
use super::*;
#[test]
fn list_displays_recipes_in_submodules() {
Test::new()
.write("foo.just", "bar:\n @echo FOO")
.justfile(
"
mod foo
",
)
.test_round_trip(false)
.arg("--unstable")
.arg("--list")
.stdout(
"
Available recipes:
foo:
bar
",
)
.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)
.arg("--unstable")
.arg("--list")
.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)
.arg("--unstable")
.arg("--list")
.stdout(
"
Available recipes:
foo:
bar:
baz
",
)
.run();
}

View File

@ -512,28 +512,6 @@ fn missing_optional_modules_do_not_conflict() {
.run();
}
#[test]
fn list_displays_recipes_in_submodules() {
Test::new()
.write("foo.just", "bar:\n @echo FOO")
.justfile(
"
mod foo
",
)
.test_round_trip(false)
.arg("--unstable")
.arg("--list")
.stdout(
"
Available recipes:
foo:
bar
",
)
.run();
}
#[test]
fn root_dotenv_is_available_to_submodules() {
Test::new()
@ -695,37 +673,6 @@ fn module_paths_beginning_with_tilde_are_expanded_to_homdir() {
.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)
.arg("--unstable")
.arg("--list")
.stdout(
"Available recipes:
foo:
foo # foos
",
)
.run();
}
#[test]
fn recipes_with_same_name_are_both_run() {
Test::new()