Merge branch 'sb/show-branch-parse-options' into sb/opt-filename
authorJunio C Hamano <gitster@pobox.com>
Mon, 25 May 2009 07:59:29 +0000 (00:59 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 25 May 2009 07:59:29 +0000 (00:59 -0700)
* sb/show-branch-parse-options:
show-branch: migrate to parse-options API
parse-options: add PARSE_OPT_LITERAL_ARGHELP for complicated argh's

Conflicts:
parse-options.h

1  2 
parse-options.c
parse-options.h
diff --combined parse-options.c
index c52b8ccf59a4848be6f3f810e01029f7c6625c78,e8955be7b4ae0ccbf72b341130af3345f81b08c4..1d25b94c72b3fc52eabbdc31a61e43e404ddb303
@@@ -50,7 -50,6 +50,7 @@@ static int get_value(struct parse_opt_c
                        /* FALLTHROUGH */
                case OPTION_BOOLEAN:
                case OPTION_BIT:
 +              case OPTION_NEGBIT:
                case OPTION_SET_INT:
                case OPTION_SET_PTR:
                        return opterror(opt, "takes no value", flags);
                        *(int *)opt->value |= opt->defval;
                return 0;
  
 +      case OPTION_NEGBIT:
 +              if (unset)
 +                      *(int *)opt->value |= opt->defval;
 +              else
 +                      *(int *)opt->value &= ~opt->defval;
 +              return 0;
 +
        case OPTION_BOOLEAN:
                *(int *)opt->value = unset ? 0 : *(int *)opt->value + 1;
                return 0;
  
  static int parse_short_opt(struct parse_opt_ctx_t *p, const struct option *options)
  {
 +      const struct option *numopt = NULL;
 +
        for (; options->type != OPTION_END; options++) {
                if (options->short_name == *p->opt) {
                        p->opt = p->opt[1] ? p->opt + 1 : NULL;
                        return get_value(p, options, OPT_SHORT);
                }
 +
 +              /*
 +               * Handle the numerical option later, explicit one-digit
 +               * options take precedence over it.
 +               */
 +              if (options->type == OPTION_NUMBER)
 +                      numopt = options;
 +      }
 +      if (numopt && isdigit(*p->opt)) {
 +              size_t len = 1;
 +              char *arg;
 +              int rc;
 +
 +              while (isdigit(p->opt[len]))
 +                      len++;
 +              arg = xmemdupz(p->opt, len);
 +              p->opt = p->opt[len] ? p->opt + len : NULL;
 +              rc = (*numopt->callback)(numopt, arg, 0) ? (-1) : 0;
 +              free(arg);
 +              return rc;
        }
        return -2;
  }
@@@ -245,25 -215,6 +245,25 @@@ is_abbreviated
        return -2;
  }
  
 +static int parse_nodash_opt(struct parse_opt_ctx_t *p, const char *arg,
 +                          const struct option *options)
 +{
 +      for (; options->type != OPTION_END; options++) {
 +              if (!(options->flags & PARSE_OPT_NODASH))
 +                      continue;
 +              if ((options->flags & PARSE_OPT_OPTARG) ||
 +                  !(options->flags & PARSE_OPT_NOARG))
 +                      die("BUG: dashless options don't support arguments");
 +              if (!(options->flags & PARSE_OPT_NONEG))
 +                      die("BUG: dashless options don't support negation");
 +              if (options->long_name)
 +                      die("BUG: dashless options can't be long");
 +              if (options->short_name == arg[0] && arg[1] == '\0')
 +                      return get_value(p, options, OPT_SHORT);
 +      }
 +      return -2;
 +}
 +
  static void check_typos(const char *arg, const struct option *options)
  {
        if (strlen(arg) < 3)
@@@ -314,8 -265,6 +314,8 @@@ int parse_options_step(struct parse_opt
                const char *arg = ctx->argv[0];
  
                if (*arg != '-' || !arg[1]) {
 +                      if (parse_nodash_opt(ctx, arg, options) == 0)
 +                              continue;
                        if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION)
                                break;
                        ctx->out[ctx->cpidx++] = ctx->argv[0];
@@@ -412,6 -361,20 +412,20 @@@ int parse_options(int argc, const char 
        return parse_options_end(&ctx);
  }
  
+ static int usage_argh(const struct option *opts)
+ {
+       const char *s;
+       int literal = opts->flags & PARSE_OPT_LITERAL_ARGHELP;
+       if (opts->flags & PARSE_OPT_OPTARG)
+               if (opts->long_name)
+                       s = literal ? "[=%s]" : "[=<%s>]";
+               else
+                       s = literal ? "[%s]" : "[<%s>]";
+       else
+               s = literal ? " %s" : " <%s>";
+       return fprintf(stderr, s, opts->argh);
+ }
  #define USAGE_OPTS_WIDTH 24
  #define USAGE_GAP         2
  
@@@ -448,18 -411,12 +462,18 @@@ int usage_with_options_internal(const c
                        continue;
  
                pos = fprintf(stderr, "    ");
 -              if (opts->short_name)
 -                      pos += fprintf(stderr, "-%c", opts->short_name);
 +              if (opts->short_name) {
 +                      if (opts->flags & PARSE_OPT_NODASH)
 +                              pos += fprintf(stderr, "%c", opts->short_name);
 +                      else
 +                              pos += fprintf(stderr, "-%c", opts->short_name);
 +              }
                if (opts->long_name && opts->short_name)
                        pos += fprintf(stderr, ", ");
                if (opts->long_name)
                        pos += fprintf(stderr, "--%s", opts->long_name);
 +              if (opts->type == OPTION_NUMBER)
 +                      pos += fprintf(stderr, "-NUM");
  
                switch (opts->type) {
                case OPTION_ARGUMENT:
                                break;
                        /* FALLTHROUGH */
                case OPTION_STRING:
-                       if (opts->argh) {
-                               if (opts->flags & PARSE_OPT_OPTARG)
-                                       if (opts->long_name)
-                                               pos += fprintf(stderr, "[=<%s>]", opts->argh);
-                                       else
-                                               pos += fprintf(stderr, "[<%s>]", opts->argh);
-                               else
-                                       pos += fprintf(stderr, " <%s>", opts->argh);
-                       } else {
+                       if (opts->argh)
+                               pos += usage_argh(opts);
+                       else {
                                if (opts->flags & PARSE_OPT_OPTARG)
                                        if (opts->long_name)
                                                pos += fprintf(stderr, "[=...]");
                                        pos += fprintf(stderr, " ...");
                        }
                        break;
 -              default: /* OPTION_{BIT,BOOLEAN,SET_INT,SET_PTR} */
 +              default: /* OPTION_{BIT,BOOLEAN,NUMBER,SET_INT,SET_PTR} */
                        break;
                }
  
diff --combined parse-options.h
index 919b9b441f97511695308287a2fdc6f3a45e383d,910aa1e9f1827f119fb445e281e02235e6f99df3..fe41ab2c67024b91794c483c2436e33e205f5f62
@@@ -6,10 -6,8 +6,10 @@@ enum parse_opt_type 
        OPTION_END,
        OPTION_ARGUMENT,
        OPTION_GROUP,
 +      OPTION_NUMBER,
        /* options with no arguments */
        OPTION_BIT,
 +      OPTION_NEGBIT,
        OPTION_BOOLEAN, /* _INCR would have been a better name */
        OPTION_SET_INT,
        OPTION_SET_PTR,
@@@ -33,7 -31,7 +33,8 @@@ enum parse_opt_option_flags 
        PARSE_OPT_NONEG   = 4,
        PARSE_OPT_HIDDEN  = 8,
        PARSE_OPT_LASTARG_DEFAULT = 16,
 +      PARSE_OPT_NODASH = 32,
+       PARSE_OPT_LITERAL_ARGHELP = 64,
  };
  
  struct option;
@@@ -67,11 -65,11 +68,14 @@@ typedef int parse_opt_cb(const struct o
   *   PARSE_OPT_OPTARG: says that the argument is optional (not for BOOLEANs)
   *   PARSE_OPT_NOARG: says that this option takes no argument, for CALLBACKs
   *   PARSE_OPT_NONEG: says that this option cannot be negated
 - *   PARSE_OPT_HIDDEN this option is skipped in the default usage, showed in
 - *                    the long one.
 + *   PARSE_OPT_HIDDEN: this option is skipped in the default usage, and
 + *                     shown only in the full usage.
 + *   PARSE_OPT_LASTARG_DEFAULT: if no argument is given, the default value
 + *                              is used.
 + *   PARSE_OPT_NODASH: this option doesn't start with a dash.
+  *   PARSE_OPT_LITERAL_ARGHELP: says that argh shouldn't be enclosed in brackets
+  *                            (i.e. '<argh>') in the help message.
+  *                            Useful for options with multiple parameters.
   *
   * `callback`::
   *   pointer to the callback to use for OPTION_CALLBACK.
@@@ -99,7 -97,6 +103,7 @@@ struct option 
  #define OPT_ARGUMENT(l, h)          { OPTION_ARGUMENT, 0, (l), NULL, NULL, (h) }
  #define OPT_GROUP(h)                { OPTION_GROUP, 0, NULL, NULL, NULL, (h) }
  #define OPT_BIT(s, l, v, h, b)      { OPTION_BIT, (s), (l), (v), NULL, (h), 0, NULL, (b) }
 +#define OPT_NEGBIT(s, l, v, h, b)   { OPTION_NEGBIT, (s), (l), (v), NULL, (h), 0, NULL, (b) }
  #define OPT_BOOLEAN(s, l, v, h)     { OPTION_BOOLEAN, (s), (l), (v), NULL, (h) }
  #define OPT_SET_INT(s, l, v, h, i)  { OPTION_SET_INT, (s), (l), (v), NULL, (h), 0, NULL, (i) }
  #define OPT_SET_PTR(s, l, v, h, p)  { OPTION_SET_PTR, (s), (l), (v), NULL, (h), 0, NULL, (p) }
          parse_opt_approxidate_cb }
  #define OPT_CALLBACK(s, l, v, a, h, f) \
        { OPTION_CALLBACK, (s), (l), (v), (a), (h), 0, (f) }
 +#define OPT_NUMBER_CALLBACK(v, h, f) \
 +      { OPTION_NUMBER, 0, NULL, (v), NULL, (h), \
 +        PARSE_OPT_NOARG | PARSE_OPT_NONEG, (f) }
  
  /* parse_options() will filter out the processed options and leave the
   * non-option arguments in argv[].