Revamp ggo help.
authorAndre Noll <maan@systemlinux.org>
Fri, 12 Apr 2013 11:54:37 +0000 (13:54 +0200)
committerAndre Noll <maan@systemlinux.org>
Thu, 13 Jun 2013 16:29:03 +0000 (18:29 +0200)
This adds usage and description fields to struct ggo_help and
changes ggo_print_help() to optionally print these.

The boolean detailed_help flag of ggo_print_help() is replaced by a
bitmask which lets the caller specify what to print. Four pre-defined
masks are used to print the normal help, the detailed help, the help
for modules (receivers, filters, writers) and the detailed module help.

The new macro DEFINE_GGO_HELP can be employed to create a struct
ggo_help from a gengetopt structure.

28 files changed:
afh_recv.c
alsa_write.c
amp_filter.c
ao_write.c
audiod.c
compress_filter.c
configure.ac
dccp_recv.c
file_write.c
filter.c
filter.h
filter_common.c
ggo.c
ggo.h
http_recv.c
mp3dec_filter.c
oss_write.c
osx_write.c
play.c
prebuffer_filter.c
recv.c
recv.h
recv_common.c
resample_filter.c
udp_recv.c
write.c
write_common.c
write_common.h

index 96f0d7e..5c17dab 100644 (file)
@@ -254,9 +254,6 @@ void afh_recv_init(struct receiver *r)
        r->parse_config = afh_recv_parse_config;
        r->free_config = afh_recv_free_config;
        r->execute = afh_execute;
-       r->help = (struct ggo_help) {
-               .short_help = afh_recv_args_info_help,
-               .detailed_help = afh_recv_args_info_detailed_help
-       };
+       r->help = (struct ggo_help)DEFINE_GGO_HELP(afh_recv);
        afh_recv_cmdline_parser_free(&dummy);
 }
index 88e48b4..a3912c1 100644 (file)
@@ -361,9 +361,6 @@ void alsa_write_init(struct writer *w)
        w->post_select = alsa_write_post_select;
        w->parse_config_or_die = alsa_parse_config_or_die;
        w->free_config = alsa_free_config;
-       w->help = (struct ggo_help) {
-               .short_help = alsa_write_args_info_help,
-               .detailed_help = alsa_write_args_info_detailed_help
-       };
+       w->help = (struct ggo_help)DEFINE_GGO_HELP(alsa_write);
        alsa_write_cmdline_parser_free(&dummy);
 }
index a6bfca2..f62ea8a 100644 (file)
@@ -137,8 +137,5 @@ void amp_filter_init(struct filter *f)
        f->post_select = amp_post_select;
        f->parse_config = amp_parse_config;
        f->free_config = amp_free_config;
-       f->help = (struct ggo_help) {
-               .short_help = amp_filter_args_info_help,
-               .detailed_help = amp_filter_args_info_detailed_help
-       };
+       f->help = (struct ggo_help)DEFINE_GGO_HELP(amp_filter);
 }
index 9d204ff..fdae8ee 100644 (file)
@@ -371,9 +371,7 @@ void ao_write_init(struct writer *w)
        w->post_select = aow_post_select;
        w->parse_config_or_die = aow_parse_config_or_die;
        w->free_config = aow_free_config;
-       w->help = (struct ggo_help) {
-               .short_help = ao_write_args_info_help,
-       };
+       w->help = (struct ggo_help)DEFINE_GGO_HELP(ao_write);
        /* create detailed help containing all supported drivers/options */
        for (i = 0; ao_write_args_info_detailed_help[i]; i++)
                ; /* nothing */
