[gimp] app, libgimp, pdb, plug-ins: batch CLI options now interpreter aware.



commit de1d71bb3f981cdeb7eea458aa254a5481a17408
Author: Jehan <jehan girinstud io>
Date:   Sat Apr 16 23:13:50 2022 +0200

    app, libgimp, pdb, plug-ins: batch CLI options now interpreter aware.
    
    The CLI options now know which procedures are batch procedures or not.
    First it means that it won't just randomly try any procedure name one
    may pass and will properly output an error if you pass a non-existing
    interpreter procedure.
    
    Secondly, there is no default interpreter anymore (unless only one
    interpreter exists). If you don't set an interpreter procedure with
    --batch-interpreter or if you pass a wrong one, it will output the list
    of available batch procedure, thus helping you understanding how to use
    the --batch option.

 app/core/gimp-batch.c                   |  90 ++++++++++++++--
 app/pdb/pdb-cmds.c                      |  14 ++-
 app/plug-in/gimpplugin-proc.c           |  24 ++++-
 app/plug-in/gimpplugin-proc.h           |   1 +
 app/plug-in/gimppluginmanager-restore.c |   4 +
 app/plug-in/gimppluginmanager.c         |  22 ++++
 app/plug-in/gimppluginmanager.h         |   5 +
 app/plug-in/gimppluginprocedure.c       |  12 ++-
 app/plug-in/gimppluginprocedure.h       |   4 +-
 app/plug-in/plug-in-rc.c                | 185 ++++++++++++++++++--------------
 libgimp/gimpbatchprocedure.c            |  13 ++-
 libgimp/gimpbatchprocedure.h            |   1 +
 libgimp/gimppdb_pdb.c                   |   5 +-
 libgimp/gimppdb_pdb.h                   |   3 +-
 pdb/groups/pdb.pdb                      |   7 +-
 plug-ins/python/python-eval.py          |   2 +-
 plug-ins/script-fu/script-fu.c          |   2 +-
 17 files changed, 290 insertions(+), 104 deletions(-)
---
diff --git a/app/core/gimp-batch.c b/app/core/gimp-batch.c
index 059be443e8..bc20768259 100644
--- a/app/core/gimp-batch.c
+++ b/app/core/gimp-batch.c
@@ -34,10 +34,10 @@
 #include "pdb/gimppdb.h"
 #include "pdb/gimpprocedure.h"
 
-#include "gimp-intl.h"
-
+#include "plug-in/gimppluginmanager.h"
+#include "plug-in/gimppluginprocedure.h"
 
-#define BATCH_DEFAULT_EVAL_PROC   "plug-in-script-fu-eval"
+#include "gimp-intl.h"
 
 
 static void  gimp_batch_exit_after_callback (Gimp          *gimp) G_GNUC_NORETURN;
