summaryrefslogtreecommitdiff
path: root/src/options.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/options.c')
-rw-r--r--src/options.c125
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]);