index c183491..8552af6 100644 (file)
--- a/audiod.c
+++ b/audiod.c
@@ -1301,17 +1301,17 @@ static void set_initial_status(void)
 
 __noreturn static void print_help_and_die(void)
 {
-       int d = conf.detailed_help_given;
-       const char **p = d? audiod_args_info_detailed_help
-               : audiod_args_info_help;
-
-       printf_or_die("%s\n\n", version_single_line("audiod"));
-       printf_or_die("%s\n\n", audiod_args_info_usage);
-       for (; *p; p++)
-               printf_or_die("%s\n", *p);
-       print_receiver_helps(d);
-       print_filter_helps(d);
-       print_writer_helps(d);
+       struct ggo_help h = DEFINE_GGO_HELP(audiod);
+       bool d = conf.detailed_help_given;
+       unsigned flags;
+
+       flags = d? GPH_STANDARD_FLAGS_DETAILED : GPH_STANDARD_FLAGS;
+       ggo_print_help(&h, flags);
+
+       flags = d? GPH_MODULE_FLAGS_DETAILED : GPH_MODULE_FLAGS;
+       print_receiver_helps(flags);
+       print_filter_helps(flags);
+       print_writer_helps(flags);
        exit(0);
 }
 
index d716279..f6108c7 100644 (file)
@@ -153,8 +153,5 @@ void compress_filter_init(struct filter *f)
        f->post_select = compress_post_select;
        f->parse_config = compress_parse_config;
        f->free_config = compress_free_config;
-       f->help = (struct ggo_help) {
-               .short_help = compress_filter_args_info_help,
-               .detailed_help = compress_filter_args_info_detailed_help
-       };
+       f->help = (struct ggo_help)DEFINE_GGO_HELP(compress_filter);
 }
index 0bd4791..e3d1b40 100644 (file)
@@ -138,7 +138,7 @@ audiod_audio_formats="wma"
 
 afh_cmdline_objs="add_cmdline(afh)"
 afh_errlist_objs="afh string fd mp3_afh afh_common time wma_afh wma_common
-       version"
+       version ggo"
 afh_ldflags=""
 
 write_cmdline_objs="add_cmdline(write file_write)"
index 875d838..c751f2f 100644 (file)
@@ -180,9 +180,6 @@ void dccp_recv_init(struct receiver *r)
        r->post_select = dccp_recv_post_select;
        r->parse_config = dccp_recv_parse_config;
        r->free_config = dccp_recv_free_config;
-       r->help = (struct ggo_help) {
-               .short_help = dccp_recv_args_info_help,
-               .detailed_help = dccp_recv_args_info_detailed_help
-       };
+       r->help = (struct ggo_help)DEFINE_GGO_HELP(dccp_recv);
        dccp_recv_cmdline_parser_free(&dummy);
 }
index cea21cb..f7b2b30 100644 (file)
@@ -157,9 +157,6 @@ void file_write_init(struct writer *w)
        w->parse_config_or_die = file_write_parse_config_or_die;
        w->free_config = file_write_free_config;
        w->close = file_write_close;
-       w->help = (struct ggo_help) {
-               .short_help = file_write_args_info_help,
-               .detailed_help = file_write_args_info_detailed_help
-       };
+       w->help = (struct ggo_help)DEFINE_GGO_HELP(file_write);
        file_write_cmdline_parser_free(&dummy);
 }
index 9ece063..3b68857 100644 (file)
--- a/filter.c
+++ b/filter.c
@@ -47,15 +47,11 @@ INIT_STDERR_LOGGING(loglevel);
 
 __noreturn static void print_help_and_die(void)
 {
-       int d = conf.detailed_help_given;
-       const char **p = d? filter_args_info_detailed_help
-               : filter_args_info_help;
-
-       printf_or_die("%s\n\n", version_single_line("filter"));
-       printf_or_die("%s\n\n", filter_args_info_usage);
-       for (; *p; p++)
-               printf_or_die("%s\n", *p);
-       print_filter_helps(d);
+       struct ggo_help h = DEFINE_GGO_HELP(filter);
+       bool d = conf.detailed_help_given;
+
+       ggo_print_help(&h, d? GPH_STANDARD_FLAGS_DETAILED : GPH_STANDARD_FLAGS);
+       print_filter_helps(d? GPH_MODULE_FLAGS_DETAILED : GPH_MODULE_FLAGS);
        exit(0);
 }
 
