Re: Plugin API



Morten Welinder wrote:
Is that's how it's supposed to be handled in the
Perl and Python loaders, too? Right now, they don't provide any help
information at all.

That's the plan (and help would be appreciated).

There you go, patch against 1.9.12 attached. This is only for the Perl
plugin, though, and it might be less than optimal since I don't know
much about Perl, so someone in the know please review it. The patch also
includes a suitably updated version of the perl-func.pl script. I tested
that here on a x86_64 Linux system, and it seems to work fine.

Unfortunately, the Python plugin will require more work, since right now
it's set up to use the Python docstrings. I'll leave that to someone who
knows more about the Python C API. ;-) But of course the same kind of
approach as in the Perl plugin could be used instead.

I've also fixed my Pure plugin accordingly, so it's a well-behaved
citizen in Gnumeric 1.9.12 now.

Cheers,
Albert

-- 
Dr. Albert Gr"af
Dept. of Music-Informatics, University of Mainz, Germany
Email:  Dr Graef t-online de, ag muwiinfa geschichte uni-mainz de
WWW:    http://www.musikinformatik.uni-mainz.de/ag
diff -ru gnumeric-1.9.12.orig//plugins/perl-func/perl_func.pl gnumeric-1.9.12/plugins/perl-func/perl_func.pl
--- gnumeric-1.9.12.orig//plugins/perl-func/perl_func.pl        2009-05-19 04:04:09.000000000 +0200
+++ gnumeric-1.9.12/plugins/perl-func/perl_func.pl      2009-09-15 21:54:11.000000000 +0200
@@ -6,16 +6,15 @@
 }
 
 sub help_perl_adder {
-  return<<'EOS';
- FUNCTION=PERL_ADDER
- SYNTAX=PERL_ADDER(a,b)
- DESCRIPTION=
-Adds two numbers. It is just an example function.
-EOS
+  return ($GNM_FUNC_HELP_NAME, "PERL_ADDER:adds two numbers",
+         $GNM_FUNC_HELP_ARG, "a:number",
+         $GNM_FUNC_HELP_ARG, "b:number",
+         $GNM_FUNC_HELP_DESCRIPTION, "Adds two numbers. It is just an example function.",
+         $GNM_FUNC_HELP_EXAMPLES, "=PERL_ADDER(17,22)");
 }
 
 sub desc_perl_adder {
-  return ("ff", "a,b,c");
+  return "ff";
 }
 
 sub func_perl_date {
@@ -24,16 +23,13 @@
 }
 
 sub help_perl_date {
-  return<<'EOS';
- FUNCTION=PERL_DATE
- SYNTAX=PERL_DATE()
- DESCRIPTION=
-Return today's date as string.
-EOS
+  return ($GNM_FUNC_HELP_NAME, "PERL_DATE:today's date",
+         $GNM_FUNC_HELP_DESCRIPTION, "Return today's date as string.",
+         $GNM_FUNC_HELP_EXAMPLES, "=PERL_DATE()");
 }
 
 sub desc_perl_date {
-  return ("", "");
+  return "";
 }
 
 sub func_perl_sed {
@@ -47,14 +43,16 @@
 }
 
 sub help_perl_sed {
-  return<<'EOS';
- FUNCTION=PERL_SED
- SYNTAX=PERL_SED(a,b,c)
- DESCRIPTION=
-Substite string with matching pattern. Same as $a =~ s/$b/$c/g .
+  return ($GNM_FUNC_HELP_NAME, "PERL_SED:string substitution",
+         $GNM_FUNC_HELP_ARG, "a:string",
+         $GNM_FUNC_HELP_ARG, "b:string",
+         $GNM_FUNC_HELP_ARG, "c:string",
+         $GNM_FUNC_HELP_DESCRIPTION, <<'EOS',
+Substitute string with matching pattern. Same as $ {a} =~ s/$ {b}/$ {c}/g.
 EOS
+         $GNM_FUNC_HELP_EXAMPLES, "=PERL_SED(\"abc\",\"b\",\"d\")");
 }
 
 sub desc_perl_sed {
-  return ("sss", "a,b,c");
+  return "sss";
 }
