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.cu...@free.fr> --- doc/Makefile.am | 8 +++- doc/wmmenugen.1 | 89 +++++++++++++++++++++++++++++++++++++----- util/wmmenugen.c | 117 ++++++++++++++++++++++++++++++++++++++++--------------- 3 files changed, 172 insertions(+), 42 deletions(-) diff --git a/doc/Makefile.am b/doc/Makefile.am index 26187f5..500e33a 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -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 diff --git a/doc/wmmenugen.1 b/doc/wmmenugen.1 index 4a9f588..1617648 100644 --- a/doc/wmmenugen.1 +++ b/doc/wmmenugen.1 @@ -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 +.BR \-\-help ", " \-h +print a help message with the list of options +.TP .B \-parser -\fRspecify the parser. Known parsers are xdg and wmconfig. +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 -.B \-fspec -\fRspecify the file. +.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 diff --git a/util/wmmenugen.c b/util/wmmenugen.c index 0c55d51..5839189 100644 --- a/util/wmmenugen.c +++ b/util/wmmenugen.c @@ -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++) + 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 (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; + } + + 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 (stat(argv[i], &st) == -1) { - fprintf(stderr, "%s: unable to stat \"%s\"\n", prog_name, argv[i]); - } 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 { + 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\", %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]); + 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; } -- 2.1.4 -- To unsubscribe, send mail to wmaker-dev-unsubscr...@lists.windowmaker.org.