Browse code

Merge pull request #121 from jhawthorn/read-null

Add -0/--read-null

John Hawthorn authored on 16/08/2019 08:17:40 • GitHub committed on 16/08/2019 08:17:40
Showing 9 changed files

... ...
@@ -46,7 +46,7 @@ static void *safe_realloc(void *buffer, size_t size) {
46 46
 	return buffer;
47 47
 }
48 48
 
49
-void choices_fread(choices_t *c, FILE *file) {
49
+void choices_fread(choices_t *c, FILE *file, char input_delimiter) {
50 50
 	/* Save current position for parsing later */
51 51
 	size_t buffer_start = c->buffer_size;
52 52
 
... ...
@@ -72,9 +72,10 @@ void choices_fread(choices_t *c, FILE *file) {
72 72
 	 */
73 73
 
74 74
 	/* Tokenize input and add to choices */
75
+	const char *line_end = c->buffer + c->buffer_size;
75 76
 	char *line = c->buffer + buffer_start;
76 77
 	do {
77
-		char *nl = strchr(line, '\n');
78
+		char *nl = strchr(line, input_delimiter);
78 79
 		if (nl)
79 80
 			*nl++ = '\0';
80 81
 
... ...
@@ -83,7 +84,7 @@ void choices_fread(choices_t *c, FILE *file) {
83 84
 			choices_add(c, line);
84 85
 
85 86
 		line = nl;
86
-	} while (line);
87
+	} while (line && line < line_end);
87 88
 }
88 89
 
89 90
 static void choices_resize(choices_t *c, size_t new_capacity) {
... ...
@@ -28,7 +28,7 @@ typedef struct {
28 28
 } choices_t;
29 29
 
30 30
 void choices_init(choices_t *c, options_t *options);
31
-void choices_fread(choices_t *c, FILE *file);
31
+void choices_fread(choices_t *c, FILE *file, char input_delimiter);
32 32
 void choices_destroy(choices_t *c);
33 33
 void choices_add(choices_t *c, const char *choice);
34 34
 size_t choices_available(choices_t *c);
... ...
@@ -27,11 +27,11 @@ int main(int argc, char *argv[]) {
27 27
 			fprintf(stderr, "Must specify -e/--show-matches with --benchmark\n");
28 28
 			exit(EXIT_FAILURE);
29 29
 		}
30
-		choices_fread(&choices, stdin);
30
+		choices_fread(&choices, stdin, options.input_delimiter);
31 31
 		for (int i = 0; i < options.benchmark; i++)
32 32
 			choices_search(&choices, options.filter);
33 33
 	} else if (options.filter) {
34
-		choices_fread(&choices, stdin);
34
+		choices_fread(&choices, stdin, options.input_delimiter);
35 35
 		choices_search(&choices, options.filter);
36 36
 		for (size_t i = 0; i < choices_available(&choices); i++) {
37 37
 			if (options.show_scores)
... ...
@@ -42,13 +42,13 @@ int main(int argc, char *argv[]) {
42 42
 		/* interactive */
43 43
 
44 44
 		if (isatty(STDIN_FILENO))
45
-			choices_fread(&choices, stdin);
45
+			choices_fread(&choices, stdin, options.input_delimiter);
46 46
 
47 47
 		tty_t tty;
48 48
 		tty_init(&tty, options.tty_filename);
49 49
 
50 50
 		if (!isatty(STDIN_FILENO))
51
-			choices_fread(&choices, stdin);
51
+			choices_fread(&choices, stdin, options.input_delimiter);
52 52
 
53 53
 		if (options.num_lines > choices.size)
54 54
 			options.num_lines = choices.size;
... ...
@@ -17,6 +17,7 @@ static const char *usage_str =
17 17
     " -e, --show-matches=QUERY Output the sorted matches of QUERY\n"
18 18
     " -t, --tty=TTY            Specify file to use as TTY device (default /dev/tty)\n"
19 19
     " -s, --show-scores        Show the scores of each match\n"
20
+    " -0, --read-null          Read input delimited by ASCII NUL characters\n"
20 21
     " -j, --workers NUM        Use NUM workers for searching. (default is # of CPUs)\n"
21 22
     " -h, --help     Display this help and exit\n"
22 23
     " -v, --version  Output version information and exit\n";
... ...
@@ -31,6 +32,7 @@ static struct option longopts[] = {{"show-matches", required_argument, NULL, 'e'
31 32
 				   {"tty", required_argument, NULL, 't'},
32 33
 				   {"prompt", required_argument, NULL, 'p'},
33 34
 				   {"show-scores", no_argument, NULL, 's'},
35
+				   {"read-null", no_argument, NULL, '0'},
34 36
 				   {"version", no_argument, NULL, 'v'},
35 37
 				   {"benchmark", optional_argument, NULL, 'b'},
36 38
 				   {"workers", required_argument, NULL, 'j'},
... ...
@@ -39,22 +41,23 @@ static struct option longopts[] = {{"show-matches", required_argument, NULL, 'e'
39 41
 
40 42
 void options_init(options_t *options) {
41 43
 	/* set defaults */
42
-	options->benchmark    = 0;
43
-	options->filter       = NULL;
44
-	options->init_search  = NULL;
45
-	options->show_scores  = 0;
46
-	options->scrolloff    = 1;
47
-	options->tty_filename = DEFAULT_TTY;
48
-	options->num_lines    = DEFAULT_NUM_LINES;
49
-	options->prompt       = DEFAULT_PROMPT;
50
-	options->workers      = DEFAULT_WORKERS;
44
+	options->benchmark       = 0;
45
+	options->filter          = NULL;
46
+	options->init_search     = NULL;
47
+	options->show_scores     = 0;
48
+	options->scrolloff       = 1;
49
+	options->tty_filename    = DEFAULT_TTY;
50
+	options->num_lines       = DEFAULT_NUM_LINES;
51
+	options->prompt          = DEFAULT_PROMPT;
52
+	options->workers         = DEFAULT_WORKERS;
53
+	options->input_delimiter = '\n';
51 54
 }
52 55
 
53 56
 void options_parse(options_t *options, int argc, char *argv[]) {
54 57
 	options_init(options);
55 58
 
56 59
 	int c;
57
-	while ((c = getopt_long(argc, argv, "vhse:q:l:t:p:j:", longopts, NULL)) != -1) {
60
+	while ((c = getopt_long(argc, argv, "vhs0e:q:l:t:p:j:", longopts, NULL)) != -1) {
58 61
 		switch (c) {
59 62
 			case 'v':
60 63
 				printf("%s " VERSION " © 2014-2018 John Hawthorn\n", argv[0]);
... ...
@@ -62,6 +65,9 @@ void options_parse(options_t *options, int argc, char *argv[]) {
62 65
 			case 's':
63 66
 				options->show_scores = 1;
64 67
 				break;
68
+			case '0':
69
+				options->input_delimiter = '\0';
70
+				break;
65 71
 			case 'q':
66 72
 				options->init_search = optarg;
67 73
 				break;
... ...
@@ -11,6 +11,7 @@ typedef struct {
11 11
 	unsigned int scrolloff;
12 12
 	const char *prompt;
13 13
 	unsigned int workers;
14
+	char input_delimiter;
14 15
 } options_t;
15 16
 
16 17
 void options_init(options_t *options);
... ...
@@ -184,6 +184,10 @@ void tty_printf(tty_t *tty, const char *fmt, ...) {
184 184
 	va_end(args);
185 185
 }
186 186
 
187
+void tty_putc(tty_t *tty, char c) {
188
+	fputc(c, tty->fout);
189
+}
190
+
187 191
 void tty_flush(tty_t *tty) {
188 192
 	fflush(tty->fout);
189 193
 }
... ...
@@ -51,6 +51,7 @@ void tty_moveup(tty_t *tty, int i);
51 51
 void tty_setcol(tty_t *tty, int col);
52 52
 
53 53
 void tty_printf(tty_t *tty, const char *fmt, ...);
54
+void tty_putc(tty_t *tty, char c);
54 55
 void tty_flush(tty_t *tty);
55 56
 
56 57
 size_t tty_getwidth(tty_t *tty);
... ...
@@ -65,7 +65,11 @@ static void draw_match(tty_interface_t *state, const char *choice, int selected)
65 65
 		} else {
66 66
 			tty_setfg(tty, TTY_COLOR_NORMAL);
67 67
 		}
68
-		tty_printf(tty, "%c", choice[i]);
68
+		if (choice[i] == '\n') {
69
+			tty_putc(tty, ' ');
70
+		} else {
71
+			tty_printf(tty, "%c", choice[i]);
72
+		}
69 73
 	}
70 74
 	tty_setwrap(tty);
71 75
 	tty_setnormal(tty);
... ...
@@ -456,6 +456,7 @@ Usage: fzy [OPTION]...
456 456
  -e, --show-matches=QUERY Output the sorted matches of QUERY
457 457
  -t, --tty=TTY            Specify file to use as TTY device (default /dev/tty)
458 458
  -s, --show-scores        Show the scores of each match
459
+ -0, --read-null          Read input delimited by ASCII NUL characters
459 460
  -j, --workers NUM        Use NUM workers for searching. (default is # of CPUs)
460 461
  -h, --help     Display this help and exit
461 462
  -v, --version  Output version information and exit