@@ -54,15 +54,22 @@ gimp_batch_run (Gimp         *gimp,
                 const gchar  *batch_interpreter,
                 const gchar **batch_commands)
 {
+  GSList *batch_procedures;
+  GSList *iter;
   gulong  exit_id;
   gint    retval = EXIT_SUCCESS;
 
   if (! batch_commands || ! batch_commands[0])
     return retval;
 
-  exit_id = g_signal_connect_after (gimp, "exit",
-                                    G_CALLBACK (gimp_batch_exit_after_callback),
-                                    NULL);
+  batch_procedures = gimp_plug_in_manager_get_batch_procedures (gimp->plug_in_manager);
+  if (g_slist_length (batch_procedures) == 0)
+    {
+      g_message (_("No batch interpreters are available. "
+                   "Batch mode disabled."));
+      retval = 69; /* EX_UNAVAILABLE - service unavailable (sysexits.h) */
+      return retval;
+    }
 
   if (! batch_interpreter)
     {
@@ -70,14 +77,77 @@ gimp_batch_run (Gimp         *gimp,
 
       if (! batch_interpreter)
         {
-          batch_interpreter = BATCH_DEFAULT_EVAL_PROC;
+          if (g_slist_length (batch_procedures) == 1)
+            {
+              batch_interpreter = gimp_object_get_name (batch_procedures->data);;
+
+              if (gimp->be_verbose)
+                g_printerr (_("No batch interpreter specified, using "
+                              "'%s'.\n"), batch_interpreter);
+            }
+          else
+            {
+              retval = 64; /* EX_USAGE - command line usage error */
+              g_print ("%s\n%s\n",
+                       _("No batch interpreter specified."),
+                       _("Available interpreters are:"));
+
+              for (iter = batch_procedures; iter; iter = iter->next)
+                {
+                  GimpPlugInProcedure *proc = iter->data;
+                  gchar               *locale_name;
+
+                  locale_name = g_locale_from_utf8 (proc->batch_interpreter_name,
+                                                    -1, NULL, NULL, NULL);
+
+                  g_print ("- %s (%s)\n",
+                           gimp_object_get_name (iter->data),
+                           locale_name ? locale_name : proc->batch_interpreter_name);
+
+                  g_free (locale_name);
+                }
+
+              return retval;
+            }
+        }
+    }
+  for (iter = batch_procedures; iter; iter = iter->next)
+    {
+      if (g_strcmp0 (gimp_object_get_name (iter->data),
+                     batch_interpreter) == 0)
+        break;
+    }
+
+  if (iter == NULL)
+    {
+      retval = 69; /* EX_UNAVAILABLE - service unavailable (sysexits.h) */
+      g_print (_("The procedure '%s' is not a valid batch interpreter."),
+                 batch_interpreter);
+      g_print ("\n%s\n%s\n",
+               _("Batch mode disabled."),
+               _("Available interpreters are:"));
+
+      for (iter = batch_procedures; iter; iter = iter->next)
+        {
+          GimpPlugInProcedure *proc = iter->data;
+          gchar               *locale_name;
+
+          locale_name = g_locale_from_utf8 (proc->batch_interpreter_name,
+                                            -1, NULL, NULL, NULL);
+
+          g_print ("- %s (%s)\n",
+                   gimp_object_get_name (iter->data),
+                   locale_name ? locale_name : proc->batch_interpreter_name);
 
-          if (gimp->be_verbose)
-            g_printerr (_("No batch interpreter specified, using the default "
-                          "'%s'.\n"), batch_interpreter);
+          g_free (locale_name);
         }
+      return retval;
     }
 
+  exit_id = g_signal_connect_after (gimp, "exit",
+                                    G_CALLBACK (gimp_batch_exit_after_callback),
+                                    NULL);
+
   /*  script-fu text console, hardcoded for backward compatibility  */
 
   if (strcmp (batch_interpreter, "plug-in-script-fu-eval") == 0 &&
diff --git a/app/pdb/pdb-cmds.c b/app/pdb/pdb-cmds.c
index e94579a95c..f7cd0fa9d9 100644
--- a/app/pdb/pdb-cmds.c
+++ b/app/pdb/pdb-cmds.c
@@ -1091,8 +1091,10 @@ pdb_set_batch_interpreter_invoker (GimpProcedure         *procedure,
 {
   gboolean success = TRUE;
   const gchar *procedure_name;
+  const gchar *interpreter_name;
 
   procedure_name = g_value_get_string (gimp_value_array_index (args, 0));
+  interpreter_name = g_value_get_string (gimp_value_array_index (args, 1));
 
   if (success)
     {
@@ -1102,8 +1104,9 @@ pdb_set_batch_interpreter_invoker (GimpProcedure         *procedure,
           gimp_pdb_is_canonical_procedure (procedure_name, error))
         {
           success = gimp_plug_in_set_batch_interpreter (plug_in,
-                                                                  procedure_name,
-                                                                  error);
+                                                        procedure_name,
+                                                        interpreter_name,
+                                                        error);
         }
       else
         success = FALSE;
@@ -2192,6 +2195,13 @@ register_pdb_procs (GimpPDB *pdb)
                                                        FALSE, FALSE, TRUE,
                                                        NULL,
                                                        GIMP_PARAM_READWRITE));
+  gimp_procedure_add_argument (procedure,
+                               gimp_param_spec_string ("interpreter-name",
+                                                       "interpreter name",
+                                                       "A public-facing name for the interpreter, such as 
\"Python 3\".",
+                                                       FALSE, FALSE, FALSE,
+                                                       NULL,
+                                                       GIMP_PARAM_READWRITE));
   gimp_pdb_register_procedure (pdb, procedure);
   g_object_unref (procedure);
 
diff --git a/app/plug-in/gimpplugin-proc.c b/app/plug-in/gimpplugin-proc.c
index 145b8154f7..0d7edf6398 100644
--- a/app/plug-in/gimpplugin-proc.c
+++ b/app/plug-in/gimpplugin-proc.c
@@ -601,9 +601,11 @@ gimp_plug_in_set_file_proc_thumb_loader (GimpPlugIn   *plug_in,
 gboolean
 gimp_plug_in_set_batch_interpreter (GimpPlugIn   *plug_in,
                                     const gchar  *proc_name,
+                                    const gchar  *interpreter_name,
                                     GError      **error)
 {
   GimpPlugInProcedure *proc;
+  GimpProcedure       *procedure;
 
   g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in), FALSE);
   g_return_val_if_fail (proc_name != NULL, FALSE);
@@ -625,7 +627,27 @@ gimp_plug_in_set_batch_interpreter (GimpPlugIn   *plug_in,
       return FALSE;
     }
 
-  gimp_plug_in_procedure_set_batch_interpreter (proc);
+  procedure = GIMP_PROCEDURE (proc);
+
+  if (procedure->num_args < 2                            ||
+      ! GIMP_IS_PARAM_SPEC_RUN_MODE (procedure->args[0]) ||
+      ! G_IS_PARAM_SPEC_STRING   (procedure->args[1]))
+    {
+      g_set_error (error, GIMP_PDB_ERROR, GIMP_PDB_ERROR_FAILED,
+                   "Plug-in \"%s\"\n(%s)\n"
+                   "attempted to register procedure \"%s\" "
+                   "as a batch interpreter which does not take the standard "
+                   "batch interpreter procedure arguments: "
+                   "(GimpRunMode, gchar *) -> ()",
+                   gimp_object_get_name (plug_in),
+                   gimp_file_get_utf8_name (plug_in->file),
+                   proc_name);
+
+      return FALSE;
+    }
+
+  gimp_plug_in_procedure_set_batch_interpreter (proc, interpreter_name);
+  gimp_plug_in_manager_add_batch_procedure (plug_in->manager, proc);
 
   return TRUE;
 }
diff --git a/app/plug-in/gimpplugin-proc.h b/app/plug-in/gimpplugin-proc.h
index dd53a9d340..9c12b82706 100644
--- a/app/plug-in/gimpplugin-proc.h
+++ b/app/plug-in/gimpplugin-proc.h
@@ -87,6 +87,7 @@ gboolean   gimp_plug_in_set_file_proc_thumb_loader   (GimpPlugIn    *plug_in,
                                                       GError       **error);
 gboolean   gimp_plug_in_set_batch_interpreter        (GimpPlugIn   *plug_in,
                                                       const gchar  *proc_name,
+                                                      const gchar  *interpreter_name,
                                                       GError      **error);
 
 
diff --git a/app/plug-in/gimppluginmanager-restore.c b/app/plug-in/gimppluginmanager-restore.c
index e2102d1873..32f12f68d5 100644
--- a/app/plug-in/gimppluginmanager-restore.c
+++ b/app/plug-in/gimppluginmanager-restore.c
@@ -854,6 +854,10 @@ gimp_plug_in_manager_add_to_db (GimpPlugInManager   *manager,
           gimp_plug_in_manager_add_load_procedure (manager, proc);
         }
     }
+  else if (proc->batch_interpreter)
+    {
+      gimp_plug_in_manager_add_batch_procedure (manager, proc);
+    }
 }
 
 static void
