Script-Fu Programmer’s Reference
About
This describes Script-Fu, a language for scripting or writing plugins for the GIMP application. This is a reference, not a tutorial.
Audience
Authors of GIMP plugins that use the Script-Fu language.
Disambiguation
Script-Fu can refer to the language or the system that implements it. Script-Fu the system has several associated tools, notably the Script-Fu Console which is a GUI REPL to execute short scripts. Many scripts in the Script-Fu language are distributed with GIMP and implement some menu items in GIMP.
Alternatives
You can write GIMP plugins in other languages such as C, Python, Lua, and Vala. In any language that supports GObject Introspection.
Versions
This documents version 3 of Script-Fu, with notes where it differs from version 2.
Script-Fu itself has not changed much in GIMP version 3, but the bound PDB API has. Thus many scripts that worked in GIMP version 2 will need porting to work in GIMP version3. Porting is usually simple, requiring a few name changes and a few signature changes to calls to PDB procedures.
A document explains the changes needed to port a script from GIMP version 2 to 3.
References to underlying languages
Script-Fu language is a dialect or extension of underlying languages. This documents what is atop or special or different from the underlying languages. See also:
The procedures in the GIMP Programmers Data Base (PDB) are callable in the Script-Fu language. To explore the PDB, use the PDB Browser in the GIMP app.
Overview
Script-Fu is a language and a set of tools for programming plugins of the GIMP application.
What is a GIMP plugin?
A plugin is a program that extends the GIMP application. You can only launch plugins from within the GIMP app. You can use Script-Fu to write plugins for GIMP.
Some plugins appear as menu items in the GIMP app. Many plugins are “filters” that alter an image.
Other plugins save or load image files of different formats. Such plugins are usually written in C.
Other plugins are “apps” that are long-lived and show windows for tasks. For example, the PDB Browser and the Script-Fu Console, which help authors of Script-Fu scripts. Such plugins are often written in C.
Script-Fu interpreters
The Script-Fu language is interpreted. An embedded interpreter underlies each plugin written in Script-Fu.
Since the language is interpreted, there is no compilation step. There is an install and registration step. Installation is just copying a script file to a certain directory. Registration happens when GIMP runs and queries the files in the directory. Registration enters the plugin in the PDB as a procedure.
Since GIMP 3, there is a separate executable program called “the Script-Fu interpreter” just as there is “the Python interpreter.” But many of the Script-Fu tools also have an embedded interpreter and some plugins (those in the /scripts directory) are interpreted by the long-lived “Script-Fu extension” process.
Architecturally, the Script-Fu interpreter wraps another interpreter, the TinyScheme interpreter.
Script-Fu language derives from Lisp
Script-Fu interprets the TinyScheme dialect of the Scheme language, augmented by functions to call the GIMP PDB and augmented by functions to declare plugins.
TinyScheme language is a subset of the Scheme language defined by the RSR5 standard. TinyScheme lacks hygenic macros and some other features of the RSR5 standard.
Scheme language is a dialect of Lisp. Lisp is a functional programming language with support for imperative programming.
Plugin features and Script-Fu
Most plugins of GIMP have these features:
- an optional GUI e.g. a dialog of settings for the plugin
- settings (i.e. preferences i.e. defaults) persistent between runs of the plugin, even in different sessions of GIMP
- a run mode i.e. interactive or non-interactive
- exists in the PDB so it is callable by other plugins, browseable, and introspectable
- can display progress and messages to the user
The Script-Fu system implements much of these features on behalf of a plugin written in Script-Fu. (In other language plugins, these features are inherited from a class: GIMP Plugin.)
This document does not describe in detail these general features of GIMP plugins, or the GIMP PDB. See elsewhere.
Templates for a Script-Fu plugin
Minimal, hello-world plugin
This is a minimal plugin:
(define (script-fu-basic-plug-in) (gimp-message " hello world "))
(script-fu-register "script-fu-basic-plug-in" "Basic" "test" "me" "free" "2023" "")
(script-fu-menu-register "script-fu-basic-plug-in" "<Image>/Fu-plug-in")
The first line defines the “run function” of the plugin. Here the run function has no arguments and just says “hello world.” You would craft a run function to do something useful.
The second and third lines are special functions of Script-Fu.
The second line declares metadata and the signature of the plugin. Here, the plugin has no arguments, and empty signature.
The third line declares the plugin’s appearance in the GIMP app menus, which is optional.
This text would be in a file named “hello-world.scm” installed in the /scripts directory.
Version 3 filter plugin
This is a minimal plugin in the new style of version 3:
#!/usr/bin/env gimp-script-fu-interpreter-3.0
(define (script-fu-basic-plug-in
image
drawables)
(gimp-message " hello world "))
(script-fu-register-filter "script-fu-basic-plug-in" "Basic" "test" "me" "free" "2023" ""
SF-ONE-DRAWABLE)
(script-fu-menu-register "script-fu-basic-plug-in" "<Image>/Fu-plug-in")
One difference is the shebang in the first line. This means the standalone Script-Fu interpreter will interpret the script, independently from other plugins.
Another difference is the run function has formal arguments for the standard arguments for a filter: image and drawables, but the call to script-fu-register-filter does not declare them.
Another difference is the call to script-fu-register-filter has the argument SF-ONE-DRAWABLE to specify the capability of the plugin re multi layers. This example is contrived, because the plugin actually ignores the drawables and actually could work no matter how many layers the user selected.
This text would be in a file named “hello-world.scm” installed in the /plug-ins/hello-world directory (a directory having the same name as the plugin script file.) The file must have executable permissions.
Other example plugins
A more elaborate hello-world in the Gimp repo illustrates a version 3 plugin, installed to the /plug-ins directory and independently interpreted, but not registering as a filter.
A script in the Gimp repo illustrates all types of arguments that you can declare in the signature of a plugin and demonstrates the corresponding widgets.
Features of the Script-Fu language
These are features beyond simple Scheme or TinyScheme:
- special functions to declare and define a GIMP plugin
- binding to the GIMP PDB procedures for processing images
- pre-defined symbols for GIMP constants i.e. enumerations
- Unicode strings
- i18n internationalization/localization of any GUI
- ftx extension for filesystem operations
- re extension for regular expressions
- byte IO
- a few functions not in Scheme, defined in the usual init.scm for a Scheme interpreter
- other Scheme functions whose meaning is implementation dependant (e.g. quit)
Script-Fu special functions
The special functions are:
- script-fu-register (deprecated)
- script-fu-register-filter
- script-fu-register-procedure
- script-fu-menu-register
- script-fu-register-18n (since GIMP v3.2)
These declare a plugin to the PDB. These functions are not in the Scheme language proper, and not in the PDB.
Calls to these functions are usually located towards the end of a plugin script file. Order is important; they are usually in an order like above.
They are implemented in C language and bound as foreign functions to Scheme.
The first argument to these functions is a string name. The name is the name of the plugin procedure registered in the PDB, and must match the name of the run function defined in Scheme at the top of a script. The name should have prefix “plug-in-”, by convention. We recommend not using the prefix “script-fu-” in the name, but you may still see it used.
The function script-fu-register-filter is new for version 3. It registers an “image procedure”, one that always receives the image and list of drawables that a GIMP user must have already selected. You don’t declare the image and drawables arguments in a call to script-fu-register-filter. Also, a plugin that registers by this function gets a GUI more similar to plugins in other languages (by the class GimpProcedureDialog.) You can only use script-fu-register-filter in new style plugin scripts.
Similarly, script-fu-register-procedure and script-fu-register-18n are new for version 3.
The Script-Fu binding to the PDB
The binding from Scheme to GIMP is part of the Script-Fu system.
Unlike bindings for other languages of plugins (such as the Python binding) the binding is not automatic using GObject Introspection (GIR.) Instead, the binding is mostly hand-coded in C.
The binding is to the PDB API, instead of the libgimp API. The binding defines a symbol into the Scheme language for each procedure in the GIMP PDB. Other languages bind to the similar but distinct libgimp API.
The binding also marshalls arguments to and return values from calls to the PDB. The binding marshalls C types to Lisp types and vice versa.
To understand the signatures of Script-Fu’s binding of calls to the PDB, read the C signatures in the PDB Browser and mentally convert to a Scheme type.
Most conversions of elementary types are natural. For example, a C integer converts to a Scheme numeric and a C string converts to a Scheme string.
A document in the Gimp repo describes other conversions from GIMP types to Scheme types.
Pre-defined symbols
Script-Fu defines many symbols over and above TinyScheme and Scheme.
These symbols are immutable and you cannot globally redefine them although you could redefine them in a let block.
Pre-defined symbols for GIMP constants i.e. enumerations
The Script-Fu language defines symbols for each enumeration value of the GIMP library and the GEGL library. You often pass these symbols as arguments to calls to the PDB. These symbols are in upper case. These symbols match the symbols in the respective libraries, except they omit the “GIMP_” or “GEGL_” prefix.
For example, RUN-INTERACTIVE is the symbol for one of the enumerated values in the GimpRunMode enumeration.
Script-Fu specific pre-defined symbols for constants
Script-Fu defines these symbols:
TRUE alias for 1
FALSE alias for 0
NULL alias for 0
These are C-isms that you should not use in new code.
Symbols for strings about the filesystem:
gimp-directory the path to the directory where GIMP is installed, aka PREFIX
gimp-data-directory
gimp-plug-in-directory
gimp-locale-directory
gimp-sysconf-directory
script-fu-sys-init-directory the directory containing init.scm that ScriptFu reads
script-fu-user-init-director the directory where users install .scm files read at init time
DIR-SEPARATOR the ASCII character used as separator in filesystem paths, e.g. forward slash
SEARCHPATH-SEPARATOR the ASCII character used as separator in PATH lists, e.g. colon
The SF- enumeration of argument types
Script-Fu defines symbols used to declare types of arguments to a plugin. They are of the form “SF-xxx” e.g. SF-STRING. See “Signatures of Script-Fu Plugins”.
Script-Fu defines symbols SF-SLIDER and SF-SPINNER used to declare widget types for arguments of type SF-ADJUSTMENT.
The SF- enumeration of plugin capabilities
Since GIMP version 3, a plugin can declare its capabilities re whether it can process multiple drawables. Then a plugin’s menu item is enabled in the GIMP GUI only when the user has selected an appropriate count of drawables.
These only declare a contract, which an ill-behaved plugin might fail to fulfill. A well-behaved plugin should return an error when passed a list of drawables that doesn’t meet the contract.
SF-ONE-DRAWABLE Requires exactly one drawable
SF-ONE-OR-MORE-DRAWABLE All drawables often processed independently,
sequentially, with side effects on the drawables.
SF-TWO-OR-MORE-DRAWABLE Requires two or more drawables. Often a binary operation
yielding a new drawable.
These are valid only for new-style, version 3 plugins that register by script-fu-register-filter.
When a plugin’s menu item should always be enabled (regardless of how many layers a user has selected) use script-fu-register-procedure.
Unicode support
Unlike some Scheme dialects and unlike the original TinyScheme, the Script-Fu interpreter implements Unicode strings.
All data of string type in Script-Fu are sequences of Unicode characters, i.e. wide characters. Script-Fu encodes Unicode character using UTF-8, so a character is one to three bytes.
The length of a string is the length in characters, not bytes.
In a Lisp script, you represent certain literals by a sharp constant. In Script-Fu, you can represent Unicode characters by sharp character constants :
#\a
represents lower case ASCII “a”.
You can also represent Unicode characters by sharp numeric constants, for example:
#\x3bb
represents the two byte encoding of the Greek character called lambda, whose codepoint is hexadecimal 3bb.
Symbols are not Unicode but ASCII. (Here symbol has the Lisp meaning of a name in the script.) So a script’s text must be ASCII. Evaluation of string data that is Unicode might not work.
i18n internationalization/localization
See “ScriptFu User Guide / Internationalizing” for more information.
In a Script-Fu plugin script, you can annotate a string literal for translation:
_"To be translated."
Any string literal so annotated will usually appear in the user’s native language in the GUI dialog for a plugin.
You only use this annotation in declarations of a plugin’s signature and the plugin’s appearance in the GIMP GUI.
(In Lisp terminology, the “_” character marks a special form that the Script-Fu interpreter recognizes. It is not in the form of a function call in Lisp.)
For internationalization to succeed, you must process plugins as follows. A translator must translate annotated strings, into a .po file. At install time, the build system must compile and install the translations.
Third-party annotated plugins won’t actually be translated unless the author follows a similar process and distributes compiled translation files with the plugin script.
Translated strings are known in advance and fixed at distribution time. Script-Fu does not support translation of strings generated at run time.
ftx and re extensions
Script-Fu includes the ftx (OS and filesystem) and re (regular expression) extensions. An extension in Scheme is C code that defines more functions into the language.
See the gimp repo for more information:
Byte IO
Since characters are Unicode in Script-Fu, you can’t use characters as bytes. Since version 3, ScriptFu has functions to read and write streams a byte at a time.
Byte IO is not part of the RSR5 standard.
See the separate document on this site.
Other defined functions
Script-Fu has some functions not in Scheme and not specific to GIMP. Some are implemented in the TinyScheme interpreter itself, and some in Scheme scripts in the usual init.scm for a Scheme interpreter.
The print function is not in RSR5 but is defined in ScriptFu. It is a call to the display function on the current output stream, but adds a newline. (Probably for backward compatibility with scripts written in the SIOD dialect.)
The quit function is usually defined in Scheme but with implementation dependent meaning re a process. In Script-Fu, it stops evaluation of the script and returns the optional error-code argument to the caller of the plugin script. Note that it does not stop the execution of the Script-Fu extension process, only the evaluation of the current script. It does not stop the Script-Fu Console process.
The cond-eval function is defined but in a limited way. That function lets you evaluate conditionally on the prior loading of other Scheme modules following the SRFI conventions.
Signatures of Script-Fu plugins
You declare the signature of a Script-Fu plugin by calling one of the special functions such as script-fu-register. The call declares:
- metadata of the plugin
- arguments of the plugin
You declare each in argument in a sequence of three values, and you can declare many arguments.
For example:
(script-fu-register "script-fu-test-sphere"
... metadata arguments...
SF-ADJUSTMENT "Radius (in pixels)" (list 100 1 5000 1 10 0 SF-SPINNER)
... more triples, one for each additional argument ...
)
The three values in a triple are:
- an SF- constant
- a string label to appear alongside a widget in the plugin’s dialog
- a value that defines a default or further constrains the argument (a list for some argument types)
Declaring IN arguments to a plugin
The SF- enumeration declares the type of a plugin argument. The corresponding type in Scheme and C is not well documented, but you can easily infer it. When you browse the PDB to study the signature of a plugin, you will see the declared types as the corresponding bound C types.
The SF- enumeration declares not only the type of the argument, but the kind of widget used in a dialog for the plugin. For example, SF-STRING and SF-TEXT yield argument of type string, but the first appears as a widget for entering a single line while the second appears appears as a widget for entering multiple lines.
Declaring resource arguments to a plugin
SF-BRUSH, SF-FONT, SF-GRADIENT, SF-PALETTE, and SF-PATTERN all specify an argument of type GIMP Resource. Resources are data installed with GIMP.
In ScriptFu, resources are represented by their integer ID’s. A script should treat these opaquely, receiving them and passing them unaltered to other functions.
In version 2, an SF-BRUSH triplet had a list for the third element of the triple. In version 3, Script-Fu only reads the first element of the list, the name of the brush.
A version 3 script that needs attributes of a brush should call methods of the brush. Version 2 scripts that used a brush may need porting.
Declaring arguments having a GIMP type to a plugin
Similarly, SF-IMAGE, SF-LAYER, SF-CHANNEL, SF-DRAWABLE, and SF-VECTORS all specify an argument having one of GIMP’s object type.
In ScriptFu, GIMP objects are represented by their integer ID’s. That is, of Scheme type numeric. A script should treat these opaquely, receiving them and passing them unaltered to other functions.
When you declare an argument having the type of a GIMP object, the third argument is usually just an ignored place holder “-1”. Since object ID’s are not persistent you should not generally code integer literals for ID’s. Note that in a newly started GIMP app, the first opened image usually has ID 1, and you can use guessed integer literals in the Script-Fu Console.
SF-VALUE
SF-VALUE is obsolete. An old script that uses it should be ported to work in GIMP version 3.
In GIMP version 2 SF-VALUE yields a string type in Scheme. In GIMP version 2 SF-VALUE does not imply a numeric value. The corresponding widget let the user enter any string.
Now, when you want the user to enter a string, use SF-STRING. Now, when you want the user to enter a number, use SF-INTEGER or similar.
Correspondence of signature in PDB and run function definition
The declaration of a plugin’s signature describes both the signature registered in the PDB and the signature of the run function defined in Scheme at the top of a script. The signature of the defined run function must match, else you get a run time error. Except the match is not exact, as explained below.
Undeclared run mode argument
You don’t need to declare the run mode argument to a plugin. GIMP passes each plugin a first argument the run mode. You see that in the PDB Browser. But the signature of the run function in a Script-Fu script does not have a run mode argument. Script-Fu hides it from a script. A script does not need to know what the run mode is (since a script should not implement GUI directly) and if it calls other plugins (in the PDB), it should usually pass run mode NON-INTERACTIVE so the called plugin does not present its dialog.
Undeclared arguments to filter plugins
In a call to script-fu-register-filter (new to version 3) you also do not declare the image and drawables arguments to a plugin. All “filter” plugins receive these arguments implicitly. The defined run function signature must have those formal arguments, and the PDB Browser will show those arguments. You just don’t need to declare triplets for them.
Return values from a plugin
Plugins written in Script-Fu language do not return a value, other than an error status. All normal results are side-effects, usually on an image.
In Lisp, the value of a function is the value of the last evaluation. But Script-Fu discards the value of the last evaluation in the run function of a plugin. A Script-Fu plugin returns a success error status unless
- the interpreter throws an error in Scheme code
- or a called PDB procedure returns an error
- or the plugin calls the quit or error functions
Plugins in other languages can declare and return values, unlike Script-Fu scripts.
Binding of values returned from calls to the PDB
General discussion
A Script-Fu plugin script can call a PDB procedure.
In C language terms, such a call yields an error status separate from normal returned values.
On a successful call to the PDB, Script-Fu binds the normal returned values into a Scheme data structure. The call yields that Scheme data structure.
On a failed call to the PDB, the calling script usually does not continue. Instead, the plugin returns, propagating the error. In Scheme terminology, the script’s call to the PDB throws a Scheme exception, which if not caught calls the error function which terminates the plugin script that is calling the PDB. In other words, you can’t check the error status value from a call to the PDB. A script could catch an error but most scripts don’t bother.
New dialect for values returned from a call to PDB
Since version 3 of Script-Fu you can optionally alter interpretation by calling a new special function:
(script-fu-use-v3)
This gives a more natural binding. It gives a new dialect of the language, the v3 dialect.
The default dialect is v2.
See also ScriptFu User Guide / Using the version 3 dialect for valued to and from the PDB
v2 dialect: binding of values returned from a call to PDB
A call to the PDB that succeeds yields a list, always. The list can contain zero or many values. List elements can themselves be lists.
When a PDB procedure declares returning void, the list is empty.
When a PDB procedure declares returning one value, the list has one element.
When a PDB procedure declares returning many values, the list has many elements.
When a PDB procedure declares returning boolean the returned list contains TRUE (1) or FALSE (0).
v3 dialect: binding of values returned from the PDB
A call to a PDB procedure returning a single element yields just that element, not wrapped in a list.
Thus for v2 dialect:
(set* filename (car (gimp-image-get-file 1)))
you can write in v3 dialect:
(set* filename (gimp-image-get-file 1))
That is, you don’t need to unwrap a returned list.
A call to a PDB procedure returning boolean returns #t or #f, not wrapped in a list.
Thus for v2 dialect:
(if (= (car (gimp-image-is-valid 1))
TRUE)
do-something)
you can write in v3 dialect:
(if (gimp-image-is-valid 1)
do-something)
A script should not mix the old and new dialects. Also, a script in the v3 dialect cannot call a PDB procedure that is itself a script using the old v2 dialect. script-fu-use-v3 sets a flag in the interpreter in the current process which is the same interpreter that interprets called old scripts. Since most useful PDB procedures are not themselves Script-Fu scripts, i.e. few Script-Fu plugins call old-style Script-Fu plugins, this is usually not a problem.
PDB C types and Scheme types
This table shows the corresponding Scheme type for each declared C type in the PDB documentation.
Declared C type | Scheme type |
---|---|
int | Integer |
double | Float |
char* | String |
gboolean | #t or #f |
GStrv | List of String |
Gimp objects e.g. GimpImage | Integer (ID) |
GimpCoreObjectArray | Vector of Numeric (ID) |
A GimpCoreObjectArray is an array of Gimp object instances (pointers.)
(In Gimp v2, a C array corresponded to a list containing an Integer length and a List of Number)
Old and new styles of Script-Fu plugins
There are two styles of Script-Fu plugins:
- old-style, in version 2 and version 3
- new-style, only in version 3
Old-style plugins:
- are installed in /scripts
- are served by the Script-Fu extension process
- call script-fu-register, declaring all arguments
- have a GUI implemented by the Script-Fu system
New-style plugins:
- are installed in /plug-ins like other plugins
- are interpreted each in a separate process
- can call script-fu-register-filter, not declaring standard args
- have a GUI provided by the GimpProcedureDialog class of libgimp
The differences are slight but important:
- Old-style plugins that crash cripple the GIMP app.
- Old-style plugin dialogs look and feel different from new-style plugin dialogs.
More about the Script-Fu extension process
Most plugin authors can skip this material.
The Script-Fu extension process serves plugins in the /scripts directory.
This process is started by the GIMP app when the GIMP app starts. This process querys the /scripts directory and registers in the PDB all the plugins there. It registers them as kind TEMPORARY (as seen in the PDB Browser.)
The process stays resident i.e. executing. The process communicates with the GIMP app via the extension protocol. When a user chooses a script’s menu item, GIMP sends the name of the plugin procedure, and arguments, to this process via the extension protocol.
When an old-style plugin crashes, it takes down the Script-Fu extension process. Then the GIMP app cannot communicate with it, and some menu items disappear from the GIMP app. That requires a user to restart GIMP.
The extension protocol is different from the plugin protocol. The plugin protocol is used by plugins in other languages and Script-Fu new-style plugins. In that protocol, when a user chooses the menu item for a plugin in the GIMP app, GIMP forks a new process, an interpreter, to interpret the script associated with the plugin. If the plugin crashes, the GIMP app is unaffected.
Errors
This discusses the kinds of errors from a Script-Fu plugin script.
-
Syntax Discovered at query time i.e. after the first install, by the embedded TinyScheme interpreter. For example, unmatched parenthesis.
-
Registration Discovered at query time i.e. after the first install, by Script-Fu. The data for registration in a call to script-fu-register is flawed, e.g. not a sequence of triplets.
-
Binding Discovered at run time, by the embedded TinyScheme interpreter. A name i.e. symbol is not bound. Typically a typo. Or, a function name that is in Scheme but not TinyScheme, or a named procedure that is no longer in the PDB. Also known as “unbound variable.”
-
Scheme Type Discovered at run time, by the embedded TinyScheme interpreter. Some Scheme functions dynamically check the type of their arguments.
-
PDB Type Discovered at run time, by the Script-Fu wrapper. Script-Fu checks the Scheme type of arguments in calls to a PDB procedure, and the PDB checks the C type of arguments in calls to a PDB procedure. The PDB also range checks some arguments. Also know as a “calling error.”
-
Run-time PDB Discovered at run time, by a called PDB procedure. For example, passed an image type that the procedure cannot handle. Also known as an “execution error.”
-
Script data Discovered at run time, by a script, in some data. A script should call throw, quit, or error to declare such an error. Calling gimp-message is not sufficient, since it does not always mean an error, and can be invisible to a user.
-
System error Discovered at run time, by the OS or by the embedded TinyScheme interpreter. For example, a runaway script exhausted memory allocated by the interpreter, or a file operation failed.
Errors detected in newly installed scripts: querying of plugin scripts
This is about errors detected in newly installed scripts, i.e. at query time:
- syntax errors
- errors in the registration metadata and signature declaration (which is just data)
Such errors are only printed to stderr/stdout. So authors of new scripts should start GIMP in a terminal/console, and monitor for errors in stderr/stdout. (There is an issue/enhancement to log registration time errors to Gimp Error Console.)
When there are such errors:
- the plugin fails to register
- its menu item is not in the GIMP app
- you can’t invoke the plugin
Other error kinds will not be detected until run time of the plugin’s run function, when a user invokes the plugin.
GIMP queries the /scripts and /plug-in directories when GIMP starts. To query means to interpret/evaluate, passing an argument denoting the query phase. In the query phase, each script registers it’s plugin in the PDB. In other words, the call to script-fu-register is evaluated. The define of the run function of the plugin is also evaluated, but this only parses the run function for syntax errors, and does not evaluate the run function itself.
(Note that GIMP persists i.e. caches the registered information into a config file. Only script files which have changed since persisted are queried.)
Exceptions, catch, and the *error-hook*
Errors are usually fatal i.e. stop evaluation of a plugin script.
Errors are Scheme exceptions. On an exception, the interpreter unwinds call frames to the first catch Scheme function or finally calls the error Scheme function which is fatal.
Most scripts do not use a catch. An example of a script that does is contact-sheet.scm which catches file opening errors and ignores them.
They symbol *error-hook* is a hook in the embedded TinyScheme interpreter. You can redefine the symbol to alter error handling. Typically used in test frameworks.
(There are other hook symbols in the embedded TinyScheme interpreter, e.g. *sharp-hook* which you can redefine to alter the parsing of sharp constants.)
Initialization of the Script-Fu interpreter
This is for advanced authors, who might want to understand the implementation of some built-in Scheme function. This describes how the interpreter state is initialized.
We use the words “Script-Fu loads” to mean similar to the Scheme load function, which reads a script file and evaluates it. Often a loaded file contains only definitions, i.e. calls to “(define …)”, which is similar to an import in other languages. But a loaded file may have more than just defines. See the special case for Script-Fu below.
The initialization process provides some backward compatibility. Any backward compatibility in Script-Fu might change in the future. For forward compatibility or future-proofing, a script author should not use deprecated functions in newly written scripts.
-
Script-Fu initializes the embedded TinyScheme interpreter. This defines core Lisp functions into the interpreter state. The embedded TinyScheme interpreter and these core functions are written in C.
-
Script-Fu makes extensions ftx and re define their functions into the interpreter. These extensions are in C.
-
Script-Fu defines its special functions into the interpreter. The special functions are written in C.
-
Script-Fu introspects or queries the PDB and defines into the interpreter each procedure in the PDB. A Scheme call to the PDB passes through wrapper functions written in C.
-
Script-Fu defines into the interpreter aliases for PDB procedures whose name has changed from prior versions of GIMP. A table in C associates alias names to new names. This is for backward compatibility. (Only in Script-Fu are the old names deprecated, i.e. aliased and still useable. In other GIMP plugin languages in GIMP version 3, the old names may be obsolete and not useable. In Script-Fu version 2, the names are useable.)
-
Script-Fu loads all the scripts in the directory /scripts/script-fu-init. This directory is part of a GIMP installation. This directory always contains the conventional script file: init.scm, as in other Scheme implementations. The file init.scm defines more core functions into the interpreter, such as cadr. This step is typical of Lisp interpreters. But the file is slightly altered from the usual TinyScheme init.scm.
-
Script-Fu loads /scripts/script-fu-init/script-fu-compat.scm This file is a Scheme script. For backward compatibility, it might define certain deprecated Scheme functions from earlier versions of Script-Fu that used the SIOD dialect of Lisp. It also defines the not-deprecated random function for random number generation.
-
Script-Fu loads /scripts/script-fu-init/plug-in-compat.scm This file is a Scheme script. For backward compatibility, it might define functions for certain deprecated PDB procedures from earlier versions of the GIMP PDB. The functions are written in Scheme and wrap calls to newer PDB procedures. They are not just aliases for renamed PDB procedures, the wrappers may do more or convert signatures.
-
Script-Fu loads each script file in two /script directories, the user owned /script directory and the system-wide /script directory. This defines into the interpreter state all the PDB functions that are old-style plugins written in the Script-Fu language as well as any other defined functions in those files!
The last step deserves more discussion. Script-Fu specially loads the files, at times suppressing calls to Script-Fu special functions like script-fu-register. (When the script-fu extension process initializes the interpreter, it doesn’t suppress those calls.) Thus every instance of the Script-Fu interpreter locally has the body of the functions defined in those files. Thus calls from a Scheme script to a PDB function whose implementation is also an old-style Scheme script do not result in a remote procedure call back to GIMP to the PDB.
This also means that any Scheme files (.scm) in those directories that do not define plugins can never-the-less define into the interpreter state. For example, the file /scripts/script-fu-util.scm defines several “utility” functions into the interpreter state. In other words, script files in those directories can serve as libraries.
The order in which the files in /scripts are loaded is undefined.
As of GIMP version 3.0, the script-fu-compat.scm file does NOT define any functions for SIOD compatibility. The plug-in-compat.scm file does NOT define any functions for compatibility with GIMP PDB API v2. In other words, there is a clean API break. You usually must port old scripts that might have worked in older GIMP versions.
Loading other Scheme scripts
A script can also load Scheme text files, even one whose suffix is not .scm, by explicitly calling load passing a path to a file. You can form a path to the standard script directories with the string constant gimp-directory.