Script-Fu Tools
This is a user manual for the ScriptFu tools.
The ScriptFu tools let you develop plugins and to process images in batches. They are more general purpose than, for example, image filter plugins.
The ScriptFu tools are:
- Console: a graphical IDE letting plugin authors edit and test snippets.
 - Eval: a PDB procedure that lets other languages call the ScriptFu interpreter to execute snippets. It is not an application program, but a function.
 - Server: a plugin that runs a server background process that evaluates snippets, submitted over the network by clients. It is not an application program, but a daemon. The server can run in a host computer and a client in a separate computer can access the remote server.
 - Text Console: a textual command line similar to the graphical ScriptFu Console. It is an application program.
 
Terminology
ScriptFu’s language is a dialect of the Scheme programming language, augmented with functions to call the Gimp PDB. The tools interpret “snippets” of that language. By “snippet” we mean a piece of text in ScriptFu’s dialect of the Scheme language.
ScriptFu Console
The ScriptFu Console is a graphical IDE letting plugin authors edit and test snippets. Probably the most popular ScriptFu tool.
It is most like a command-line program in a terminal: you type some text, hit the Return key, and see the result scroll by. But it has a graphical user interface, using a mouse.
Starting the console
Start the Gimp app.
If you are debugging a snippet, you might start Gimp in a terminal so you can see debugging messages from the ScriptFu interpreter.
Choose the menu Filters>Development>Script-Fu>Console. Expect a window to appear.
Using the console
The pane at the bottom is a text editor. Click the cursor into it, type some text, and press the Return key. You can also cut and paste, or drag-and-drop, into the text editor.
ScriptFu interprets the text and appends the result to the history in the top pane. The displayed result is:
- what the snippet writes to stdout (the default output port of Scheme language)
 - and what the ScriptFu Interpreter writes to stdout as the yielded value of each top level expression in the snippet.
 - and any error message
 
When a snippet is in an installed plugin, it’s stdout will be printed in the terminal in which Gimp was started, if any (unless the snippet itself redirects the Scheme output port).
Scrolling the history
The Up and Down Arrow keys will scroll through the history. Pressing the Up Arrow key will put the prior command into the editor pane.
The history of commands, but not the history of results, is persistent across sessions of Gimp.
The history is finite; the editor discards the oldest commands.
Browsing
The Browse button opens a new window showing the PDB Browser. Then choose the Apply button of the PDB Browser. That will insert a template of a call to the selected PDB procedure, into the editor pane. You will usually need to substitute actual argument values for formal argument names in the template.
(You can also start a PDB Browser from the Help menu, but it won’t have an Apply button.)
Other limitations
Currently, the window will not stay on top, and may get hidden behind the main Gimp window.
Currently, the text editor is only one line tall, and shows line breaks as a character glyph.
It is primitive, and doesn’t have the features of a full-fledged IDE, such a command completion and syntax highlighting.
ScriptFu Eval
ScriptFu Eval is a PDB procedure that lets other languages call the ScriptFu interpreter to execute snippets. It is not an application program, but a PDB procedure.
So, Eval is unlike Script-Fu Server, because:
- the process starts and stops for every evaluated snippet.
 - it has no long running interpreter state
 - it runs in the current Gimp context of the calling plugin.
 
As a plugin, it has no user interface and cannot be called except in run mode NONINTERACTIVE.
Calling ScriptFu Eval from Python
You can call plug-in-script-fu-eval from the Gimp Python Console, or from a Gimp plugin in the Python language.
In the Gimp Python Console:
proc = Gimp.get_pdb().lookup_procedure('plug-in-script-fu-eval')
# A Config is a set of arguments
config = proc.create_config()
# Arguments to the procedure are each a property of the config.
# Here, the arg is the snippet to be evaluated, a string text
# and the name of the argument is "script".
config.set_property('script', '(quit 1)')
result = proc.run(config)
print (result)
print (result.index[0])This prints:
<Gimp.ValueArray object at 0x7f3847b4b1d0 (GimpValueArray at 0x2520640)>
<enum GIMP_PDB_EXECUTION_ERROR of type Gimp.PDBStatusType>In this example, the evaluated Scheme snippet does nothing but quit with error code 1. Again, most snippets are executed for their side effects.
Note that the Gimp Python Console does not show what the ScriptFu interpreter printed or what the snippet output. That output goes to the terminal where Gimp was started, expect:
script quit with code: 1Also, since the snippet returned an error, expect in the Gimp Error Console:
GIMP Error Calling error for procedure 'pug-in-script-fu-eval': Unknown error.Calling ScriptFu Eval in batch mode
A more frequent use is to run a snippet in batch mode. You can’t just execute ScriptFu Eval from a command line, because, as said, it is not a program, it is a plugin that must be invoked from within Gimp.
gimp-console --batch-interpreter=plug-in-script-fu-eval --batch="(gimp-message \"foo\")"Expect in the terminal:
script-fu-Warning: foo
batch command executed successfullyHere the first line is due to the snippet’s call to gimp-message, which prints to stdout when Gimp is in batch mode. Here the second line is printed by Gimp as the result of the batch.
A more useful example is to evaluate a file of Scheme language:
gimp-console --batch-interpreter=plug-in-script-fu-eval --batch="(load \"my.scm\")"This also will print to the terminal.
ScriptFu Server
You start the server, then send snippets using a client, and receive results in the client.
The server is:
- is a long-running process
 - has persistent interpreter state
 - starts in the context of the Gimp app at the time the server is started.
 
