aboutsummaryrefslogtreecommitdiffstats
path: root/options.c
diff options
context:
space:
mode:
authorNRK <nrk@disroot.org>2022-08-16 10:43:50 +0200
committerNRK <nrk@disroot.org>2022-08-16 10:43:50 +0200
commit216f312578be5c959527c03ccc70d27eebcc76aa (patch)
tree0dac281db909a1d27cc248c63f3c939f2632863d /options.c
parentd9f20a41224265573395381fbbdea40ac9891d84 (diff)
downloadnsxiv-216f312578be5c959527c03ccc70d27eebcc76aa.tar.zst
add support for long-opts (#332)
Uses [optparse] to add support for long-opts. optparse is posix compliant with getopt(3) and thus would be backwards compatible. It does not have any dependency (not even the c standard library!) and is C89 compatible and thus fits our current code-style. [optparse]: https://github.com/skeeto/optparse Note that we're using a couple `pragma`-s to silence some harmless warnings. This should be portable because these pragma-s don't change the behavior of the program. Furthermore, C standard mandates that unknown pragma's should be ignored by the compiler and thus would not result in build failure on compilers which do not recognize them. Closes: https://codeberg.org/nsxiv/nsxiv/issues/328 Reviewed-on: https://codeberg.org/nsxiv/nsxiv/pulls/332 Reviewed-by: eylles <eylles@noreply.codeberg.org>
Diffstat (limited to 'options.c')
-rw-r--r--options.c92
1 files changed, 68 insertions, 24 deletions
diff --git a/options.c b/options.c
index 69b45b9..3b191ea 100644
--- a/options.c
+++ b/options.c
@@ -20,11 +20,20 @@
#include "nsxiv.h"
#include "version.h"
+#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#define OPTPARSE_IMPLEMENTATION
+#define OPTPARSE_API static
+#pragma GCC diagnostic push /* also works on clang */
+#pragma GCC diagnostic ignored "-Wshadow"
+#pragma GCC diagnostic ignored "-Wunused-function"
+#include "optparse.h"
+#pragma GCC diagnostic pop
+
const opt_t *options;
void print_usage(void)
@@ -54,12 +63,41 @@ static void print_version(void)
void parse_options(int argc, char **argv)
{
+ static const struct optparse_long longopts[] = {
+ { "framerate", 'A', OPTPARSE_REQUIRED },
+ { "animate", 'a', OPTPARSE_NONE },
+ { "no-bar", 'b', OPTPARSE_NONE },
+ { "clean-cache", 'c', OPTPARSE_NONE },
+ { "embed", 'e', OPTPARSE_REQUIRED },
+ { "fullscreen", 'f', OPTPARSE_NONE },
+ { "gamma", 'G', OPTPARSE_REQUIRED },
+ { "geometry", 'g', OPTPARSE_REQUIRED },
+ { "help", 'h', OPTPARSE_NONE },
+ { "stdin", 'i', OPTPARSE_NONE },
+ { "class", 'N', OPTPARSE_REQUIRED },
+ { "start-at", 'n', OPTPARSE_REQUIRED },
+ { "stdout", 'o', OPTPARSE_NONE },
+ { "private", 'p', OPTPARSE_NONE },
+ { "quiet", 'q', OPTPARSE_NONE },
+ { "recursive", 'r', OPTPARSE_NONE },
+ { "ss-delay", 'S', OPTPARSE_REQUIRED },
+ { "scale-mode", 's', OPTPARSE_REQUIRED },
+ { NULL, 'T', OPTPARSE_REQUIRED },
+ { "thumbnail", 't', OPTPARSE_NONE },
+ { "version", 'v', OPTPARSE_NONE },
+ { "zoom-100", 'Z', OPTPARSE_NONE },
+ { "zoom", 'z', OPTPARSE_REQUIRED },
+ { "null", '0', OPTPARSE_NONE },
+ { 0 }, /* end */
+ };
+
int n, opt;
char *end, *s;
- const char *scalemodes = "dfFwh";
+ struct optparse op;
+ const char scalemodes[] = "dfFwh"; /* must be sorted according to scalemode_t */
static opt_t _options;
- options = &_options;
+ options = &_options;
progname = strrchr(argv[0], '/');
progname = progname ? progname + 1 : argv[0];
@@ -87,15 +125,21 @@ void parse_options(int argc, char **argv)
_options.clean_cache = false;
_options.private_mode = false;
- while ((opt = getopt(argc, argv, "A:abce:fG:g:hin:N:opqrS:s:T:tvZz:0")) != -1) {
+ optparse_init(&op, argv);
+ while ((opt = optparse_long(&op, longopts, NULL)) != -1) {
+ for (n = 0; n < (int)ARRLEN(longopts); ++n) { /* clang-tidy finds some non-sensical branch and thinks optarg == NULL is possible */
+ if (opt == longopts[n].shortname && longopts[n].argtype == OPTPARSE_REQUIRED)
+ assert(op.optarg != NULL);
+ }
switch (opt) {
case '?':
+ fprintf(stderr, "%s\n", op.errmsg);
print_usage();
exit(EXIT_FAILURE);
case 'A':
- n = strtol(optarg, &end, 0);
+ n = strtol(op.optarg, &end, 0);
if (*end != '\0' || n <= 0)
- error(EXIT_FAILURE, 0, "Invalid argument for option -A: %s", optarg);
+ error(EXIT_FAILURE, 0, "Invalid argument for option -A: %s", op.optarg);
_options.framerate = n;
/* fall through */
case 'a':
@@ -108,22 +152,22 @@ void parse_options(int argc, char **argv)
_options.clean_cache = true;
break;
case 'e':
- n = strtol(optarg, &end, 0);
+ n = strtol(op.optarg, &end, 0);
if (*end != '\0')
- error(EXIT_FAILURE, 0, "Invalid argument for option -e: %s", optarg);
+ error(EXIT_FAILURE, 0, "Invalid argument for option -e: %s", op.optarg);
_options.embed = n;
break;
case 'f':
_options.fullscreen = true;
break;
case 'G':
- n = strtol(optarg, &end, 0);
+ n = strtol(op.optarg, &end, 0);
if (*end != '\0')
- error(EXIT_FAILURE, 0, "Invalid argument for option -G: %s", optarg);
+ error(EXIT_FAILURE, 0, "Invalid argument for option -G: %s", op.optarg);
_options.gamma = n;
break;
case 'g':
- _options.geometry = optarg;
+ _options.geometry = op.optarg;
break;
case 'h':
print_usage();
@@ -132,13 +176,13 @@ void parse_options(int argc, char **argv)
_options.from_stdin = true;
break;
case 'n':
- n = strtol(optarg, &end, 0);
+ n = strtol(op.optarg, &end, 0);
if (*end != '\0' || n <= 0)
- error(EXIT_FAILURE, 0, "Invalid argument for option -n: %s", optarg);
+ error(EXIT_FAILURE, 0, "Invalid argument for option -n: %s", op.optarg);
_options.startnum = n - 1;
break;
case 'N':
- _options.res_name = optarg;
+ _options.res_name = op.optarg;
break;
case 'o':
_options.to_stdout = true;
@@ -153,15 +197,15 @@ void parse_options(int argc, char **argv)
_options.recursive = true;
break;
case 'S':
- n = strtof(optarg, &end) * 10;
+ n = strtof(op.optarg, &end) * 10;
if (*end != '\0' || n <= 0)
- error(EXIT_FAILURE, 0, "Invalid argument for option -S: %s", optarg);
+ error(EXIT_FAILURE, 0, "Invalid argument for option -S: %s", op.optarg);
_options.slideshow = n;
break;
case 's':
- s = strchr(scalemodes, optarg[0]);
- if (s == NULL || *s == '\0' || strlen(optarg) != 1)
- error(EXIT_FAILURE, 0, "Invalid argument for option -s: %s", optarg);
+ s = strchr(scalemodes, op.optarg[0]);
+ if (s == NULL || *s == '\0' || strlen(op.optarg) != 1)
+ error(EXIT_FAILURE, 0, "Invalid argument for option -s: %s", op.optarg);
_options.scalemode = s - scalemodes;
break;
case 'T':
@@ -175,14 +219,14 @@ void parse_options(int argc, char **argv)
exit(EXIT_SUCCESS);
case 'Z':
_options.scalemode = SCALE_ZOOM;
- _options.zoom = 1.0;
+ _options.zoom = 1.0f;
break;
case 'z':
- n = strtol(optarg, &end, 0);
+ n = strtol(op.optarg, &end, 0);
if (*end != '\0' || n <= 0)
- error(EXIT_FAILURE, 0, "Invalid argument for option -z: %s", optarg);
+ error(EXIT_FAILURE, 0, "Invalid argument for option -z: %s", op.optarg);
_options.scalemode = SCALE_ZOOM;
- _options.zoom = (float) n / 100.0;
+ _options.zoom = (float) n / 100.0f;
break;
case '0':
_options.using_null = true;
@@ -190,8 +234,8 @@ void parse_options(int argc, char **argv)
}
}
- _options.filenames = argv + optind;
- _options.filecnt = argc - optind;
+ _options.filenames = argv + op.optind;
+ _options.filecnt = argc - op.optind;
if (_options.filecnt == 1 && STREQ(_options.filenames[0], "-")) {
_options.filenames++;