diff options
Diffstat (limited to 'src/options.c')
-rw-r--r-- | src/options.c | 125 |
1 files changed, 113 insertions, 12 deletions
diff --git a/src/options.c b/src/options.c index e35402f..e06b421 100644 --- a/src/options.c +++ b/src/options.c @@ -1,3 +1,5 @@ +#include <ctype.h> +#include <errno.h> #include <getopt.h> #include <limits.h> #include <stdio.h> @@ -11,17 +13,20 @@ static const char *usage_str = "" "Usage: fzy [OPTION]...\n" - " -l, --lines=LINES Specify how many lines of results to show (default 10)\n" - " -p, --prompt=PROMPT Input prompt (default '> ')\n" - " -q, --query=QUERY Use QUERY as the initial search string\n" - " -e, --show-matches=QUERY Output the sorted matches of QUERY\n" - " -t, --tty=TTY Specify file to use as TTY device (default /dev/tty)\n" - " -s, --show-scores Show the scores of each match\n" - " -0, --read-null Read input delimited by ASCII NUL characters\n" - " -j, --workers NUM Use NUM workers for searching. (default is # of CPUs)\n" - " -i, --show-info Show selection info line\n" - " -h, --help Display this help and exit\n" - " -v, --version Output version information and exit\n"; + " -l, --lines=LINES Specify how many lines of results to show (default 10)\n" + " -p, --prompt=PROMPT Input prompt (default '> ')\n" + " -q, --query=QUERY Use QUERY as the initial search string\n" + " -e, --show-matches=QUERY Output the sorted matches of QUERY\n" + " -t, --tty=TTY Specify file to use as TTY device (default /dev/tty)\n" + " -s, --show-scores Show the scores of each match\n" + " -0, --read-null Read input delimited by ASCII NUL characters\n" + " -j, --workers NUM Use NUM workers for searching. (default is # of CPUs)\n" + " -i, --show-info Show selection info line\n" + " -f, --search-fields=SELECTOR Use these fields for searching. Default is the whole line.\n" + " -F, --output-fields=SELECTOR Use these fields for output. Default is the whole line)\n" + " -d, --delimiters=DELIM Use these delimiters to split input lines into fields. Default is '<space><Tab>'.\n" + " -h, --help Display this help and exit\n" + " -v, --version Output version information and exit\n"; static void usage(const char *argv0) { fprintf(stderr, usage_str, argv0); @@ -38,11 +43,87 @@ static struct option longopts[] = {{"show-matches", required_argument, NULL, 'e' {"benchmark", optional_argument, NULL, 'b'}, {"workers", required_argument, NULL, 'j'}, {"show-info", no_argument, NULL, 'i'}, + {"search-fields", required_argument, NULL, 'f'}, + {"output-fields", required_argument, NULL, 'F'}, + {"delimiter", required_argument, NULL, 'd'}, {"help", no_argument, NULL, 'h'}, {NULL, 0, NULL, 0}}; +static void field_selector_uninit(FieldSelector *fs) +{ + if (!fs) + return; + + free(fs->ranges); + fs->ranges = NULL; + fs->nb_ranges = 0; +} + +static int field_selector_parse(FieldSelector *fs, char *str) +{ + size_t nb_ranges; + int cur_range; + + field_selector_uninit(fs); + + if (!str || !*str) + return 0; + + nb_ranges = 1; + for (const char *p = str; *p; p++) { + if (*p == ',') + nb_ranges++; + } + + fs->ranges = calloc(nb_ranges, sizeof(*fs->ranges)); + if (!fs->ranges) + return -ENOMEM; + fs->nb_ranges = nb_ranges; + + cur_range = 0; + while (*str) { + int start, end; + + start = 0; + if (*str == '-' || isdigit(*str)) + start = strtol(str, &str, 0); + + if (*str == ':') { + str++; + end = (*str == '-' || isdigit(*str)) ? + strtol(str, &str, 0) : -1; + } else + end = start; + + if (*str) { + if (*str != ',') { + field_selector_uninit(fs); + return -EINVAL; + } + + str++; + } + + fs->ranges[cur_range].start = start; + fs->ranges[cur_range].end = end; + cur_range++; + } + + return 0; +} + +void options_uninit(options_t *options) +{ + field_selector_uninit(&options->search_fields); + field_selector_uninit(&options->output_fields); + + memset(options, 0, sizeof(*options)); +} + void options_init(options_t *options) { /* set defaults */ + memset(options, 0, sizeof(*options)); + options->benchmark = 0; options->filter = NULL; options->init_search = NULL; @@ -54,13 +135,14 @@ void options_init(options_t *options) { options->workers = DEFAULT_WORKERS; options->input_delimiter = '\n'; options->show_info = DEFAULT_SHOW_INFO; + options->delimiters = DEFAULT_DELIMITERS; } void options_parse(options_t *options, int argc, char *argv[]) { options_init(options); int c; - while ((c = getopt_long(argc, argv, "vhs0e:q:l:t:p:j:i", longopts, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "vhs0e:q:l:t:p:j:id:f:F:", longopts, NULL)) != -1) { switch (c) { case 'v': printf("%s " VERSION " © 2014-2018 John Hawthorn\n", argv[0]); @@ -114,6 +196,25 @@ void options_parse(options_t *options, int argc, char *argv[]) { case 'i': options->show_info = 1; break; + case 'd': + options->delimiters = optarg; + break; + case 'f': { + int ret = field_selector_parse(&options->search_fields, optarg); + if (ret < 0) { + fprintf(stderr, "Invalid format for --search-fields: %s\n", optarg); + usage(argv[0]); + exit(EXIT_FAILURE); + } + } break; + case 'F': { + int ret = field_selector_parse(&options->output_fields, optarg); + if (ret < 0) { + fprintf(stderr, "Invalid format for --output-field: %s\n", optarg); + usage(argv[0]); + exit(EXIT_FAILURE); + } + } break; case 'h': default: usage(argv[0]); |