From c4524ae7aaa85f1569d6be1a8538b3650bc06f89 Mon Sep 17 00:00:00 2001 From: Ashkan Kiani Date: Fri, 3 May 2019 03:30:13 -0700 Subject: Add ability to use null as input delimiter. Update tty to print newline as space Add tty_putc --- src/choices.c | 11 +++++++++-- src/choices.h | 1 + src/options.c | 8 +++++++- src/options.h | 1 + src/tty.c | 4 ++++ src/tty.h | 1 + src/tty_interface.c | 6 +++++- test/acceptance/acceptance_test.rb | 1 + 8 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/choices.c b/src/choices.c index a8c24b6..b6d5f0e 100644 --- a/src/choices.c +++ b/src/choices.c @@ -72,9 +72,10 @@ void choices_fread(choices_t *c, FILE *file) { */ /* Tokenize input and add to choices */ + const char *line_end = c->buffer + c->buffer_size; char *line = c->buffer + buffer_start; do { - char *nl = strchr(line, '\n'); + char *nl = strchr(line, c->input_delimiter); if (nl) *nl++ = '\0'; @@ -83,7 +84,7 @@ void choices_fread(choices_t *c, FILE *file) { choices_add(c, line); line = nl; - } while (line); + } while (line && line < line_end); } static void choices_resize(choices_t *c, size_t new_capacity) { @@ -113,6 +114,12 @@ void choices_init(choices_t *c, options_t *options) { c->worker_count = (int)sysconf(_SC_NPROCESSORS_ONLN); } + if (options->read_null) { + c->input_delimiter = '\0'; + } else { + c->input_delimiter = '\n'; + } + choices_reset_search(c); } diff --git a/src/choices.h b/src/choices.h index e8a598b..c2bbcd9 100644 --- a/src/choices.h +++ b/src/choices.h @@ -25,6 +25,7 @@ typedef struct { size_t selection; unsigned int worker_count; + char input_delimiter; } choices_t; void choices_init(choices_t *c, options_t *options); diff --git a/src/options.c b/src/options.c index 7e4d414..85eeac3 100644 --- a/src/options.c +++ b/src/options.c @@ -17,6 +17,7 @@ static const char *usage_str = " -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" " -h, --help Display this help and exit\n" " -v, --version Output version information and exit\n"; @@ -31,6 +32,7 @@ static struct option longopts[] = {{"show-matches", required_argument, NULL, 'e' {"tty", required_argument, NULL, 't'}, {"prompt", required_argument, NULL, 'p'}, {"show-scores", no_argument, NULL, 's'}, + {"read-null", no_argument, NULL, '0'}, {"version", no_argument, NULL, 'v'}, {"benchmark", optional_argument, NULL, 'b'}, {"workers", required_argument, NULL, 'j'}, @@ -48,13 +50,14 @@ void options_init(options_t *options) { options->num_lines = DEFAULT_NUM_LINES; options->prompt = DEFAULT_PROMPT; options->workers = DEFAULT_WORKERS; + options->read_null = 0; } void options_parse(options_t *options, int argc, char *argv[]) { options_init(options); int c; - while ((c = getopt_long(argc, argv, "vhse:q:l:t:p:j:", longopts, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "vhs0e:q:l:t:p:j:", longopts, NULL)) != -1) { switch (c) { case 'v': printf("%s " VERSION " © 2014-2018 John Hawthorn\n", argv[0]); @@ -62,6 +65,9 @@ void options_parse(options_t *options, int argc, char *argv[]) { case 's': options->show_scores = 1; break; + case '0': + options->read_null = 1; + break; case 'q': options->init_search = optarg; break; diff --git a/src/options.h b/src/options.h index 01a43fd..7113ccf 100644 --- a/src/options.h +++ b/src/options.h @@ -11,6 +11,7 @@ typedef struct { unsigned int scrolloff; const char *prompt; unsigned int workers; + int read_null; } options_t; void options_init(options_t *options); diff --git a/src/tty.c b/src/tty.c index f8de9f5..733477e 100644 --- a/src/tty.c +++ b/src/tty.c @@ -184,6 +184,10 @@ void tty_printf(tty_t *tty, const char *fmt, ...) { va_end(args); } +void tty_putc(tty_t *tty, char c) { + fputc(c, tty->fout); +} + void tty_flush(tty_t *tty) { fflush(tty->fout); } diff --git a/src/tty.h b/src/tty.h index 6c73a6e..013360e 100644 --- a/src/tty.h +++ b/src/tty.h @@ -51,6 +51,7 @@ void tty_moveup(tty_t *tty, int i); void tty_setcol(tty_t *tty, int col); void tty_printf(tty_t *tty, const char *fmt, ...); +void tty_putc(tty_t *tty, char c); void tty_flush(tty_t *tty); size_t tty_getwidth(tty_t *tty); diff --git a/src/tty_interface.c b/src/tty_interface.c index f366a23..225f33a 100644 --- a/src/tty_interface.c +++ b/src/tty_interface.c @@ -65,7 +65,11 @@ static void draw_match(tty_interface_t *state, const char *choice, int selected) } else { tty_setfg(tty, TTY_COLOR_NORMAL); } - tty_printf(tty, "%c", choice[i]); + if (choice[i] == '\n') { + tty_putc(tty, ' '); + } else { + tty_printf(tty, "%c", choice[i]); + } } tty_setwrap(tty); tty_setnormal(tty); diff --git a/test/acceptance/acceptance_test.rb b/test/acceptance/acceptance_test.rb index 52c6af0..ba3ec01 100644 --- a/test/acceptance/acceptance_test.rb +++ b/test/acceptance/acceptance_test.rb @@ -456,6 +456,7 @@ Usage: fzy [OPTION]... -e, --show-matches=QUERY Output the sorted matches of QUERY -t, --tty=TTY Specify file to use as TTY device (default /dev/tty) -s, --show-scores Show the scores of each match + -0, --read-null Read input delimited by ASCII NUL characters -j, --workers NUM Use NUM workers for searching. (default is # of CPUs) -h, --help Display this help and exit -v, --version Output version information and exit -- cgit v1.2.3 From 79e48082f579f6c02a55b7cff81ecee1c4127b29 Mon Sep 17 00:00:00 2001 From: John Hawthorn Date: Fri, 16 Aug 2019 01:09:29 -0700 Subject: Simplify input_delimiter handling --- src/choices.c | 10 ++-------- src/choices.h | 3 +-- src/fzy.c | 8 ++++---- src/options.c | 22 +++++++++++----------- src/options.h | 2 +- 5 files changed, 19 insertions(+), 26 deletions(-) diff --git a/src/choices.c b/src/choices.c index b6d5f0e..fe2f80b 100644 --- a/src/choices.c +++ b/src/choices.c @@ -46,7 +46,7 @@ static void *safe_realloc(void *buffer, size_t size) { return buffer; } -void choices_fread(choices_t *c, FILE *file) { +void choices_fread(choices_t *c, FILE *file, char input_delimiter) { /* Save current position for parsing later */ size_t buffer_start = c->buffer_size; @@ -75,7 +75,7 @@ void choices_fread(choices_t *c, FILE *file) { const char *line_end = c->buffer + c->buffer_size; char *line = c->buffer + buffer_start; do { - char *nl = strchr(line, c->input_delimiter); + char *nl = strchr(line, input_delimiter); if (nl) *nl++ = '\0'; @@ -114,12 +114,6 @@ void choices_init(choices_t *c, options_t *options) { c->worker_count = (int)sysconf(_SC_NPROCESSORS_ONLN); } - if (options->read_null) { - c->input_delimiter = '\0'; - } else { - c->input_delimiter = '\n'; - } - choices_reset_search(c); } diff --git a/src/choices.h b/src/choices.h index c2bbcd9..925478e 100644 --- a/src/choices.h +++ b/src/choices.h @@ -25,11 +25,10 @@ typedef struct { size_t selection; unsigned int worker_count; - char input_delimiter; } choices_t; void choices_init(choices_t *c, options_t *options); -void choices_fread(choices_t *c, FILE *file); +void choices_fread(choices_t *c, FILE *file, char input_delimiter); void choices_destroy(choices_t *c); void choices_add(choices_t *c, const char *choice); size_t choices_available(choices_t *c); diff --git a/src/fzy.c b/src/fzy.c index 6b9aa5a..c2e5600 100644 --- a/src/fzy.c +++ b/src/fzy.c @@ -27,11 +27,11 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Must specify -e/--show-matches with --benchmark\n"); exit(EXIT_FAILURE); } - choices_fread(&choices, stdin); + choices_fread(&choices, stdin, options.input_delimiter); for (int i = 0; i < options.benchmark; i++) choices_search(&choices, options.filter); } else if (options.filter) { - choices_fread(&choices, stdin); + choices_fread(&choices, stdin, options.input_delimiter); choices_search(&choices, options.filter); for (size_t i = 0; i < choices_available(&choices); i++) { if (options.show_scores) @@ -42,13 +42,13 @@ int main(int argc, char *argv[]) { /* interactive */ if (isatty(STDIN_FILENO)) - choices_fread(&choices, stdin); + choices_fread(&choices, stdin, options.input_delimiter); tty_t tty; tty_init(&tty, options.tty_filename); if (!isatty(STDIN_FILENO)) - choices_fread(&choices, stdin); + choices_fread(&choices, stdin, options.input_delimiter); if (options.num_lines > choices.size) options.num_lines = choices.size; diff --git a/src/options.c b/src/options.c index 85eeac3..58f8fa0 100644 --- a/src/options.c +++ b/src/options.c @@ -41,16 +41,16 @@ static struct option longopts[] = {{"show-matches", required_argument, NULL, 'e' void options_init(options_t *options) { /* set defaults */ - options->benchmark = 0; - options->filter = NULL; - options->init_search = NULL; - options->show_scores = 0; - options->scrolloff = 1; - options->tty_filename = DEFAULT_TTY; - options->num_lines = DEFAULT_NUM_LINES; - options->prompt = DEFAULT_PROMPT; - options->workers = DEFAULT_WORKERS; - options->read_null = 0; + options->benchmark = 0; + options->filter = NULL; + options->init_search = NULL; + options->show_scores = 0; + options->scrolloff = 1; + options->tty_filename = DEFAULT_TTY; + options->num_lines = DEFAULT_NUM_LINES; + options->prompt = DEFAULT_PROMPT; + options->workers = DEFAULT_WORKERS; + options->input_delimiter = '\n'; } void options_parse(options_t *options, int argc, char *argv[]) { @@ -66,7 +66,7 @@ void options_parse(options_t *options, int argc, char *argv[]) { options->show_scores = 1; break; case '0': - options->read_null = 1; + options->input_delimiter = '\0'; break; case 'q': options->init_search = optarg; diff --git a/src/options.h b/src/options.h index 7113ccf..6098a64 100644 --- a/src/options.h +++ b/src/options.h @@ -11,7 +11,7 @@ typedef struct { unsigned int scrolloff; const char *prompt; unsigned int workers; - int read_null; + char input_delimiter; } options_t; void options_init(options_t *options); -- cgit v1.2.3