Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Break long help messages #60

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 54 additions & 9 deletions argparse.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#include <errno.h>
#include "argparse.h"

#define LINE_WRAP 80

#define OPT_UNSET 1
#define OPT_LONG (1 << 1)

Expand Down Expand Up @@ -286,6 +288,55 @@ argparse_parse(struct argparse *self, int argc, const char **argv)
return self->cpidx + self->argc;
}

void argparse_print_help(const char *help, int indent, int offset, int line_wrap)
{
if (offset > indent) {
fputs("\n", stdout);
offset = 0;
}

if (line_wrap - indent <= 1) {
line_wrap = indent + 2;
}

size_t pos = 0;
size_t len = strlen(help);
while (pos < len) {
fprintf(stdout, "%*s", indent - offset, "");
offset = 0;
size_t towrite = line_wrap - indent;
while (help[pos] == ' ') {
pos++;
}
if (pos + towrite > len) {
towrite = len - pos;
fwrite(help + pos, 1, towrite, stdout);
} else {
int space_break = towrite;
while (space_break > 0 && help[pos + space_break - 1] != ' ') {
space_break--;
}

int print_hyphen = 0;
if (space_break == 0) {
print_hyphen = 1;
towrite--;
} else {
towrite = space_break;
}

fwrite(help + pos, 1, towrite, stdout);

if (print_hyphen) {
fputs("-", stdout);
}
}

fputs("\n", stdout);
pos += towrite;
}
}

void
argparse_usage(struct argparse *self)
{
Expand Down Expand Up @@ -329,7 +380,8 @@ argparse_usage(struct argparse *self)
len += strlen("=<str>");
}
len = (len + 3) - ((len + 3) & 3);
if (usage_opts_width < len) {
// If len >= LINE_WRAP / 2, we prints the option on a separate line.
if (len < LINE_WRAP / 2 && usage_opts_width < len) {
usage_opts_width = len;
}
}
Expand All @@ -338,7 +390,6 @@ argparse_usage(struct argparse *self)
options = self->options;
for (; options->type != ARGPARSE_OPT_END; options++) {
size_t pos = 0;
size_t pad = 0;
if (options->type == ARGPARSE_OPT_GROUP) {
fputc('\n', stdout);
fprintf(stdout, "%s", options->help);
Expand All @@ -362,13 +413,7 @@ argparse_usage(struct argparse *self)
} else if (options->type == ARGPARSE_OPT_STRING) {
pos += fprintf(stdout, "=<str>");
}
if (pos <= usage_opts_width) {
pad = usage_opts_width - pos;
} else {
fputc('\n', stdout);
pad = usage_opts_width;
}
fprintf(stdout, "%*s%s\n", (int)pad + 2, "", options->help);
argparse_print_help(options->help, usage_opts_width + 2, pos, LINE_WRAP);
}

// print epilog
Expand Down
4 changes: 4 additions & 0 deletions tests/basic.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ main(int argc, const char **argv)
float flt_num = 0.f;
const char *path = NULL;
int perms = 0;
int long_opt = 0;
struct argparse_option options[] = {
OPT_HELP(),
OPT_GROUP("Basic options"),
Expand All @@ -30,6 +31,9 @@ main(int argc, const char **argv)
OPT_STRING('p', "path", &path, "path to read", NULL, 0, 0),
OPT_INTEGER('i', "int", &int_num, "selected integer", NULL, 0, 0),
OPT_FLOAT('s', "float", &flt_num, "selected float", NULL, 0, 0),
OPT_BOOLEAN('l', "long", &long_opt, "a option that has a really really long help message, "
"used to demonstrate that argparse can automatically break up long help messages "
"into multiple lines.", NULL, 0, 0),
OPT_GROUP("Bits options"),
OPT_BIT(0, "read", &perms, "read perm", NULL, PERM_READ, OPT_NONEG),
OPT_BIT(0, "write", &perms, "write perm", NULL, PERM_WRITE, 0),
Expand Down
3 changes: 3 additions & 0 deletions tests/basic.sh
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ Basic options
-p, --path=<str> path to read
-i, --int=<int> selected integer
-s, --float=<flt> selected float
-l, --long a option that has a really really long help message,
used to demonstrate that argparse can automatically
break up long help messages into multiple lines.

Bits options
--read read perm
Expand Down