git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] Add a simple option parser.
@ 2007-10-03 21:45 Kristian Høgsberg
  2007-10-03 21:45 ` [PATCH] Port builtin-add.c to use the new " Kristian Høgsberg
                   ` (3 more replies)
  0 siblings, 4 replies; 30+ messages in thread
From: Kristian Høgsberg @ 2007-10-03 21:45 UTC (permalink / raw)
  To: git; +Cc: gitster, Kristian Høgsberg

The option parser takes argc, argv, an array of struct option
and a usage string.  Each of the struct option elements in the array
describes a valid option, its type and a pointer to the location where the
value is written.  The entry point is parse_options(), which scans through
the given argv, and matches each option there against the list of valid
options.  During the scan, argv is rewritten to only contain the
non-option command line arguments and the number of these is returned.

Signed-off-by: Kristian Høgsberg <krh@redhat.com>
---
 Makefile        |    2 +-
 parse-options.c |  106 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 parse-options.h |   33 +++++++++++++++++
 3 files changed, 140 insertions(+), 1 deletions(-)
 create mode 100644 parse-options.c
 create mode 100644 parse-options.h

diff --git a/Makefile b/Makefile
index 62bdac6..d90e959 100644
--- a/Makefile
+++ b/Makefile
@@ -310,7 +310,7 @@ LIB_OBJS = \
 	alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \
 	color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \
 	convert.o attr.o decorate.o progress.o mailmap.o symlinks.o remote.o \
-	transport.o bundle.o
+	transport.o bundle.o parse-options.o
 
 BUILTIN_OBJS = \
 	builtin-add.o \
diff --git a/parse-options.c b/parse-options.c
new file mode 100644
index 0000000..130b609
--- /dev/null
+++ b/parse-options.c
@@ -0,0 +1,106 @@
+#include "git-compat-util.h"
+#include "parse-options.h"
+
+static int parse_one(const char **argv,
+		     struct option *options, int count,
+		     const char *usage_string)
+{
+	const char *eq, *arg, *value;
+	int i, processed;
+
+	arg = argv[0];
+	value = NULL;
+
+	if (arg[0] != '-')
+		return 0;
+
+	for (i = 0; i < count; i++) {
+		if (arg[1] == '-') {
+			if (!prefixcmp(options[i].long_name, arg + 2)) {
+				if (options[i].type != OPTION_BOOLEAN) {
+					value = argv[1];
+					processed = 2;
+				} else {
+					processed = 1;
+				}
+				break;
+			}
+
+			eq = strchr(arg + 2, '=');
+			if (eq && options[i].type != OPTION_BOOLEAN &&
+			    !strncmp(arg + 2,
+				     options[i].long_name, eq - arg - 2)) {
+				value = eq + 1;
+				processed = 1;
+				break;
+			}
+		}
+
+		if (arg[1] == options[i].short_name) {
+			if (arg[2] == '\0') {
+				if (options[i].type != OPTION_BOOLEAN) {
+					value = argv[1];
+					processed = 2;
+				} else {
+					processed = 1;
+				}
+				break;
+			}
+
+			if (options[i].type != OPTION_BOOLEAN) {
+				value = arg + 2;
+				processed = 1;
+				break;
+			}
+		}
+	}
+
+	if (i == count)
+		usage(usage_string);
+	else switch (options[i].type) {
+	case OPTION_BOOLEAN:
+		(*(int *)options[i].value)++;
+		break;
+	case OPTION_STRING:
+		if (value == NULL) {
+			error("option %s requires a value.", arg);
+			usage(usage_string);
+		}
+		*(const char **)options[i].value = value;
+		break;
+	case OPTION_INTEGER:
+		if (value == NULL) {
+			error("option %s requires a value.", argv);
+			usage(usage_string);
+		}
+		*(int *)options[i].value = atoi(value);
+		break;
+	default:
+		assert(0);
+	}
+
+	return processed;
+}
+
+int parse_options(int argc, const char **argv,
+		  struct option *options, int count,
+		  const char *usage_string)
+{
+	int i, j, processed;
+
+	for (i = 1, j = 0; i < argc; ) {
+		if (!strcmp(argv[i], "--"))
+			break;
+		processed = parse_one(argv + i, options, count, usage_string);
+		if (processed == 0)
+			argv[j++] = argv[i++];
+		else
+			i += processed;
+	}
+
+	while (i < argc)
+		argv[j++] = argv[i++];
+	argv[j] = NULL;
+
+	return j;
+}
diff --git a/parse-options.h b/parse-options.h
new file mode 100644
index 0000000..5be9c20
--- /dev/null
+++ b/parse-options.h
@@ -0,0 +1,33 @@
+#ifndef PARSE_OPTIONS_H
+#define PARSE_OPTIONS_H
+
+enum option_type {
+	OPTION_BOOLEAN,
+	OPTION_STRING,
+	OPTION_INTEGER,
+	OPTION_LAST,
+};
+
+struct option {
+	enum option_type type;
+	const char *long_name;
+	char short_name;
+	void *value;
+};
+
+/* Parse the given options against the list of known options.  The
+ * order of the option structs matters, in that ambiguous
+ * abbreviations (eg, --in could be short for --include or
+ * --interactive) are matched by the first option that share the
+ * prefix.
+ *
+ * parse_options() will filter out the processed options and leave the
+ * non-option argments in argv[].  The return value is the number of
+ * arguments left in argv[].
+ */
+
+extern int parse_options(int argc, const char **argv,
+			 struct option *options, int count,
+			 const char *usage_string);
+
+#endif
-- 
1.5.2.5