diff -ru gnumeric-1.9.12.orig//plugins/perl-loader/perl-loader.c 
gnumeric-1.9.12/plugins/perl-loader/perl-loader.c
--- gnumeric-1.9.12.orig//plugins/perl-loader/perl-loader.c     2009-08-24 02:38:06.000000000 +0200
+++ gnumeric-1.9.12/plugins/perl-loader/perl-loader.c   2009-09-15 21:51:51.000000000 +0200
@@ -43,19 +43,6 @@
 } GnmPerlPluginLoader;
 typedef GObjectClass GnmPerlPluginLoaderClass;
 
-static const char help_template_text[] =
-       N_("@FUNCTION=PERL_FUNCTION_TEMPLATE\n"
-          "@SYNTAX=PERL_FUNCTION_TEMPLATE(value1, value2, ...)\n"
-          "@DESCRIPTION="
-          "This is the perl function template. \n");
-
-static GnmFuncHelp help_template[] = {
-#if 0
-       { GNM_FUNC_HELP_OLD, help_template_text },
-#endif
-       { GNM_FUNC_HELP_END }
-};
-
 static GnmValue*
 call_perl_function_args (GnmFuncEvalInfo *ei, GnmValue const * const *args)
 {
@@ -104,6 +91,102 @@
        return result;
 }
 
