2 * Copyright © 2021 Nick Bowler
4 * Helper functions for formatting --help program output.
6 * In order to support localized output, this depends on the Gnulib gettext-h
7 * and mbswidth modules. However, if ENABLE_NLS is not defined (or defined to
8 * 0) then these modules are not required.
10 * License WTFPL2: Do What The Fuck You Want To Public License, version 2.
11 * This is free software: you are free to do what the fuck you want to.
12 * There is NO WARRANTY, to the extent permitted by law.
32 # include <mbswidth.h>
34 # define gettext(s) (s)
35 # define pgettext_expr(c, s) (s)
36 # define mbsnwidth(a, b, c) (assert(0), 0)
39 #define _(s) gettext(s)
41 /* Returns a single numeric value depending on the type of option:
43 * 6 - if the option has a short option character and an optional argument
44 * 5 - if the option has a short option character and a mandatory argument
45 * 4 - if the option has a short option charater and no argument
47 * 2 - if the option has no short option character and an optional argument
48 * 1 - if the option has no short option character and a mandatory argument
49 * 0 - if the option has no short option character and no argument
51 static int option_type(const struct option *opt)
53 return ((opt->val <= CHAR_MAX) << 2) | (opt->has_arg & 3);
57 OPT_SHORT_WITH_OPTIONAL_ARG = 6,
58 OPT_SHORT_WITH_MANDATORY_ARG = 5,
59 OPT_SHORT_WITHOUT_ARG = 4,
60 OPT_LONG_WITH_OPTIONAL_ARG = 2,
61 OPT_LONG_WITH_MANDATORY_ARG = 1,
62 OPT_LONG_WITHOUT_ARG = 0,
65 int help_print_optstring(const struct option *opt, const char *argname, int l)
73 switch (option_type(opt)) {
74 case OPT_SHORT_WITH_OPTIONAL_ARG:
75 w = snprintf(optstring, sizeof optstring,
76 _(" -%c, --%s[=%s]"), opt->val, opt->name,
77 pgettext_expr(opt->name, argname));
79 case OPT_LONG_WITH_OPTIONAL_ARG:
80 w = snprintf(optstring, sizeof optstring,
81 _(" --%s[=%s]"), opt->name,
82 pgettext_expr(opt->name, argname));
84 case OPT_SHORT_WITH_MANDATORY_ARG:
85 w = snprintf(optstring, sizeof optstring,
86 _(" -%c, --%s=%s"), opt->val, opt->name,
87 pgettext_expr(opt->name, argname));
89 case OPT_LONG_WITH_MANDATORY_ARG:
90 w = snprintf(optstring, sizeof optstring,
91 _(" --%s=%s"), opt->name,
92 pgettext_expr(opt->name, argname));
94 case OPT_SHORT_WITHOUT_ARG:
95 w = snprintf(optstring, sizeof optstring,
96 _(" -%c, --%s"), opt->val, opt->name);
98 case OPT_LONG_WITHOUT_ARG:
99 w = snprintf(optstring, sizeof optstring,
100 _(" --%s"), opt->name);
109 w = mbsnwidth(optstring, w, 0);
110 printf("%s", optstring);
114 switch (option_type(opt)) {
115 case OPT_SHORT_WITH_OPTIONAL_ARG:
116 w = printf(" -%c, --%s[=%s]", opt->val, opt->name, argname);
118 case OPT_LONG_WITH_OPTIONAL_ARG:
119 w = printf(" --%s[=%s]", opt->name, argname);
121 case OPT_SHORT_WITH_MANDATORY_ARG:
122 w = printf(" -%c, --%s=%s", opt->val, opt->name, argname);
124 case OPT_LONG_WITH_MANDATORY_ARG:
125 w = printf(" --%s=%s", opt->name, argname);
127 case OPT_SHORT_WITHOUT_ARG:
128 w = printf(" -%c, --%s", opt->val, opt->name);
130 case OPT_LONG_WITHOUT_ARG:
131 w = printf(" --%s", opt->name);
137 if (w < 0 || w > l) {
145 void help_print_desc(const struct option *opt, const char *s, int i, int w)
147 for (s = pgettext_expr(opt->name, s); *s; w = 0) {
148 const char *nl = strchr(s, '\n');
149 int n = (nl ? nl-s : -1);
151 printf("%*s%.*s\n", i-w, "", n, s);