index 9c57904..1cda119 100644 (file)
--- a/filter.h
+++ b/filter.h
@@ -121,7 +121,7 @@ struct filter {
 
 void filter_init(void);
 int check_filter_arg(char *filter_arg, void **conf);
-void print_filter_helps(int detailed);
+void print_filter_helps(unsigned flags);
 void generic_filter_pre_select(struct sched *s, struct task *t);
 int decoder_execute(const char *cmd, unsigned sample_rate, unsigned channels,
                char **result);
index 6eb550e..787255a 100644 (file)
@@ -101,9 +101,9 @@ int check_filter_arg(char *fa, void **conf)
 /**
  * Print help text of each filter to stdout.
  *
- * \param detailed If non-zero, print detailed help.
+ * \param flags Passed to \ref ggo_print_help().
  */
-void print_filter_helps(int detailed)
+void print_filter_helps(unsigned flags)
 {
        int i, num = 0;
 
@@ -122,8 +122,8 @@ void print_filter_helps(int detailed)
 
                if (!f->help.short_help)
                        continue;
-               printf_or_die("Options for %s:\n", f->name);
-               ggo_print_help(&f->help, detailed);
+               printf_or_die("\nOptions for %s:", f->name);
+               ggo_print_help(&f->help, flags);
        }
 }
 
diff --git a/ggo.c b/ggo.c
index e3aa579..d8d56c0 100644 (file)
--- a/ggo.c
+++ b/ggo.c
@@ -9,6 +9,7 @@
 
 #include "para.h"
 #include "ggo.h"
+#include "version.h"
 
 /**
  * Wrapper for printf() that exits on errors.
@@ -32,20 +33,25 @@ __printf_1_2 int printf_or_die(const char *fmt, ...)
  * Print one of the two given help texts.
  *
  * \param help contains the help texts.
- * \param detailed_help Whether to print the detailed help text.
+ * \param flags What to print, see \ref ggo_print_help_flags.
  */
-void ggo_print_help(struct ggo_help *help, int detailed_help)
+void ggo_print_help(struct ggo_help *help, unsigned flags)
 {
        const char **p;
 
-       if (!help)
-               return;
-       if (detailed_help)
+       if (flags & GPH_PRINT_NAME_VERSION)
+               printf_or_die("%s\n", version_single_line(help->prefix));
+       if (help->usage && (flags & GPH_PRINT_USAGE))
+               printf_or_die("\n%s\n", help->usage);
+       if (help->description && (flags & GPH_PRINT_DESCRIPTION))
+               printf_or_die("\n%s\n", help->description);
+       printf_or_die("\n");
+       if (flags & GPH_DETAILED)
                p = help->detailed_help;
        else
                p = help->short_help;
        if (!p)
                return;
        for (; *p; p++)
-               printf_or_die("\t%s\n", *p);
+               printf_or_die("%s\n", *p);
 }
diff --git a/ggo.h b/ggo.h
index be85a1b..12574db 100644 (file)
--- a/ggo.h
+++ b/ggo.h
@@ -7,14 +7,61 @@
 /** \file ggo.h Functions and structures for help text handling. */
 
 /**
- * Used by executables that can not use gengetopt's generated help function.
+ * Information extracted from the .cmdline.h header files.
  */
 struct ggo_help {
-       /** The lines of the short help text. */
+       /** Program or module (receiver, filter, writer) name. */
+       const char *prefix;
+       /** Generated by gengetopt from the options in the .ggo file. */
        const char **short_help;
-       /** The lines of the detailed help text. */
+       /** Like \a short_help, plus the \a details section. */
        const char **detailed_help;
+       /** Generated by gengetopt and exported via the *.cmdline.h file. */
+       const char *usage;
+       /** The description text given in the .ggo file. */
+       const char *description;
 };
 
