mirror of
https://github.com/ascii-boxes/boxes.git
synced 2025-01-05 21:49:04 +01:00
827 lines
26 KiB
C
827 lines
26 KiB
C
/*
|
|
* boxes - Command line filter to draw/remove ASCII boxes around text
|
|
* Copyright (c) 1999-2023 Thomas Jensen and the boxes contributors
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
|
|
* License, version 3, as published by the Free Software Foundation.
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
|
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
* details.
|
|
* You should have received a copy of the GNU General Public License along with this program.
|
|
* If not, see <https://www.gnu.org/licenses/>.
|
|
*
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
*/
|
|
|
|
/*
|
|
* Processing of command line options.
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include <errno.h>
|
|
#include <getopt.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <strings.h>
|
|
#include <uniconv.h>
|
|
#include <unistd.h>
|
|
|
|
#ifdef __MINGW32__
|
|
#include <fcntl.h> /* _O_BINARY */
|
|
#include <io.h> /* _setmode() */
|
|
#endif
|
|
|
|
#include "boxes.h"
|
|
#include "discovery.h"
|
|
#include "query.h"
|
|
#include "tools.h"
|
|
#include "cmdline.h"
|
|
|
|
|
|
extern char *optarg; /* for getopt() */
|
|
extern int optind; /* for getopt() */
|
|
|
|
|
|
/* default tab stop distance (part of -t) */
|
|
#define DEF_TABSTOP 8
|
|
|
|
/* max. allowed tab stop distance */
|
|
#define MAX_TABSTOP 16
|
|
|
|
|
|
/* System default line terminator.
|
|
* Used only for display in usage info. The real default is always "\n", with stdout in text mode. */
|
|
#ifdef __MINGW32__
|
|
#define EOL_DEFAULT "\r\n"
|
|
#else
|
|
#define EOL_DEFAULT "\n"
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
|
* Print abbreviated usage information on stream `st`.
|
|
* @param st the stream to print to
|
|
*/
|
|
static void usage_short(FILE *st)
|
|
{
|
|
bx_fprintf(st, "Usage: %s [options] [infile [outfile]]\n", PROJECT);
|
|
bx_fprintf(st, "Try `%s -h' for more information.\n", PROJECT);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Print usage information on stream `st`, including a header text.
|
|
* @param st the stream to print to
|
|
*/
|
|
void usage_long(FILE *st)
|
|
{
|
|
bxstr_t *config_file = discover_config_file(0);
|
|
|
|
fprintf(st, "%s - draws any kind of box around your text (or removes it)\n", PROJECT);
|
|
fprintf(st, " Website: https://boxes.thomasjensen.com/\n");
|
|
fprintf(st, "Usage: %s [options] [infile [outfile]]\n", PROJECT);
|
|
fprintf(st, " -a, --align <fmt> Alignment/positioning of text inside box [default: hlvt]\n");
|
|
fprintf(st, " -c, --create <str> Use single shape box design where str is the W shape\n");
|
|
fprintf(st, " --color Force output of ANSI sequences if present\n");
|
|
fprintf(st, " --no-color Force monochrome output (no ANSI sequences)\n");
|
|
fprintf(st, " -d, --design <name> Box design [default: first one in file]\n");
|
|
fprintf(st, " -e, --eol <eol> Override line break type (experimental) [default: %s]\n",
|
|
strcmp(EOL_DEFAULT, "\r\n") == 0 ? "CRLF" : "LF");
|
|
fprintf(st, " -f, --config <file> Configuration file [default: %s]\n",
|
|
config_file != NULL ? bxs_to_output(config_file) : "none");
|
|
fprintf(st, " -h, --help Print usage information\n");
|
|
fprintf(st, " -i, --indent <mode> Indentation mode [default: box]\n");
|
|
fprintf(st, " -k <bool> Leading/trailing blank line retention on removal\n");
|
|
fprintf(st, " --kill-blank Kill leading/trailing blank lines on removal (like -k true)\n");
|
|
fprintf(st, " --no-kill-blank Retain leading/trailing blank lines on removal (like -k false)\n");
|
|
fprintf(st, " -l, --list List available box designs w/ samples\n");
|
|
fprintf(st, " -m, --mend Mend (repair) box\n");
|
|
fprintf(st, " -n, --encoding <enc> Character encoding of input and output [default: %s]\n", locale_charset());
|
|
fprintf(st, " -p, --padding <fmt> Padding [default: none]\n");
|
|
fprintf(st, " -q, --tag-query <qry> Query the list of designs by tag\n"); /* with "(undoc)" as query, trigger undocumented webui stuff instead */
|
|
fprintf(st, " -r, --remove Remove box\n");
|
|
fprintf(st, " -s, --size <wxh> Box size (width w and/or height h)\n");
|
|
fprintf(st, " -t, --tabs <str> Tab stop distance and expansion [default: %de]\n", DEF_TABSTOP);
|
|
fprintf(st, " -v, --version Print version information\n");
|
|
|
|
bxs_free(config_file);
|
|
}
|
|
|
|
|
|
|
|
static opt_t *create_new_opt()
|
|
{
|
|
opt_t *result = (opt_t *) calloc(1, sizeof(opt_t));
|
|
if (result != NULL) {
|
|
/* all values initialized with 0 or NULL */
|
|
result->color = color_from_terminal;
|
|
result->tabstop = DEF_TABSTOP;
|
|
result->eol = "\n"; /* we must default to "\n" instead of EOL_DEFAULT as long as stdout is in text mode */
|
|
result->tabexp = 'e';
|
|
result->killblank = -1;
|
|
for (int i = 0; i < NUM_SIDES; ++i) {
|
|
result->padding[i] = -1;
|
|
}
|
|
}
|
|
else {
|
|
perror(PROJECT);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Alignment/positioning of text inside box.
|
|
* @param result the options struct we are building
|
|
* @param optarg the argument to `-a` on the command line
|
|
* @returns 0 on success, anything else on error
|
|
*/
|
|
static int alignment(opt_t *result, char *optarg)
|
|
{
|
|
int errfl = 1;
|
|
char *p = optarg;
|
|
|
|
while (*p) {
|
|
errfl = 0;
|
|
if (p[1] == '\0' && !strchr("lLcCrR", *p)) {
|
|
errfl = 1;
|
|
break;
|
|
}
|
|
|
|
switch (*p) {
|
|
case 'h': case 'H':
|
|
switch (p[1]) {
|
|
case 'c': case 'C': result->halign = 'c'; break;
|
|
case 'l': case 'L': result->halign = 'l'; break;
|
|
case 'r': case 'R': result->halign = 'r'; break;
|
|
default: errfl = 1; break;
|
|
}
|
|
++p;
|
|
break;
|
|
|
|
case 'v': case 'V':
|
|
switch (p[1]) {
|
|
case 'c': case 'C': result->valign = 'c'; break;
|
|
case 't': case 'T': result->valign = 't'; break;
|
|
case 'b': case 'B': result->valign = 'b'; break;
|
|
default: errfl = 1; break;
|
|
}
|
|
++p;
|
|
break;
|
|
|
|
case 'j': case 'J':
|
|
switch (p[1]) {
|
|
case 'l': case 'L': result->justify = 'l'; break;
|
|
case 'c': case 'C': result->justify = 'c'; break;
|
|
case 'r': case 'R': result->justify = 'r'; break;
|
|
default: errfl = 1; break;
|
|
}
|
|
++p;
|
|
break;
|
|
|
|
case 'l': case 'L':
|
|
result->justify = 'l';
|
|
result->halign = 'l';
|
|
result->valign = 'c';
|
|
break;
|
|
|
|
case 'r': case 'R':
|
|
result->justify = 'r';
|
|
result->halign = 'r';
|
|
result->valign = 'c';
|
|
break;
|
|
|
|
case 'c': case 'C':
|
|
result->justify = 'c';
|
|
result->halign = 'c';
|
|
result->valign = 'c';
|
|
break;
|
|
|
|
default:
|
|
errfl = 1;
|
|
break;
|
|
}
|
|
|
|
if (errfl) {
|
|
break;
|
|
} else {
|
|
++p;
|
|
}
|
|
}
|
|
|
|
if (errfl) {
|
|
bx_fprintf(stderr, "%s: Illegal text format -- %s\n", PROJECT, optarg);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Command line design definition.
|
|
* @param result the options struct we are building
|
|
* @param optarg the argument to `-c` on the command line
|
|
* @returns 0 on success, anything else on error
|
|
*/
|
|
static int command_line_design(opt_t *result, char *optarg)
|
|
{
|
|
if (strlen(optarg) == 0) {
|
|
bx_fprintf(stderr, "%s: empty command line design definition\n", PROJECT);
|
|
return 2;
|
|
}
|
|
result->cld = (char *) strdup(optarg);
|
|
if (result->cld == NULL) {
|
|
perror(PROJECT);
|
|
return 1;
|
|
}
|
|
result->design_choice_by_user = 1;
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Box design selection.
|
|
* @param result the options struct we are building
|
|
* @param optarg the argument to `-d` on the command line
|
|
* @returns 0 on success, anything else on error
|
|
*/
|
|
static int design_choice(opt_t *result, char *optarg)
|
|
{
|
|
BFREE (result->design);
|
|
result->design = (design_t *) ((char *) strdup(optarg));
|
|
if (result->design == NULL) {
|
|
perror(PROJECT);
|
|
return 1;
|
|
}
|
|
result->design_choice_by_user = 1;
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* EOL Override.
|
|
* @param result the options struct we are building
|
|
* @param optarg the argument to `-e` on the command line
|
|
* @returns 0 on success, anything else on error
|
|
*/
|
|
static int eol_override(opt_t *result, char *optarg)
|
|
{
|
|
result->eol_overridden = 1;
|
|
if (strcasecmp(optarg, "CRLF") == 0) {
|
|
result->eol = "\r\n";
|
|
}
|
|
else if (strcasecmp(optarg, "LF") == 0) {
|
|
result->eol = "\n";
|
|
}
|
|
else if (strcasecmp(optarg, "CR") == 0) {
|
|
result->eol = "\r";
|
|
}
|
|
else {
|
|
bx_fprintf(stderr, "%s: invalid eol spec -- %s\n", PROJECT, optarg);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Indentation mode.
|
|
* @param result the options struct we are building
|
|
* @param optarg the argument to `-i` on the command line
|
|
* @returns 0 on success, anything else on error
|
|
*/
|
|
static int indentation_mode(opt_t *result, char *optarg)
|
|
{
|
|
size_t optlen = strlen(optarg);
|
|
if (optlen <= 3 && !strncasecmp("box", optarg, optlen)) {
|
|
result->indentmode = 'b';
|
|
}
|
|
else if (optlen <= 4 && !strncasecmp("text", optarg, optlen)) {
|
|
result->indentmode = 't';
|
|
}
|
|
else if (optlen <= 4 && !strncasecmp("none", optarg, optlen)) {
|
|
result->indentmode = 'n';
|
|
}
|
|
else {
|
|
bx_fprintf(stderr, "%s: invalid indentation mode\n", PROJECT);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Kill blank lines or not [default: design-dependent].
|
|
* @param result the options struct we are building
|
|
* @param optarg the argument to `-k` on the command line
|
|
* @returns 0 on success, anything else on error
|
|
*/
|
|
static int killblank(opt_t *result, char *optarg)
|
|
{
|
|
if (result->killblank == -1) {
|
|
if (strisyes(optarg)) {
|
|
result->killblank = 1;
|
|
}
|
|
else if (strisno(optarg)) {
|
|
result->killblank = 0;
|
|
}
|
|
else {
|
|
bx_fprintf(stderr, "%s: -k: invalid parameter\n", PROJECT);
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Padding. Format is `([ahvtrbl]n)+`.
|
|
* @param result the options struct we are building
|
|
* @param optarg the argument to `-p` on the command line
|
|
* @returns 0 on success, anything else on error
|
|
*/
|
|
static int padding(opt_t *result, char *optarg)
|
|
{
|
|
int errfl = 1;
|
|
char *p = optarg;
|
|
|
|
while (*p) {
|
|
errfl = 0;
|
|
if (p[1] == '\0') {
|
|
errfl = 1;
|
|
break;
|
|
}
|
|
char c = *p;
|
|
errno = 0;
|
|
int size = (int) strtol(p + 1, &p, 10);
|
|
if (errno || size < 0) {
|
|
errfl = 1;
|
|
break;
|
|
}
|
|
switch (c) {
|
|
case 'a': case 'A':
|
|
result->padding[BTOP] = size;
|
|
result->padding[BBOT] = size;
|
|
result->padding[BLEF] = size;
|
|
result->padding[BRIG] = size;
|
|
break;
|
|
case 'h': case 'H':
|
|
result->padding[BLEF] = size;
|
|
result->padding[BRIG] = size;
|
|
break;
|
|
case 'v': case 'V':
|
|
result->padding[BTOP] = size;
|
|
result->padding[BBOT] = size;
|
|
break;
|
|
case 't': case 'T':
|
|
result->padding[BTOP] = size;
|
|
break;
|
|
case 'l': case 'L':
|
|
result->padding[BLEF] = size;
|
|
break;
|
|
case 'b': case 'B':
|
|
result->padding[BBOT] = size;
|
|
break;
|
|
case 'r': case 'R':
|
|
result->padding[BRIG] = size;
|
|
break;
|
|
default:
|
|
errfl = 1;
|
|
break;
|
|
}
|
|
if (errfl) {
|
|
break;
|
|
}
|
|
}
|
|
if (errfl) {
|
|
bx_fprintf(stderr, "%s: invalid padding specification - %s\n", PROJECT, optarg);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Parse the tag query specified with `-q`.
|
|
* @param result the options struct we are building
|
|
* @param optarg the argument to `-q` on the command line
|
|
* @returns 0 on success, anything else on error
|
|
*/
|
|
static int query(opt_t *result, char *optarg)
|
|
{
|
|
char **query = parse_query(optarg);
|
|
result->query = query;
|
|
return query != NULL ? 0 : 1;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Specify desired box target size.
|
|
* @param result the options struct we are building
|
|
* @param optarg the argument to `-s` on the command line
|
|
* @returns 0 on success, anything else on error
|
|
*/
|
|
static int size_of_box(opt_t *result, char *optarg)
|
|
{
|
|
char *p = strchr(optarg, 'x');
|
|
if (!p) {
|
|
p = strchr(optarg, 'X');
|
|
}
|
|
if (p) {
|
|
*p = '\0';
|
|
}
|
|
errno = 0;
|
|
if (optarg != p) {
|
|
result->reqwidth = strtol(optarg, NULL, 10);
|
|
}
|
|
if (p) {
|
|
result->reqheight = strtol(p + 1, NULL, 10);
|
|
*p = 'x';
|
|
}
|
|
if (errno || (result->reqwidth == 0 && result->reqheight == 0) || result->reqwidth < 0 || result->reqheight < 0) {
|
|
bx_fprintf(stderr, "%s: invalid box size specification -- %s\n", PROJECT, optarg);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Tab handling. Format is `n[eku]`.
|
|
* @param result the options struct we are building
|
|
* @param optarg the argument to `-t` on the command line
|
|
* @returns 0 on success, anything else on error
|
|
*/
|
|
static int tab_handling(opt_t *result, char *optarg)
|
|
{
|
|
char *p;
|
|
int width = (int) strtol(optarg, &p, 10);
|
|
if (width < 1 || width > MAX_TABSTOP) {
|
|
bx_fprintf(stderr, "%s: invalid tab stop distance -- %d\n", PROJECT, width);
|
|
return 1;
|
|
}
|
|
result->tabstop = width;
|
|
|
|
int errfl = 0;
|
|
if (*p != '\0') {
|
|
if (p[1] != '\0') {
|
|
errfl = 1;
|
|
}
|
|
else {
|
|
switch (*p) {
|
|
case 'e': case 'E':
|
|
result->tabexp = 'e';
|
|
break;
|
|
case 'k': case 'K':
|
|
result->tabexp = 'k';
|
|
break;
|
|
case 'u': case 'U':
|
|
result->tabexp = 'u';
|
|
break;
|
|
default:
|
|
errfl = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (errfl) {
|
|
bx_fprintf(stderr, "%s: invalid tab handling specification - %s\n", PROJECT, optarg);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Set *stdout* to binary mode, so that we can control the line terminator. This function only ever does anything on
|
|
* Windows, because on Linux, we already do have control over line terminators.
|
|
* @param result the options struct we are building
|
|
* @return the *stdout* stream, reconfigured to binary if necessary
|
|
*/
|
|
static FILE *get_stdout_configured(opt_t *result)
|
|
{
|
|
if (result->eol_overridden) {
|
|
#ifdef __MINGW32__
|
|
int rc = _setmode(fileno(stdout), _O_BINARY);
|
|
if (rc == -1) {
|
|
perror(PROJECT);
|
|
}
|
|
#endif
|
|
}
|
|
return stdout;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Input and Output Files. After any command line options, an input file and an output file may be specified (in that
|
|
* order). "-" may be substituted for standard input or output. A third file name would be invalid.
|
|
* @param result the options struct we are building
|
|
* @param argv the original command line options as specified
|
|
* @param optind the index of the next element to be processed in `argv`
|
|
* @returns 0 on success, anything else on error
|
|
*/
|
|
static int input_output_files(opt_t *result, char *argv[], int optind)
|
|
{
|
|
if (argv[optind] == NULL) { /* neither infile nor outfile given */
|
|
result->infile = stdin;
|
|
result->outfile = get_stdout_configured(result);
|
|
}
|
|
|
|
else if (argv[optind + 1] && argv[optind + 2]) { /* illegal third file */
|
|
bx_fprintf(stderr, "%s: illegal parameter -- %s\n", PROJECT, argv[optind + 2]);
|
|
usage_short(stderr);
|
|
return 1;
|
|
}
|
|
|
|
else {
|
|
if (strcmp(argv[optind], "-") == 0) {
|
|
result->infile = stdin; /* use stdin for input */
|
|
}
|
|
else {
|
|
result->infile = fopen(argv[optind], "r");
|
|
if (result->infile == NULL) {
|
|
bx_fprintf(stderr, "%s: Can\'t open input file -- %s\n", PROJECT, argv[optind]);
|
|
return 9; /* can't read infile */
|
|
}
|
|
}
|
|
|
|
if (argv[optind + 1] == NULL) {
|
|
result->outfile = get_stdout_configured(result); /* no outfile given */
|
|
}
|
|
else if (strcmp(argv[optind + 1], "-") == 0) {
|
|
result->outfile = get_stdout_configured(result); /* use stdout for output */
|
|
}
|
|
else {
|
|
result->outfile = fopen(argv[optind + 1], "wb");
|
|
if (result->outfile == NULL) {
|
|
perror(PROJECT);
|
|
if (result->infile != stdin) {
|
|
fclose(result->infile);
|
|
}
|
|
return 10;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
static void print_debug_info(opt_t *result)
|
|
{
|
|
if (result != NULL) {
|
|
#if defined(DEBUG)
|
|
fprintf (stderr, "Command line option settings (excerpt):\n");
|
|
fprintf (stderr, "- Alignment (-a): horiz %c, vert %c\n",
|
|
result->halign ? result->halign : '?', result->valign ? result->valign : '?');
|
|
fprintf (stderr, "- Line justification (-a): \'%c\'\n", result->justify ? result->justify : '?');
|
|
fprintf (stderr, "- Design Definition W shape (-c): %s\n", result->cld ? result->cld : "n/a");
|
|
fprintf (stderr, "- Color mode: %d\n", result->color);
|
|
fprintf (stderr, "- Line terminator used (-e): %s\n",
|
|
strcmp(result->eol, "\r\n") == 0 ? "CRLF" : (strcmp(result->eol, "\r") == 0 ? "CR" : "LF"));
|
|
fprintf (stderr, "- Explicit config file (-f): %s\n", result->f ? result->f : "no");
|
|
fprintf (stderr, "- Indentmode (-i): \'%c\'\n", result->indentmode ? result->indentmode : '?');
|
|
fprintf (stderr, "- Kill blank lines (-k): %d\n", result->killblank);
|
|
fprintf (stderr, "- Mend box (-m): %d\n", result->mend);
|
|
fprintf (stderr, "- Padding (-p): l:%d t:%d r:%d b:%d\n",
|
|
result->padding[BLEF], result->padding[BTOP], result->padding[BRIG], result->padding[BBOT]);
|
|
fprintf (stderr, "- Tag Query / Special handling for Web UI (-q): ");
|
|
if (result->query != NULL) {
|
|
for (size_t qidx = 0; result->query[qidx] != NULL; ++qidx) {
|
|
fprintf(stderr, "%s%s", qidx > 0 ? ", " : "", result->query[qidx]);
|
|
}
|
|
} else {
|
|
fprintf (stderr, "(none)");
|
|
}
|
|
fprintf (stderr, "\n");
|
|
fprintf (stderr, "- Remove box (-r): %d\n", result->r);
|
|
fprintf (stderr, "- Requested box size (-s): %ldx%ld\n", result->reqwidth, result->reqheight);
|
|
fprintf (stderr, "- Tabstop distance (-t): %d\n", result->tabstop);
|
|
fprintf (stderr, "- Tab handling (-t): \'%c\'\n", result->tabexp);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
|
|
opt_t *process_commandline(int argc, char *argv[])
|
|
{
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "argc = %d\n", argc);
|
|
fprintf(stderr, "argv = [");
|
|
for(int i=0; i<=argc; i++) {
|
|
fprintf(stderr, "%s%s", argv[i], i < argc ? ", " : "");
|
|
}
|
|
fprintf(stderr, "]\n");
|
|
#endif
|
|
|
|
opt_t *result = create_new_opt();
|
|
|
|
/* Intercept '-?' case first, as it is not supported by getopt_long() */
|
|
if (argc >= 2 && argv[1] != NULL && strcmp(argv[1], "-?") == 0) {
|
|
result->help = 1;
|
|
return result;
|
|
}
|
|
|
|
optind = 1; /* ensure that getopt() will process all arguments, even in unit test situations */
|
|
int option_index = 0;
|
|
const struct option long_options[] = {
|
|
{ "align", required_argument, NULL, 'a' },
|
|
{ "create", required_argument, NULL, 'c' },
|
|
{ "color", no_argument, NULL, OPT_COLOR },
|
|
{ "no-color", no_argument, NULL, OPT_NO_COLOR },
|
|
{ "design", required_argument, NULL, 'd' },
|
|
{ "eol", required_argument, NULL, 'e' },
|
|
{ "config", required_argument, NULL, 'f' },
|
|
{ "help", no_argument, NULL, 'h' },
|
|
{ "indent", required_argument, NULL, 'i' },
|
|
{ "kill-blank", no_argument, NULL, OPT_KILLBLANK },
|
|
{ "no-kill-blank", no_argument, NULL, OPT_NO_KILLBLANK },
|
|
{ "list", no_argument, NULL, 'l' },
|
|
{ "mend", no_argument, NULL, 'm' },
|
|
{ "encoding", required_argument, NULL, 'n' },
|
|
{ "padding", required_argument, NULL, 'p' },
|
|
{ "tag-query", required_argument, NULL, 'q' },
|
|
{ "remove", no_argument, NULL, 'r' },
|
|
{ "size", required_argument, NULL, 's' },
|
|
{ "tabs", required_argument, NULL, 't' },
|
|
{ "version", no_argument, NULL, 'v' },
|
|
{ NULL, 0, NULL, 0 }
|
|
};
|
|
const char *short_options = "a:c:d:e:f:hi:k:lmn:p:q:rs:t:v";
|
|
|
|
int oc; /* option character */
|
|
do {
|
|
oc = getopt_long(argc, argv, short_options, long_options, &option_index);
|
|
|
|
switch (oc) {
|
|
|
|
case 'a':
|
|
if (alignment(result, optarg) != 0) {
|
|
BFREE(result);
|
|
return NULL;
|
|
}
|
|
break;
|
|
|
|
case 'c':
|
|
if (command_line_design(result, optarg) != 0) {
|
|
BFREE(result);
|
|
return NULL;
|
|
}
|
|
break;
|
|
|
|
case OPT_COLOR:
|
|
result->color = force_ansi_color;
|
|
break;
|
|
|
|
case OPT_NO_COLOR:
|
|
result->color = force_monochrome;
|
|
break;
|
|
|
|
case 'd':
|
|
if (design_choice(result, optarg) != 0) {
|
|
BFREE(result);
|
|
return NULL;
|
|
}
|
|
break;
|
|
|
|
case 'e':
|
|
if (eol_override(result, optarg) != 0) {
|
|
BFREE(result);
|
|
return NULL;
|
|
}
|
|
break;
|
|
|
|
case 'f':
|
|
result->f = strdup(optarg); /* input file */
|
|
break;
|
|
|
|
case 'h':
|
|
result->help = 1;
|
|
return result;
|
|
|
|
case 'i':
|
|
if (indentation_mode(result, optarg) != 0) {
|
|
BFREE(result);
|
|
return NULL;
|
|
}
|
|
break;
|
|
|
|
case 'k':
|
|
if (killblank(result, optarg) != 0) {
|
|
BFREE(result);
|
|
return NULL;
|
|
}
|
|
break;
|
|
|
|
case OPT_KILLBLANK:
|
|
if (result->killblank == -1) {
|
|
result->killblank = 1;
|
|
}
|
|
break;
|
|
|
|
case OPT_NO_KILLBLANK:
|
|
if (result->killblank == -1) {
|
|
result->killblank = 0;
|
|
}
|
|
break;
|
|
|
|
case 'l':
|
|
result->l = 1; /* list available box styles */
|
|
break;
|
|
|
|
case 'm':
|
|
result->mend = 2; /* Mend box: remove, then redraw */
|
|
result->r = 1;
|
|
result->killblank = 0;
|
|
break;
|
|
|
|
case 'n':
|
|
result->encoding = strdup(optarg); /* character encoding */
|
|
if (result->encoding == NULL) {
|
|
perror(PROJECT);
|
|
BFREE(result);
|
|
return NULL;
|
|
}
|
|
break;
|
|
|
|
case 'p':
|
|
if (padding(result, optarg) != 0) {
|
|
BFREE(result);
|
|
return NULL;
|
|
}
|
|
break;
|
|
|
|
case 'q':
|
|
if (query(result, optarg) != 0) {
|
|
BFREE(result);
|
|
return NULL;
|
|
}
|
|
break;
|
|
|
|
case 'r':
|
|
result->r = 1; /* remove box */
|
|
break;
|
|
|
|
case 's':
|
|
if (size_of_box(result, optarg) != 0) {
|
|
BFREE(result);
|
|
return NULL;
|
|
}
|
|
break;
|
|
|
|
case 't':
|
|
if (tab_handling(result, optarg) != 0) {
|
|
BFREE(result);
|
|
return NULL;
|
|
}
|
|
break;
|
|
|
|
case 'v':
|
|
result->version_requested = 1; /* print version number */
|
|
return result;
|
|
|
|
case ':':
|
|
case '?':
|
|
/* Missing argument or illegal option - do nothing else */
|
|
usage_short(stderr);
|
|
BFREE(result);
|
|
return NULL;
|
|
|
|
case EOF:
|
|
/* End of list, do nothing more */
|
|
break;
|
|
|
|
default:
|
|
bx_fprintf(stderr, "%s: internal error\n", PROJECT);
|
|
BFREE(result);
|
|
return NULL;
|
|
}
|
|
} while (oc != EOF);
|
|
|
|
if (input_output_files(result, argv, optind) != 0) {
|
|
BFREE(result);
|
|
return NULL;
|
|
}
|
|
|
|
print_debug_info(result);
|
|
return result;
|
|
}
|
|
|
|
|
|
/*EOF*/ /* vim: set sw=4: */
|