List groups in source order with just --groups --unsorted (#2160)

This commit is contained in:
Casey Rodarmor 2024-06-14 13:35:03 -07:00 committed by GitHub
parent 5f91b37c82
commit b05a75d168
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 124 additions and 31 deletions

View File

@ -1861,6 +1861,8 @@ Recipe groups:
rust recipes
```
Use `just --groups --unsorted` to print groups in their justfile order.
### Command Evaluation Using Backticks
Backticks can be used to store the result of commands:

View File

@ -4,7 +4,7 @@ use super::*;
pub(crate) type Assignment<'src> = Binding<'src, Expression<'src>>;
impl<'src> Display for Assignment<'src> {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
if self.export {
write!(f, "export ")?;
}

View File

@ -12,7 +12,7 @@ pub(crate) struct Ast<'src> {
}
impl<'src> Display for Ast<'src> {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
let mut iter = self.items.iter().peekable();
while let Some(item) = iter.next() {

View File

@ -110,7 +110,7 @@ impl<'src> Attribute<'src> {
}
impl<'src> Display for Attribute<'src> {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}", self.name())?;
if let Some(argument) = self.argument() {
write!(f, "({argument})")?;

View File

@ -28,7 +28,7 @@ fn capitalize(s: &str) -> String {
}
impl Display for CompileError<'_> {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
use CompileErrorKind::*;
match &*self.kind {

View File

@ -8,7 +8,7 @@ pub(crate) struct Condition<'src> {
}
impl<'src> Display for Condition<'src> {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{} {} {}", self.lhs, self.operator, self.rhs)
}
}

View File

@ -8,7 +8,7 @@ pub(crate) struct Dependency<'src> {
}
impl<'src> Display for Dependency<'src> {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
if self.arguments.is_empty() {
write!(f, "{}", self.recipe.name())
} else {

View File

@ -51,7 +51,7 @@ impl<'src> Expression<'src> {
}
impl<'src> Display for Expression<'src> {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
Self::Assert { condition, error } => write!(f, "assert({condition}, {error})"),
Self::Backtick { token, .. } => write!(f, "{}", token.lexeme()),

View File

@ -365,13 +365,13 @@ impl<'src> Justfile<'src> {
modules
}
pub(crate) fn public_recipes(&self, config: &Config) -> Vec<&Recipe<'src, Dependency>> {
pub(crate) fn public_recipes(&self, config: &Config) -> Vec<&Recipe> {
let mut recipes = self
.recipes
.values()
.map(AsRef::as_ref)
.filter(|recipe| recipe.is_public())
.collect::<Vec<&Recipe<Dependency>>>();
.collect::<Vec<&Recipe>>();
if config.unsorted {
recipes.sort_by_key(|recipe| (&recipe.import_offsets, recipe.name.offset));
@ -380,19 +380,33 @@ impl<'src> Justfile<'src> {
recipes
}
pub(crate) fn public_groups(&self) -> BTreeSet<String> {
self
.recipes
.values()
.map(AsRef::as_ref)
.filter(|recipe| recipe.is_public())
.flat_map(Recipe::groups)
.collect()
pub(crate) fn public_groups(&self, config: &Config) -> Vec<String> {
let mut groups = Vec::new();
for recipe in self.recipes.values() {
if recipe.is_public() {
for group in recipe.groups() {
groups.push((&recipe.import_offsets, recipe.name.offset, group));
}
}
}
if config.unsorted {
groups.sort();
} else {
groups.sort_by(|(_, _, a), (_, _, b)| a.cmp(b));
}
let mut seen = HashSet::new();
groups.retain(|(_, _, group)| seen.insert(group.clone()));
groups.into_iter().map(|(_, _, group)| group).collect()
}
}
impl<'src> ColorDisplay for Justfile<'src> {
fn fmt(&self, f: &mut Formatter, color: Color) -> Result<(), fmt::Error> {
fn fmt(&self, f: &mut Formatter, color: Color) -> fmt::Result {
let mut items = self.recipes.len() + self.assignments.len() + self.aliases.len();
for (name, assignment) in &self.assignments {
if assignment.export {

View File

@ -15,7 +15,7 @@ pub(crate) enum OutputError {
}
impl Display for OutputError {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match *self {
Self::Code(code) => write!(f, "Process exited with status code {code}"),
Self::Io(ref io_error) => write!(f, "Error executing process: {io_error}"),

View File

@ -14,7 +14,7 @@ pub(crate) struct Parameter<'src> {
}
impl<'src> ColorDisplay for Parameter<'src> {
fn fmt(&self, f: &mut Formatter, color: Color) -> Result<(), fmt::Error> {
fn fmt(&self, f: &mut Formatter, color: Color) -> fmt::Result {
if let Some(prefix) = self.kind.prefix() {
write!(f, "{}", color.annotation().paint(prefix))?;
}

View File

@ -476,7 +476,7 @@ impl<'src, D> Recipe<'src, D> {
}
impl<'src, D: Display> ColorDisplay for Recipe<'src, D> {
fn fmt(&self, f: &mut Formatter, color: Color) -> Result<(), fmt::Error> {
fn fmt(&self, f: &mut Formatter, color: Color) -> fmt::Result {
if let Some(doc) = self.doc {
writeln!(f, "# {doc}")?;
}

View File

@ -13,7 +13,7 @@ impl<'src> Keyed<'src> for Set<'src> {
}
impl<'src> Display for Set<'src> {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "set {} := {}", self.name, self.value)
}
}

View File

@ -20,7 +20,7 @@ pub(crate) enum Setting<'src> {
}
impl<'src> Display for Setting<'src> {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
Self::AllowDuplicateRecipes(value)
| Self::AllowDuplicateVariables(value)

View File

@ -7,7 +7,7 @@ pub(crate) struct Shell<'src> {
}
impl<'src> Display for Shell<'src> {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "[{}", self.command)?;
for argument in &self.arguments {

View File

@ -97,7 +97,7 @@ impl Subcommand {
fn groups(config: &Config, justfile: &Justfile) {
println!("Recipe groups:");
for group in justfile.public_groups() {
for group in justfile.public_groups(config) {
println!("{}{group}", config.list_prefix);
}
}
@ -215,7 +215,7 @@ impl Subcommand {
overrides: &BTreeMap<String, String>,
chooser: Option<&str>,
) -> Result<(), Error<'src>> {
let mut recipes = Vec::<&Recipe<Dependency>>::new();
let mut recipes = Vec::<&Recipe>::new();
let mut stack = vec![justfile];
while let Some(module) = stack.pop() {
recipes.extend(

View File

@ -39,7 +39,7 @@ pub(crate) enum TokenKind {
}
impl Display for TokenKind {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
use TokenKind::*;
write!(
f,

View File

@ -7,7 +7,7 @@ pub(crate) struct UnresolvedDependency<'src> {
}
impl<'src> Display for UnresolvedDependency<'src> {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
if self.arguments.is_empty() {
write!(f, "{}", self.recipe)
} else {

View File

@ -157,12 +157,89 @@ fn list_groups_with_shorthand_syntax() {
bar:
",
)
.args(["--groups", "--list-prefix", "..."])
.arg("--groups")
.stdout(
"
Recipe groups:
...A
...B
A
B
",
)
.run();
}
#[test]
fn list_groups_unsorted() {
Test::new()
.justfile(
"
[group: 'Z']
baz:
[group: 'B']
foo:
[group: 'A', group: 'B']
bar:
",
)
.args(["--groups", "--unsorted"])
.stdout(
"
Recipe groups:
Z
B
A
",
)
.run();
}
#[test]
fn list_groups_private_unsorted() {
Test::new()
.justfile(
"
[private]
[group: 'A']
foo:
[group: 'B']
bar:
[group: 'A']
baz:
",
)
.args(["--groups", "--unsorted"])
.stdout(
"
Recipe groups:
B
A
",
)
.run();
}
#[test]
fn list_groups_private() {
Test::new()
.justfile(
"
[private]
[group: 'A']
foo:
[group: 'B']
bar:
",
)
.args(["--groups", "--unsorted"])
.stdout(
"
Recipe groups:
B
",
)
.run();