diff --git a/README.md b/README.md
index ae57d71a09..bf347d6309 100644
--- a/README.md
+++ b/README.md
@@ -1851,6 +1851,17 @@ for details.
`requirement`, e.g., `">=0.1.0"`, returning `"true"` if so and `"false"`
otherwise.
+#### Style
+
+- `style(name)`master - Return terminal display attribute escape
+ sequence used by `just`. Unlike terminal display attribute escape sequence
+ constants, which contain standard colors and styles, `style(name)` returns an
+ escape sequence used by `just` itself, and can be used to make recipe output
+ match `just`'s own output.
+
+ Recognized values for `name` are `'command'`, for echoed recipe lines,
+ `error`, for errors, and `warning`, for warnings.
+
##### XDG Directories1.23.0
These functions return paths to user-specific directories for things like
diff --git a/src/color.rs b/src/color.rs
index 953b8ae9b4..7742597be4 100644
--- a/src/color.rs
+++ b/src/color.rs
@@ -35,7 +35,6 @@ impl Color {
Self::default()
}
- #[cfg(test)]
pub(crate) fn always() -> Self {
Self {
use_color: UseColor::Always,
diff --git a/src/function.rs b/src/function.rs
index a714a8d0fd..61a20aef4a 100644
--- a/src/function.rs
+++ b/src/function.rs
@@ -98,6 +98,7 @@ pub(crate) fn get(name: &str) -> Option {
"snakecase" => Unary(snakecase),
"source_directory" => Nullary(source_directory),
"source_file" => Nullary(source_file),
+ "style" => Unary(style),
"titlecase" => Unary(titlecase),
"trim" => Unary(trim),
"trim_end" => Unary(trim_end),
@@ -623,6 +624,20 @@ fn source_file(context: Context) -> FunctionResult {
})
}
+fn style(context: Context, s: &str) -> FunctionResult {
+ match s {
+ "command" => Ok(
+ Color::always()
+ .command(context.evaluator.context.config.command_color)
+ .prefix()
+ .to_string(),
+ ),
+ "error" => Ok(Color::always().error().prefix().to_string()),
+ "warning" => Ok(Color::always().warning().prefix().to_string()),
+ _ => Err(format!("Unknown style: `{s}`")),
+ }
+}
+
fn titlecase(_context: Context, s: &str) -> FunctionResult {
Ok(s.to_title_case())
}
diff --git a/tests/functions.rs b/tests/functions.rs
index 76964b74b4..025db08284 100644
--- a/tests/functions.rs
+++ b/tests/functions.rs
@@ -1183,3 +1183,56 @@ bar:
.args(["foo", "bar"])
.run();
}
+
+#[test]
+fn style_command_default() {
+ Test::new()
+ .justfile(
+ r#"
+ foo:
+ @echo '{{ style("command") }}foo{{NORMAL}}'
+ "#,
+ )
+ .stdout("\x1b[1mfoo\x1b[0m\n")
+ .run();
+}
+
+#[test]
+fn style_command_non_default() {
+ Test::new()
+ .justfile(
+ r#"
+ foo:
+ @echo '{{ style("command") }}foo{{NORMAL}}'
+ "#,
+ )
+ .args(["--command-color", "red"])
+ .stdout("\x1b[1;31mfoo\x1b[0m\n")
+ .run();
+}
+
+#[test]
+fn style_error() {
+ Test::new()
+ .justfile(
+ r#"
+ foo:
+ @echo '{{ style("error") }}foo{{NORMAL}}'
+ "#,
+ )
+ .stdout("\x1b[1;31mfoo\x1b[0m\n")
+ .run();
+}
+
+#[test]
+fn style_warning() {
+ Test::new()
+ .justfile(
+ r#"
+ foo:
+ @echo '{{ style("warning") }}foo{{NORMAL}}'
+ "#,
+ )
+ .stdout("\x1b[1;33mfoo\x1b[0m\n")
+ .run();
+}