Commit 2a28ab58 2a28ab58762f9ae9cd00ca3e467ee6f90f241201 by Sergey Poznyakoff

Rewrite parseopt help routines using wordwrap streams

* include/mailutils/stream.h (MU_IOCTL_WORDWRAP_SET_NEXT_MARGIN)
(MU_IOCTL_WORDWRAP_GET_OFFSET): New opcodes.
* libmailutils/stream/wordwrap.c (_wordwrap_flush_line): Replace
whitespace-only lines with single newline on output.
(_wordwrap_flush): Fix condition.
(set_margin): Bugfix.
(_wordwrap_ctl): Handle new opcodes.

* include/mailutils/cli.h (mu_version_func): Change signature.
* include/mailutils/opt.h (mu_parseopt) <po_help_hook>
<po_version_hook>: Change signature.
(mu_parseopt_fmt_text): Remove.
(mu_option_describe_options, mu_program_help)
(mu_program_usage): Change signature.
(mu_program_version): New prototype.
* libmailutils/cli/cli.c (mu_version_func): Take mu_stream_t as
2nd argument.  Use mu_stream_printf for output.
(extra_help_hook): Likewise.
* libmailutils/opt/help.c: Rewrite using wordwrap streams.
* libmailutils/opt/opt.c (fn_help, fn_usage, fn_version): Update.
* libmailutils/tests/parseopt.c (version_hook): Write to mu_stream_t.

