1
0
mirror of https://github.com/gryf/wmaker.git synced 2025-12-19 20:38:08 +01:00

util: improve the command line argument parsing in wmmenugen

The code ignored the last argument provided on the command line;

It did not support the recommended '--version' and '--help' from GNU which
are often handy;

It used an unusual syntax to specify the parser, now it can also use more
usual "-parser=name" and "-parser name", the old syntax is still supported
to avoid breaking compatibility;

When a problem is found with an argument, the program stops instead of
printing an error message and continuing;

There's been updates on the exit codes in case of problem because it is an
information that could be useful for people calling the program from a
script;

Took the opportunity to provide more information in the man page and to
get it cross-checked against the program's option list during "make check".

Signed-off-by: Christophe CURIS <christophe.curis@free.fr>
This commit is contained in:
Christophe CURIS
2015-05-23 17:19:30 +02:00
committed by Carlos R. Mafra
parent 8088dc1eab
commit 0a009143c3
3 changed files with 173 additions and 43 deletions

View File

@@ -49,7 +49,7 @@ am__v_CHKOPTS_0 = @echo " CHK $@" ;
am__v_CHKOPTS_1 =
check-local: wmaker-args WPrefs-args wmagnify-args geticonset-args getstyle-args seticons-args setstyle-args \
wdread-args wdwrite-args wmgenmenu-args wmsetbg-args wxcopy-args wxpaste-args
wdread-args wdwrite-args wmgenmenu-args wmmenugen-args wmsetbg-args wxcopy-args wxpaste-args
wmaker-args:
$(AM_V_CHKOPTS)$(top_srcdir)/script/check-cmdline-options-doc.sh \
@@ -91,6 +91,10 @@ wmgenmenu-args:
$(AM_V_CHKOPTS)$(top_srcdir)/script/check-cmdline-options-doc.sh \
--program "$(top_builddir)/util/wmgenmenu" --man-page "$(top_srcdir)/doc/wmgenmenu.1"
wmmenugen-args:
$(AM_V_CHKOPTS)$(top_srcdir)/script/check-cmdline-options-doc.sh \
--program "$(top_builddir)/util/wmmenugen" --man-page "$(top_srcdir)/doc/wmmenugen.1"
wmsetbg-args:
$(AM_V_CHKOPTS)$(top_srcdir)/script/check-cmdline-options-doc.sh \
--program "$(top_builddir)/util/wmsetbg" --man-page "wmsetbg.1"
@@ -104,4 +108,4 @@ wxpaste-args:
--program "$(top_builddir)/util/wxpaste" --man-page "$(top_srcdir)/doc/wxpaste.1"
.PHONY: wmaker-args WPrefs-args wmagnify-args geticonset-args getstyle-args seticons-args setstyle-args \
wdread-args wdwrite-args wmgenmenu-args wmsetbg-args wxcopy-args wxpaste-args
wdread-args wdwrite-args wmgenmenu-args wmmenugen-args wmsetbg-args wxcopy-args wxpaste-args

View File

