From: Johannes Schindelin <Johannes.Schindelin@gmx.de>
To: Pierre Habouzit <madcoder@debian.org>
Cc: Junio C Hamano <gitster@pobox.com>, git@vger.kernel.org
Subject: [PATCH 3/3] parseopt: do not list options with the same name twice
Date: Mon, 5 Nov 2007 13:15:58 +0000 (GMT) [thread overview]
Message-ID: <Pine.LNX.4.64.0711051315460.4362@racer.site> (raw)
In-Reply-To: <Pine.LNX.4.64.0711051237420.4362@racer.site>
The option parser will take the first exact match, and happily ignore
it when a later option has the same name. For example, when you have
something like
OPT_BOOLEAN('i', NULL, &troz, "blah"),
OPT_BOOLEAN('i', NULL, &brain, "blub"),
in your options array, a command line "prog -i" will increment the
variable "troz", and leave the variable "brain" alone.
This behavior is all good and well, especially since we plan to
have recursive options, e.g. for the diff options, and in some cases
options should be overridden (see for example format-patch's "-n").
This patch matches the usage to this behavior: whenever an option name
was overridden by another option, it is no longer shown. In the
example above, that means that the usage would only show
-i blah
and not print anything about "blub".
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
Okay, my plan was borked: the options struct is passed as a
const. So this is plan B.
parse-options.c | 37 ++++++++++++++++++++++++++-----------
test-parse-options.c | 2 ++
2 files changed, 28 insertions(+), 11 deletions(-)
diff --git a/parse-options.c b/parse-options.c
index ed8e951..83a221b 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -1,5 +1,6 @@
#include "git-compat-util.h"
#include "parse-options.h"
+#include "path-list.h"
#define OPT_SHORT 1
#define OPT_UNSET 2
@@ -261,15 +262,18 @@ int parse_options(int argc, const char **argv, const struct option *options,
#define USAGE_OPTS_WIDTH 24
#define USAGE_GAP 2
-static void usage_show_options(const struct option *opts)
+static void usage_show_options(const struct option *opts,
+ char *seen_short_names, struct path_list *seen_long_names)
{
for (; opts->type != OPTION_END; opts++) {
- size_t pos;
+ const char *before_option = " ";
+ size_t pos = 0;
int pad;
if (opts->type == OPTION_RECURSE) {
const struct option *sub = opts->value;
- usage_show_options(sub);
+ usage_show_options(sub,
+ seen_short_names, seen_long_names);
continue;
}
@@ -280,13 +284,19 @@ static void usage_show_options(const struct option *opts)
continue;
}
- pos = fprintf(stderr, " ");
- if (opts->short_name)
- 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->short_name && !seen_short_names[opts->short_name]) {
+ pos += fprintf(stderr, "%s-%c",
+ before_option, opts->short_name);
+ seen_short_names[opts->short_name] = 1;
+ before_option = ", ";
+ }
+ if (opts->long_name && !path_list_has_path(seen_long_names,
+ opts->long_name)) {
+ pos += fprintf(stderr, "%s--%s",
+ before_option, opts->long_name);
+ path_list_insert(opts->long_name, seen_long_names);
+ } else if (*before_option != ',')
+ continue;
switch (opts->type) {
case OPTION_INTEGER:
@@ -329,6 +339,9 @@ static void usage_show_options(const struct option *opts)
void usage_with_options(const char * const *usagestr,
const struct option *opts)
{
+ char seen_short_names[256];
+ struct path_list seen_long_names = { NULL, 0, 0, 0 };
+
fprintf(stderr, "usage: %s\n", *usagestr++);
while (*usagestr && **usagestr)
fprintf(stderr, " or: %s\n", *usagestr++);
@@ -338,7 +351,9 @@ void usage_with_options(const char * const *usagestr,
if (opts->type != OPTION_GROUP)
fputc('\n', stderr);
- usage_show_options(opts);
+ memset(seen_short_names, 0, sizeof(seen_short_names));
+ usage_show_options(opts, seen_short_names, &seen_long_names);
+ path_list_clear(&seen_long_names, 0);
fputc('\n', stderr);
diff --git a/test-parse-options.c b/test-parse-options.c
index ee64fb3..56f6f24 100644
--- a/test-parse-options.c
+++ b/test-parse-options.c
@@ -16,6 +16,7 @@ int main(int argc, const char **argv)
struct option sub[] = {
OPT_BOOLEAN('n', "narf", &narf, "what are we doing tonight?"),
OPT_INTEGER('z', "zort", &zort, "try to take over the world"),
+ OPT_INTEGER('j', NULL, &boolean, "ignored option"),
OPT_END(),
};
struct option options[] = {
@@ -27,6 +28,7 @@ int main(int argc, const char **argv)
OPT_STRING('s', "string", &string, "string", "get a string"),
OPT_STRING(0, "string2", &string, "str", "get another string"),
OPT_STRING(0, "st", &string, "st", "get another string (pervert ordering)"),
+ OPT_INTEGER(0, "string", &boolean, "ignored option"),
OPT_END(),
};
int i;
--
1.5.3.5.1549.g91a3
next prev parent reply other threads:[~2007-11-05 13:17 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-11-05 12:03 proposal for an OPTION_SUBARRAY (recursive parser) Pierre Habouzit
2007-11-05 12:03 ` [PATCH 1/4] parse-options: abbreviation engine fix Pierre Habouzit
2007-11-05 12:03 ` [PATCH 2/4] Some better parse-options documentation Pierre Habouzit
2007-11-05 12:03 ` [PATCH 3/4] Add OPTION_BASEOFFSET/OPTION_SUBARRAY Pierre Habouzit
2007-11-05 12:03 ` [PATCH 4/4] Implement OPTION_SUBARRAY handling Pierre Habouzit
2007-11-05 12:34 ` [PATCH] parse-options: abbreviation engine fix Johannes Schindelin
2007-11-05 12:38 ` Johannes Schindelin
2007-11-05 13:15 ` [PATCH 1/3] " Johannes Schindelin
2007-11-05 13:15 ` [PATCH 2/3] parseopt: introduce OPT_RECURSE to specify shared options Johannes Schindelin
2007-11-05 13:46 ` Johannes Schindelin
2007-11-05 16:15 ` Linus Torvalds
2007-11-05 16:29 ` Johannes Schindelin
2007-11-05 16:53 ` Pierre Habouzit
2007-11-05 21:48 ` Junio C Hamano
2007-11-05 22:14 ` Pierre Habouzit
2007-11-05 13:15 ` Johannes Schindelin [this message]
2007-11-05 12:59 ` [PATCH] parse-options: abbreviation engine fix Pierre Habouzit
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Pine.LNX.4.64.0711051315460.4362@racer.site \
--to=johannes.schindelin@gmx.de \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=madcoder@debian.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).