argtable / argtable3

A single-file, ANSI C, command-line parsing library that parses GNU-style command-line options.
http://www.argtable.org
Other
372 stars 65 forks source link

long glossary line wraps without indentation #52

Closed bguo068 closed 3 years ago

bguo068 commented 3 years ago
/tmp $ ./a.out --help
Usage: util.exe [-v] [--help] [--version] [--level=<n>] [-o myfile] <file> [<file>]...
Demonstrate command-line parsing in argtable3.

  --help                    If the glossary is very long, it will wrap to the next line with no indentation in the following lines. It will 
be great to have a function to format the long line into several lines with indentations!
  --version                 display version info and exit
  --level=<n>               foo value
  -v, --verbose             verbose output
  -o myfile                 output file
  <file>                    input files

If the glossary is very long (--help option for example) , it will wrap to the next line with no indentation in the following lines. It will be great to have a function to format the long line into several lines with indentations!

tomghuang commented 3 years ago

Hi @gbinux , Argtable3 does have a function, arg_rem, to resolve this issue. For example:

struct arg_lit *update  = arg_litn("u", "update", 0, 1, "copy only when SOURCE files are");
struct arg_rem *update1 = arg_rem(NULL,                 "  newer than destination files");
struct arg_rem *update1 = arg_rem(NULL,                 "  or when destination files");
struct arg_rem *update2 = arg_rem(NULL,                 "  are missing");

The example above will generate the following glossary:

-u, --update                   copy only when SOURCE files are
                                 newer than destination files
                                 or when the destination files
                                 are missing
bguo068 commented 3 years ago

Thanks for the reply @tomghuang . I understand that arg_remcan help manually wrap the text and it might take some efforts to do it for every option. I was thinking about a function that can automatically wap the long string according to a specified width. For example,

/*
 * indent1 for the first line
 * indent2 for the following lines
 * width for the maximum text width
 */

int
fprint_wrap(FILE *file, const char *str, int indent1, int indent2, int width)
{
    int str_len;
    char *buf, *p1, *p2, *end, tmp_char;
    int indent, lineno;

    /* make a copy */
    str_len = strlen(str);
    buf = malloc(sizeof(*buf) * (str_len + 1));
    memcpy(buf, str, str_len + 1);

    p1 = p2 = buf;
    end = buf + str_len;
    lineno = -1;
    while (p1 < end) {
        lineno++;
        indent = lineno > 0 ? indent2 : indent1;
        while (p2 < end && p2 < p1 + width - indent && *p2 != '\n') {
            p2++;
        }
        if (*p2 == '\n') {
            *p2 = '\0';
            fprintf(stdout, "%*s %s\n", -indent, "", p1);
            p2++;
            p1 = p2;
        } else if (p2 == end) {
            fprintf(stdout, "%*s %s\n", -indent, "", p1);
            p1 = end;
        } else {
            while (*p2 != ' ' && p2 > p1) {
                p2--;
            }
            if (*p2 == ' ') {
                *p2 = '\0';
                fprintf(stdout, "%*s %s\n", -indent, "", p1);
                p2++;
                p1 = p2;
            } else if (p2 == p1) {
                p2 = p1 + width;
                tmp_char = *p2;
                *p2 = '\0';
                fprintf(stdout, "%*s %s\n", -indent, "", p1);
                *p2 = tmp_char;
                p1 = p2;
            }
        }
    }

    free(buf);
    return 0;
}
tomghuang commented 3 years ago

Hi @gbinux , thank you for your suggestion. I'm planning the public interface for the next minor version (3.2.0), and I'll think about this suggestion.

The benefit of the current arg_rem mechanism is that, you can see exactly what the glossary will look like in the source code. Although it's tedious, it can let you control where to wrap your string. When you can see how the wrapped glossary strings look like, you can feel whether it is easy to browse the glossary or not, and you may change words and sentence structure to make them easier to read.