Repository: casey/just
Pull request #1118 (2022-02-24 04:10:28)

Add new built-in: error(msg)
Fixes: https://github.com/casey/just/issues/1073

Error will fail execution with the message given

    error: Call to function `error` failed: something is wrong, yo!
       |
       24 | x := error("something is wrong, yo!")

When provided no message, it however behaves:

    error: Call to function `error` failed:
       |
       24 | x := error("")

chamons: Feel free to wordsmith the readme text as desired. I consider it a rough draft at best.
chamons: As a second comment, thinking about this, it is annoying that you have to do x := error("foo") and not just error("foo"). I'm assuming that's a general grammar issue, and not something I should fix here?
chamons: I'll update the readme tonight. 
casey: Sorry for losing track of this! I don't have notifications turned on when someone pushes to a PR branch, so you have to ping me. This looks good, merging! Definitely a nice function to have.

Patch:
diff --git a/README.md b/README.md
index 167ab1bc..5b82c275 100644
--- a/README.md
+++ b/README.md
@@ -1012,6 +1012,10 @@ These functions can fail, for example if a path does not have an extension, whic
 
 - `path_exists(path)` - Returns `true` if the path points at an existing entity and `false` otherwise. Traverses symbolic links, and returns `false` if the path is inaccessible or points to a broken symlink.
 
+##### Error Reporting
+
+- `error(message)` - Abort execution and report error `message` to user.
+
 ### Command Evaluation Using Backticks
 
 Backticks can be used to store the result of commands:
@@ -1118,6 +1122,28 @@ $ just bar
 abc
 ```
 
+### Stopping execution with error
+
+Execution can be halted with the `error` function. For example:
+
+```
+foo := if "hello" == "goodbye" {
+  "xyz"
+} else if "a" == "b" {
+  "abc"
+} else {
+  error("123")
+}
+```
+
+Which produce the following error when run:
+
+```
+error: Call to function `error` failed: 123
+   |
+16 |   error("123")
+```
+
 ### Setting Variables from the Command Line
 
 Variables can be overridden from the command line.
diff --git a/src/function.rs b/src/function.rs
index cc7116e0..96dc6ed1 100644
--- a/src/function.rs
+++ b/src/function.rs
@@ -19,6 +19,7 @@ lazy_static! {
     ("clean", Unary(clean)),
     ("env_var", Unary(env_var)),
     ("env_var_or_default", Binary(env_var_or_default)),
+    ("error", Unary(error)),
     ("extension", Unary(extension)),
     ("file_name", Unary(file_name)),
     ("file_stem", Unary(file_stem)),
@@ -117,6 +118,10 @@ fn env_var_or_default(
   }
 }
 
+fn error(_context: &FunctionContext, message: &str) -> Result<String, String> {
+  Err(message.to_owned())
+}
+
 fn extension(_context: &FunctionContext, path: &str) -> Result<String, String> {
   Utf8Path::new(path)
     .extension()


Test patch:
diff --git a/tests/functions.rs b/tests/functions.rs
index 5eb865e0..713f1dde 100644
--- a/tests/functions.rs
+++ b/tests/functions.rs
@@ -404,6 +404,16 @@ fn test_path_exists_filepath_doesnt_exist() {
     .run();
 }
 
+#[test]
+fn error_errors_with_message() {
+  Test::new()
+    .justfile("x := error ('Thing Not Supported')")
+    .args(&["--evaluate"])
+    .status(1)
+    .stderr("error: Call to function `error` failed: Thing Not Supported\n  |\n1 | x := error ('Thing Not Supported')\n  |      ^^^^^\n")
+    .run();
+}
+
 #[test]
 fn test_absolute_path_resolves() {
   let test_object = Test::new()