* libmailutils/tests/parseopt_help00.at: Fix expected output.
* libmailutils/tests/parseopt_help01.at: Likewise.
* libmailutils/tests/parseopt_help02.at: Likewise.
* libmailutils/tests/parseopt_help03.at: Likewise.
* libmailutils/tests/parseopt_help04.at: Likewise.
* libmailutils/tests/parseopt_help05.at: Likewise.
* libmailutils/tests/parseopt_help06.at: Likewise.
* libmailutils/tests/parseopt_help07.at: Likewise.
* libmailutils/tests/parseopt_help08.at: Likewise.
* libmailutils/tests/parseopt_help09.at: Likewise.
* libmailutils/tests/parseopt_help10.at: Likewise.
* libmailutils/tests/parseopt_help11.at: Likewise.
1 parent 06c13b34
......@@ -50,7 +50,7 @@ struct mu_cli_setup
errors */
};
void mu_version_func (struct mu_parseopt *po, FILE *stream);
void mu_version_func (struct mu_parseopt *po, mu_stream_t stream);
void mu_cli (int argc, char **argv, struct mu_cli_setup *setup,
char **capa, void *data,
int *ret_argc, char ***ret_argv);
......
......@@ -131,9 +131,8 @@ struct mu_parseopt
char const *po_package_url;
char const *po_extra_info;
/* FIXME: should these take mu_stream_t ?*/
void (*po_help_hook) (struct mu_parseopt *po, FILE *stream);
void (*po_version_hook) (struct mu_parseopt *po, FILE *stream);
void (*po_help_hook) (struct mu_parseopt *po, mu_stream_t stream);
void (*po_version_hook) (struct mu_parseopt *po, mu_stream_t stream);
/* Output data */
int po_ind; /* Index of the next option */
......@@ -169,11 +168,12 @@ int mu_parseopt_apply (struct mu_parseopt *p);
void mu_parseopt_free (struct mu_parseopt *p);
unsigned mu_parseopt_getcolumn (const char *name);
void mu_parseopt_fmt_text (const char *text, size_t col);
void mu_option_describe_options (struct mu_option **optbuf, size_t optcnt);
void mu_program_help (struct mu_parseopt *p);
void mu_program_usage (struct mu_parseopt *p);
void mu_option_describe_options (mu_stream_t str,
struct mu_option **optbuf, size_t optcnt);
void mu_program_help (struct mu_parseopt *p, mu_stream_t str);
void mu_program_usage (struct mu_parseopt *p, mu_stream_t str);
void mu_program_version (struct mu_parseopt *po, mu_stream_t str);
void mu_option_set_value (struct mu_parseopt *po, struct mu_option *opt,
char const *arg);
......
......@@ -208,10 +208,12 @@ enum mu_buffer_type
((n) == MU_TRANSPORT_INPUT || (n) == MU_TRANSPORT_OUTPUT)
/* Word wrapper streams */
#define MU_IOCTL_WORDWRAP_GET_MARGIN 0
#define MU_IOCTL_WORDWRAP_SET_MARGIN 1
#define MU_IOCTL_WORDWRAP_MOVE_MARGIN 2
#define MU_IOCTL_WORDWRAP_GET_MARGIN 0
#define MU_IOCTL_WORDWRAP_SET_MARGIN 1
#define MU_IOCTL_WORDWRAP_MOVE_MARGIN 2
#define MU_IOCTL_WORDWRAP_SET_NEXT_MARGIN 3
#define MU_IOCTL_WORDWRAP_GET_OFFSET 4
struct mu_nullstream_pattern
{
char *pattern;
......
......@@ -53,40 +53,37 @@ const char mu_version_copyright[] =
"Copyright %s 2007-2016 Free Software Foundation, inc.";
void
mu_version_func (struct mu_parseopt *po, FILE *stream)
mu_version_func (struct mu_parseopt *po, mu_stream_t stream)
{
#ifdef GIT_DESCRIBE
fprintf (stream, "%s (%s) %s [%s]\n",
mu_program_name, PACKAGE_NAME, PACKAGE_VERSION, GIT_DESCRIBE);
mu_stream_printf (stream, "%s (%s) %s [%s]\n",
mu_program_name, PACKAGE_NAME, PACKAGE_VERSION,
GIT_DESCRIBE);
#else
fprintf (stream, "%s (%s) %s\n", mu_program_name,
PACKAGE_NAME, PACKAGE_VERSION);
mu_stream_printf (stream, "%s (%s) %s\n", mu_program_name,
PACKAGE_NAME, PACKAGE_VERSION);
#endif
/* TRANSLATORS: Translate "(C)" to the copyright symbol
(C-in-a-circle), if this symbol is available in the user's
locale. Otherwise, do not translate "(C)"; leave it as-is. */
fprintf (stream, mu_version_copyright, _("(C)"));
fputs (_("\
mu_stream_printf (stream, mu_version_copyright, _("(C)"));
mu_stream_printf (stream, _("\
\n\
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\nThis is free software: you are free to change and redistribute it.\n\
There is NO WARRANTY, to the extent permitted by law.\n\
\n\
"),
stream);
"));
}
static char gnu_general_help_url[] =
N_("General help using GNU software: <http://www.gnu.org/gethelp/>");
static void
extra_help_hook (struct mu_parseopt *po, FILE *stream)
extra_help_hook (struct mu_parseopt *po, mu_stream_t stream)
{
struct mu_cfg_parse_hints *hints = po->po_data;
struct mu_cli_setup *setup = hints->data;
char *extra_doc = _(setup->prog_extra_doc);
/* FIXME: mu_parseopt help output should get FILE * argument */
mu_parseopt_fmt_text (extra_doc, 0);
fputc ('\n', stdout);
mu_stream_printf (stream, "%s\n", _(setup->prog_extra_doc));
}
static void
......
......@@ -24,6 +24,7 @@
#include <mailutils/opt.h>
#include <mailutils/nls.h>
#include <mailutils/errno.h>
#include <mailutils/stdstream.h>
#define EXIT_SUCCESS 0
#define EXIT_ERROR 1
......@@ -78,7 +79,7 @@ sort_group (struct mu_option **optbuf, size_t start)
static void
fn_help (struct mu_parseopt *po, struct mu_option *opt, char const *unused)
{
mu_program_help (po);
mu_program_help (po, mu_strout);
exit (EXIT_SUCCESS);
}
......@@ -86,14 +87,14 @@ fn_help (struct mu_parseopt *po, struct mu_option *opt, char const *unused)
static void
fn_usage (struct mu_parseopt *po, struct mu_option *opt, char const *unused)
{
mu_program_usage (po);
mu_program_usage (po, mu_strout);
exit (EXIT_SUCCESS);
}
static void
fn_version (struct mu_parseopt *po, struct mu_option *opt, char const *unused)
{
po->po_version_hook (po, stdout);
mu_program_version (po, mu_strout);
exit (EXIT_SUCCESS);
}
......
......@@ -88,7 +88,7 @@ _wordwrap_flush_line (struct mu_wordwrap_stream *str, int lookahead)
}
}
while (length > 0 && mu_isblank (str->buffer[length - 1]))
while (length > 0 && mu_isspace (str->buffer[length - 1]))
length--;
if (length == 0 || str->buffer[length - 1] != '\n')
......@@ -147,7 +147,7 @@ static int
_wordwrap_flush (mu_stream_t stream)
{
struct mu_wordwrap_stream *str = (struct mu_wordwrap_stream *)stream;
if (str->offset)
if (str->offset > str->left_margin)
_wordwrap_flush_line (str, 0);
return mu_stream_flush (str->transport);
}
......@@ -177,18 +177,19 @@ set_margin (mu_stream_t stream, unsigned lmargin, int off)
if (lmargin >= str->right_margin)
return EINVAL;
if (lmargin < str->offset)
str->left_margin = lmargin;
if (lmargin < str->offset ||
(str->offset > 0 && str->buffer[str->offset - 1] == '\n'))
{
str->left_margin = lmargin;
_wordwrap_flush (stream);
}
else if (lmargin > str->offset)
{
memset (str->buffer + str->offset, ' ',
lmargin - str->offset);
str->left_margin = lmargin;
memset (str->buffer + str->offset, ' ', lmargin - str->offset);
str->offset = lmargin;
}
return 0;
}
......@@ -217,12 +218,30 @@ _wordwrap_ctl (mu_stream_t stream, int code, int opcode, void *arg)
else
return set_margin (stream, *(unsigned*)arg, 0);
case MU_IOCTL_WORDWRAP_SET_NEXT_MARGIN:
if (!arg)
return EINVAL;
else
{
unsigned marg = *(unsigned*)arg;
if (marg >= str->right_margin)
return EINVAL;
str->left_margin = marg;
}
break;
case MU_IOCTL_WORDWRAP_MOVE_MARGIN:
if (!arg)
return EINVAL;
else
return set_margin (stream, str->offset, *(int*)arg);
case MU_IOCTL_WORDWRAP_GET_OFFSET:
if (!arg)
return EINVAL;
*(unsigned*)arg = str->offset;
break;
default:
return EINVAL;
}
......
......@@ -64,9 +64,9 @@ struct mu_option group_b[] = {
struct mu_option *optv[] = { group_a, group_b, NULL };
static void
version_hook (struct mu_parseopt *po, FILE *fp)
version_hook (struct mu_parseopt *po, mu_stream_t str)
{
fputs ("version hook called\n", fp);
mu_stream_printf (str, "version hook called\n");
}
#define S(s) ((s)?(s):"(null)")
......
......@@ -30,8 +30,8 @@ parseopt --help
-x short-only option
Group B
-F, --find=VALUE find VALUE
-d, -v, --debug, --verbose another option
-F, --find=VALUE find VALUE
-j, --jobs=N sets numeric value
-?, --help give this help list
......
......@@ -21,8 +21,8 @@ PARSEOPT_DEFAULT
parseopt --usage
],
[0],
[[Usage: parseopt [-advx?] [-f FILE] [-F VALUE] [-j N] [-o FILE] [--all]
[[Usage: parseopt [-advx?] [-f FILE] [-F VALUE] [-j N] [-o[FILE]] [--all]
[--debug] [--file=FILE] [--find=VALUE] [--help] [--jobs=N]
[--optional=FILE] [--usage] [--verbose]
[--optional[=FILE]] [--usage] [--verbose]
]])
AT_CLEANUP
......
......@@ -30,8 +30,8 @@ MU_PARSEOPT_PROG_NAME=newname parseopt --help
-x short-only option
Group B
-F, --find=VALUE find VALUE
-d, -v, --debug, --verbose another option
-F, --find=VALUE find VALUE
-j, --jobs=N sets numeric value
-?, --help give this help list
......
......@@ -31,8 +31,8 @@ Tests option parsing
-x short-only option
Group B
-F, --find=VALUE find VALUE
-d, -v, --debug, --verbose another option
-F, --find=VALUE find VALUE
-j, --jobs=N sets numeric value
-?, --help give this help list
......
......@@ -30,8 +30,8 @@ MU_PARSEOPT_PROG_ARGS="SOME MORE ARGS" parseopt --help
-x short-only option
Group B
-F, --find=VALUE find VALUE
-d, -v, --debug, --verbose another option
-F, --find=VALUE find VALUE
-j, --jobs=N sets numeric value
-?, --help give this help list
......
......@@ -30,8 +30,8 @@ MU_PARSEOPT_BUG_ADDRESS='gray@gnu.org' parseopt --help
-x short-only option
Group B
-F, --find=VALUE find VALUE
-d, -v, --debug, --verbose another option
-F, --find=VALUE find VALUE
-j, --jobs=N sets numeric value
-?, --help give this help list
......
......@@ -30,8 +30,8 @@ MU_PARSEOPT_PACKAGE_NAME='GNU Mailutils' MU_PARSEOPT_PACKAGE_URL='http://mailuti
-x short-only option
Group B
-F, --find=VALUE find VALUE
-d, -v, --debug, --verbose another option
-F, --find=VALUE find VALUE
-j, --jobs=N sets numeric value
-?, --help give this help list
......
......@@ -37,8 +37,8 @@ Tests option parsing
-x short-only option
Group B
-F, --find=VALUE find VALUE
-d, -v, --debug, --verbose another option
-F, --find=VALUE find VALUE
-j, --jobs=N sets numeric value
-?, --help give this help list
......
......@@ -31,8 +31,8 @@ ARGP_HELP_FMT=dup-args,no-dup-args-note,short-opt-col=1,opt-doc-col=32,header-co
-x short-only option
Group B
-F VALUE, --find=VALUE find VALUE
-d, -v, --debug, --verbose another option
-F VALUE, --find=VALUE find VALUE
-j N, --jobs=N sets numeric value
-?, --help give this help list
......
......@@ -23,7 +23,7 @@ ARGP_HELP_FMT=rmargin=62,usage-indent=1\
],
[0],
[[Usage: parseopt [-advx?] [-f FILE] [-F VALUE] [-j N]
[-o FILE] [--all] [--debug] [--file=FILE] [--find=VALUE]
[--help] [--jobs=N] [--optional=FILE] [--usage] [--verbose]
[-o[FILE]] [--all] [--debug] [--file=FILE] [--find=VALUE]
[--help] [--jobs=N] [--optional[=FILE]] [--usage] [--verbose]
]])
AT_CLEANUP
......
......@@ -21,8 +21,8 @@ PARSEOPT_DEFAULT
MU_PARSEOPT_VERSION_HOOK=1 parseopt --usage
],
[0],
[[Usage: parseopt [-advVx?] [-f FILE] [-F VALUE] [-j N] [-o FILE] [--all]
[[Usage: parseopt [-advVx?] [-f FILE] [-F VALUE] [-j N] [-o[FILE]] [--all]
[--debug] [--file=FILE] [--find=VALUE] [--help] [--jobs=N]
[--optional=FILE] [--usage] [--verbose] [--version]
[--optional[=FILE]] [--usage] [--verbose] [--version]
]])
AT_CLEANUP
......
......@@ -30,8 +30,8 @@ MU_PARSEOPT_VERSION_HOOK=1 parseopt --help
-x short-only option
Group B
-F, --find=VALUE find VALUE
-d, -v, --debug, --verbose another option
-F, --find=VALUE find VALUE
-j, --jobs=N sets numeric value
-?, --help give this help list
......