-void ggo_print_help(struct ggo_help *help, int detailed_help);
+/**
+ * Control the output of \ref ggo_print_help().
+ *
+ * Any combination of these flags may be passed to ggo_print_help().
+ * Note that the list of supported options is always printed.
+ */
+enum ggo_print_help_flags {
+       /** Whether to print the short help or the detailed help. */
+       GPH_DETAILED = 1 << 0,
+       /** Print the program or module name, git version and codename. */
+       GPH_PRINT_NAME_VERSION = 1 << 1,
+       /** Print the synopsis. */
+       GPH_PRINT_USAGE = 1 << 2,
+       /** Print the description text. */
+       GPH_PRINT_DESCRIPTION = 1 << 3,
+};
+
+/** Used to print the normal help of programs (--help) */
+#define GPH_STANDARD_FLAGS \
+       (GPH_PRINT_NAME_VERSION | GPH_PRINT_USAGE)
+
+/** Additional information for --detailed-help. */
+#define GPH_STANDARD_FLAGS_DETAILED \
+       (GPH_STANDARD_FLAGS | GPH_DETAILED | GPH_PRINT_DESCRIPTION)
+
+/** For module help embedded in a program help. */
+#define GPH_MODULE_FLAGS 0
+
+/** Modules help with detailed descriptions. */
+#define GPH_MODULE_FLAGS_DETAILED GPH_DETAILED | GPH_PRINT_DESCRIPTION
+
+/** Make a ggo_help structure using information from the .cmdline.h file. */
+#define DEFINE_GGO_HELP(_prefix) \
+       { \
+               .prefix = #_prefix, \
+               .short_help = _prefix ## _args_info_help, \
+               .detailed_help = _prefix ## _args_info_detailed_help, \
+               .usage = _prefix ## _args_info_usage, \
+               .description = _prefix ## _args_info_description, \
+       }
+
+void ggo_print_help(struct ggo_help *help, unsigned flags);
 __printf_1_2 int printf_or_die(const char *fmt, ...);
index 8cb984f..7db8ba1 100644 (file)
@@ -193,9 +193,6 @@ void http_recv_init(struct receiver *r)
        r->post_select = http_recv_post_select;
        r->parse_config = http_recv_parse_config;
        r->free_config = http_recv_free_config;
-       r->help = (struct ggo_help) {
-               .short_help = http_recv_args_info_help,
-               .detailed_help = http_recv_args_info_detailed_help
-       };
+       r->help = (struct ggo_help)DEFINE_GGO_HELP(http_recv);
        http_recv_cmdline_parser_free(&dummy);
 }
index 9862750..33c0dfc 100644 (file)
@@ -221,8 +221,5 @@ void mp3dec_filter_init(struct filter *f)
        f->pre_select = generic_filter_pre_select;
        f->post_select = mp3dec_post_select;
        f->execute = mp3dec_execute;
-       f->help = (struct ggo_help) {
-               .short_help = mp3dec_filter_args_info_help,
-               .detailed_help = mp3dec_filter_args_info_detailed_help
-       };
+       f->help = (struct ggo_help)DEFINE_GGO_HELP(mp3dec_filter);
 }
index cd32724..3c61a44 100644 (file)
@@ -235,9 +235,6 @@ void oss_write_init(struct writer *w)
        w->post_select = oss_post_select;
        w->parse_config_or_die = oss_parse_config_or_die;
        w->free_config = oss_free_config;
-       w->help = (struct ggo_help) {
-               .short_help = oss_write_args_info_help,
-               .detailed_help = oss_write_args_info_detailed_help
-       };
+       w->help = (struct ggo_help)DEFINE_GGO_HELP(oss_write);
        oss_write_cmdline_parser_free(&dummy);
 }
index 41b1903..f1e308d 100644 (file)
@@ -366,9 +366,6 @@ void osx_write_init(struct writer *w)
        w->post_select = osx_write_post_select;
        w->parse_config_or_die = osx_write_parse_config_or_die;
        w->free_config = osx_free_config;
-       w->help = (struct ggo_help) {
-               .short_help = osx_write_args_info_help,
-               .detailed_help = osx_write_args_info_detailed_help
-       };
+       w->help = (struct ggo_help)DEFINE_GGO_HELP(osx_write);
        osx_write_cmdline_parser_free(&dummy);
 }
