diff --git a/README.md b/README.md
index 1b5adc4..f0a6fcd 100644
--- a/README.md
+++ b/README.md
@@ -1079,6 +1079,27 @@ Available recipes:
test # test stuff
```
+The `[doc]` attribute can be used to set or suppress a recipe's doc comment:
+
+```just
+# This comment won't appear
+[doc('Build stuff')]
+build:
+ ./bin/build
+
+# This one won't either
+[doc]
+test:
+ ./bin/test
+```
+
+```sh
+$ just --list
+Available recipes:
+ build # Build stuff
+ test
+```
+
### Variables and Substitution
Variables, strings, concatenation, path joining, and substitution using `{{…}}`
@@ -1622,8 +1643,9 @@ Recipes may be annotated with attributes that change their behavior.
| Name | Description |
|------|-------------|
| `[confirm]`1.17.0 | Require confirmation prior to executing recipe. |
-| `[confirm('prompt')]`1.23.0 | Require confirmation prior to executing recipe with a custom prompt. |
-| `[group('NAME"']`master | Put recipe in [recipe group](#recipe-groups) `NAME`.
+| `[confirm('PROMPT')]`1.23.0 | Require confirmation prior to executing recipe with a custom prompt. |
+| `[doc('DOC')]`master | Set recipe's [documentation comment](#documentation-comments) to `DOC`. |
+| `[group('NAME"']`master | Put recipe in [recipe group](#recipe-groups) `NAME`. |
| `[linux]`1.8.0 | Enable recipe on Linux. |
| `[macos]`1.8.0 | Enable recipe on MacOS. |
| `[no-cd]`1.9.0 | Don't change directory before executing recipe. |
diff --git a/src/attribute.rs b/src/attribute.rs
index e650a90..bf657a0 100644
--- a/src/attribute.rs
+++ b/src/attribute.rs
@@ -10,6 +10,7 @@ use super::*;
#[strum_discriminants(strum(serialize_all = "kebab-case"))]
pub(crate) enum Attribute<'src> {
Confirm(Option>),
+ Doc(Option>),
Group(StringLiteral<'src>),
Linux,
Macos,
@@ -24,7 +25,7 @@ pub(crate) enum Attribute<'src> {
impl AttributeDiscriminant {
fn argument_range(self) -> RangeInclusive {
match self {
- Self::Confirm => 0..=1,
+ Self::Confirm | Self::Doc => 0..=1,
Self::Group => 1..=1,
Self::Linux
| Self::Macos
@@ -72,6 +73,7 @@ impl<'src> Attribute<'src> {
Ok(match discriminant {
Confirm => Self::Confirm(argument),
+ Doc => Self::Doc(argument),
Group => Self::Group(argument.unwrap()),
Linux => Self::Linux,
Macos => Self::Macos,
@@ -91,7 +93,8 @@ impl<'src> Attribute<'src> {
fn argument(&self) -> Option<&StringLiteral> {
match self {
Self::Confirm(prompt) => prompt.as_ref(),
- Self::Group(name) => Some(name),
+ Self::Doc(doc) => doc.as_ref(),
+ Self::Group(group) => Some(group),
Self::Linux
| Self::Macos
| Self::NoCd
@@ -107,7 +110,6 @@ impl<'src> Attribute<'src> {
impl<'src> Display for Attribute<'src> {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
write!(f, "{}", self.name())?;
-
if let Some(argument) = self.argument() {
write!(f, "({argument})")?;
}
diff --git a/src/recipe.rs b/src/recipe.rs
index a6afe2f..f974e39 100644
--- a/src/recipe.rs
+++ b/src/recipe.rs
@@ -450,6 +450,15 @@ impl<'src, D> Recipe<'src, D> {
})
.collect()
}
+
+ pub(crate) fn doc(&self) -> Option<&str> {
+ for attribute in &self.attributes {
+ if let Attribute::Doc(doc) = attribute {
+ return doc.as_ref().map(|s| s.cooked.as_ref());
+ }
+ }
+ self.doc
+ }
}
impl<'src, D: Display> ColorDisplay for Recipe<'src, D> {
diff --git a/src/subcommand.rs b/src/subcommand.rs
index 18af7c0..f7733fc 100644
--- a/src/subcommand.rs
+++ b/src/subcommand.rs
@@ -573,7 +573,7 @@ impl Subcommand {
);
let doc = if i == 0 {
- recipe.doc.map(Cow::Borrowed)
+ recipe.doc().map(Cow::Borrowed)
} else {
Some(Cow::Owned(format!("alias for `{}`", recipe.name)))
};
diff --git a/tests/attributes.rs b/tests/attributes.rs
index 055ec9e..d527b0e 100644
--- a/tests/attributes.rs
+++ b/tests/attributes.rs
@@ -129,3 +129,45 @@ fn unexpected_attribute_argument() {
.status(1)
.run();
}
+
+#[test]
+fn doc_attribute() {
+ Test::new()
+ .justfile(
+ "
+ # Non-document comment
+ [doc('The real docstring')]
+ foo:
+ echo foo
+ ",
+ )
+ .args(["--list"])
+ .stdout(
+ "
+ Available recipes:
+ foo # The real docstring
+ ",
+ )
+ .run();
+}
+
+#[test]
+fn doc_attribute_suppress() {
+ Test::new()
+ .justfile(
+ "
+ # Non-document comment
+ [doc]
+ foo:
+ echo foo
+ ",
+ )
+ .args(["--list"])
+ .stdout(
+ "
+ Available recipes:
+ foo
+ ",
+ )
+ .run();
+}