+static void init_help_consts(void)
+{
+  SV* x;
+  x = get_sv("GNM_FUNC_HELP_NAME", TRUE); sv_setiv(x, GNM_FUNC_HELP_NAME);
+  x = get_sv("GNM_FUNC_HELP_ARG", TRUE); sv_setiv(x, GNM_FUNC_HELP_ARG);
+  x = get_sv("GNM_FUNC_HELP_DESCRIPTION", TRUE); sv_setiv(x, GNM_FUNC_HELP_DESCRIPTION);
+  x = get_sv("GNM_FUNC_HELP_NOTE", TRUE); sv_setiv(x, GNM_FUNC_HELP_NOTE);
+  x = get_sv("GNM_FUNC_HELP_EXAMPLES", TRUE); sv_setiv(x, GNM_FUNC_HELP_EXAMPLES);
+  x = get_sv("GNM_FUNC_HELP_SEEALSO", TRUE); sv_setiv(x, GNM_FUNC_HELP_SEEALSO);
+  x = get_sv("GNM_FUNC_HELP_EXTREF", TRUE); sv_setiv(x, GNM_FUNC_HELP_EXTREF);
+  x = get_sv("GNM_FUNC_HELP_EXCEL", TRUE); sv_setiv(x, GNM_FUNC_HELP_EXCEL);
+  x = get_sv("GNM_FUNC_HELP_ODF", TRUE); sv_setiv(x, GNM_FUNC_HELP_ODF);
+}
+
+static const char help_template_text[] =
+  "This Perl function hasn't been documented.";
+
+static GnmFuncHelp help_template[] = {
+  { GNM_FUNC_HELP_NAME, NULL },
+  { GNM_FUNC_HELP_DESCRIPTION, NULL },
+  { GNM_FUNC_HELP_END }
+};
+
+static GnmFuncHelp *default_gnm_help(const char *name)
+{
+  GnmFuncHelp *help = g_new(GnmFuncHelp, 3);
+  if (help) {
+    int i;
+    for (i = 0; i < 3; i++)
+      help[i] = help_template[i];
+    help[0].text = g_strdup_printf("%s:", name);
+    help[1].text = g_strdup(help_template_text);
+  }
+  return help;
+}
+
+static GnmFuncHelp *make_gnm_help(const char *name, int count, SV **SP)
+{
+  gchar *help_perl_func = g_strconcat ("help_", name, NULL);
+  GnmFuncHelp *help = NULL;
+  /* We assume that the description is a Perl array of the form
+     (key, text, key, text, ...). */
+  int n = count/2, m = 0, k, type = GNM_FUNC_HELP_END;
+  GnmFuncHelp *helptmp = g_new(GnmFuncHelp, n+1);
+  if (count%2) POPs, count--;
+  for (k = n; k-- > 0; ) {
+    SV *sv = POPs;
+    if (SvPOK(sv)) {
+      STRLEN size;
+      gchar *tmp;
+      tmp = SvPV(sv, size);
+      helptmp[k].text = g_strndup(tmp, size);
+    } else {
+      helptmp[k].text = NULL;
+    }
+    sv = POPs;
+    if (SvIOK(sv)) type = SvIV(sv);
+    if (helptmp[k].text &&
+       type >= GNM_FUNC_HELP_NAME && GNM_FUNC_HELP_ODF) {
+      helptmp[k].type = type; m++;
+    } else {
+      helptmp[k].type = GNM_FUNC_HELP_END;
+      if (helptmp[k].text) g_free((char*)helptmp[k].text);
+      helptmp[k].text = NULL;
+    }
+  }
+  if (m == 0) {
+    /* No valid entries. */
+    g_free(helptmp);
+  } else {
+    /* Collect all valid entries in a new array. */
+    if (n == m)
+      help = helptmp;
+    else {
+      int i;
+      help = g_new(GnmFuncHelp, m+1);
+      for (i = 0, k = 0; k < n; k++)
+       if (helptmp[k].type != GNM_FUNC_HELP_END &&
+           helptmp[k].text)
+         help[i++] = helptmp[k];
+      g_free(helptmp);
+    }
+    help[m].type = GNM_FUNC_HELP_END;
+    help[m].text = NULL;
+  }
+  if (!help) /* Provide a reasonable default. */
+    help = default_gnm_help(name);
+#if 0
+  fprintf(stderr, "help_%s [%d] = {\n", name, m);
+  for (k = 0; k < m; k++)
+    fprintf(stderr, "%d => '%s',\n", help[k].type, help[k].text);
+  fprintf(stderr, "}\n");
+#endif
+  return help;
+}
+
 static gboolean
 gplp_func_desc_load (GOPluginService *service,
                     char const *name,
@@ -112,24 +195,24 @@
        char *args[] = { NULL };
        gchar *help_perl_func = g_strconcat ("help_", name, NULL);
        gchar *desc_perl_func = g_strconcat ("desc_", name, NULL);
-       gchar *help_text = NULL;
+       GnmFuncHelp *help = NULL;
        gchar *arg_spec = NULL;
-       gchar *arg_names = NULL;
+       int count;
 
        dSP;
        ENTER;
        SAVETMPS;
        PUSHMARK(SP);
        PUTBACK;
-       call_argv (help_perl_func, G_EVAL | G_SCALAR | G_NOARGS, args);
+       count = call_argv (help_perl_func, G_EVAL | G_ARRAY | G_NOARGS, args);
        SPAGAIN;
 
        if (SvTRUE(ERRSV)) { /* Error handling */
                STRLEN n_a;
                g_print ( _("Perl error: %s\n"), SvPV (ERRSV, n_a));
-               POPs;
+               while (count-- > 0) POPs;
        } else {
-               help_text = g_strdup (POPp);
+         help = make_gnm_help(name, count, SP);
        }
 
        PUTBACK;
@@ -148,7 +231,6 @@
                g_print ( _("Perl error: %s\n"), SvPV (ERRSV, n_a));
                POPs;
        } else {
-               arg_names = g_strdup (POPp);
                arg_spec = g_strdup (POPp);
        }
 
@@ -162,11 +244,7 @@
        res->name = g_strdup(name);
        res->arg_spec = arg_spec;
 
-#if 0
-       help_template[0].text = help_text ? help_text : help_template_text;
-#endif
-
-       res->help = g_slice_dup (GnmFuncHelp, help_template);
+       res->help = help;
        res->fn_args = NULL;
        res->fn_args = &call_perl_function_args;
        res->fn_nodes = NULL;
@@ -213,6 +291,7 @@
                perl_construct (gnm_perl_interp);
                perl_parse (gnm_perl_interp, xs_init, 3, argv, NULL);
                my_perl = gnm_perl_interp;
+               init_help_consts();
 #ifdef PERL_EXIT_DESTRUCT_END
                PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
 #endif


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