diff --git a/play.c b/play.c
index 7c1ee93..35b2511 100644 (file)
--- a/play.c
+++ b/play.c
@@ -139,16 +139,11 @@ static void check_afh_receiver_or_die(void)
 
 __noreturn static void print_help_and_die(void)
 {
-       int d = conf.detailed_help_given;
-       const char **p = d? play_args_info_detailed_help
-               : play_args_info_help;
-
-       printf_or_die("%s\n\n", version_single_line("play"));
-       printf_or_die("%s\n\n", play_args_info_usage);
-       if (d)
-               printf_or_die("%s\n", play_args_info_description);
-       for (; *p; p++)
-               printf_or_die("%s\n", *p);
+       struct ggo_help help = DEFINE_GGO_HELP(play);
+       unsigned flags = conf.detailed_help_given?
+               GPH_STANDARD_FLAGS_DETAILED : GPH_STANDARD_FLAGS;
+
+       ggo_print_help(&help, flags);
        exit(0);
 }
 
index 0759d67..655c981 100644 (file)
@@ -123,8 +123,5 @@ void prebuffer_filter_init(struct filter *f)
        f->free_config = prebuffer_free_config;
        f->pre_select = prebuffer_pre_select;
        f->post_select = prebuffer_post_select;
-       f->help = (struct ggo_help) {
-               .short_help = prebuffer_filter_args_info_help,
-               .detailed_help = prebuffer_filter_args_info_detailed_help
-       };
+       f->help = (struct ggo_help)DEFINE_GGO_HELP(prebuffer_filter);
 }
diff --git a/recv.c b/recv.c
index a3fdd30..7a5549a 100644 (file)
--- a/recv.c
+++ b/recv.c
@@ -39,15 +39,11 @@ INIT_RECV_ERRLISTS;
 
 __noreturn static void print_help_and_die(void)
 {
-       int d = conf.detailed_help_given;
-       const char **p = d? recv_args_info_detailed_help
-               : recv_args_info_help;
-
-       printf_or_die("%s\n\n", version_single_line("recv"));
-       printf_or_die("%s\n\n", recv_args_info_usage);
-       for (; *p; p++)
-               printf_or_die("%s\n", *p);
-       print_receiver_helps(d);
+       struct ggo_help h = DEFINE_GGO_HELP(recv);
+       bool d = conf.detailed_help_given;
+
+       ggo_print_help(&h, d? GPH_STANDARD_FLAGS_DETAILED : GPH_STANDARD_FLAGS);
+       print_receiver_helps(d? GPH_MODULE_FLAGS_DETAILED : GPH_MODULE_FLAGS);
        exit(0);
 }
 
diff --git a/recv.h b/recv.h
index cc44a60..008af39 100644 (file)
--- a/recv.h
+++ b/recv.h
@@ -141,7 +141,7 @@ struct receiver {
 
 void recv_init(void);
 void *check_receiver_arg(char *ra, int *receiver_num);
-void print_receiver_helps(int detailed);
+void print_receiver_helps(unsigned flags);
 int generic_recv_pre_select(struct sched *s, struct task *t);
 
 /** \cond receiver */
index f899c30..fe74591 100644 (file)
@@ -92,22 +92,22 @@ void *check_receiver_arg(char *ra, int *receiver_num)
 /**
  * Print out the help texts to all receivers.
  *
- * \param detailed Whether the detailed help should be printed.
+ * \param flags Passed to \ref ggo_print_help().
  */
-void print_receiver_helps(int detailed)
+void print_receiver_helps(unsigned flags)
 {
        int i;
 
-       printf_or_die("\nAvailable receivers: \n\t");
+       printf_or_die("\nAvailable receivers: ");
        FOR_EACH_RECEIVER(i)
                printf_or_die("%s%s", i? " " : "", receivers[i].name);
-       printf_or_die("\n\n");
+       printf_or_die("\n");
        FOR_EACH_RECEIVER(i) {
                struct receiver *r = receivers + i;
                if (!r->help.short_help)
                        continue;
-               printf_or_die("Options for %s:\n", r->name);
-               ggo_print_help(&r->help, detailed);
+               printf_or_die("\nOptions for %s:", r->name);
+               ggo_print_help(&r->help, flags);
        }
 }
 
index bd8ece9..5ad584d 100644 (file)
@@ -310,8 +310,5 @@ void resample_filter_init(struct filter *f)
        f->parse_config = resample_parse_config;
        f->free_config = resample_free_config;
        f->execute = resample_execute;
-       f->help = (struct ggo_help) {
-               .short_help = resample_filter_args_info_help,
-               .detailed_help = resample_filter_args_info_detailed_help
-       };
+       f->help = (struct ggo_help)DEFINE_GGO_HELP(resample_filter);
 }
