GIMP Developer Site now have improved navigation!
Using the version 3 dialect for PDB values

Using the version 3 dialect for PDB values

This describes a new and improved dialect of the ScriptFu language and how to port old scripts to the new dialect.

Note we say “version 3 dialect” to mean this optional dialect introduced along with GIMP version 3. Script-Fu per se is not versioned.

Pure Scheme is unaffected

The dialect only affects calls to the PDB. A script that uses the v3 dialect binds to certain PDB calls differently.

This means you can usually call most library scripts when using v3, since most library scripts are pure Scheme, that is, with no calls to the GIMP PDB.

Where to call script-fu-use-v3 in scripts

ScriptFu interprets the old version 2 dialect for PDB binding by default for compatibility reasons. The Script-Fu Console also always starts in the v2 dialect. In other words, it is optional to use the dialect.

To use it, call (script-fu-use-v3) at the beginning of the run function. Example:

Scheme
(define (script-fu-testv3 img drawables )
  (script-fu-use-v3) ; <<<
  (let* (
        ...
Do not call script-fu-use-v3 at the top level of a script. This has no effect, since it is only executed in the query phase of a plugin.

After a call to script-fu-use-v3, ScriptFu interprets the new dialect globally (that is: even for other functions defined in the same script but lexically outside the function where the dialect is set) until the script finishes, or until the script calls (script-fu-use-v2). More details below.

Details of the implementation

Both script-fu-use-v2 and script-fu-use-v3 always return the empty list(). But they have different side-effects on the state of the interpreter.

A call to script-fu-use-v3 sets a flag in the state of the interpreter. When the flag is set, the interpreter binds arguments to PDB calls slightly differently:

  1. Single return values from the PDB are not wrapped in lists.
  2. Boolean return values from the PDB are bound to #t and #f.
  3. Boolean values to the PDB can be #t and #f (this is optional).

Similarly, a call to script-fu-use-v2 clears the flag and restores the interpreter state to binding using the v2 dialect.

When using the v3 dialect, you cannot call plugin Scheme scripts or other library scripts that are in the v2 dialect, and vice versa, since a new interpreter process is not started.

Plans for the future

The long-term goal is for the v3 dialect to be the only dialect of ScriptFu, since it is shorter and more natural for Scheme programmers as you will see below.

You should write any new scripts in the v3 dialect, and call script-fu-use-v3.

You should also plan on porting existing scripts to the v3 dialect, since, as said, eventually ScriptFu may obolete the v2 dialect.

Conversions from v2 to v3 dialects

An example script using v3 dialect

Scheme
; !!! Usually not call (script-fu-use-v3) here in global scope

(define script-fu-my-plugin (should-invert)
     ; the body switches to the v3 dialect
     (script-fu-use-v3)

     (let* (
          ; don't need a car, unlike v2
          (angle gimp-context-get-brush-angle)))

     ; call PDB returning boolean
     ; don't need (= (car (gimp-context-get-feather)) TRUE)
     (if (gimp-context-get-feather)
          ; do feather
          )

     ; boolean arg to script is still C notion of truth
     (if (= should-invert TRUE)
         (
               ; do invert
         ))

     ; calling a v2 plugin, temporarily switch to v2 dialect
     (script-fu-use-v2)
     (script-fu-add-bevel ...)

     ; rest of script in v3 dialect
     (script-fu-use-v3)
     ...
)

(script-fu-register-procedure "script-fu-my-plugin"
     "My plugin..."
     ...
     SF-TOGGLE "Invert?" FALSE
)

A call to a PDB procedure returning a single value

A call to a PDB procedure returning e.g. a single integer

Scheme
(set! (width (car (gimp-drawable-get-width pic-layer))))

must become

Scheme
(set! (width (gimp-drawable-get-width pic-layer)))

The PDB call returns a single integer, so no car is needed.

A call to a PDB procedure returning a list

Scheme
(set! brushes (car (gimp-brushes-get-list)))

must become:

Scheme
(set! brushes (gimp-brushes-get-list))

Formerly, the PDB procedure returned a list wrapped in a list, i.e. ((…)) In the v3 dialect, it returns just a list, i.e. (…) which is a single value, a single container.

A call to a PDB procedure returning a list, getting the first element

Scheme
(set! first-brush (caar (gimp-brushes-get-list)))

Gets the first brush in GIMP. This must become:

Scheme
(set! first-brush (car (gimp-brushes-get-list)))

The call to caar is consecutive calls to car, and you must eliminate the first call to car.

In short, you should eliminate many, but not all, uses of the car function wrapping a call to the PDB, where the PDB procedure returns a single value. There are several hundred such PDB procedures in the PDB. Examine the signature of a PDB procedure using the Procedure Browser.

A call to a PDB procedure returning boolean

Scheme
(if (= (gimp-image-is-rgb image) TRUE) ...

must become:

Scheme
(if (gimp-image-is-rgb image) ...

The PDB procedure returns a boolean, which is bound to #t or #f, the usual symbols for Scheme truth.

If it is a call to a PDB procedure taking a boolean, you should (but are not required to) eliminate most uses of symbols TRUE and FALSE from a script using v3 dialect. To not repeat ourselves, see: FALSE and TRUE symbols are deprecated

Does not require changes to calls to PDB procedures returning void

You should not need to change scripts on calls to PDB procedures returning C void because a script should not be examining the result.

Some scripts might examine the result of a call to a void PDB procedure, thinking that (#t) is the success of the call, but that is a misconception and should be fixed.

Calls to PDB procedures that return C void return (#t) in v2 and the empty list () i.e. nil in v3 dialect.

Last updated on