Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow groups on submodules #2263

Merged
merged 2 commits into from
Jul 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/analyzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,20 @@ impl<'src> Analyzer<'src> {
pub(crate) fn analyze(
asts: &HashMap<PathBuf, Ast<'src>>,
doc: Option<String>,
groups: &[String],
loaded: &[PathBuf],
name: Option<Name<'src>>,
paths: &HashMap<PathBuf, PathBuf>,
root: &Path,
) -> CompileResult<'src, Justfile<'src>> {
Self::default().justfile(asts, doc, loaded, name, paths, root)
Self::default().justfile(asts, doc, groups, loaded, name, paths, root)
}

fn justfile(
mut self,
asts: &HashMap<PathBuf, Ast<'src>>,
doc: Option<String>,
groups: &[String],
loaded: &[PathBuf],
name: Option<Name<'src>>,
paths: &HashMap<PathBuf, PathBuf>,
Expand Down Expand Up @@ -94,9 +96,12 @@ impl<'src> Analyzer<'src> {
..
} => {
let mut doc_attr: Option<&str> = None;
let mut groups = Vec::new();
for attribute in attributes {
if let Attribute::Doc(ref doc) = attribute {
doc_attr = Some(doc.as_ref().map(|s| s.cooked.as_ref()).unwrap_or_default());
} else if let Attribute::Group(ref group) = attribute {
groups.push(group.cooked.clone());
} else {
return Err(name.token.error(InvalidAttribute {
item_kind: "Module",
Expand All @@ -111,6 +116,7 @@ impl<'src> Analyzer<'src> {
modules.insert(Self::analyze(
asts,
doc_attr.or(*doc).map(ToOwned::to_owned),
groups.as_slice(),
loaded,
Some(*name),
paths,
Expand Down Expand Up @@ -216,6 +222,7 @@ impl<'src> Analyzer<'src> {
}),
}),
doc,
groups: groups.into(),
loaded: loaded.into(),
modules,
name,
Expand Down
4 changes: 2 additions & 2 deletions src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ impl Compiler {
asts.insert(current.path, ast.clone());
}

let justfile = Analyzer::analyze(&asts, None, &loaded, None, &paths, root)?;
let justfile = Analyzer::analyze(&asts, None, &[], &loaded, None, &paths, root)?;

Ok(Compilation {
asts,
Expand Down Expand Up @@ -229,7 +229,7 @@ impl Compiler {
asts.insert(root.clone(), ast);
let mut paths: HashMap<PathBuf, PathBuf> = HashMap::new();
paths.insert(root.clone(), root.clone());
Analyzer::analyze(&asts, None, &[], None, &paths, &root)
Analyzer::analyze(&asts, None, &[], &[], None, &paths, &root)
}
}

Expand Down
13 changes: 12 additions & 1 deletion src/justfile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub(crate) struct Justfile<'src> {
pub(crate) default: Option<Rc<Recipe<'src>>>,
#[serde(skip)]
pub(crate) loaded: Vec<PathBuf>,
pub(crate) groups: Vec<String>,
pub(crate) modules: Table<'src, Justfile<'src>>,
#[serde(skip)]
pub(crate) name: Option<Name<'src>>,
Expand Down Expand Up @@ -395,17 +396,27 @@ impl<'src> Justfile<'src> {
recipes
}

pub(crate) fn groups(&self) -> &[String] {
&self.groups
}

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));
groups.push((recipe.import_offsets.as_slice(), recipe.name.offset, group));
}
}
}

for submodule in self.modules.values() {
for group in submodule.groups() {
groups.push((&[], submodule.name.unwrap().offset, group.to_string()));
}
}

if config.unsorted {
groups.sort();
} else {
Expand Down
141 changes: 80 additions & 61 deletions src/subcommand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@ impl Subcommand {
print!("{}", config.list_heading);
}

let groups = {
let recipe_groups = {
let mut groups = BTreeMap::<Option<String>, Vec<&Recipe>>::new();
for recipe in module.public_recipes(config) {
let recipe_groups = recipe.groups();
Expand All @@ -535,19 +535,41 @@ impl Subcommand {
groups
};

let mut ordered = module
let submodule_groups = {
let mut groups = BTreeMap::<Option<String>, Vec<&Justfile>>::new();
for submodule in module.modules(config) {
let submodule_groups = submodule.groups();
if submodule_groups.is_empty() {
groups.entry(None).or_default().push(submodule);
} else {
for group in submodule_groups {
groups
.entry(Some(group.to_string()))
.or_default()
.push(submodule);
}
}
}
groups
};

let mut ordered_groups = module
.public_groups(config)
.into_iter()
.map(Some)
.collect::<Vec<Option<String>>>();

if groups.contains_key(&None) {
ordered.insert(0, None);
if recipe_groups.contains_key(&None) || submodule_groups.contains_key(&None) {
ordered_groups.insert(0, None);
}

let no_groups = groups.contains_key(&None) && groups.len() == 1;
let no_groups = ordered_groups.len() == 1 && ordered_groups.first() == Some(&None);
let mut groups_count = 0;
if !no_groups {
groups_count = ordered_groups.len();
}

for (i, group) in ordered.into_iter().enumerate() {
for (i, group) in ordered_groups.into_iter().enumerate() {
if i > 0 {
println!();
}
Expand All @@ -561,69 +583,66 @@ impl Subcommand {
}
}

for recipe in groups.get(&group).unwrap() {
for (i, name) in iter::once(&recipe.name())
.chain(aliases.get(recipe.name()).unwrap_or(&Vec::new()))
.enumerate()
{
let doc = if i == 0 {
recipe.doc().map(Cow::Borrowed)
} else {
Some(Cow::Owned(format!("alias for `{}`", recipe.name)))
};

if let Some(doc) = &doc {
if doc.lines().count() > 1 {
for line in doc.lines() {
println!(
"{list_prefix}{} {}",
config.color.stdout().doc().paint("#"),
config.color.stdout().doc().paint(line),
);
if let Some(recipes) = recipe_groups.get(&group) {
for recipe in recipes {
for (i, name) in iter::once(&recipe.name())
.chain(aliases.get(recipe.name()).unwrap_or(&Vec::new()))
.enumerate()
{
let doc = if i == 0 {
recipe.doc().map(Cow::Borrowed)
} else {
Some(Cow::Owned(format!("alias for `{}`", recipe.name)))
};

if let Some(doc) = &doc {
if doc.lines().count() > 1 {
for line in doc.lines() {
println!(
"{list_prefix}{} {}",
config.color.stdout().doc().paint("#"),
config.color.stdout().doc().paint(line),
);
}
}
}
}

print!(
"{list_prefix}{}",
RecipeSignature { name, recipe }.color_display(config.color.stdout())
);

format_doc(
config,
name,
doc.as_deref(),
max_signature_width,
&signature_widths,
);
print!(
"{list_prefix}{}",
RecipeSignature { name, recipe }.color_display(config.color.stdout())
);

format_doc(
config,
name,
doc.as_deref(),
max_signature_width,
&signature_widths,
);
}
}
}
}

if config.list_submodules {
for (i, submodule) in module.modules(config).into_iter().enumerate() {
if i + groups.len() > 0 {
println!();
}

println!("{list_prefix}{}:", submodule.name());
if let Some(submodules) = submodule_groups.get(&group) {
for (i, submodule) in submodules.iter().enumerate() {
if config.list_submodules {
if no_groups && (i + groups_count > 0) {
println!();
}
println!("{list_prefix}{}:", submodule.name());

Self::list_module(config, submodule, depth + 1);
}
} else {
for (i, submodule) in module.modules(config).into_iter().enumerate() {
if !no_groups && !groups.is_empty() && i == 0 {
println!();
Self::list_module(config, submodule, depth + 1);
} else {
print!("{list_prefix}{} ...", submodule.name());
format_doc(
config,
submodule.name(),
submodule.doc.as_deref(),
max_signature_width,
&signature_widths,
);
}
}

print!("{list_prefix}{} ...", submodule.name());
format_doc(
config,
submodule.name(),
submodule.doc.as_deref(),
max_signature_width,
&signature_widths,
);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/testing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ pub(crate) fn analysis_error(
let mut paths: HashMap<PathBuf, PathBuf> = HashMap::new();
paths.insert("justfile".into(), "justfile".into());

match Analyzer::analyze(&asts, None, &[], None, &paths, &root) {
match Analyzer::analyze(&asts, None, &[], &[], None, &paths, &root) {
Ok(_) => panic!("Analysis unexpectedly succeeded"),
Err(have) => {
let want = CompileError {
Expand Down
Loading