]> mj.ucw.cz Git - paperjam.git/blobdiff - parse.cc
TODO
[paperjam.git] / parse.cc
index aa840ba2af6cdda39bdb7382d84727c7aa8fe384..d1573c88e84561bca9540231218f2dc441e5440a 100644 (file)
--- a/parse.cc
+++ b/parse.cc
@@ -297,35 +297,49 @@ static void parse_args(cmd *c)
       t = next_token();
       if (t == TOK_CLOSE_PAREN)
         break;
+
+      while (next_pos < num_args && !(adefs[next_pos].type & AT_POSITIONAL))
+       next_pos++;
+
       uint argi = 0;
       bool has_value = false;
+
       if (t == TOK_IDENT)
        {
          while (adefs[argi].name && token != adefs[argi].name)
            argi++;
-         if (!adefs[argi].name)
-           err("Command %s has no argument %s", cdef->name, token.c_str());
-         if (c->args.count(token))
-           err("Argument %s given multiple times", token.c_str());
-         t = next_token();
-         if (t == TOK_EQUAL)
-           has_value = true;
+         if (adefs[argi].name)
+           {
+             if (c->args.count(token))
+               err("Argument %s given multiple times", token.c_str());
+             t = next_token();
+             if (t == TOK_EQUAL)
+               has_value = true;
+             else
+               return_token();
+             saw_named = true;
+           }
+         else if (next_pos < num_args && (adefs[next_pos].type & AT_TYPE_MASK) == AT_STRING)
+           {
+             // Shortcut syntax: positional arguments of string type can be specified
+             // as bare identifiers if they do not collide with names or other arguments.
+             return_token();
+             argi = next_pos++;
+             has_value = true;
+           }
          else
-           return_token();
-         saw_named = true;
+           err("Command %s has no argument %s", cdef->name, token.c_str());
        }
       else if (saw_named)
        err("Positional arguments must precede named ones");
-      else
+      else if (next_pos < num_args)
        {
          return_token();
-         while (next_pos < num_args && !(adefs[next_pos].type & AT_POSITIONAL))
-           next_pos++;
-         if (next_pos >= num_args)
-           err("Too many positional arguments for command %s", cdef->name);
          argi = next_pos++;
          has_value = true;
        }
+      else
+       err("Too many positional arguments for command %s", cdef->name);
 
       const arg_def *adef = &adefs[argi];
       uint type = adef->type & AT_TYPE_MASK;
@@ -336,8 +350,8 @@ static void parse_args(cmd *c)
            {
            case AT_STRING:
              t = next_token();
-             if (t != TOK_STRING)
-               err("Argument %s must be a string", adef->name);
+             if (t != TOK_STRING && t != TOK_IDENT)
+               err("Argument %s must be a string or identifier", adef->name);
              val = new arg_string(token);
              break;
            case AT_INT:
@@ -505,23 +519,25 @@ void parser_help()
   for (int i=0; cmd_table[i].name; i++)
     {
       const cmd_def *def = &cmd_table[i];
-      printf("%s\n", def->name);
+      printf("%s - %s\n", def->name, def->help);
 
       const arg_def *arg = def->arg_defs;
       static const char * const type_names[] = {
-       "string", "int", "double", "dimen", "switch"
+       "string", "int", "real", "dimen", "switch"
       };
       while (arg->name)
        {
-         printf("\t%s (%s)%s%s\n",
+         char a[32];
+         snprintf(a, sizeof(a), "%s%s=%s<%s>",
+           (arg->type & AT_POSITIONAL) ? "[" : "",
            arg->name,
-           type_names[arg->type & AT_TYPE_MASK],
-           (arg->type & AT_MANDATORY) ? " [mandatory]" : "",
-           (arg->type & AT_POSITIONAL) ? " [positional]" : "");
+           (arg->type & AT_POSITIONAL) ? "]" : "",
+           type_names[arg->type & AT_TYPE_MASK]);
+         printf("   %-20s %s\n", a, arg->help);
          arg++;
        }
 
        if (def->has_pipeline)
-         printf("\t{ pipeline }\n");
+         printf("   { pipeline }\n");
     }
 }