^ permalink raw reply related	[flat|nested] 30+ messages in thread
* [RFC] CLI option parsing and usage generation for porcelains
@ 2007-10-13 13:29 Pierre Habouzit
       [not found] ` <1192282153-26684-2-git-send-email-madcoder@debian.org>
  0 siblings, 1 reply; 30+ messages in thread
From: Pierre Habouzit @ 2007-10-13 13:29 UTC (permalink / raw)
  To: git

  Following Kristian momentum, I've reworked his parse_option module
quite a lot, and now have some quite interesting features. The series is
available from git://git.madism.org/git.git (branch ph/strbuf).

  The following series is open for comments, it's not 100% ready for
inclusion IMHO, as some details may need to be sorted out first, and
that I've not re-read the patches thoroughly yet. Though I uses the tip
of that branch as my everyday git for 2 weeks or so without any
noticeable issues.

  And as examples are always easier to grok:

$ git fetch -h
usage: git-fetch [options] [<repository> <refspec>...]

  -q, --quiet           be quiet
  -v, --verbose         be verbose

  -a, --append          append in .git/FETCH_HEAD
  -f, --force           force non fast-forwards updates
  --no-tags             don't follow tags at all
  -t, --tags            fetch all tags
  --depth <depth>       deepen history of a shallow clone

Advanced Options
  -k, --keep            keep downloaded pack
  -u, --update-head-ok  allow to update the head in the current branch
  --upload-pack <path>  path to git-upload-pack on the remote

$ git rm -rf xdiff # yeah -rf now works !
rm 'xdiff/xdiff.h'
rm 'xdiff/xdiffi.c'
rm 'xdiff/xdiffi.h'
rm 'xdiff/xemit.c'
rm 'xdiff/xemit.h'
rm 'xdiff/xinclude.h'
rm 'xdiff/xmacros.h'
rm 'xdiff/xmerge.c'
rm 'xdiff/xprepare.c'
rm 'xdiff/xprepare.h'
rm 'xdiff/xtypes.h'
rm 'xdiff/xutils.c'
rm 'xdiff/xutils.h'

^ permalink raw reply	[flat|nested] 30+ messages in thread

end of thread, other threads:[~2007-10-13 20:27 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-10-03 21:45 [PATCH] Add a simple option parser Kristian Høgsberg
2007-10-03 21:45 ` [PATCH] Port builtin-add.c to use the new " Kristian Høgsberg
2007-10-03 23:11 ` [PATCH] Add a simple " Pierre Habouzit
2007-10-04 14:57   ` Kristian Høgsberg
2007-10-04 15:15     ` Pierre Habouzit
2007-10-04 16:31       ` Pierre Habouzit
2007-10-04 16:39         ` Johannes Schindelin
2007-10-05 10:08 ` Pierre Habouzit
2007-10-05 14:21 ` Pierre Habouzit
2007-10-05 14:25   ` [ALTERNATE PATCH] " Pierre Habouzit
2007-10-05 14:30     ` Mike Hommey
2007-10-05 14:45       ` Pierre Habouzit
2007-10-05 15:45         ` Medve Emilian-EMMEDVE1
2007-10-05 15:56           ` Pierre Habouzit
2007-10-05 16:10             ` Medve Emilian-EMMEDVE1
2007-10-05 16:20               ` David Kastrup
2007-10-05 16:38                 ` Pierre Habouzit
2007-10-06  8:46                   ` Sven Verdoolaege
2007-10-05 16:28               ` Linus Torvalds
2007-10-05 16:41                 ` Medve Emilian-EMMEDVE1
2007-10-05 16:49                   ` Pierre Habouzit
2007-10-05 16:51                   ` Linus Torvalds
2007-10-05 14:59       ` David Kastrup
2007-10-05 15:33     ` Kristian Høgsberg
2007-10-05 15:54       ` Pierre Habouzit
2007-10-07 17:01     ` Pierre Habouzit
  -- strict thread matches above, loose matches on Subject: below --
2007-10-13 13:29 [RFC] CLI option parsing and usage generation for porcelains Pierre Habouzit
     [not found] ` <1192282153-26684-2-git-send-email-madcoder@debian.org>
     [not found]   ` <1192282153-26684-3-git-send-email-madcoder@debian.org>
2007-10-13 14:47     ` [PATCH] Port builtin-add.c to use the new option parser Johannes Schindelin
2007-10-13 15:03       ` Pierre Habouzit
2007-10-13 19:22         ` Alex Riesen
2007-10-13 20:27           ` Pierre Habouzit

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).