bug-gnulib
[Top][All Lists]
Advanced

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

Re: argmatch: accept perfect matches in documented arglists


From: Akim Demaille
Subject: Re: argmatch: accept perfect matches in documented arglists
Date: Thu, 2 May 2019 12:55:39 +0200

Hi Bruno,

> Le 27 avr. 2019 à 19:56, Bruno Haible <address@hidden> a écrit :
> 
> Hi Akim,
> 
>> Because that's not what argmatch provides.  You seem to be referring to
>> a fully blown feature, and support for internationalization I guess.
> 
> And support for help2man should not be forgotten either.

Sure.

>> I'm just exploiting the unique prefix feature to shoehorn the
>> documentation in there.
> 
> I would find it better to go with a more featureful facility, then
> (among getopt, argmatch, argp, AutoOpts [1], etc.) - or invent a new one.

Is this what you have in mind?  It's in the test because it's
simpler to prototype there.  I should probably make the argmatch_group
private and provide pseudo constructors to be more robust to adding
new members if needed in the future.  Of course the construction
would be runtime, but I suppose it will not be costly enough to be a
problem.

Most existing functions should probably be rewritten on top of
argmatch_group, with backward compatibility of course.

I'd be happy to check the output of argmatch_usage, but I don't think
we have the equivalent of string streams in gnulib, do we?

I did not try to depend on $COLUMNS, because it is not used so far in
gnulib.

commit 7fc2a29e4d82c7bf7882421e65af6224bfc30188
Author: Akim Demaille <address@hidden>
Date:   Tue Apr 30 08:01:14 2019 +0200

    WIP: argmatch: provide support for documentation

diff --git a/tests/test-argmatch.c b/tests/test-argmatch.c
index 9335adf55..99666a12c 100644
--- a/tests/test-argmatch.c
+++ b/tests/test-argmatch.c
@@ -21,10 +21,16 @@
 
 #include "argmatch.h"
 
+#include <gettext.h>
+#include <stdbool.h>
 #include <stdlib.h>
+#include <string.h> /* memcmp */
 
 #include "macros.h"
 
+#define _(Msgid)  gettext (Msgid)
+#define N_(Msgid) (Msgid)
+
 /* Some packages define ARGMATCH_DIE and ARGMATCH_DIE_DECL in <config.h>, and
    thus must link with a definition of that function.  Provide it here.  */
 #ifdef ARGMATCH_DIE_DECL
@@ -59,6 +65,105 @@ static const enum backup_type backup_vals[] =
   numbered_backups, numbered_backups, numbered_backups
 };
 
+static const char *const backup_docs[] =
+{
+  N_("never make backups (even if --backup is given)"),
+  N_("make numbered backups"),
+  N_("numbered if numbered backups exist, simple otherwise"),
+  N_("always make simple backups"),
+  NULL
+};
+
+static const enum backup_type backup_doc_vals[] =
+{
+  no_backups,
+  simple_backups,
+  numbered_existing_backups,
+  numbered_backups
+};
+
+typedef struct argmatch_group
+{
+  /* Printed before the usage message.  */
+  const char *doc_pre;
+  /* Printed after the usage message.  */
+  const char *doc_post;
+  /* Size of the values (in bytes).  */
+  size_t val_size;
+
+  /* The documentation of each documented value.
+     This dictates the order in which values are documented.
+     docs[i] documents doc_vals[i].  */
+  const char *const *docs;
+  /* Values that we document.  */
+  const void *doc_vals;
+
+  /* Arguments denoting a value.  */
+  const char *const *args;
+  /* vals[i] is the value for args[i].  */
+  const void *vals;
+} argmatch_group;
+
+argmatch_group backup_group =
+{
+  N_("\
+The backup suffix is '~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX.\n\
+The version control method may be selected via the --backup option or 
through\n\
+the VERSION_CONTROL environment variable.  Here are the values:\n"),
+  NULL,
+  sizeof *backup_vals,
+  backup_docs,
+  backup_doc_vals,
+  backup_args,
+  backup_vals
+};
+
+void
+argmatch_usage (FILE *out, const argmatch_group *g)
+{
+  /* Width of the screen.  Help2man does not seem to support arguments
+     on several lines, so in that case pretend a very large width. */
+  const int screen_width = getenv ("HELP2MAN") ? INT_MAX : 80;
+  if (g->doc_pre)
+    fprintf (out, "%s\n", _(g->doc_pre));
+  for (int i = 0; g->docs[i]; ++i)
+    {
+      int col = 0;
+      bool first = true;
+      for (int j = 0; g->args[j]; ++j)
+        if (! memcmp ((const char *)g->doc_vals + i * g->val_size,
+                      (const char *)g->vals     + j * g->val_size,
+                      g->val_size))
+          {
+            if (!first
+                && screen_width < col + 2 + strlen (g->args[j]))
+              {
+                fprintf (out, ",\n");
+                col = 0;
+                first = true;
+              }
+            if (first)
+              {
+                col += fprintf (out, " ");
+                first = false;
+              }
+            else
+              col += fprintf (out, ",");
+            col += fprintf (out,  " %s", g->args[j]);
+          }
+      /* The doc.  Must be on column 20 separated by at least two
+         spaces. */
+      if (20 < col + 2)
+        {
+          fprintf (out, "\n");
+          col = 0;
+        }
+      fprintf (out, "%*s%s\n", 20 - col, "", _(g->docs[i]));
+    }
+  if (g->doc_post)
+    fprintf (out, "%s\n", _(g->doc_post));
+}
+
 int
 main (int argc, char *argv[])
 {
@@ -90,9 +195,11 @@ main (int argc, char *argv[])
   /* Ambiguous abbreviated.  */
   ASSERT (ARGMATCH ("ne", backup_args, backup_vals) == -2);
 
-  /* Ambiguous abbreviated, but same value.  */
+  /* Ambiguous abbreviated, but same value ("single" and "simple").  */
   ASSERT (ARGMATCH ("si", backup_args, backup_vals) == 3);
   ASSERT (ARGMATCH ("s", backup_args, backup_vals) == 3);
 
+  argmatch_usage (stdout, &backup_group);
+
   return 0;
 }




reply via email to

[Prev in Thread] Current Thread [Next in Thread]