diff --git a/app/plug-in/gimppluginmanager.c b/app/plug-in/gimppluginmanager.c
index 83b73354c8..31b86e1cde 100644
--- a/app/plug-in/gimppluginmanager.c
+++ b/app/plug-in/gimppluginmanager.c
@@ -134,6 +134,7 @@ gimp_plug_in_manager_finalize (GObject *object)
   g_clear_pointer (&manager->save_procs,     g_slist_free);
   g_clear_pointer (&manager->export_procs,   g_slist_free);
   g_clear_pointer (&manager->raw_load_procs, g_slist_free);
+  g_clear_pointer (&manager->batch_procs,    g_slist_free);
 
   g_clear_pointer (&manager->display_load_procs,     g_slist_free);
   g_clear_pointer (&manager->display_save_procs,     g_slist_free);
@@ -184,6 +185,7 @@ gimp_plug_in_manager_get_memsize (GimpObject *object,
   memsize += gimp_g_slist_get_memsize (manager->save_procs, 0);
   memsize += gimp_g_slist_get_memsize (manager->export_procs, 0);
   memsize += gimp_g_slist_get_memsize (manager->raw_load_procs, 0);
+  memsize += gimp_g_slist_get_memsize (manager->batch_procs, 0);
   memsize += gimp_g_slist_get_memsize (manager->display_load_procs, 0);
   memsize += gimp_g_slist_get_memsize (manager->display_save_procs, 0);
   memsize += gimp_g_slist_get_memsize (manager->display_export_procs, 0);
@@ -316,6 +318,7 @@ gimp_plug_in_manager_add_procedure (GimpPlugInManager   *manager,
           manager->save_procs             = g_slist_remove (manager->save_procs,             tmp_proc);
           manager->export_procs           = g_slist_remove (manager->export_procs,           tmp_proc);
           manager->raw_load_procs         = g_slist_remove (manager->raw_load_procs,         tmp_proc);
+          manager->batch_procs            = g_slist_remove (manager->batch_procs,            tmp_proc);
           manager->display_load_procs     = g_slist_remove (manager->display_load_procs,     tmp_proc);
           manager->display_save_procs     = g_slist_remove (manager->display_save_procs,     tmp_proc);
           manager->display_export_procs   = g_slist_remove (manager->display_export_procs,   tmp_proc);
@@ -334,6 +337,25 @@ gimp_plug_in_manager_add_procedure (GimpPlugInManager   *manager,
                                                  g_object_ref (procedure));
 }
 
+void
+gimp_plug_in_manager_add_batch_procedure (GimpPlugInManager   *manager,
+                                          GimpPlugInProcedure *proc)
+{
+  g_return_if_fail (GIMP_IS_PLUG_IN_MANAGER (manager));
+  g_return_if_fail (GIMP_IS_PLUG_IN_PROCEDURE (proc));
+
+  if (! g_slist_find (manager->batch_procs, proc))
+    manager->batch_procs = g_slist_prepend (manager->batch_procs, proc);
+}
+
+GSList *
+gimp_plug_in_manager_get_batch_procedures (GimpPlugInManager *manager)
+{
+  g_return_val_if_fail (GIMP_IS_PLUG_IN_MANAGER (manager), NULL);
+
+  return manager->batch_procs;
+}
+
 void
 gimp_plug_in_manager_add_temp_proc (GimpPlugInManager      *manager,
                                     GimpTemporaryProcedure *procedure)
diff --git a/app/plug-in/gimppluginmanager.h b/app/plug-in/gimppluginmanager.h
index 11f80b120f..18328e3750 100644
--- a/app/plug-in/gimppluginmanager.h
+++ b/app/plug-in/gimppluginmanager.h
@@ -48,6 +48,7 @@ struct _GimpPlugInManager
   GSList            *save_procs;
   GSList            *export_procs;
   GSList            *raw_load_procs;
+  GSList            *batch_procs;
 
   GSList            *display_load_procs;
   GSList            *display_save_procs;
@@ -100,6 +101,10 @@ void    gimp_plug_in_manager_exit                 (GimpPlugInManager   *manager)
 void    gimp_plug_in_manager_add_procedure        (GimpPlugInManager   *manager,
                                                    GimpPlugInProcedure *procedure);
 
+void    gimp_plug_in_manager_add_batch_procedure  (GimpPlugInManager      *manager,
+                                                   GimpPlugInProcedure    *proc);
+GSList * gimp_plug_in_manager_get_batch_procedures (GimpPlugInManager      *manager);
+
 void    gimp_plug_in_manager_add_temp_proc        (GimpPlugInManager      *manager,
                                                    GimpTemporaryProcedure *procedure);
 void    gimp_plug_in_manager_remove_temp_proc     (GimpPlugInManager      *manager,
diff --git a/app/plug-in/gimppluginprocedure.c b/app/plug-in/gimppluginprocedure.c
index 9ba1469ab4..cb2594595c 100644
--- a/app/plug-in/gimppluginprocedure.c
+++ b/app/plug-in/gimppluginprocedure.c
@@ -171,6 +171,7 @@ gimp_plug_in_procedure_finalize (GObject *object)
   g_slist_free_full (proc->mime_types_list, (GDestroyNotify) g_free);
 
   g_free (proc->thumb_loader);
+  g_free (proc->batch_interpreter_name);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -207,6 +208,7 @@ gimp_plug_in_procedure_get_memsize (GimpObject *object,
   memsize += gimp_string_get_memsize (proc->magics);
   memsize += gimp_string_get_memsize (proc->mime_types);
   memsize += gimp_string_get_memsize (proc->thumb_loader);
+  memsize += gimp_string_get_memsize (proc->batch_interpreter_name);
 
   for (slist = proc->extensions_list; slist; slist = g_slist_next (slist))
     memsize += sizeof (GSList) + gimp_string_get_memsize (slist->data);
@@ -1275,11 +1277,17 @@ gimp_plug_in_procedure_set_thumb_loader (GimpPlugInProcedure *proc,
 }
 
 void
-gimp_plug_in_procedure_set_batch_interpreter (GimpPlugInProcedure *proc)
+gimp_plug_in_procedure_set_batch_interpreter (GimpPlugInProcedure *proc,
+                                              const gchar         *name)
 {
   g_return_if_fail (GIMP_IS_PLUG_IN_PROCEDURE (proc));
+  g_return_if_fail (name != NULL);
 
-  proc->batch_interpreter = TRUE;
+  if (proc->batch_interpreter_name)
+    g_free (proc->batch_interpreter_name);
+
+  proc->batch_interpreter      = TRUE;
+  proc->batch_interpreter_name = g_strdup (name);
 }
 
 void
diff --git a/app/plug-in/gimppluginprocedure.h b/app/plug-in/gimppluginprocedure.h
index efa91b1eba..83500be4c0 100644
--- a/app/plug-in/gimppluginprocedure.h
+++ b/app/plug-in/gimppluginprocedure.h
@@ -66,6 +66,7 @@ struct _GimpPlugInProcedure
   gboolean             handles_remote;
   gboolean             handles_raw;
   gboolean             batch_interpreter;
+  gchar               *batch_interpreter_name;
   GSList              *extensions_list;
   GSList              *prefixes_list;
   GSList              *magics_list;
@@ -142,7 +143,8 @@ void          gimp_plug_in_procedure_set_handles_remote(GimpPlugInProcedure *pro
 void          gimp_plug_in_procedure_set_handles_raw   (GimpPlugInProcedure *proc);
 void          gimp_plug_in_procedure_set_thumb_loader  (GimpPlugInProcedure *proc,
                                                         const gchar         *thumbnailer);
-void          gimp_plug_in_procedure_set_batch_interpreter (GimpPlugInProcedure *proc);
+void      gimp_plug_in_procedure_set_batch_interpreter (GimpPlugInProcedure *proc,
+                                                        const gchar         *name);
 
 void       gimp_plug_in_procedure_handle_return_values (GimpPlugInProcedure *proc,
                                                         Gimp                *gimp,
diff --git a/app/plug-in/plug-in-rc.c b/app/plug-in/plug-in-rc.c
index 1070fd10fc..500e6f1404 100644
--- a/app/plug-in/plug-in-rc.c
+++ b/app/plug-in/plug-in-rc.c
@@ -60,8 +60,8 @@ static GTokenType plug_in_menu_path_deserialize  (GScanner             *scanner,
                                                   GimpPlugInProcedure  *proc);
 static GTokenType plug_in_icon_deserialize       (GScanner             *scanner,
                                                   GimpPlugInProcedure  *proc);
-static GTokenType plug_in_file_proc_deserialize  (GScanner             *scanner,
-                                                  GimpPlugInProcedure  *proc);
+static GTokenType plug_in_file_or_batch_proc_deserialize  (GScanner             *scanner,
+                                                           GimpPlugInProcedure  *proc);
 static GTokenType plug_in_proc_arg_deserialize   (GScanner             *scanner,
                                                   Gimp                 *gimp,
                                                   GimpProcedure        *procedure,
@@ -95,7 +95,8 @@ enum
   MIME_TYPES,
   HANDLES_REMOTE,
   HANDLES_RAW,
-  THUMB_LOADER
+  THUMB_LOADER,
+  BATCH_INTERPRETER,
 };
 
 
@@ -149,6 +150,8 @@ plug_in_rc_parse (Gimp    *gimp,
                               "load-proc", GINT_TO_POINTER (LOAD_PROC));
   g_scanner_scope_add_symbol (scanner, PLUG_IN_DEF,
                               "save-proc", GINT_TO_POINTER (SAVE_PROC));
+  g_scanner_scope_add_symbol (scanner, PLUG_IN_DEF,
+                              "batch-interpreter", GINT_TO_POINTER (BATCH_INTERPRETER));
 
   g_scanner_scope_add_symbol (scanner, LOAD_PROC,
                               "extensions", GINT_TO_POINTER (EXTENSIONS));
@@ -449,7 +452,7 @@ plug_in_procedure_deserialize (GScanner             *scanner,
   if (token != G_TOKEN_LEFT_PAREN)
     return token;
 
-  token = plug_in_file_proc_deserialize (scanner, *proc);
+  token = plug_in_file_or_batch_proc_deserialize (scanner, *proc);
   if (token != G_TOKEN_LEFT_PAREN)
     return token;
 
@@ -609,8 +612,8 @@ plug_in_icon_deserialize (GScanner            *scanner,
 }
 
 static GTokenType
-plug_in_file_proc_deserialize (GScanner            *scanner,
-                               GimpPlugInProcedure *proc)
+plug_in_file_or_batch_proc_deserialize (GScanner            *scanner,
+                                        GimpPlugInProcedure *proc)
 {
   GTokenType token;
   gint       symbol;
@@ -622,113 +625,126 @@ plug_in_file_proc_deserialize (GScanner            *scanner,
     return G_TOKEN_SYMBOL;
 
   symbol = GPOINTER_TO_INT (scanner->value.v_symbol);
-  if (symbol != LOAD_PROC && symbol != SAVE_PROC)
+  if (symbol != LOAD_PROC && symbol != SAVE_PROC && symbol != BATCH_INTERPRETER)
     return G_TOKEN_SYMBOL;
 
-  proc->file_proc = TRUE;
+  if (symbol == BATCH_INTERPRETER)
+    {
+      gchar *interpreter_name;
 
-  g_scanner_set_scope (scanner, symbol);
+      if (! gimp_scanner_parse_string (scanner, &interpreter_name))
+        return G_TOKEN_STRING;
 
-  while (g_scanner_peek_next_token (scanner) == G_TOKEN_LEFT_PAREN)
+      gimp_plug_in_procedure_set_batch_interpreter (proc, interpreter_name);
+      g_free (interpreter_name);
+    }
+  else
     {
-      token = g_scanner_get_next_token (scanner);
+      proc->file_proc = TRUE;
 
-      if (token != G_TOKEN_LEFT_PAREN)
-        return token;
+      g_scanner_set_scope (scanner, symbol);
 
-      if (! gimp_scanner_parse_token (scanner, G_TOKEN_SYMBOL))
-        return G_TOKEN_SYMBOL;
+      while (g_scanner_peek_next_token (scanner) == G_TOKEN_LEFT_PAREN)
+        {
+          token = g_scanner_get_next_token (scanner);
 
-      symbol = GPOINTER_TO_INT (scanner->value.v_symbol);
+          if (token != G_TOKEN_LEFT_PAREN)
+            return token;
 
-      switch (symbol)
-        {
-        case EXTENSIONS:
-          {
-            gchar *extensions;
+          if (! gimp_scanner_parse_token (scanner, G_TOKEN_SYMBOL))
+            return G_TOKEN_SYMBOL;
 
-            if (! gimp_scanner_parse_string (scanner, &extensions))
-              return G_TOKEN_STRING;
+          symbol = GPOINTER_TO_INT (scanner->value.v_symbol);
 
-            g_free (proc->extensions);
-            proc->extensions = extensions;
-          }
-          break;
+          switch (symbol)
+            {
+            case EXTENSIONS:
+                {
+                  gchar *extensions;
 
-        case PREFIXES:
-          {
-            gchar *prefixes;
+                  if (! gimp_scanner_parse_string (scanner, &extensions))
+                    return G_TOKEN_STRING;
 
-            if (! gimp_scanner_parse_string (scanner, &prefixes))
-              return G_TOKEN_STRING;
+                  g_free (proc->extensions);
+                  proc->extensions = extensions;
+                }
+              break;
 
-            g_free (proc->prefixes);
-            proc->prefixes = prefixes;
-          }
-          break;
+            case PREFIXES:
+                {
+                  gchar *prefixes;
 
-        case MAGICS:
-          {
-            gchar *magics;
+                  if (! gimp_scanner_parse_string (scanner, &prefixes))
+                    return G_TOKEN_STRING;
 
-            if (! gimp_scanner_parse_string_no_validate (scanner, &magics))
-              return G_TOKEN_STRING;
+                  g_free (proc->prefixes);
+                  proc->prefixes = prefixes;
+                }
+              break;
 
-            g_free (proc->magics);
-            proc->magics = magics;
-          }
-          break;
+            case MAGICS:
+                {
+                  gchar *magics;
+
+                  if (! gimp_scanner_parse_string_no_validate (scanner, &magics))
+                    return G_TOKEN_STRING;
+
+                  g_free (proc->magics);
+                  proc->magics = magics;
+                }
+              break;
 
-        case PRIORITY:
-          {
-            gint priority;
+            case PRIORITY:
+                {
+                  gint priority;
 
-            if (! gimp_scanner_parse_int (scanner, &priority))
-              return G_TOKEN_INT;
+                  if (! gimp_scanner_parse_int (scanner, &priority))
+                    return G_TOKEN_INT;
 
-            gimp_plug_in_procedure_set_priority (proc, priority);
-          }
-          break;
+                  gimp_plug_in_procedure_set_priority (proc, priority);
+                }
+              break;
 
-        case MIME_TYPES:
-          {
-            gchar *mime_types;
+            case MIME_TYPES:
+                {
+                  gchar *mime_types;
 
-            if (! gimp_scanner_parse_string (scanner, &mime_types))
-              return G_TOKEN_STRING;
+                  if (! gimp_scanner_parse_string (scanner, &mime_types))
+                    return G_TOKEN_STRING;
 
-            gimp_plug_in_procedure_set_mime_types (proc, mime_types);
+                  gimp_plug_in_procedure_set_mime_types (proc, mime_types);
 
-            g_free (mime_types);
-          }
-          break;
+                  g_free (mime_types);
+                }
+              break;
 
-        case HANDLES_REMOTE:
-          gimp_plug_in_procedure_set_handles_remote (proc);
-          break;
+            case HANDLES_REMOTE:
+              gimp_plug_in_procedure_set_handles_remote (proc);
+              break;
 
-        case HANDLES_RAW:
-          gimp_plug_in_procedure_set_handles_raw (proc);
-          break;
+            case HANDLES_RAW:
+              gimp_plug_in_procedure_set_handles_raw (proc);
+              break;
 
-        case THUMB_LOADER:
-          {
-            gchar *thumb_loader;
+            case THUMB_LOADER:
+                {
+                  gchar *thumb_loader;
 
-            if (! gimp_scanner_parse_string (scanner, &thumb_loader))
-              return G_TOKEN_STRING;
+                  if (! gimp_scanner_parse_string (scanner, &thumb_loader))
+                    return G_TOKEN_STRING;
 
-            gimp_plug_in_procedure_set_thumb_loader (proc, thumb_loader);
+                  gimp_plug_in_procedure_set_thumb_loader (proc, thumb_loader);
 
-            g_free (thumb_loader);
-          }
-          break;
+                  g_free (thumb_loader);
+                }
+              break;
 
-        default:
-           return G_TOKEN_SYMBOL;
+            default:
+              return G_TOKEN_SYMBOL;
+            }
+          if (! gimp_scanner_parse_token (scanner, G_TOKEN_RIGHT_PAREN))
+            return G_TOKEN_RIGHT_PAREN;
         }
-      if (! gimp_scanner_parse_token (scanner, G_TOKEN_RIGHT_PAREN))
-        return G_TOKEN_RIGHT_PAREN;
     }
 
   if (! gimp_scanner_parse_token (scanner, G_TOKEN_RIGHT_PAREN))
@@ -1281,6 +1297,13 @@ plug_in_rc_write (GSList  *plug_in_defs,
 
                   gimp_config_writer_close (writer);
                 }
+              else if (proc->batch_interpreter)
+                {
+                  gimp_config_writer_open (writer, "batch-interpreter");
+                  gimp_config_writer_string (writer, proc->batch_interpreter_name);
+                  gimp_config_writer_close (writer);
+                }
+
 
               gimp_config_writer_linefeed (writer);
 
diff --git a/libgimp/gimpbatchprocedure.c b/libgimp/gimpbatchprocedure.c
index 73f21b3b96..c7f16487e5 100644
--- a/libgimp/gimpbatchprocedure.c
+++ b/libgimp/gimpbatchprocedure.c
@@ -108,9 +108,14 @@ gimp_batch_procedure_finalize (GObject *object)
 static void
 gimp_batch_procedure_install (GimpProcedure *procedure)
 {
+  GimpBatchProcedure *proc = GIMP_BATCH_PROCEDURE (procedure);
+
+  g_return_if_fail (proc->priv->interpreter_name != NULL);
+
   GIMP_PROCEDURE_CLASS (parent_class)->install (procedure);
 
-  _gimp_pdb_set_batch_interpreter (gimp_procedure_get_name (procedure));
+  _gimp_pdb_set_batch_interpreter (gimp_procedure_get_name (procedure),
+                                   proc->priv->interpreter_name);
 }
 
 #define ARG_OFFSET 2
@@ -175,6 +180,7 @@ gimp_batch_procedure_create_config (GimpProcedure  *procedure,
  * gimp_batch_procedure_new:
  * @plug_in:          a #GimpPlugIn.
  * @name:             the new procedure's name.
+ * @interpreter_name: the public-facing name, e.g. "Python 3".
  * @proc_type:        the new procedure's #GimpPDBProcType.
  * @run_func:         the run function for the new procedure.
  * @run_data:         user data passed to @run_func.
@@ -207,6 +213,7 @@ gimp_batch_procedure_create_config (GimpProcedure  *procedure,
 GimpProcedure  *
 gimp_batch_procedure_new (GimpPlugIn       *plug_in,
                           const gchar      *name,
+                          const gchar      *interpreter_name,
                           GimpPDBProcType   proc_type,
                           GimpBatchFunc     run_func,
                           gpointer          run_data,
@@ -216,6 +223,7 @@ gimp_batch_procedure_new (GimpPlugIn       *plug_in,
 
   g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in), NULL);
   g_return_val_if_fail (gimp_is_canonical_identifier (name), NULL);
+  g_return_val_if_fail (interpreter_name != NULL && g_utf8_validate (interpreter_name, -1, NULL), NULL);
   g_return_val_if_fail (proc_type != GIMP_PDB_PROC_TYPE_INTERNAL, NULL);
   g_return_val_if_fail (proc_type != GIMP_PDB_PROC_TYPE_EXTENSION, NULL);
   g_return_val_if_fail (run_func != NULL, NULL);
@@ -230,6 +238,8 @@ gimp_batch_procedure_new (GimpPlugIn       *plug_in,
   procedure->priv->run_data         = run_data;
   procedure->priv->run_data_destroy = run_data_destroy;
 
+  gimp_batch_procedure_set_interpreter_name (procedure, interpreter_name);
+
   return GIMP_PROCEDURE (procedure);
 }
 
@@ -263,6 +273,7 @@ gimp_batch_procedure_set_interpreter_name (GimpBatchProcedure *procedure,
                                            const gchar        *interpreter_name)
 {
   g_return_if_fail (GIMP_IS_BATCH_PROCEDURE (procedure));
+  g_return_if_fail (interpreter_name != NULL && g_utf8_validate (interpreter_name, -1, NULL));
 
   g_free (procedure->priv->interpreter_name);
   procedure->priv->interpreter_name = g_strdup (interpreter_name);
diff --git a/libgimp/gimpbatchprocedure.h b/libgimp/gimpbatchprocedure.h
index 080e3d9cb4..aab7c01a90 100644
--- a/libgimp/gimpbatchprocedure.h
+++ b/libgimp/gimpbatchprocedure.h
@@ -79,6 +79,7 @@ GType           gimp_batch_procedure_get_type             (void) G_GNUC_CONST;
 
 GimpProcedure * gimp_batch_procedure_new                  (GimpPlugIn      *plug_in,
                                                            const gchar     *name,
+                                                           const gchar     *interpreter_name,
                                                            GimpPDBProcType  proc_type,
                                                            GimpBatchFunc    run_func,
                                                            gpointer         run_data,
diff --git a/libgimp/gimppdb_pdb.c b/libgimp/gimppdb_pdb.c
index 0278366741..fcff5f4ab1 100644
--- a/libgimp/gimppdb_pdb.c
+++ b/libgimp/gimppdb_pdb.c
@@ -1140,6 +1140,7 @@ _gimp_pdb_set_file_proc_thumbnail_loader (const gchar *load_proc,
 /**
  * _gimp_pdb_set_batch_interpreter:
  * @procedure_name: The name of the procedure to be used for running batch commands.
+ * @interpreter_name: A public-facing name for the interpreter, such as \"Python 3\".
  *
  * Registers a batch interpreter procedure.
  *
@@ -1151,7 +1152,8 @@ _gimp_pdb_set_file_proc_thumbnail_loader (const gchar *load_proc,
  * Since: 3.0
  **/
 gboolean
-_gimp_pdb_set_batch_interpreter (const gchar *procedure_name)
+_gimp_pdb_set_batch_interpreter (const gchar *procedure_name,
+                                 const gchar *interpreter_name)
 {
   GimpValueArray *args;
   GimpValueArray *return_vals;
@@ -1159,6 +1161,7 @@ _gimp_pdb_set_batch_interpreter (const gchar *procedure_name)
 
   args = gimp_value_array_new_from_types (NULL,
                                           G_TYPE_STRING, procedure_name,
+                                          G_TYPE_STRING, interpreter_name,
                                           G_TYPE_NONE);
 
   return_vals = gimp_pdb_run_procedure_array (gimp_get_pdb (),
diff --git a/libgimp/gimppdb_pdb.h b/libgimp/gimppdb_pdb.h
index f39465c0fb..3ffd4ae568 100644
--- a/libgimp/gimppdb_pdb.h
+++ b/libgimp/gimppdb_pdb.h
@@ -97,7 +97,8 @@ G_GNUC_INTERNAL gboolean    _gimp_pdb_set_file_proc_handles_remote   (const gcha
 G_GNUC_INTERNAL gboolean    _gimp_pdb_set_file_proc_handles_raw      (const gchar       *procedure_name);
 G_GNUC_INTERNAL gboolean    _gimp_pdb_set_file_proc_thumbnail_loader (const gchar       *load_proc,
                                                                       const gchar       *thumb_proc);
-G_GNUC_INTERNAL gboolean    _gimp_pdb_set_batch_interpreter          (const gchar       *procedure_name);
+G_GNUC_INTERNAL gboolean    _gimp_pdb_set_batch_interpreter          (const gchar       *procedure_name,
+                                                                      const gchar       *interpreter_name);
 G_GNUC_INTERNAL gboolean    _gimp_pdb_get_data                       (const gchar       *identifier,
                                                                       gint              *bytes,
                                                                       guint8           **data);
diff --git a/pdb/groups/pdb.pdb b/pdb/groups/pdb.pdb
index 5aafff8874..bcc0644dab 100644
--- a/pdb/groups/pdb.pdb
+++ b/pdb/groups/pdb.pdb
@@ -1171,6 +1171,8 @@ HELP
     @inargs = (
         { name => 'procedure_name', type => 'string', non_empty => 1,
           desc => 'The name of the procedure to be used for running batch commands' },
+        { name => 'interpreter_name', type => 'string',
+          desc => 'A public-facing name for the interpreter, such as "Python 3".' }
     );
 
     %invoke = (
@@ -1182,8 +1184,9 @@ HELP
       gimp_pdb_is_canonical_procedure (procedure_name, error))
     {
       success = gimp_plug_in_set_batch_interpreter (plug_in,
-                                                              procedure_name,
-                                                              error);
+                                                    procedure_name,
+                                                    interpreter_name,
+                                                    error);
     }
   else
     success = FALSE;
diff --git a/plug-ins/python/python-eval.py b/plug-ins/python/python-eval.py
index c0b51a0338..f351de2a85 100644
--- a/plug-ins/python/python-eval.py
+++ b/plug-ins/python/python-eval.py
@@ -42,7 +42,7 @@ class PythonEval (Gimp.PlugIn):
         return ['python-fu-eval']
 
     def do_create_procedure(self, name):
-        procedure = Gimp.BatchProcedure.new(self, name,
+        procedure = Gimp.BatchProcedure.new(self, name, "Python 3",
                                             Gimp.PDBProcType.PLUGIN,
                                             code_eval, None)
         procedure.set_documentation ("Evaluate Python code",
diff --git a/plug-ins/script-fu/script-fu.c b/plug-ins/script-fu/script-fu.c
index 5dd8e90aac..87b87b5fb7 100644
--- a/plug-ins/script-fu/script-fu.c
+++ b/plug-ins/script-fu/script-fu.c
@@ -243,7 +243,7 @@ script_fu_create_procedure (GimpPlugIn  *plug_in,
     }
   else if (! strcmp (name, "plug-in-script-fu-eval"))
     {
-      procedure = gimp_batch_procedure_new (plug_in, name,
+      procedure = gimp_batch_procedure_new (plug_in, name, "Script-fu (scheme)",
                                             GIMP_PDB_PROC_TYPE_PLUGIN,
                                             script_fu_batch_run, NULL, NULL);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]