List groups in source order with just --groups --unsorted
(#2160)
This commit is contained in:
parent
5f91b37c82
commit
b05a75d168
@ -1861,6 +1861,8 @@ Recipe groups:
|
|||||||
rust recipes
|
rust recipes
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Use `just --groups --unsorted` to print groups in their justfile order.
|
||||||
|
|
||||||
### Command Evaluation Using Backticks
|
### Command Evaluation Using Backticks
|
||||||
|
|
||||||
Backticks can be used to store the result of commands:
|
Backticks can be used to store the result of commands:
|
||||||
|
@ -4,7 +4,7 @@ use super::*;
|
|||||||
pub(crate) type Assignment<'src> = Binding<'src, Expression<'src>>;
|
pub(crate) type Assignment<'src> = Binding<'src, Expression<'src>>;
|
||||||
|
|
||||||
impl<'src> Display for Assignment<'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 {
|
if self.export {
|
||||||
write!(f, "export ")?;
|
write!(f, "export ")?;
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ pub(crate) struct Ast<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> Display for 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();
|
let mut iter = self.items.iter().peekable();
|
||||||
|
|
||||||
while let Some(item) = iter.next() {
|
while let Some(item) = iter.next() {
|
||||||
|
@ -110,7 +110,7 @@ impl<'src> Attribute<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> Display for 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())?;
|
write!(f, "{}", self.name())?;
|
||||||
if let Some(argument) = self.argument() {
|
if let Some(argument) = self.argument() {
|
||||||
write!(f, "({argument})")?;
|
write!(f, "({argument})")?;
|
||||||
|
@ -28,7 +28,7 @@ fn capitalize(s: &str) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Display for CompileError<'_> {
|
impl Display for CompileError<'_> {
|
||||||
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
use CompileErrorKind::*;
|
use CompileErrorKind::*;
|
||||||
|
|
||||||
match &*self.kind {
|
match &*self.kind {
|
||||||
|
@ -8,7 +8,7 @@ pub(crate) struct Condition<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> Display for 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)
|
write!(f, "{} {} {}", self.lhs, self.operator, self.rhs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ pub(crate) struct Dependency<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> Display for 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() {
|
if self.arguments.is_empty() {
|
||||||
write!(f, "{}", self.recipe.name())
|
write!(f, "{}", self.recipe.name())
|
||||||
} else {
|
} else {
|
||||||
|
@ -51,7 +51,7 @@ impl<'src> Expression<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> Display for 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 {
|
match self {
|
||||||
Self::Assert { condition, error } => write!(f, "assert({condition}, {error})"),
|
Self::Assert { condition, error } => write!(f, "assert({condition}, {error})"),
|
||||||
Self::Backtick { token, .. } => write!(f, "{}", token.lexeme()),
|
Self::Backtick { token, .. } => write!(f, "{}", token.lexeme()),
|
||||||
|
@ -365,13 +365,13 @@ impl<'src> Justfile<'src> {
|
|||||||
modules
|
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
|
let mut recipes = self
|
||||||
.recipes
|
.recipes
|
||||||
.values()
|
.values()
|
||||||
.map(AsRef::as_ref)
|
.map(AsRef::as_ref)
|
||||||
.filter(|recipe| recipe.is_public())
|
.filter(|recipe| recipe.is_public())
|
||||||
.collect::<Vec<&Recipe<Dependency>>>();
|
.collect::<Vec<&Recipe>>();
|
||||||
|
|
||||||
if config.unsorted {
|
if config.unsorted {
|
||||||
recipes.sort_by_key(|recipe| (&recipe.import_offsets, recipe.name.offset));
|
recipes.sort_by_key(|recipe| (&recipe.import_offsets, recipe.name.offset));
|
||||||
@ -380,19 +380,33 @@ impl<'src> Justfile<'src> {
|
|||||||
recipes
|
recipes
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn public_groups(&self) -> BTreeSet<String> {
|
pub(crate) fn public_groups(&self, config: &Config) -> Vec<String> {
|
||||||
self
|
let mut groups = Vec::new();
|
||||||
.recipes
|
|
||||||
.values()
|
for recipe in self.recipes.values() {
|
||||||
.map(AsRef::as_ref)
|
if recipe.is_public() {
|
||||||
.filter(|recipe| recipe.is_public())
|
for group in recipe.groups() {
|
||||||
.flat_map(Recipe::groups)
|
groups.push((&recipe.import_offsets, recipe.name.offset, group));
|
||||||
.collect()
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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> {
|
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();
|
let mut items = self.recipes.len() + self.assignments.len() + self.aliases.len();
|
||||||
for (name, assignment) in &self.assignments {
|
for (name, assignment) in &self.assignments {
|
||||||
if assignment.export {
|
if assignment.export {
|
||||||
|
@ -15,7 +15,7 @@ pub(crate) enum OutputError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Display for OutputError {
|
impl Display for OutputError {
|
||||||
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
match *self {
|
match *self {
|
||||||
Self::Code(code) => write!(f, "Process exited with status code {code}"),
|
Self::Code(code) => write!(f, "Process exited with status code {code}"),
|
||||||
Self::Io(ref io_error) => write!(f, "Error executing process: {io_error}"),
|
Self::Io(ref io_error) => write!(f, "Error executing process: {io_error}"),
|
||||||
|
@ -14,7 +14,7 @@ pub(crate) struct Parameter<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> ColorDisplay for 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() {
|
if let Some(prefix) = self.kind.prefix() {
|
||||||
write!(f, "{}", color.annotation().paint(prefix))?;
|
write!(f, "{}", color.annotation().paint(prefix))?;
|
||||||
}
|
}
|
||||||
|
@ -476,7 +476,7 @@ impl<'src, D> Recipe<'src, D> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'src, D: Display> ColorDisplay for 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 {
|
if let Some(doc) = self.doc {
|
||||||
writeln!(f, "# {doc}")?;
|
writeln!(f, "# {doc}")?;
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ impl<'src> Keyed<'src> for Set<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> Display 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)
|
write!(f, "set {} := {}", self.name, self.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ pub(crate) enum Setting<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> Display for 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 {
|
match self {
|
||||||
Self::AllowDuplicateRecipes(value)
|
Self::AllowDuplicateRecipes(value)
|
||||||
| Self::AllowDuplicateVariables(value)
|
| Self::AllowDuplicateVariables(value)
|
||||||
|
@ -7,7 +7,7 @@ pub(crate) struct Shell<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> Display for 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)?;
|
write!(f, "[{}", self.command)?;
|
||||||
|
|
||||||
for argument in &self.arguments {
|
for argument in &self.arguments {
|
||||||
|
@ -97,7 +97,7 @@ impl Subcommand {
|
|||||||
|
|
||||||
fn groups(config: &Config, justfile: &Justfile) {
|
fn groups(config: &Config, justfile: &Justfile) {
|
||||||
println!("Recipe groups:");
|
println!("Recipe groups:");
|
||||||
for group in justfile.public_groups() {
|
for group in justfile.public_groups(config) {
|
||||||
println!("{}{group}", config.list_prefix);
|
println!("{}{group}", config.list_prefix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -215,7 +215,7 @@ impl Subcommand {
|
|||||||
overrides: &BTreeMap<String, String>,
|
overrides: &BTreeMap<String, String>,
|
||||||
chooser: Option<&str>,
|
chooser: Option<&str>,
|
||||||
) -> Result<(), Error<'src>> {
|
) -> Result<(), Error<'src>> {
|
||||||
let mut recipes = Vec::<&Recipe<Dependency>>::new();
|
let mut recipes = Vec::<&Recipe>::new();
|
||||||
let mut stack = vec![justfile];
|
let mut stack = vec![justfile];
|
||||||
while let Some(module) = stack.pop() {
|
while let Some(module) = stack.pop() {
|
||||||
recipes.extend(
|
recipes.extend(
|
||||||
|
@ -39,7 +39,7 @@ pub(crate) enum TokenKind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Display for TokenKind {
|
impl Display for TokenKind {
|
||||||
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
use TokenKind::*;
|
use TokenKind::*;
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
|
@ -7,7 +7,7 @@ pub(crate) struct UnresolvedDependency<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> Display for 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() {
|
if self.arguments.is_empty() {
|
||||||
write!(f, "{}", self.recipe)
|
write!(f, "{}", self.recipe)
|
||||||
} else {
|
} else {
|
||||||
|
@ -157,12 +157,89 @@ fn list_groups_with_shorthand_syntax() {
|
|||||||
bar:
|
bar:
|
||||||
",
|
",
|
||||||
)
|
)
|
||||||
.args(["--groups", "--list-prefix", "..."])
|
.arg("--groups")
|
||||||
.stdout(
|
.stdout(
|
||||||
"
|
"
|
||||||
Recipe groups:
|
Recipe groups:
|
||||||
...A
|
A
|
||||||
...B
|
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();
|
.run();
|
||||||
|
Loading…
Reference in New Issue
Block a user