@@ -1,22 +1,93 @@
.TH "wmmenugen" "1" "15 August 2011"
.TH "wmmenugen" "1" "16 May 2015"
.SH "NAME"
\fBwmmenugen\fR \- Window Maker PropList menu generator
.PP
.SH "SYNOPSIS"
.B wmmenugen \fI\-parser:<parser> fspec \fR[ fpsec ... \fR]
\fR[\fI\-parser:<parser> fspec \fR[ fpsec ... \fR] ... \fR]
.PP
.B wmmenugen
.RI [ options ...]
.BI \-parser= <name>
.IR fspec " [" fspec "...]"
.BI \fR[\fP\-parser= <name>
.IR fspec " [" fspec "...]...]"
.SH "DESCRIPTION"
\fBwmmenugen \fR\- Window Maker PropList menu generator
.PP
.B wmmenugen
generates a menu in the
.I PropList
format for Window Maker from the input file
.IR fspec .
In the case where
.I fspec
is a directory instead of a file, then
.B wmmenugen
will read all the files present in the hierarchy of this directory.
.SH "OPTIONS"
.TP
.B \-parser
\fRspecify the parser. Known parsers are xdg and wmconfig.
.BR \-\-help ", " \-h
print a help message with the list of options
.TP
.B \-fspec
\fRspecify the file.
.B \-parser
specify the format of the file to be parsed
.TP
.B \-\-version
print the version of Window Maker from which the program comes
.SH "PARSERS"
.B wmmenugen
supports these file formats for input files:
.TP
.I wmconfig
the format of the menu generation tool for X of the same name
.TP
.I xdg
the format of the menu specification as defined by the
.I FreeDesktop
standard, currently at version 1.1
.SH "RETURN VALUE"
The exit status from the
.B wmmenugen
command provides information for the caller:
.TP
.B 0
when the
.I PropList
menu was successfully generated on
.IR stdout .
.TP
.B 1
when a
.I fspec
caused a problem (non readable file, ...)
.TP
.B 2
the arguments of the command line where not recognised
.TP
.B 3
the program met an unexpected menu structure;
you probably want to look at the section
.B BUGS
below.
.SH "BUGS"
If you get the exit status
.B 3
with the unclear error message about
.IR "unprocessed levels on the stack" ,
you encountered a limitation of
.BR wmmenugen .
It would be a good idea to prepare an archive with the files incriminated and submit them to the
mailing list (wmaker-dev@lists.windowmaker.org) with you command line, so the team can work on
improving the behaviour of the program on this case.
.SH "SEE ALSO"
.BR wmgenmenu (1),
the tool to generate a default menu
.PP
the
.I Wmconfig
program can be found at:
<http://www.arrishq.net/index.html>
.PP
the
.I xdg
specification can be found at:
<http://standards.freedesktop.org/menu-spec/menu-spec-1.1.html>
.SH "AUTHOR"
wmmenugen is a part of Window Maker. It was written by Tamas TEVESZ.
.PP

View File

@@ -28,6 +28,7 @@
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <errno.h>
#include "wmmenugen.h"
@@ -54,6 +55,35 @@ static const char *prog_name;
WMTreeNode *menu;
char *env_lang, *env_ctry, *env_enc, *env_mod;
static void print_help(void)
{
printf("Usage: %s -parser:<parser> fspec [fspec...]\n", prog_name);
puts("Dynamically generate a menu in Property List format for Window Maker");
puts("");
puts(" -h, --help\t\tdisplay this help and exit");
puts(" -parser=<name>\tspecify the format of the input, see below");
puts(" --version\t\toutput version information and exit");
puts("");
puts("fspec: the file to be converted or the directory containing all the menu files");
puts("");
puts("Known parsers:");
puts(" xdg\t\tDesktop Entry from FreeDesktop standard");
puts(" wmconfig\tfrom the menu generation tool by the same name");
}
#ifdef DEBUG
static const char *get_parser_name(void)
{
if (parse == &parse_xdg)
return "xdg";
if (parse == &parse_wmconfig)
return "wmconfig";
/* This case is not supposed to happen, but if it does it means that someone to update this list */
return "<unknown>";
}
#endif
int main(int argc, char **argv)
{
struct stat st;
@@ -76,45 +106,69 @@ int main(int argc, char **argv)
parse_locale(NULL, &env_lang, &env_ctry, &env_enc, &env_mod);
terminal = find_terminal_emulator();
if (argc < 3) {
fprintf(stderr, "Usage: %s -parser:<parser> fspec [fpsec...] "
"[-parser:<parser> fspec [fpsec...]...]\n", prog_name);
fputs( "Known parsers: xdg wmconfig\n", stderr);
return 1;
for (i = 1; i <= argc; i++)
{
if (strncmp(argv[i], "-parser", 7) == 0 &&
(argv[i][7] == '=' ||
argv[i][7] == ':' || /* for legacy compatibility */
argv[i][7] == '\0')) {
const char *name;
if (argv[i][7] == '\0') {
if (++i > argc) {
fprintf(stderr, "%s: Missing parser name after \"-parser\"\n", prog_name);
return 2;
}
name = argv[i];
} else {
name = argv[i] + 8;
}
for (i = 1; i < argc; i++)
{
if (strncmp(argv[i], "-parser:", 8) == 0) {
if (strcmp(argv[i] + 8, "xdg") == 0) {
#if DEBUG
fputs("Using parser \"xdg\"\n", stderr);
#endif
if (strcmp(name, "xdg") == 0) {
parse = &parse_xdg;
} else if (strcmp(argv[i] + 8, "wmconfig") == 0) {
#if DEBUG
fputs("Using parser \"wmconfig\"\n", stderr);
#endif
} else if (strcmp(name, "wmconfig") == 0) {
parse = &parse_wmconfig;
validateFilename = &wmconfig_validate_file;
} else {
fprintf(stderr, "%s: Unknown parser \"%s\"\n", prog_name, argv[i] + 8);
fprintf(stderr, "%s: Unknown parser \"%s\"\n", prog_name, name);
return 2;
}
continue;
}
if (parse) {
if (strcmp(argv[i], "--version") == 0) {
printf("%s (Window Maker %s)\n", prog_name, VERSION);
return 0;
}
if (strcmp(argv[i], "-h") == 0 ||
strcmp(argv[i], "-help") == 0 ||
strcmp(argv[i], "--help") == 0) {
print_help();
return 0;
}
if (parse == NULL) {
fprintf(stderr, "%s: argument \"%s\" with no valid parser\n", prog_name, argv[i]);
return 2;
}
#if DEBUG
fprintf(stderr, "%s: Using parser \"%s\" to process \"%s\"\n",
prog_name, get_parser_name(), argv[i]);
#endif
if (stat(argv[i], &st) == -1) {
fprintf(stderr, "%s: unable to stat \"%s\"\n", prog_name, argv[i]);
fprintf(stderr, "%s: unable to stat \"%s\", %s\n",
prog_name, argv[i], strerror(errno));
return 1;
} else if (S_ISREG(st.st_mode)) {
parse(argv[i], addWMMenuEntryCallback);
} else if (S_ISDIR(st.st_mode)) {
nftw(argv[i], dirParseFunc, 16, FTW_PHYS);
} else {
fprintf(stderr, "%s: \"%s\" is not a file or directory\n", prog_name, argv[i]);
}
} else {
fprintf(stderr, "%s: argument \"%s\" with no valid parser\n", prog_name, argv[i]);
return 1;
}
}
@@ -129,16 +183,17 @@ int main(int argc, char **argv)
i = WMGetArrayItemCount(plMenuNodes);
if (i > 2) { /* more than one submenu unprocessed is almost certainly an error */
fprintf(stderr, "%s: unprocessed levels on the stack. fishy.\n", prog_name);
return 1;
return 3;
} else if (i > 1 ) { /* possibly the top-level attachment is not yet done */
WMPropList *first, *next;
next = WMPopFromArray(plMenuNodes);
first = WMPopFromArray(plMenuNodes);
WMAddToPLArray(first, next);
WMAddToArray(plMenuNodes, first);
}
printf("%s\n", WMGetPropListDescription((WMPropList *)WMGetFromArray(plMenuNodes, 0), True));
puts(WMGetPropListDescription((WMPropList *)WMGetFromArray(plMenuNodes, 0), True));
return 0;
}