devel-docs: delete ScriptFu docs

After moved to gimp-web-devel repo.
This commit is contained in:
lloyd konneker 2024-10-25 10:07:49 -04:00
parent 0db5f7dd72
commit cb4687633c
6 changed files with 0 additions and 1738 deletions

View file

@ -1,160 +0,0 @@
PDB-compatability
# Programmers Reference: PDB procedures for compatabililty
## About
The audience is GIMP maintainers.
This discusses procedures for compatability in the PDB and ScriptFu.
A procedure for compatability is:
* deprecated
* OR a wrapper for a plugin now in GEGL
## What
### Deprecated
A deprecated procedure is one provided for backward compatibility.
Older plugins calling a deprecated procedure still work.
Plugin authors should not use deprecated procedures in new plugin code.
In the future, gimp.org may obsolete i.e. delete the procedures.
Thus breaking any existing plugins still using the procedures.
A deprecated procedure can for:
* a renaming, to correct a naming mistake
and thereby conform to naming conventions
* an adaptor, having a signature different from a new signature.
For example, to accomodate the "multi-layer select" feature,
a new signature takes a container of layers,
and a deprecated signature takes a single layer and adapts.
### Wrappers for GEGL
These are wrappers/adaptors.
In early GIMP 2, the procedures were C plugins in GIMP.
Now (since about GIMP 2.8) they are C plugins in GEGL
and a wrapper/adaptor delegates to GEGL.
These are NOT planned for obsolescence.
Most GEGL plugins are wrapped.
A few are not.
Occasionally, new GEGL plugins are mistakenly not wrapped in GIMP.
A plugin in an introspected language can avoid a wrapper
by creating a GEGL node and calling GEGL directly.
(That is the recourse when there is no wrapper for a GEGL plugin.)
## Categories of deprecation and wrapping
1. Aliases for renamed procedures:
these are not separate procedures,
just alternate names pointing to another procedure
2. True deprecated procedures:
these are separately defined procedures
3. ScriptFu deprecated procedures:
separately defined procedures or aliases, in the Scheme language
4. GEGL wrappers:
separately defined procedures that wrap GEGL plugin filters
## GUI: how the PDB Browser shows deprecated and wrapped PDB procedures
This describes how a plugin author may know what procedures are deprecated or wrappers.
The PDB Browser inconsistently shows this information.
1. Aliases for renamed procedures:
the PDB browser does not reveal this at all.
2. True deprecated procedures:
the PDB browser indicates they are deprecated in the "blurb" field.
3. ScriptFu deprecated procedures:
the PDB browser doesn't show these,
since they are Scheme procedures not PDB procedures.
4. GEGL wrappers:
the PDB browser indicates they are GEGL wrappers in the "author" field.
## Implementation
This describes how deprecation and wrappers are implemented.
Read this if you are a maintainer and you want to deprecate a procedure
or obsolete a deprecated procedure.
### Aliased deprecated procedures
The GIMP core implementation of the PDB has an aliasing mechanism.
Declared in app/pdb/gimp-pdb-compat.c.
The code enters an alias name in the hash table of PDB procedure names, pointing to the same procedure as another name.
The name usually starts with "gimp-".
ScriptFu has its own aliasing mechanism.
ScriptFu has its own mechanism so its can deprecate even after
the core PDB has obsoleted a name.
Declared in plug-ins/script-fu/libscriptfu/script-fu-compat.c.
The name usually starts with "gimp-".
### True deprecated procedures
Defined in in pdb/groups/foo.pdb using the "std_pdb_deprecated" tag.
The name usually starts with "gimp-".
These also generate deprecated functions in libgimp.
### ScriptFu deprecated
ScriptFu provides some compatibility on top of "true deprecated procedures"
1. Defined in the latter half of plug-ins/script-fu/scripts/script-fu-compat.init.
Adaptors for Scheme functions present in the SIOD dialect of Scheme.
That dialect was used in early GIMP ScriptFu.
This provides backward compatibility for some older ScriptFu scripts.
2. Defined in plug-ins/script-fu/scripts/plug-in-compat.init.
Adaptors for PDB procedures present in earlier GIMP 2.
For example, at one time "plug-in-color-map"
and "gimp-image-get-active-layer" were defined in ScriptFu
(but not elsewhere) for compatibility.
The names can start with "gimp-" or "plug-in" or just be from some Scheme language dialect.
### GEGL wrappers
Defined in pdb/groups/plug_in_compat.pdb.
!!! These do not generate functions in libgimp.
A C plugin or plugin in an introspected language
must call GEGL directly,
or call the wrapping PDB procedure.
The names start with "plug-in-".
## Process for deprecation, and status
At a major release,
gimp.org might obsolete formerly deprecated procedures.
This breaks API (for the PDB and libgimp.)
API is not usually broken for a minor release.
Deprecated procedures are sometimes added, but not removed,
for a minor release.
As of the time of this writing (GIMP 3.0) there are:
* no aliased procedures
* no true deprecated procedures
* no ScriptFu deprecated procedures for SIOD dialect or older PDB
The mechanisms for deprecation (the implementation as described above)
is still in place.

View file