You should only have one client at a time, since all clients share the same execution environment. A client can define objects such as images into the serving interpreter’s environment.
Starting the server
Start the Gimp app. Start it from a console i.e. terminal when you want the server to log to a terminal instead of a file.
- Choose the menu Filters>Development>Script-Fu>Start Server. Expect a dialog to appear.
 - Choose the OK button. Expect the dialog to disappear. Also expect the server to be a running process and for it to write log messages to the console in which Gimp was started.
 - Alternatively, in the dialog for the server, you choose a file for the server to log to. Then you can “tail -f” the file to see the log.
 
You can also start the server without a visible Gimp window by starting Gimp in batch (or headless) mode:
gimp-console --batch-interpreter=plug-in-script-fu-eval --batch="(plug-in-script-fu-server 1 \"127.0.0.1\" 10008 \"/tmp/SFserver.log\" )"Monitoring the server
The server logs to stdout i.e. the terminal where it was started, or to a file.
Gimp’s Client for the ScriptFu Server
The Python 3 program plug-ins/script-fu/server/servertest.py on GIMP source is
a simple client. It prompts you for snippets.
Usage: servertest.py <host> <port>
       (if omitted connect to localhost, port 10008)Start it:
python3 path_to_gimp_source/plug-ins/script-fu/server/servertest.pyExpect a banner and a prompt:
Script-Fu-Remote - Testclient
>Enter a snippet and press the Return key. Expect a result to be printed. Repeat.
Enter Control-D to quit the client.
The protocol
A client sends a header of three bytes. The first byte is a magic byte indicating the protocol in use. The second and third byte are the length of the subsequent command.
A client then sends the command itself.
The server receives the header and the command, and interprets it as a Scheme text. Then the server responds.
The server first sends a header of four bytes. The first byte is a magic byte indicating the protocol in use. The second byte is a boolean that is true if the interpreter returned an error. The third and fourth bytes encode a 16-bit integer length of the rest of the response.
Then the server sends the rest of the response. Which is either the output to stdout of the interpreted snippet, or an error message.
For both the server and the client,
when they use the recv() system call that is non-blocking,
the call might use the flag MSG_WAITALL
to ensure that all bytes are received,
since recv() can return with whatever bytes are available.
Or the server and client should use some other strategy
for assembling the components of the protocol.
The server sends a header and a response body in separate messages,
in two sends.
The recv() call does not guarantee that a message is complete.
When there are network errors, partial messages might be received, or the header message might be received and the response message never received.
Stopping the server
You can stop the server by quitting the Gimp app. The server is a separate process, but a child process of the Gimp app.
ScriptFu Text Console
ScriptFu Text Console is a textual command line similar to the graphical ScriptFu Console. It is an application program.
Using the Text Console
In an Unix terminal i.e. at a command line:
gimp-console --batch-interpreter=plug-in-script-fu-eval --batch=-Expect to see in the terminal:
Welcome to TinyScheme, Version 1.40
Copyright (c) Dimitrios Souflis
ts>This magic encantation doesn’t name “plug-in-script-fu-text-console”,
the name of the PDB procedure that is the plugin for ScriptFu Text Console.
So how does it work? Behind the scenes, that plugin is invoked.
Loosely speaking --batch=- denotes: read from stdin.
Other plugins should not call the PDB procedure “plug-in-script-fu-text-console”;
only the magic incantation should call it.
Now you can enter snippets followed by carriage return:
ts> (+ 2 3)
5
ts>The text console responds with the result of interpretation, and then another prompt.
The prompt is “ts>” but the interpreter is ScriptFu, Gimp’s wrapper of the original TinyScheme interpreter. So you can also call Gimp’s PDB procedures:
ts> (gimp-get-images)
(0 #())
ts>Control-C will terminate the text console, reverting to the shell prompt.