commit e54f54c03160ab7e6615e15f9ee0984ab5d2e9dc
parent 0255257e75f6f3820d695394eb80cd20dcf78e78
Author: Christoph Lohmann <20h@r-36.net>
Date: Sat, 4 Aug 2012 22:30:22 +0200
Adding ARGBEGIN for flexible parameter handling and fixing the manpage.
Diffstat:
arg.h | | | 41 | +++++++++++++++++++++++++++++++++++++++++ |
thingmenu.1 | | | 11 | ++++------- |
thingmenu.c | | | 113 | ++++++++++++++++++++++++++++++++----------------------------------------------- |
3 files changed, 91 insertions(+), 74 deletions(-)
diff --git a/arg.h b/arg.h
@@ -0,0 +1,41 @@
+/*
+ * Copy me if you can.
+ * by 20h
+ */
+
+#ifndef __ARG_H__
+#define __ARG_H__
+
+extern char *argv0;
+
+#define USED(x) ((void)(x))
+
+#define ARGBEGIN for (argv0 = *argv, argv++, argc--;\
+ argv[0] && argv[0][1]\
+ && argv[0][0] == '-';\
+ argc--, argv++) {\
+ char _argc;\
+ char **_argv;\
+ if (argv[0][1] == '-' && argv[0][2] == '\0') {\
+ argv++;\
+ argc--;\
+ break;\
+ }\
+ for (argv[0]++, _argv = argv; argv[0][0];\
+ argv[0]++) {\
+ if (_argv != argv)\
+ break;\
+ _argc = argv[0][0];\
+ switch (_argc)
+
+#define ARGEND }\
+ USED(_argc);\
+ }\
+ USED(argv);\
+ USED(argc);
+
+#define EARGF(x) ((argv[1] == NULL)? ((x), abort(), (char *)0) :\
+ (argc--, argv++, argv[0]))
+
+#endif
+
diff --git a/thingmenu.1 b/thingmenu.1
@@ -13,8 +13,8 @@
.Op Fl s
.Op Fl o
.Op Fl g Ar geometry
-.Op Fl ws Ar widthscaling
-.Op Fl hs Ar heightscaling
+.Op Fl w Ar widthscaling
+.Op Fl e Ar heightscaling
.Op Fl -
.Ar label0 cmd0 [label1 cmd1 ...]
.Ek
@@ -49,7 +49,6 @@ options and default settings.
Do not append a
.Qq "Cancel"
menu item.
-.
.Bd -filled
.It Fl s
Disable the oneshot behaviour. After one button click
@@ -66,10 +65,10 @@ Use the horizontal layout.
.It Fl g
Define the X11 geometry string, which is to be used.
.
-.It Fl ws
+.It Fl w
Define the width scaling.
.
-.It Fl hs
+.It Fl e
Define the height scaling.
.
.El
@@ -91,7 +90,6 @@ After that the menu will not exit (-s).
.Ed
.Bd -literal
% thingmenu -s -ww 300 -- "Reboot now" reboot
-
.Ed
.Bd -filled
This will create a centered menu, which is aligned based on the length of the
@@ -99,7 +97,6 @@ label texts. After the first clicked entry it will exit.
.Ed
.Bd -literal
% thingmenu "Force reboot" "reboot -f" Shutdown shutdown
-
.Ed
.Bd -filled
An example how to create multi-level menus is shown in the thingmenu-menu.sh
diff --git a/thingmenu.c b/thingmenu.c
@@ -106,6 +106,10 @@ int nentries = 0;
int oneshot = 1;
Bool ispressing = 0;
+char *argv0;
+
+#include "arg.h"
+
/* configuration, allows nested code to access above variables */
#include "config.h"
@@ -594,10 +598,10 @@ updateentries(void)
}
void
-usage(char *argv0)
+usage(void)
{
- fprintf(stderr, "usage: %s [-hxso] [-g geometry] [-ws widthscaling] "
- "[-hs heightscaling] [--] "
+ fprintf(stderr, "usage: %s [-hxso] [-g geometry] [-w widthscaling] "
+ "[-e heightscaling] [--] "
"label0 cmd0 [label1 cmd1 ...]\n", argv0);
exit(1);
}
@@ -610,74 +614,49 @@ main(int argc, char *argv[])
int i, xr, yr, bitm;
unsigned int wr, hr;
+ argv0 = argv[0];
addexit = True;
if (argc < 2)
- usage(argv[0]);
- i = 1;
- for (; argv[i]; i++) {
- if (argv[i][0] != '-')
- break;
- if (argv[i][1] == '-') {
- i++;
- break;
- }
-
- switch (argv[i][1]) {
- case 'g':
- if (i >= argc - 1)
- break;
- bitm = XParseGeometry(argv[i+1], &xr, &yr, &wr, &hr);
- if (bitm & XValue)
- wx = xr;
- if (bitm & YValue)
- wy = yr;
- if (bitm & WidthValue)
- ww = (int)wr;
- if (bitm & HeightValue)
- wh = (int)hr;
- if (bitm & XNegative && wx == 0)
- wx = -1;
- if (bitm & YNegative && wy == 0)
- wy = -1;
- i++;
- break;
- case 'h':
- switch ((i >= argc - 1)? 0 : argv[i][2]) {
- case 's':
- heightscaling = atof(argv[i+1]);
- i++;
- break;
- default:
- usage(argv[0]);
- }
- break;
- case 'o':
- horizontal = True;
- break;
- case 's':
- oneshot = 0;
- break;
- case 'w':
- switch ((i >= argc - 1)? 0 : argv[i][2]) {
- case 's':
- widthscaling = atof(argv[i+1]);
- i++;
- break;
- default:
- usage(argv[0]);
- }
- break;
- case 'x':
- addexit = False;
- break;
- default:
- usage(argv[0]);
- }
- }
+ usage();
+
+ ARGBEGIN {
+ case 'g':
+ bitm = XParseGeometry(EARGF(usage()), &xr, &yr, &wr, &hr);
+ if (bitm & XValue)
+ wx = xr;
+ if (bitm & YValue)
+ wy = yr;
+ if (bitm & WidthValue)
+ ww = (int)wr;
+ if (bitm & HeightValue)
+ wh = (int)hr;
+ if (bitm & XNegative && wx == 0)
+ wx = -1;
+ if (bitm & YNegative && wy == 0)
+ wy = -1;
+ break;
+ case 'e':
+ heightscaling = atof(EARGF(usage()));
+ break;
+ case 'o':
+ horizontal = True;
+ break;
+ case 's':
+ oneshot = 0;
+ break;
+ case 'w':
+ widthscaling = atof(EARGF(usage()));
+ break;
+ case 'x':
+ addexit = False;
+ break;
+ default:
+ usage();
+ } ARGEND;
- for (; argv[i]; i++) {
+ for (i = 0; argv[i]; i++) {
label = argv[i];
if (!argv[i+1])
break;
@@ -696,7 +675,7 @@ main(int argc, char *argv[])
die("strdup returned NULL\n");
}
if (nentries < 1)
- usage(argv[0]);
+ usage();
if (addexit) {
entries = realloc(entries, sizeof(entries[0])*(++nentries));