@ -1,175 +0,0 @@
## About this document
This describes *some* changes needed to port a Scriptfu script to GIMP 3:
- changes in types
- changes in PDB signatures for multi-layer support
- changes in error messages
- changes in logging
It does *not* document:
- PDB procedures whose names have changed (see pdb-calls.md)
- PDB procedures that have been removed (see removed_functions.md)
- PDB procedures that have been added
- other changes in signature where arguments are reordered or changed in number
## Changes in types of PDB signatures
Calls from a script to GIMP are calls to PDB procedures.
PDB procedures are documented in terms of C and GLib types.
This table summarizes the changes:
| Purpose | Old C type | New C type | Old Scheme type | New Scheme type |
| ---------------|-----------------------|-----------------------| ----------------|-----------------------|
| Pass file name | gchar*, gchar* | GFile | string string | string |
| Recv file name | gchar* | GFile | string | string |
| pass drawable | GimpDrawable | gint, GimpObjectArray | int (an ID) | int (a length) vector |
| Pass obj array | gint, GimpInt32Array | gint, GimpObjectArray | int vector | int vector |
| Recv obj array | gint, GimpInt32Array | gint, GimpObjectArray | int vector | int vector |
| Pass set of str | gint, GimpStringArray | GStrv | int list | list |
| Recv set of str | gint, GimpStringArray | GStrv | int list | list |
(Where "obj" means an object of a GIMP type such as GimpDrawable or similar.)
### Use one string for a filename instead of two.
Formerly a PDB procedure taking a filename (usually a full path) required two strings (two gchar* .)
Now such PDB procedures require a GFile.
In Scheme, where formerly you passed two strings, now pass one string.
Formerly a script passed the second string for a URI, to specify a remote file.
Formerly, in most cases you passed an empty second string.
Now, the single string in a script can be either a local file path or a remote URI.
Example:
(gimp-file-load RUN-NONINTERACTIVE "/tmp/foo" "")
=> (gimp-file-load RUN-NONINTERACTIVE "/tmp/foo")
### PDB procedures still return a string for a filename
All PDB procedures returning a filename return a single string to Scheme scripts.
That is unchanged.
Formerly a PDB signature for a procedure returning a filename
specifies a returned type gchar*, but now specifies a returned type GFile.
But a Scheme script continues to receive a string.
The returned string is either a local file path or a URI.
### Use a vector of drawables for PDB procedures that now take an array of drawables
Formerly, some PDB procedures took a single GimpDrawable,
but now they take an array of GimpDrawable ( type GimpObjectArray.)
(Formerly, no PDB procedure took an array of drawables.
Some that formerly took a single drawable still take a single drawable.
See the list below. )
For such PDB procedures, in Scheme pass a numeric length and a vector of numeric drawable ID's.
These changes support a user selecting multiple layers for an operation.
Example:
(gimp-edit-copy drawable) => (gimp-edit-copy 1 (vector drawable))
(gimp-edit-copy 2) => (gimp-edit-copy 1 '#(2))
### The PDB procedures which formerly took single Drawable and now take GimpObjectArray
- Many of the file load/save procedures.
- gimp-color-picker
- gimp-edit-copy
- gimp-edit-cut
- gimp-edit-named-copy
- gimp-edit-named-cut
- gimp-file-save
- gimp-image-pick-color
- gimp-selection-float
- gimp-xcf-save
### Receiving an array of drawables
Formerly a PDB procedure returning an array of drawables (or other GIMP objects)
had a signature specifying a returned gint and GimpInt32Array.
Now the signature specifies a returned gint and GimpObjectArray.
A script receives an int and a vector.
The elements of the vector are numeric ID's,
but are opaque to scripts
(a script can pass them around, but should not for example use arithmetic on them.)
No changes are needed to a script.
Example:
(gimp-image-get-layers image)
Will return a list whose first element is a length,
and whose second element is a vector of drawables (Scheme numerics for drawable ID's)
In the ScriptFu console,
(gimp-image-get-layers (car (gimp-image-new 10 30 1)))
would print:
(0 #())
Meaning a list length of zero, and an empty vector.
(Since a new image has no layers.)
### Passing or receiving a set of strings
Formerly, you passed an integer count of strings, and a list of strings.
Now you only pass the list.
ScriptFu converts to/from the C type GStrv
(which is an object knowing its own length.)
An example is the PDB procedure file-gih-export.
Formerly, you received an integer count of strings, and a list of strings.
Now you only receive the list
(and subsequently get its length using "(length list)").
Examples are the many PDB procedures whose name ends in "-list".
Remember that the result of a call to the PDB is a list of values,
in this case the result is a list containing a list,
and for example you get the list of strings like "(car (gimp-fonts-get-list ".*"))"
## Changes in error messages
ScriptFu is now more forgiving.
Formerly, ScriptFu would not accept a call construct where the argument count was wrong,
except for the case when you provided one argument to a PDB procedure
that took zero arguments (sometimes called a nullary function.)
Now, when a script has the wrong count of arguments to a PDB procedure:
- too many actual arguments: ScriptFu will give a warning to the console
and call the PDB procedure with a prefix of the actual arguments.
This is now true no matter how many arguments the PDB procedure takes.
Extra arguments in the script are ignored by Scriptfu,
not evaluated and not passed to the PDB.
- too few actual arguments: ScriptFu will give a warning to the console
and call the PDB procedure with the given actual arguments.
The warning will say the expected Scheme formal type of the first missing actual argument.
Usually the PDB procedure will fail and return its own error message.
When you suspect errors in a script,
it is now important to run GIMP from a console to see warnings.
## ScriptFu logging
ScriptFu now does some logging using GLib logging.
When you define in the environment "G_MESSAGES_DEBUG=scriptfu"
ScriptFu will print many messages to the console.
This is mostly useful for GIMP developers.

View file

@ -1,625 +0,0 @@
# Guide to changes to ScriptFu v3 for script authors
## About
The audience is authors of Scriptfu plugins.
This discusses how to edit v2 scripts so they will run in GIMP 3.
It also discusses enhancements to ScriptFu and its language.
## Quickstart
A lucky few existing scripts may work in GIMP v3 without change.
### Required changes
Some changes are *required* in existing plugins:
- many PDB procedures are obsolete or renamed, or their signature changed
- the symbol SF-VALUE is obolete
Once you edit a script for these changes, the script won't work in GIMP v2.
Most scripts will require edits due to changed PDB API.
### Optional changes
Other changes to scripts are *optional*.
Such changes use improved features of ScriptFu.
In approximate order of importance:
- you can install scripts like plugins in other languages
- you can use new, specific registration functions instead of the generic script-fu-register
- scripts can use the new mult-layer selection feature of GIMP
- scripts can use a v3 dialect having more natural binding of return values from PDB calls
- the symbolic constants TRUE and FALSE are deprecated, except for SF-TOGGLE
- a script can *quit* with an error code
- a script can call *display* to print to the terminal
Enhancements to ScriptFu might not affect an existing plugin.
You need only understand those enhancements when you want to use them.
### Why these changes now?
GIMP 3 is a major version change with new features.
A major version allows breaking API,
meaning old plugins and scripts might not work.
The GIMP developers understand these changes may be onerous.
Script developers might need to maintain two different versions of their scripts.
Some users will stick with GIMP 2 for a while and some will switch to GIMP 3.
A major version is necessary to move forward.
The situation is similar to the disruption caused by the move from Python 2 to 3.
## Changed PDB API
*You must edit your scripts to conform to version 3 of the PDB API.*
The GIMP PDB (Programmers Data Base), that you can call in scripts, has changed in GIMP version 3.
That also may require you to edit scripts.
- For changes in signatures of PDB procedures,
see devel-docs/GIMP3-plug-in-porting-guide/porting_scriptfu_scripts.md
- For added, removed, and replaced PDB procedures,
see devel-docs/GIMP3-plug-in-porting-guide/removed_functions.md
Some of the changes are for the multi-layer select feature of GIMP 3.
Many PDB procedures now take a container (a Scheme vector) of drawables
instead of a single drawable.
## SF-VALUE type of argument is obsolete
*You must edit v2 scripts and replace the symbol SF-VALUE.*
In v2, SF-VALUE declared a formal argument that is an unquoted, arbitrary string.
Usually, SF-VALUE was used for an integer valued argument.
In the dialog for a script, ScriptFu showed a text entry widget.
Usually the widget showed a default integer literal,
but the widget let you enter any text into the string.
You usually will replace it with an SF-ADJUSTMENT kind of formal argument,
where the "digits" field of the SF-ADJUSTMENT is 0,
meaning no decimal places, i.e. integer valued.
You must also provide other fields, e.g. the lower and upper limits.
A script that has SF-VALUE replaced with SF-ADJUSTMENT
will remain compatible with GIMP 2.
Example:
SF-VALUE "Font size" "50"
=>
SF-ADJUSTMENT "Font size" '(50 1 1000 1 10 0 SF-SPINNER)
Here, in the seven-tuple, the 0 denotes: no decimal places.
Another example, where you formerly
used SF-VALUE to declare a formal argument that is float valued:
SF-VALUE "Lighting (degrees)" "45.0"
=>
SF-ADJUSTMENT "Lighting (degrees)" '(45.0 0 360 5 10 1 SF-SLIDER)
Here, the 1 denotes: show 1 decimal place, for example "45.0",
in the dialog widget.
### Use SF-STRING for some use cases
In v2, a SF-VALUE argument let a user enter executable Scheme code,
say "'(1 g 1)", which is a list literal,
to be injected into a Scheme call to a plugin.
That use is no longer possible.
If you must do that, use SF_STRING to get a string,
and then your plugin can eval the string.
### Arbitrary precision floats
In v2, a SF-VALUE argument let a user enter a float with arbitrary precision,
e.g. "0.00000001"
That is no longer possible. You as a script author must use SF-ADJUSTMENT
and specify the maximum precision that makes sense. The user won't be able to
enter a value with more precision (more digits after the decimal point.)
You should understand the math of your algorithm and know what precision
is excess in terms of visible results.
Example:
SF-ADJUSTMENT "Lighting (degrees)" '(45.0 0 360 5 10 4 SF-SLIDER)
Here, the user will only be able to enter four decimal places,
for example by typing "0.0001" into the widget.
If you actually need arbitrary precision, use SF_STRING to get a string,
and then your plugin can eval the string to get a Scheme numeric
of the maximum precision that Scheme supports.
### Rationale
Formerly, a SF-VALUE argument let a user enter garbage for an argument,
which caused an error in the script.
SF-ADJUSTMENT or SF-STRING is more user-friendly.
## You can optionally install scripts like plugins in other languages
*We recommend this for new plugins.*
In v3 you can install ScriptFu scripts to a /plug-ins directory,
like plugins in other languages.
This helps isolate plugins.
You must edit the script to include a shebang in the first line:
#!/usr/bin/env gimp-script-fu-interpreter-3.0
;!# Close comment started on first line.
If the script has translatable strings, it should also have a second line
as above, to accomodate parsing by gettext.
(Note that ScriptFu doesn't actually support multi-line comments using #!,
and this is a trick to fool gettext, which parses a script as if
it did support multi-line comments.)
In v2 all ScriptFu scripts were installed in a /scripts directory.
In v3 you may install ScriptFu scripts with a shebang
in a subdirectory of a /plug-ins directory.
Installation of scripts with a shebang must follow rules for interpreted plugins.
A script file must:
- have a shebang on the first line
- be in a directory having the same base name
- have executable permission
- have a file suffix corresponding to an interpreter
An example path to a script:
~/.config/GIMP/2.99/plug-ins/script-fu-my/script-fu-my.scm
The advantage of installing a script in the /plug-ins directory is that
such a script will execute in its own process.
If it crashes, it doesn't affect GIMP or other scripts.
Conversely, in v2, all scripts in the /scripts directory
are executed by the long-lived process "extension-script-fu."
If one of those scripts crash, menu items implemented by ScriptFu dissappear
from the GIMP app, and you should restart GIMP.
It is only a convention to name scripts starting with "script-fu-".
## Using new registration functions
*We recommend this.*
New registration functions let a plugin dialog have a new look-and-feel
and improved settings.
ScriptFu "registration" functions let you declare a plugin PDB procedure,
and how it's dialog will look.
ScriptFu v3 has two new registration functions:
* *script-fu-register-procedure*
* *script-fu-register-filter*
Terminology: you *declare* a plugin's attributes and signature using a registration function.
You *define* a run func with a similar signature.
ScriptFu *registers* the plugin in the PDB.
ScriptFu v2 has only *script-fu-register*.
It is a generic function used to declare procedures that are either:
* generic procedures (operating without an image.)
* filters/renderers (operating on an image)
### Registration function *script-fu-register* is now deprecated.
**You should not use script-fu-register in new ScriptFu scripts.**
In the future, the GIMP project might obsolete *script-fu-register*.
While deprecated, *script-fu-register* should still work.
But the plugin dialog will:
* have an old look-and-feel.
* will be missing some advantages, such as the handling of settings.
Also, using *script-fu-register*,
you can only declare a plugin taking one drawable (i.e. layer or mask).
But GIMP v3 now calls such plugins passing a vector of drawables.
GIMP v2 called such plugins passing one drawable.
That is, the declared and actual signatures are incongruous.
GIMP enables the menu item for such deprecated scripts,
declared to take an image and drawable,
whenever a user selects at least one drawable.
### Improved Settings for ScriptFu plugins
GIMP 3 now handles plugin settings better.
(Using more powerful machinery in GIMP that is common to plugins in all languages,
not by limited machinery in ScriptFu that is specific to Scheme language plugins.)
Scripts declared with new registration functions have settings that persist
within and between Gimp sessions.
That is, the next time a user invokes the script,
the dialog will show the same settings as the last time they chose the filter.
This is not true for v2 *script-fu-register*,
where settings persist only during a GIMP session.
The dialog for a script declared with the new registration functions
will also have buttons for resetting to initial or factory values of settings,
and buttons for saving and restoring a set of settings, by name.
### script-fu-register-procedure
Use *script-fu-register-procedure* to declare PDB procedures that are not filters
or renderers.
"Procedure" denotes the general case.
Plugins that are filters or renerers,
taking an image and drawables, are special
and you instead declare them using *script-fu-register-filter.*
*Script-fu-register-filter* declares a script that:
* is always enabled
* can save its settings between sessions
You don't declare "image types"
as you do with *script-fu-register*.
GIMP enables your plugin regardless of the mode of any image a user has selected.
You don't declare "multilayer capability"
as you do with *script-fu-register-filter*.
Your plugin doesn't necessarily need an image and drawables.
(On your behalf, ScriptFu declares to the PDB that it requires no drawables.)
The run func that you define in your script has the same signature
as you declare in the registration function.
(The registration functaion also declares the procedure signature in the PDB,
and it will be similar, but in terms of the C language
and having an extra argument for run-mode.
As in ScriptFu v2, and unlike plugins in other languages,
the run-mode argument is hidden by ScriptFu.)
#### Example
Here is an abbreviated example:
(define script-fu-my-plugin (radius)
body)
(script-fu-register-procedure "script-fu-my-plugin"
"My plugin..."
"Example plugin."
"author/copyright holder"
"copyright dates"
SF-ADJUSTMENT "Radius" (list 100 1 5000 1 10 0 SF-SPINNER)
)
#### Another example: plugins using the context
A plugin may define a menu item appearing in a context menu.
This is a common use case for *script-fu-register-procedure*.
The context is the set of choices in GIMP that affect drawing operations,
for example, the current Brush.
Note that the plugin does *NOT* receive the choice in context
but must get it from the context before operating with/on it.
Using the same registration as above:
(define script-fu-my-plugin (radius)
; do something with the current brush
(gimp-context-get-brush))
(script-fu-register-procedure "script-fu-my-brush-plugin"
...same registration as above...)
(script-fu-menu-register "script-fu-my-brush-plugin"
"<Brushes>/Brushes Menu")
In this example, the menu item "My plugin..."
appears in the context menu (pops up with right mouse button)
in the *Brushes* dockable window,
and is always enabled.
The script run func gets the current brush
and does something to or with it.
#### Another example: plugin using an unopened file
A plugin may want to use a file that is *not open as an image.*
(define script-fu-my-plugin (filename)
; open and do something with the file
)
(script-fu-register-procedure "script-fu-my-plugin"
"My plugin..."
"Example plugin."
"author/copyright holder"
"copyright dates"
SF-FILENAME "Image to do something with" ""
)
(script-fu-menu-register "script-fu-my-plugin"
"<Image>/File")
In this example, the menu item *My plugin...*
appears in the *File* menu on the menubar.
It is always enabled.
When a user chooses the menu item,
a dialog appears that lets a user choose a file.
When the user clicks *OK*,
the plugin opens the file and does something with it.
### script-fu-register-filter
Use *script-fu-register-filter* to declare a PDB procedure that take an image and drawable components of images.
*Script-fu-register-filter* declares a script that:
* is a filter or renderer: taking a user selected image and its selected components
* is multi-layer capable, processing one or more drawables
* can save its settings between sessions
* has a menu item that is enabled/sensitized when a user selects image components
You don't specify the first two arguments "image" and "drawables"
as you do with *script-fu-register* in v2.
Those arguments are implicit.
As a convenience, ScriptFu registers those arguments in the PDB for you.
The run func that you define in your script
must have those formal arguments. For example:
(define script-fu-my-plugin (image drawables arg1 arg2) body)
ScriptFu passes a Scheme vector of drawables, not just one,
to a script
registering with script-fu-register-filter.
GIMP enables the menu item of your script
when the user has selected an image of the declared image mode, e.g. *Grayscale*,
and has selected as many drawables
(layers/masks/channels)
as you have declared for multi-layer capability.
#### Declaring multi-layer capabilily
*Script-fu-register-filter* has an argument "multilayer-capability".
(Some documents may refer to the argument as "drawable arity.")
The argument declares the capability of the plugin
for processing multiple drawables (usually layers.)
The argument follows the "image types" argument,
which declares the capability of the plugin to process
various image modes.
Here is an example:
(script-fu-register-filter "script-fu-test-sphere-v3"
"Sphere v3..."
"Test script-fu-register-filter: needs 2 selected layers."
"authors"
"copyright holders"
"copyright dates"
"*" ; image modes: any
SF-TWO-OR-MORE-DRAWABLE ; multi-layer capability argument
SF-ADJUSTMENT "Radius" (list 100 1 5000 1 10 0 SF-SPINNER)
)
The "multilayer-capability" argument can have the following values:
SF-ONE-DRAWABLE expects exactly one drawable
SF-ONE-OR-MORE-DRAWABLE expects and will process one or more drawables
SF-TWO-OR-MORE-DRAWABLE expects and will process two or more drawables
This is only a declaration; whether your defined run func does what it promises is another matter.
A script declaring SF-ONE-DRAWABLE still receives a vector of drawables,
but the vector should be of length one.
These do not specify how the script will process the drawables.
Typically, SF-ONE-OR-MORE-DRAWABLE means a script will filter
the given drawables independently and sequentially.
Typically, SF-TWO-OR-MORE-DRAWABLE means a script will
combine the given drawables, say into another drawable by a binary operation.
The "multilayer-capability" argument tells GIMP to enable the script's menu item
when a user has selected the appropriate count of drawables.
#### A well-written script should check how many drawables were passed
A well-written script should throw an error when it is not passed
the declared number of drawables, either more or fewer than declared.
Starting with GIMP 3,
a plugin that takes an image takes a container of possibly many drawables.
This is the so-called "multi-layer selection" feature.
Existing plugins that don't are deprecated,
and may become obsolete in a future version of GIMP.
Plugins should declare how many drawables they can process,
also called the "multi-layer capability" or "drawable arity" of the algorithm.
The declared drawable arity
only describes how many drawables the algorithm is able to process.
The declared drawable arity does not denote the signature of the PDB procedure.
Well-written image procedures always receive a container of drawables.
For plugins invoked by a user interactively, the drawable arity describes
how many drawables the user is expected to select.
GIMP disables/enables the menu item for a plugin procedure
according to its declared drawable arity.
So a plugin procedure invoked directly by a user should never receive
a count of drawables that the plugin can't handle.
*But PDB procedures are also called from other PDB procedures.*
A call from another procedure may in fact
pass more drawables than declared for drawable arity.
That is a programming error in the calling procedure.
A well-written called plugin that is passed more drawables than declared
should return an error instead of processing any of the drawables.
Similarly for fewer than declared.
## Using the v3 dialect for PDB return values
*We recommend this for new scripts.*
ScriptFu in GIMP version 3 will optionally interpret a v3 dialect.
The dialect is more natural to the Scheme language.
The dialect affects the binding of return values from calls to the PDB.
A script opts into the v3 dialect at runtime by calling script-fu-use-v3
at the beginning of the run func..
The advantage of the v3 dialect is that scripts are smaller,
with fewer calls to car.
Also, you can more naturally examine boolean values.
For more information, see the document in the GIMP source /plugins/script-fu/docs/using-v3-binding.md
## FALSE and TRUE symbols are deprecated
*We recommend not using TRUE and FALSE in new scripts, except for an SF-TOGGLE argument.*
FALSE and TRUE symbols are deprecated in the ScriptFu language.
They never were in the Scheme language.
Instead, you should use the v3 dialect
and use the Scheme language symbols #f and #t.
In ScriptFu, FALSE is 0
and TRUE is 1.
But FALSE is not equivalent to #f.
You must use the = operator to compare to FALSE and TRUE.
FALSE and TRUE are numeric.
The = operator in Scheme is a numeric operator, not a logical operator.
In Scheme, all values are truthy except for #f.
The empty list is truthy.
The numeric 0 is truthy.
Only #f is not truthy.
In the v3 dialect, a PDB procedure returning a single Boolean (a predicate)
returns one element, for example #f or #t.
In the v2 dialect, it still returns (0) or (1),
that is, numeric 0 or 1 wrapped in a list.
*You still need to compare boolean SF_TOGGLE arguments to a script with TRUE and FALSE.
They are not #t and #f*.
#### Rationale
The ScriptFu language is simpler and smaller; TRUE and FALSE duplicated concepts already in the Scheme language.
#### Example changes
Declaring a script's SF_TOGGLE arguments can still use TRUE and FALSE.
SF-TOGGLE "Gradient reverse" FALSE
Comparing a boolean argument to a script *must* remain as in v2 dialect:
(if (= should-invert TRUE)
; do invert )
Calling a PDB procedure taking a boolean:
(gimp-context-set-feather TRUE)
=>
(gimp-context-set-feather #t)
Logically examining a variable for truth:
(if (= shadow TRUE) ...
=>
(if shadow ...
## Using the quit function to abort a script
*We recommend using quit to declare errors* along with gimp-message.
The function "quit" is in Scheme.
It causes a script to exit i.e. return to the system.
The function can be used anywhere in a script,
like you would a "return" statement in other languages.
In ScriptFu v3 it causes the interpreter to stop interpreting a script
and yield an error of type GimpPDBStatus.
That is, it immediately returns an error to the GIMP app or other caller.
The GIMP app will show an error message including the phrase
"script quit with error code x."
When the caller is another PDB procedure (a plugin or script)
the caller should check the result of a call to the script
and propagate the error.
ScriptFu itself always checks the result of a call to the PDB
and propagates the error,
concatenating error message strings.
In ScriptFu v2, a call such as (quit -1) did abort the script,
but did not return an error to the caller
(usually the GIMP app)
and did not return the error code.
### A script doesn't return a value
In ScriptFu, a script returns void.
It is not possible to define a plugin script that returns useful values.
Note that script registration functions do not declare return values.
Scripts only have side effects.
The last expression in a script plugin is *not* the value of the plugin,
as it is in Scheme.
As a PDB procedure, a script can succeed or fail.
But success does not depend on the value of the last evaluated expression.
To make a script return failure, you should call the quit function.
#### Rationale
Formerly, scripts usually called gimp-message on errors,
without yielding an error to the caller.
It was easy for a user to overlook the error message.
You should still call gimp-message just before calling quit,
with an informative error message.
The numeric code that quit prints is not informative to users,
only to the script author.
#### Example
This script quits early:
(define (script-fu-my-plugin)
...
(gimp-message "Too many drawables.")
(quit -1)
(display "this never evaluated")
)
...
## Using the display function to write to the terminal
*We recommend using the display function to help debug a script or to log,
but not to prompt for user input.*
Display is a Scheme function, in the R5RS standard.
It should write a string to any open terminal (e.g stdout on Linux.)
In ScriptFu v3, it does.
You will see the output in any terminal in which the GIMP app was started
(which is optional, and not usually done on a graphical desktop.)
In ScriptFu v2, it did not write to a terminal.
Display wrote to a stream which was returned to the GIMP app, and usually discarded (unless an error occurred, and then the stream
was the prefix of the error message.)
Example:
(display "The script is here") (newline)
Note that displayln is not in ScriptFu.

View file

@ -1,130 +0,0 @@
# Color in ScriptFu
## About
The audience is script authors and developers of ScriptFu.
For more information, see the test script script-fu/test/tests/pdb/color.scm.
The tests demonstrate exactly how ScriptFu behaves.
## Representation in Scheme
Colors are represented by lists of numerics, or string names or notation.
### List representation
A color *from* GIMP is represented in ScriptFu by a list of from one to four numerics,
depending on the image mode.
The numerics are "components" of the color.
You can also represent colors by lists of numeric in calls *to* the PDB.
Examples:
- RGBA (0 0 0 0)
- RGB (0 0 0)
- Grayscale with alpha (0 0)
- Grayscale (0)
### String name representation
Color names can be used in PDB calls *to* GIMP. Color names must be CSS names.
You can also represent default colors by name
when declaring script arguments.
#### Name "transparent"
The color name "transparent" is a CSS color name.
You can use color named by "transparent" in calls to the PDB.
When setting the context foreground color,
it sets to opaque black.
When setting pixel of an RGBA image, the pixel
is set to black transparent.
### Other CSS color notation
You can also use other string notation to denote a color.
Examples:
- "#FFFFFF" hexadecimal notation for RGB
- "hsl(0, 0, 0)" converter function call from HSL values
Note that ScriptFu still converts to RGB format.
### CSS names/notation and grayscale images
You can use CSS names in procedures on grayscale images.
GIMP converts RGB colors to grayscale.
## Colorspace and Precision
While the GIMP app supports many colorspaces and precisions,
ScriptFu does not.
Generally speaking, ScriptFu has limited support for dealing with
colorspace and precision.
Scripts may call any procedures in the PDB that deal with colorspace
and precision.
But ScriptFu does not handle pixels/colors in high precision
or in colorspaces other than RGB and grayscale.
ScriptFu is not designed for intense and complicated pixel-level operations.
### Colorspace
ScriptFu keeps colors in the sRGB colorspace,
or grayscale.
GIMP converts colorspace when a ScriptFu script operates on images in other colorspaces.
### Precision
ScriptFu keeps colors with 8-bit integer precision.
This means a script may suffer loss of precision
when processing images of higher precision.
ScriptFu clamps numerics passed to the PDB as color components
to the range [0, 255].
Numeric color components received from GIMP are also integers in the range [0,255].
Float numerics may be passed as components of a color,
but are converted to integers and clamped.
## Difference from ScriptFu version 2
Version 2 represented colors differently,
converting to and from C type GimpRGB, which is obsolete.
Most scripts using colors will continue to work,
when they use colors opaquely,
receiving and passing colors without looking inside them.
It is only scripts that deal with color components
that might need to be ported.
In version 2, gimp-drawable-get-pixel
returned a count of components and a list of components e.g. (3 (255 255 255)).
Now it just returns a list of components,
and the length of the list correlates with format length.
## The GeglColor type
In the PDB, the type of colors is GeglColor.
When you browse the PDB, you see this type.
Arguments of this type are the "colors"
that ScriptFu represents as lists of numerics.
GeglColor is a class i.e. object in GIMP.
There are no methods in the PDB API for GeglColor.
For example in ScriptFu you can't get the format of a GeglColor.
You can get the length of the list representation to know the format.
## Indexed images
Colors to and from indexed images are colors, not indexes.
That is, in ScriptFu, a color from an indexed image is
a list of four numerics, RGBA.

View file

@ -1,288 +0,0 @@
# String-like objects in ScriptFu's TinyScheme
!!! Work in progress. This documents what should be, and not what is actually implemented. There are bugs in the current implementation.
## About
This is a language reference for the string-like features of
Script-fu's TinyScheme language.
This may differ from other Scheme languages. TinyScheme is a subset of R5RS Scheme, and ScriptFu has more than the original TinyScheme because it has been modified to support unichars and bytes. Both string-ports, bytes, and unichar are recent additions to Scheme, and not standardized among Schemes.
This is not a tutorial, but a technical document intended to be testable.
Terminology. We use "read method" to denote the function whose name is "read".
We occasionally use "read" to mean "one of the functions: read, read-byte, or read-char.
## The problem of specification
TinyScheme is a loose subset of the R5RS specification.
These are not part of R5RS, but optional implementations:
- string-ports
- unichar
- byte operations
Racket is a Scheme language that also implements the above.
See Racket for specifications, examples, and tests,
but ScriptFu's TinyScheme may differ.
SRFI-6 is one specification for string-port behavior.
SRFI-6:
- has a reference implementation.
- does not describe testable behavior.
- does not discuss unichar or byte operations
## Overview
Script-fu's TinyScheme has these string-like objects:
- string
- string-port
Both are:
- sequences of chars
- practically infinite
- UTF-8 encoded, i.e. the chars are unichars of multiple bytes
They are related, you can:
- initialize an input string-port from a string
- get a string from an output string-port
However, the passed string is not owned by a string-port but is a separate object with its own lifetime.
Differences are:
- string-ports implement the port API (open, read, write, and close)
- string-ports have byte methods but strings do not
- strings have a length method but string-ports do not
- strings have indexing and substring methods but string-ports do not
- write to a string-port is less expensive than an append to a string
Note that read and write methods to a string-port traffic in objects, not chars.
In other words, they serialize or deserialize, representing objects by text, and parsing text into objects.
Symbols also have string representations, but no string-like methods besides conversion to and from strings.
## ScriptFu's implementation is in C
This section does not describe the language but helps to ground the discussion.
ScriptFu does not use the reference implementation of SRFI-6.
The reference implementation is in Scheme.
The reference implementation is on top of strings.
ScriptFu's implementation of *string-ports is not on top of strings.*
ScriptFu's implementation is in C language.
(The reason is not recorded, but probably for performance.)
The reference implementation of SRFI-6 requires that READ and WRITE be redefined to use a redefined READ-CHAR etc. that
are string-port aware.
TinyScheme does something similar: inbyte() and backbyte() dispatch on the kind of port.
Internally, TinyScheme terminates all strings and string-ports with the NUL character (the 0 byte.) This is not visible in Scheme.
## Allocations
A main concern of string-like objects is how they are allocated and their lifetimes.
All string-like objects are allocated from the heap and with one cell from TinyScheme's cell pool (which is separately allocated from the heap.)
A string-port and any string used with a string-port are separate objects with separate lifetimes.
The length of string-like objects is limited by the underlying allocator (malloc) and the OS.
### String allocations
Strings and string literals are allocated.
They are allocated exactly.
Any append to a string causes a reallocation.
Any substring of a string causes a new allocation and returns a new string instance.
String literals are allocated but are immutable.
### String-port allocations
String-ports of kind output have an allocated, internal buffer.
A buffer has a "reserve" or free space.
The buffer can sometimes accomodate writes without a reallocation.
Writes to an output string-port can be less expensive (higher performing)
than appends to a string, which always reallocates.
But note that writes are not the same as appending (see below.)
The write method can write larger than the size that is pre-allocated for the buffer (256 bytes.)
A string-port of kind input is not a buffer.
It is allocated once.
It's size is fixed when opened.
## Byte, char, and object methods
### String methods
Strings are composed of characters.
The method string-ref accesses a character component.
Strings have no byte methods.
Characters can be converted to integers and then to bytes.
See "Support for byte type" at the Gimp developer web site.
Strings have no object methods: read and write.
### Port methods
Ports, and thus string-ports, have byte and char methods:
read-byte, read-char
write-byte, write-char
Ports also have methods trafficing in objects:
read, write
### Methods and port kinds
String-ports are of two kinds:
- input
- output
*There is also an input-output kind of string-port in TinyScheme,
but this document does not describe it and any use of it is not supported in ScriptFu*
You should only use the "read" methods on a string-port of kind input.
You should only use the "write" methods on a string-port of kind output.
A call of a read method on a string-port of kind output returns an error, and vice versa.
### Mixing byte, char, and object methods
*You should not mix byte methods with char methods, unless you are careful.*
You must understand UTF-8 encoding to do so.
*You should not mix char methods with read/write methods, unless you are careful.*
You must understand parsing and representation of Scheme to do so.
### The NUL character and byte
Internally, TinyScheme terminates all strings and string-ports
with the NUL character (the 0 byte.)
*You should not write the NUL character to strings or string-ports. The result can be surprising, and is not described here.*
You must understand the role of NUL bytes in C strings.
You cannot read the NUL character or byte from a string or string-port since the interpreter always sees it as a terminator.
Note that a string escape sequence for NUL, which is itself a string without a NUL character, can be inside a string or string-port.
You can read and write the NUL character to file ports that you are treating as binary files and not text files.
## Length methods
### Strings
The length of a string is in units of characters. Remember that each character in UTF-8 encoding may comprise many bytes.
(string-length "foo") => 3
### Ports
Ports have no methods for obtaining the length, either in characters or byte units. Some other Schemes have such methods.
## String-port and initial strings
### Input ports
The method open-input-port takes an initial string.
The initial string can be large, limited only by malloc.
TinyScheme copies the initial string to the port.
Subsequently, these have no effect on the port:
- the initial string going out of scope
- an append to the initial string
Subsequent calls to read methods progress along the port contents,
until finally EOF is returned.
The initial string can be the empty string and then the first read will return the EOF object.
There are no methods for appending to an input string-port after it is opened.
### Output ports
*The method open-output-port optionally takes an initial string but it is ignored.*
In other Schemes, any initial string is the name of the port.
In version 2 of Script-Fu's TinyScheme, the initial string was loosely speaking the buffer for the string-port.
This document does not describe the version 2 behavior.
An output string-port is initially empty and not the initial string.
The initial string may go out of scope without effect on an output string-port.
You can write more to an output port than the length of the initial string.
## The get-output-string method
A string-port of kind output is a stream that can be written to
but that can be read only by getting its entire contents.
(get-output-string port)
Returns a string that is the accumulation of all prior writes to the output string-port. This is a loose definition. Chars, bytes, and objects can be written, and it is the representation of objects that accumulate.
The port must be open at the time of the call.
A get-output-string call on a newly opened empty port returns the empty string.
Consecutive calls to get-output-string return two different string objects, but they are equivalent.
The returned string is a distinct object from the port.
These subsequent events have no effect on the returned string:
- writes to the port
- closing the port
- the port subsequently going out of scope
Again, *you should not mix write-byte, write-char, and write to an output string-port, without care*
## Writing and reading strings to a string-port
These are different:
- write a string to an output string-port
- append a string to a string
A string written to an output string-port writes escaped quotes into the string-port:
```
> (define aPort (open-output-string))
> (write "foo" aPort)
> (get-output-string aPort)
"\"foo\""
```
That is, writing a string to an output string-port
writes seven characters, three for foo and two pairs of
backslash quote.
```
\"foo\"
1234567
```
This is a string, which in the REPL prints surrounded by quotes:
```
"\"foo\""
```

View file

@ -1,360 +0,0 @@
# Version 3 of the ScriptFu language
## About
This describes a new dialect of the ScriptFu language.
ScriptFu interprets the dialect after a script calls: (script-fu-use-v3).
The new dialect is more like Scheme and makes scripts shorter.
The dialect only affects calls to the PDB.
ScriptFu inteprets the old version 2 by default,
unless a script calls script-fu-use-v3.
The audience is script authors and other developers.
This describes the new dialect and how to port old scripts to the new dialect.
## Quick Start
ScriptFu inteprets the old version 2 by default,
unless a script calls script-fu-use-v3.
After a call to script-fu-use-v3,
ScriptFu interprets the new dialect until the script finishes,
or until the script calls script-fu-use-v2.
A script can switch back and forth between dialects at runtime.
A script that calls:
```
(script-fu-use-v3)
```
binds to certain PDB calls differently:
1. PDB procedures that return single values (atoms) return just that single value,
*not wrapped in a list.*
Formerly, every PDB call returned a list (possibly nesting more lists.)
2. You can use #t and #f as arguments to PDB calls taking a boolean.
3. PDB calls returning a boolean return #t or #f, not TRUE or FALSE (1 or 0.)
## Script-Fu Console
The Script-Fu Console always starts in the v2 dialect.
You can call *script-fu-use-v3* in the console.
Then, the console interprets the v3 dialect.
It continues to interpret the v3 dialect in that session,
until you call *script-fu-use-v2.*
## Where to call *script-fu-use-v3* in scripts
Call *script-fu-use-v3* at the beginning of the run function.
This sets the dialect version for the remaining interpretation
of the script.
!!! 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.
The interpreter starts at the run function during the run phase.
*The interpreter always starts interpreting each script in the v2 dialect.
This is true even for extension-script-fu, the long-running interpreter.*
There is no need to call *script-fu-use-v2* before returning from a script,
to ensure that the next script is interpreted in v2 dialect.
Example:
```
(define (script-fu-testv3 img drawables )
(script-fu-use-v3) ; <<<
(let* (
...
```
### Scope
The dialect version has "execution scope" versus "lexical scope."
Setting the dialect version is effective even for
other functions defined in the same script but lexically
outside the function where the dialect is set.
You only need to call script-fu-use-v3 once,
not in every defined function.
## Don't call v2 scripts from v3 scripts
When using the v3 dialect,
you cannot call plugin Scheme scripts or other library scripts that are in the v2 dialect.
And vice versa.
(When a script calls a PDB procedure that is a Scheme script,
a new interpreter process is *NOT* started.)
For example, a new plugin script should not call the PDB procedure
script-fu-add-bevel because it is a Scheme script in v2 dialect
and for example has:
```
(width (car (gimp-drawable-get-width pic-layer)))
```
which is v2 dialect and would throw an error such as:
```
Error: car requires a pair.
```
*It is rare that a script calls another plugin script.*
A script usually calls the PDB,
but rarely calls a plugin script of the PDB.
There are very few, obscure library scripts that call the PDB using v2 dialect.
These are in scripts/script-fu-util.scm.
## Pure Scheme is unaffected
The dialect only affects calls the to PDB.
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.
## TRUE and FALSE
TRUE and FALSE are still in v3 dialect and are still numbers 1 and 0.
But we recommend not using them.
You can still pass them as arguments to PDB calls taking a boolean,
and they are still converted to the C notion of boolean truth.
FALSE which is 0 is truthy in Scheme!!!
It converts to the C notion of false only in a call the the PDB.
In the ScriptFu Console:
```
>(equal? FALSE #t)
#t
```
TRUE and FALSE symbols may become obsolete in the future.
## An argument of type SF-TOGGLE is FALSE or TRUE, not #f or #t
The v3 dialect does not affect the binding of arguments to a script.
So the value of an argument of type SF-TOGGLE is zero or one,
not #f or #t.
You must continue to check boolean arguments to a script like this:
```
(define script-fu-my-plugin (should-invert)
(if (= should-invert TRUE)
(
; do invert
)))
(script-fu-register-procedure "script-fu-my-plugin"
"My plugin..."
...
SF-TOGGLE "Invert?" FALSE
)
```
This may change when in the future we obsolete v2 dialect
and the symbols TRUE and FALSE.
## Plans for the future
This dialect is shorter and more natural for Scheme programmers.
The long-term goal is for the v3 dialect to be the only dialect of ScriptFu.
For the short term, for backward compatibility,
the default dialect of ScriptFu is the v2 dialect.
You should write any new scripts in the v3 dialect,
and call *script-fu-use-v3*.
You should plan on porting existing scripts to the v3 dialect,
since eventually ScriptFu may obolete the v2 dialect.
## Example conversions from v2 to v3 dialects
### An example script using v3 dialect
```
; !!! 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
```
(set! (width (car (gimp-drawable-get-width pic-layer))))
```
*must* become
```
(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 boolean
```
(if (= (gimp-image-is-rgb image) TRUE) ...
```
*must* become:
```
(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.
### A call to a PDB procedure taking a boolean
```
(gimp-context-set-antialias TRUE)
```
*should* become
```
(gimp-context-set-antialias #t)
```
This doesn't *require* conversion because TRUE is 1 and is truthy in Scheme.
!!! But FALSE is 0 and 0 is truthy in Scheme
```
(gimp-context-set-antialias FALSE)
```
This *should* be converted, for clarity, but doesn't *require* conversion.
For now, ScriptFu still binds Scheme 0 to C 0.
So it still does what the script intends.
### A call to a PDB procedure returning a list
```
(set! brushes (car (gimp-brushes-get-list)))
```
*must* become:
```
(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
```
(set! first-brush (caar (gimp-brushes-get-list)))
```
Gets the first brush in GIMP.
This *must* become:
```
(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*.
## Knowing what constructs need conversion
You *should* (but are not required to)
eliminate most uses of symbols TRUE and FALSE from a script
using v3 dialect.
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 PDB Browser.
For example, gimp-brush-get-angle:
```
Return Values
angle gdouble ....
Additional Information
```
This returns a single value so no need to use car.
For example, gimp-brushes-get-list:
```
Return Values
brush-list GStrv
Additional Information
```
This also returns a single value.
But the single value is a list i.e. container, of strings.
In the v2 dialect, this returned a list wrapped in a list,
for example (("foo" "bar")).
See "Example conversions from v2 to v3"
### 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.
## Details of the implementation
There are new functions in the dialect:
```
script-fu-use-v3
script-fu-use-v2
```
These functions have side-effects on the state of the interpreter.
They always return the empty list ().
The effect is immediate.
The interpreter interprets a dialect from then on,
until the script returns,
or until the script changes the dialect again.
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, as described.
Binding of args to PDB calls is done at run time.
Similarly, a call to *script-fu-use-v2* clears the flag
and restores the interpreter state to binding using the v2 dialect.
When in the v3 state,
any PDB call constructs using v2 binding will yield errors,
and vice versa.
Note that the difference in interpretation is only in binding, but both to and from the PDB:
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.