index cff55f2..436b298 100644 (file)
@@ -220,9 +220,6 @@ void udp_recv_init(struct receiver *r)
        r->post_select = udp_recv_post_select;
        r->parse_config = udp_recv_parse_config;
        r->free_config = udp_recv_free_config;
-       r->help = (struct ggo_help) {
-               .short_help = udp_recv_args_info_help,
-               .detailed_help = udp_recv_args_info_detailed_help
-       };
+       r->help = (struct ggo_help)DEFINE_GGO_HELP(udp_recv);
        udp_recv_cmdline_parser_free(&dummy);
 }
diff --git a/write.c b/write.c
index 73cddf8..6799db4 100644 (file)
--- a/write.c
+++ b/write.c
@@ -35,15 +35,11 @@ INIT_STDERR_LOGGING(loglevel)
 
 __noreturn static void print_help_and_die(void)
 {
-       int d = conf.detailed_help_given;
-       const char **p = d? write_args_info_detailed_help
-               : write_args_info_help;
-
-       printf_or_die("%s\n\n", version_single_line("write"));
-       printf_or_die("%s\n\n", write_args_info_usage);
-       for (; *p; p++)
-               printf_or_die("%s\n", *p);
-       print_writer_helps(d);
+       struct ggo_help h = DEFINE_GGO_HELP(write);
+       bool d = conf.detailed_help_given;
+
+       ggo_print_help(&h, d? GPH_STANDARD_FLAGS_DETAILED : GPH_STANDARD_FLAGS);
+       print_writer_helps(d? GPH_MODULE_FLAGS_DETAILED : GPH_MODULE_FLAGS);
        exit(0);
 }
 
index 44ccf88..b61b938 100644 (file)
@@ -121,23 +121,23 @@ void register_writer_node(struct writer_node *wn, struct btr_node *parent,
 /**
  * Print the help text of all writers to stdout.
  *
- * \param detailed Whether to print the detailed help text.
+ * \param flags Passed to \ref ggo_print_help().
  */
-void print_writer_helps(int detailed)
+void print_writer_helps(unsigned flags)
 {
        int i;
 
-       printf_or_die("\nAvailable writers: \n\t");
+       printf_or_die("\nAvailable writers: ");
        FOR_EACH_WRITER(i)
                printf_or_die("%s%s", i? " " : "", writer_names[i]);
-       printf_or_die("\n\n");
+       printf_or_die("\n");
        FOR_EACH_WRITER(i) {
                struct writer *w = writers + i;
 
                if (!w->help.short_help)
                        continue;
-               printf_or_die("Options for %s:\n", writer_names[i]);
-               ggo_print_help(&w->help, detailed);
+               printf_or_die("\nOptions for %s:", writer_names[i]);
+               ggo_print_help(&w->help, flags);
        }
 }
 
index 8788a4c..ecad2d1 100644 (file)
@@ -8,7 +8,7 @@
 
 void writer_init(void);
 void *check_writer_arg_or_die(const char *wa, int *writer_num);
-void print_writer_helps(int detailed);
+void print_writer_helps(unsigned flags);
 void register_writer_node(struct writer_node *wn, struct btr_node *parent,
                struct sched *s);
 void get_btr_sample_rate(struct btr_node *btrn, int32_t *result);