diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2010-06-24 16:51:49 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2010-06-24 16:51:49 +0300 |
commit | c735683258070b13ff221fabb81e1c24d7805174 (patch) | |
tree | 1e7e5ecf3ef99e5706f1632103812fcf743460e7 | |
parent | 716d8fc8909b65613380c477942b05e750ef5db0 (diff) | |
download | smap-c735683258070b13ff221fabb81e1c24d7805174.tar.gz smap-c735683258070b13ff221fabb81e1c24d7805174.tar.bz2 |
Improve help output.
* src/getopt.m4 (print_usage, print_help): Sort options prior
to displaying them.
(sort_opthelp, sort_options, optcmp)
(cmpidx_short, cmpidx_long): New functions.
-rw-r--r-- | src/getopt.m4 | 199 |
1 files changed, 159 insertions, 40 deletions
diff --git a/src/getopt.m4 b/src/getopt.m4 index c8de14d..3c19865 100644 --- a/src/getopt.m4 +++ b/src/getopt.m4 @@ -251,8 +251,63 @@ print_option_descr (const char *descr, size_t lmargin, size_t rmargin) } } +#define NOPTHELP (sizeof (opthelp) / sizeof (opthelp[0])) + +static int +optcmp (const void *a, const void *b) +{ + struct opthelp const *ap = (struct opthelp const *)a; + struct opthelp const *bp = (struct opthelp const *)b; + const char *opta, *optb; + size_t alen, blen; + + for (opta = ap->opt; *opta == '-'; opta++) + ; + alen = strcspn (opta, ","); + + for (optb = bp->opt; *optb == '-'; optb++) + ; + blen = strcspn (optb, ","); + + if (alen > blen) + blen = alen; + + return strncmp (opta, optb, blen); +} + +static void +sort_options (int start, int count) +{ + qsort (opthelp + start, count, sizeof (opthelp[0]), optcmp); +} + +static int +sort_group (int start) +{ + int i; + + for (i = start; i < NOPTHELP && opthelp[i].opt; i++) + ; + sort_options (start, i - start); + return i + 1; +} + +static void +sort_opthelp (void) +{ + int start; + + for (start = 0; start < NOPTHELP; ) + { + if (!opthelp[start].opt) + start = sort_group (start + 1); + else + start = sort_group (start); + } +} + void -print_help(void) +print_help (void) { unsigned i; int argsused = 0; @@ -263,7 +318,8 @@ print_help(void) print_option_descr(gettext (doc), 0, RMARGIN); putchar ('\n'); - for (i = 0; i < sizeof (opthelp) / sizeof (opthelp[0]); i++) + sort_opthelp (); + for (i = 0; i < NOPTHELP; i++) { unsigned n; if (opthelp[i].opt) @@ -328,6 +384,39 @@ dnl ************************************************************************** printf (_("Report bugs to %s.\n"), program_bug_address); } +static int +cmpidx_short (const void *a, const void *b) +{ + unsigned const *ai = (unsigned const *)a; + unsigned const *bi = (unsigned const *)b; + + return opthelp[*ai].opt[1] - opthelp[*bi].opt[1]; +} + +static int +cmpidx_long (const void *a, const void *b) +{ + unsigned const *ai = (unsigned const *)a; + unsigned const *bi = (unsigned const *)b; + struct opthelp const *ap = opthelp + *ai; + struct opthelp const *bp = opthelp + *bi; + char const *opta, *optb; + size_t lena, lenb; + + if (ap->opt[1] == '-') + opta = ap->opt; + else + opta = ap->opt + 4; + lena = strcspn (opta, ","); + + if (bp->opt[1] == '-') + optb = bp->opt; + else + optb = bp->opt + 4; + lenb = strcspn (optb, ","); + return strncmp (opta, optb, lena > lenb ? lenb : lena); +} + void print_usage(void) { @@ -335,7 +424,9 @@ print_usage(void) int f = 0; unsigned n; char buf[RMARGIN+1]; - + unsigned *idxbuf; + unsigned nidx; + #define FLUSH dnl do dnl { dnl @@ -348,94 +439,122 @@ print_usage(void) #define ADDC(c) dnl do { if (n == RMARGIN) FLUSH; buf[n++] = c; } while (0) + idxbuf = calloc (NOPTHELP, sizeof (idxbuf[0])); + if (!idxbuf) + { + fprintf (stderr, "not enough memory"); + abort (); + } + n = snprintf (buf, sizeof buf, "%s %s ", _("Usage:"), [<$2>]); /* Print a list of short options without arguments. */ - for (i = 0; i < sizeof (opthelp) / sizeof (opthelp[0]); i++) - { + for (i = nidx = 0; i < NOPTHELP; i++) if (opthelp[i].opt && opthelp[i].descr && opthelp[i].opt[1] != '-' && opthelp[i].arg == NULL) + idxbuf[nidx++] = i; + + if (nidx) + { + qsort (idxbuf, nidx, sizeof (idxbuf[0]), cmpidx_short); + + ADDC ('['); + ADDC ('-'); + for (i = 0; i < nidx; i++) { - if (f == 0) - { - ADDC('['); - ADDC('-'); - f = 1; - } - ADDC(opthelp[i].opt[1]); + ADDC (opthelp[idxbuf[i]].opt[1]); } + ADDC (']'); } - if (f) - ADDC(']'); /* Print a list of short options with arguments. */ - for (i = 0; i < sizeof (opthelp) / sizeof (opthelp[0]); i++) + for (i = nidx = 0; i < NOPTHELP; i++) { if (opthelp[i].opt && opthelp[i].descr && opthelp[i].opt[1] != '-' && opthelp[i].arg) + idxbuf[nidx++] = i; + } + + if (nidx) + { + qsort (idxbuf, nidx, sizeof (idxbuf[0]), cmpidx_short); + + for (i = 0; i < nidx; i++) { - size_t len = 5 - + strlen (opthelp[i].arg) - + (opthelp[i].is_optional ? 2 : 1); + struct opthelp *opt = opthelp + idxbuf[i]; + size_t len = 5 + strlen (opt->arg) + + (opt->is_optional ? 2 : 1); + if (n + len > RMARGIN) FLUSH; buf[n++] = ' '; buf[n++] = '['; buf[n++] = '-'; - buf[n++] = opthelp[i].opt[1]; - if (opthelp[i].is_optional) + buf[n++] = opt->opt[1]; + if (opt->is_optional) { buf[n++] = '['; - strcpy (&buf[n], opthelp[i].arg); - n += strlen (opthelp[i].arg); + strcpy (&buf[n], opt->arg); + n += strlen (opt->arg); buf[n++] = ']'; } else { buf[n++] = ' '; - strcpy (&buf[n], opthelp[i].arg); - n += strlen (opthelp[i].arg); + strcpy (&buf[n], opt->arg); + n += strlen (opt->arg); } buf[n++] = ']'; } } + #ifdef HAVE_GETOPT_LONG /* Print a list of long options */ - for (i = 0; i < sizeof (opthelp) / sizeof (opthelp[0]); i++) + for (i = nidx = 0; i < NOPTHELP; i++) { - if (opthelp[i].opt && opthelp[i].descr) + if (opthelp[i].opt && opthelp[i].descr + && (opthelp[i].opt[1] == '-' || opthelp[i].opt[2] == ',')) + idxbuf[nidx++] = i; + } + + if (nidx) + { + qsort (idxbuf, nidx, sizeof (idxbuf[0]), cmpidx_long); + + for (i = 0; i < nidx; i++) { + struct opthelp *opt = opthelp + idxbuf[i]; size_t len; const char *longopt; - - if (opthelp[i].opt[1] == '-') - longopt = opthelp[i].opt; - else if (opthelp[i].opt[2] == ',') - longopt = opthelp[i].opt + 4; + + if (opt->opt[1] == '-') + longopt = opt->opt; + else if (opt->opt[2] == ',') + longopt = opt->opt + 4; else continue; len = 3 + strlen (longopt) - + (opthelp[i].arg ? 1 + strlen (opthelp[i].arg) - + (opthelp[i].is_optional ? 2 : 0) : 0); + + (opt->arg ? 1 + strlen (opt->arg) + + (opt->is_optional ? 2 : 0) : 0); if (n + len > RMARGIN) FLUSH; buf[n++] = ' '; buf[n++] = '['; strcpy (&buf[n], longopt); n += strlen (longopt); - if (opthelp[i].arg) + if (opt->arg) { buf[n++] = '='; - if (opthelp[i].is_optional) + if (opt->is_optional) { buf[n++] = '['; - strcpy (&buf[n], opthelp[i].arg); - n += strlen (opthelp[i].arg); + strcpy (&buf[n], opt->arg); + n += strlen (opt->arg); buf[n++] = ']'; } else { - strcpy (&buf[n], opthelp[i].arg); - n += strlen (opthelp[i].arg); + strcpy (&buf[n], opt->arg); + n += strlen (opt->arg); } } buf[n++] = ']'; @@ -443,7 +562,7 @@ print_usage(void) } #endif FLUSH; - + free (idxbuf); } const char version_etc_copyright[] = |