The Python-Fu escape hatch: run arbitrary code inside GIMP's interpreter.
Eighty typed commands cover the common ground and will never cover GIMP. This is the way out, and it is also the sharpest thing in the library, so the shape it sends is documented rather than copied.
HOW THE PLUGIN ACTUALLY DISPATCHES
execute_command is one long chain of elif j["type"] == .... Anything
that matches no branch falls through to:
elif "cmds" in j: a = ['python-fu-exec', j["cmds"]]
else: a = j["params"]['args']
and then the only test that matters:
if a[0] == 'python-fu-eval': return [str(eval(e)) for e in a[1]]
else: exec each string in a[1]
Two consequences a caller has to know:
The marker python-fu-eval is the ONLY thing that produces a VALUE.
Every other marker execs. The reference project's own protocol document
advertises pyGObject-eval for this, which matches no branch, so a
caller following that document gets exec semantics and a list of
"None" back. :eval here sends the marker that works.
The else branch reads j["params"] unguarded, so a request with no
params raises KeyError inside the plugin. Both shapes below always send
params.
State persists between calls: the plugin execs into one long-lived context
dict, so imports and variables set by an earlier call are still there. That
is useful and it is also why an exec that leaves a half-built image around
is visible to the next caller.
The Python-Fu escape hatch: run arbitrary code inside GIMP's interpreter.
Eighty typed commands cover the common ground and will never cover GIMP.
This is the way out, and it is also the sharpest thing in the library, so
the shape it sends is documented rather than copied.
HOW THE PLUGIN ACTUALLY DISPATCHES
`execute_command` is one long chain of `elif j["type"] == ...`. Anything
that matches no branch falls through to:
elif "cmds" in j: a = ['python-fu-exec', j["cmds"]]
else: a = j["params"]['args']
and then the only test that matters:
if a[0] == 'python-fu-eval': return [str(eval(e)) for e in a[1]]
else: exec each string in a[1]
Two consequences a caller has to know:
1. The marker `python-fu-eval` is the ONLY thing that produces a VALUE.
Every other marker execs. The reference project's own protocol document
advertises `pyGObject-eval` for this, which matches no branch, so a
caller following that document gets exec semantics and a list of
"None" back. `:eval` here sends the marker that works.
2. The `else` branch reads `j["params"]` unguarded, so a request with no
params raises KeyError inside the plugin. Both shapes below always send
params.
State persists between calls: the plugin execs into one long-lived context
dict, so imports and variables set by an earlier call are still there. That
is useful and it is also why an `exec` that leaves a half-built image around
is visible to the next caller.(->command {:keys [mode code]})An ExecRequest as a GimpCommand.
Pure, and separated from run so the exact bytes sent to a very sharp
interface can be asserted without a GIMP anywhere.
An `ExecRequest` as a `GimpCommand`. Pure, and separated from `run` so the exact bytes sent to a very sharp interface can be asserted without a GIMP anywhere.
The literal the plugin compares against. Not a name we chose, and not one we may spell differently.
The literal the plugin compares against. Not a name we chose, and not one we may spell differently.
Any marker that is not eval-marker execs. This one is the spelling the
reference documentation uses, so a plugin log line stays recognisable to
someone reading that project's docs.
Any marker that is not `eval-marker` execs. This one is the spelling the reference documentation uses, so a plugin log line stays recognisable to someone reading that project's docs.
(flush! transport)Push pending drawing operations to the display.
GIMP does not repaint until displays_flush() runs, so a drawing snippet
that omits it appears to have done nothing. Named as its own function
because the omission is the single most common way a correct GIMP script
looks broken.
Push pending drawing operations to the display. GIMP does not repaint until `displays_flush()` runs, so a drawing snippet that omits it appears to have done nothing. Named as its own function because the omission is the single most common way a correct GIMP script looks broken.
The bindings nearly every GIMP snippet opens by establishing.
Offered rather than imposed: with-preamble is opt-in, because a snippet
that creates its own image must not be handed one, and a snippet run against
an empty GIMP would fail on the preamble rather than on its own first line.
The bindings nearly every GIMP snippet opens by establishing. Offered rather than imposed: `with-preamble` is opt-in, because a snippet that creates its own image must not be handed one, and a snippet run against an empty GIMP would fail on the preamble rather than on its own first line.
(run transport code)(run transport code {:keys [mode preamble?] :or {mode :exec preamble? false}})Execute code inside GIMP. Returns an Outcome.
:exec returns the captured stdout of each statement; :eval returns
str() of each expression's value. Note that :eval stringifies on the
GIMP side, so a Python object comes back as its repr, not as data.
Execute `code` inside GIMP. Returns an `Outcome`. `:exec` returns the captured stdout of each statement; `:eval` returns `str()` of each expression's value. Note that `:eval` stringifies on the GIMP side, so a Python object comes back as its repr, not as data.
(with-preamble code)code prefixed with preamble.
`code` prefixed with `preamble`.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |