2.99: ScriptFu: enhance: let scripts return data errrors
Summary
Enhance ScriptFu so that scripts that return #f or that call script-fu-abort are declaring errors.
A data error is determined by a script examining its IN args, say for sanity. Since v3 (the multi-layer selection feature), a well-behaved script must check for data errors: passed fewer or more drawables than the script handles, or a class of drawable that the script does not handle (for example, foggify crashes if passed LayerMask.)
Currently, scripts cannot be written to be well-behaved. That is, there is no valid Scheme construct that engenders a suitable value of type GimpPDBStatus, say GIMP_PDB_CALLING_ERROR.
What ScriptFu does now
-
ScriptFu returns errors from the embedded interpreter TinyScheme, say a syntax or semantic error in the Scheme language.
-
ScriptFu does not allow return values (except for a status) from scripts; all scripts return void. "script-fu-register" does not have a section for declaring return values.
-
ScriptFu discards the result of evaluation of a script's run func (in Scheme.) In Scheme, the value of an evaluated text is the value of the last expression. Similarly to other functional languages. Typically the last expression in a ScriptFu script is a function call, whose value is usually not #f (false, #f is the only falsy value, any other value is truthy.)
-
Some existing ScriptFu scripts do check for data errrors and call "gimp-message" when detected. However, the message often just flashes in the status bar of the GIMP app, and is easily missed by users, and does not require acknowledgement (clicking OK) by a user. And GIMP doesn't know there was an error.
-
When any plugin calls a ScriptFu script in the PDB, it does not get an error when the inner script detects a data error and calls gimp-message.
The enhancement
Two parts:
1. scripts evaluating to #f yield a GIMP_PDB_EXECUTION_ERROR
Scriptfu will check the value of the last expression evaluated. When #f, and no other error (syntax or semantic) has already been set (by the embedded interpreter) ScriptFu will return a GimpPDBStatus that indicates an error, with the error string "Script returned #f"
This can be seen as a proper adaption of the Scheme language's error result (#f) to the PDB language's error result (a GimpPDBStatus.) Where the current adaption is improper.
Here is a script that always returns an error. Currently a user does not see that it failed unless they see the flashing message. With the enhancement, a user would see an error dialog they need to OK.
(define (script-fu-always-fail)
(begin
(gimp-message "Failing")
; since last expression, is the result, and will mean error
#f
)
)
(script-fu-register "script-fu-always-fail"
"Always fail"
...
2. scripts calling script-fu-abort yield a PDB GIMP_PDB_EXECUTION_ERROR
ScriptFu will define a new function in the ScriptFu environment: script-fu-abort. It takes a message string, that it causes to appears in GIMP's error dialog. The call causes the cessation of interpretation and immediate return from the script i.e. PDB procedure, with an error.
Scheme is a functional language, not applicative. There is no "return" statement. There is no "abort" statement (except in Chicken Scheme?) The function "script-fu-abort" is in the extended language that ScriptFu implements.
script-fu-abort would put the message string into a GError which is one of the results of a failing PDB call.
Here is an example:
(define (script-fu-always-fail)
(script-fu-abort "Failing")
(gimp-message "this never evaluated")
)
...
After this enhancement
Most existing scripts would still work, because they serendipitously end in a function call that returns not #f. Scripts in the GIMP repo could be changed if necessary. Some third party scripts might be affected.
Authors have a choice of constructs to yield data errors.
- Authors can structure code to yield a #f. This can be done as in the example, with a "(begin ...)" block. Unfortunately, this adds another set of parens, and more indentation, when indented.
Calls to the PDB from a script already yield #t or #f. Few scripts actually check for #f, or call gimp-pdb-get-last-status to check the result of the previous call. With this enhancement, a script ending in a call to the PDB would fail if that last call failed by returning #f.
- Authors can also insert calls to script-fu-abort anywhere in the body of a script.
Status
I have prototyped this. It requires only a few changed lines. I haven't found any scripts in the GIMP repo that would break.