| ... | ... |
@@ -53,8 +53,12 @@ int main(int argc, char *argv[]) {
|
| 53 | 53 |
if (options.num_lines > choices.size) |
| 54 | 54 |
options.num_lines = choices.size; |
| 55 | 55 |
|
| 56 |
- if (options.num_lines + 1 > tty_getheight(&tty)) |
|
| 57 |
- options.num_lines = tty_getheight(&tty) - 1; |
|
| 56 |
+ int num_lines_adjustment = 1; |
|
| 57 |
+ if (options.show_info) |
|
| 58 |
+ num_lines_adjustment++; |
|
| 59 |
+ |
|
| 60 |
+ if (options.num_lines + num_lines_adjustment > tty_getheight(&tty)) |
|
| 61 |
+ options.num_lines = tty_getheight(&tty) - num_lines_adjustment; |
|
| 58 | 62 |
|
| 59 | 63 |
tty_interface_t tty_interface; |
| 60 | 64 |
tty_interface_init(&tty_interface, &tty, &choices, &options); |
| ... | ... |
@@ -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; |
Previously we deferred reading choices to after initializing the tty.
This makes sense only when stdin and our tty aren't the same.
| ... | ... |
@@ -3,6 +3,7 @@ |
| 3 | 3 |
#include <stdlib.h> |
| 4 | 4 |
#include <ctype.h> |
| 5 | 5 |
#include <limits.h> |
| 6 |
+#include <unistd.h> |
|
| 6 | 7 |
|
| 7 | 8 |
#include "match.h" |
| 8 | 9 |
#include "tty.h" |
| ... | ... |
@@ -39,10 +40,15 @@ int main(int argc, char *argv[]) {
|
| 39 | 40 |
} |
| 40 | 41 |
} else {
|
| 41 | 42 |
/* interactive */ |
| 43 |
+ |
|
| 44 |
+ if (isatty(STDIN_FILENO)) |
|
| 45 |
+ choices_fread(&choices, stdin); |
|
| 46 |
+ |
|
| 42 | 47 |
tty_t tty; |
| 43 | 48 |
tty_init(&tty, options.tty_filename); |
| 44 | 49 |
|
| 45 |
- choices_fread(&choices, stdin); |
|
| 50 |
+ if (!isatty(STDIN_FILENO)) |
|
| 51 |
+ choices_fread(&choices, stdin); |
|
| 46 | 52 |
|
| 47 | 53 |
if (options.num_lines > choices.size) |
| 48 | 54 |
options.num_lines = choices.size; |
It's possible for user input to arrive while fzy was still reading
choices from stdin. Previously, this would happen before the correct
termios were set, causing fzy to misinterpret Enter as Ctrl-J for
example.
Fixes #81
| ... | ... |
@@ -20,16 +20,17 @@ int main(int argc, char *argv[]) {
|
| 20 | 20 |
|
| 21 | 21 |
choices_t choices; |
| 22 | 22 |
choices_init(&choices, &options); |
| 23 |
- choices_fread(&choices, stdin); |
|
| 24 | 23 |
|
| 25 | 24 |
if (options.benchmark) {
|
| 26 | 25 |
if (!options.filter) {
|
| 27 | 26 |
fprintf(stderr, "Must specify -e/--show-matches with --benchmark\n"); |
| 28 | 27 |
exit(EXIT_FAILURE); |
| 29 | 28 |
} |
| 29 |
+ choices_fread(&choices, stdin); |
|
| 30 | 30 |
for (int i = 0; i < options.benchmark; i++) |
| 31 | 31 |
choices_search(&choices, options.filter); |
| 32 | 32 |
} else if (options.filter) {
|
| 33 |
+ choices_fread(&choices, stdin); |
|
| 33 | 34 |
choices_search(&choices, options.filter); |
| 34 | 35 |
for (size_t i = 0; i < choices_available(&choices); i++) {
|
| 35 | 36 |
if (options.show_scores) |
| ... | ... |
@@ -41,6 +42,8 @@ int main(int argc, char *argv[]) {
|
| 41 | 42 |
tty_t tty; |
| 42 | 43 |
tty_init(&tty, options.tty_filename); |
| 43 | 44 |
|
| 45 |
+ choices_fread(&choices, stdin); |
|
| 46 |
+ |
|
| 44 | 47 |
if (options.num_lines > choices.size) |
| 45 | 48 |
options.num_lines = choices.size; |
| 46 | 49 |
|
| ... | ... |
@@ -13,6 +13,8 @@ |
| 13 | 13 |
#include "../config.h" |
| 14 | 14 |
|
| 15 | 15 |
int main(int argc, char *argv[]) {
|
| 16 |
+ int ret = 0; |
|
| 17 |
+ |
|
| 16 | 18 |
options_t options; |
| 17 | 19 |
options_parse(&options, argc, argv); |
| 18 | 20 |
|
| ... | ... |
@@ -47,10 +49,10 @@ int main(int argc, char *argv[]) {
|
| 47 | 49 |
|
| 48 | 50 |
tty_interface_t tty_interface; |
| 49 | 51 |
tty_interface_init(&tty_interface, &tty, &choices, &options); |
| 50 |
- tty_interface_run(&tty_interface); |
|
| 52 |
+ ret = tty_interface_run(&tty_interface); |
|
| 51 | 53 |
} |
| 52 | 54 |
|
| 53 | 55 |
choices_destroy(&choices); |
| 54 | 56 |
|
| 55 |
- return 0; |
|
| 57 |
+ return ret; |
|
| 56 | 58 |
} |
| ... | ... |
@@ -46,7 +46,9 @@ int main(int argc, char *argv[]) {
|
| 46 | 46 |
if (options.num_lines + 1 > tty_getheight(&tty)) |
| 47 | 47 |
options.num_lines = tty_getheight(&tty) - 1; |
| 48 | 48 |
|
| 49 |
- tty_interface_run(&tty, &choices, &options); |
|
| 49 |
+ tty_interface_t tty_interface; |
|
| 50 |
+ tty_interface_init(&tty_interface, &tty, &choices, &options); |
|
| 51 |
+ tty_interface_run(&tty_interface); |
|
| 50 | 52 |
} |
| 51 | 53 |
|
| 52 | 54 |
choices_destroy(&choices); |
| ... | ... |
@@ -8,161 +8,12 @@ |
| 8 | 8 |
#include "tty.h" |
| 9 | 9 |
#include "choices.h" |
| 10 | 10 |
#include "options.h" |
| 11 |
+#include "tty_interface.h" |
|
| 11 | 12 |
|
| 12 | 13 |
#include "../config.h" |
| 13 | 14 |
|
| 14 | 15 |
options_t options; |
| 15 | 16 |
|
| 16 |
-#define SEARCH_SIZE_MAX 4096 |
|
| 17 |
-static char search[SEARCH_SIZE_MAX + 1] = {0};
|
|
| 18 |
- |
|
| 19 |
-static void clear(tty_t *tty, options_t *options) {
|
|
| 20 |
- tty_setcol(tty, 0); |
|
| 21 |
- size_t line = 0; |
|
| 22 |
- while (line++ < options->num_lines) {
|
|
| 23 |
- tty_newline(tty); |
|
| 24 |
- } |
|
| 25 |
- tty_clearline(tty); |
|
| 26 |
- tty_moveup(tty, line - 1); |
|
| 27 |
- tty_flush(tty); |
|
| 28 |
-} |
|
| 29 |
- |
|
| 30 |
-static void draw_match(tty_t *tty, const char *choice, int selected, options_t *options) {
|
|
| 31 |
- int n = strlen(search); |
|
| 32 |
- size_t positions[n + 1]; |
|
| 33 |
- for (int i = 0; i < n + 1; i++) |
|
| 34 |
- positions[i] = -1; |
|
| 35 |
- |
|
| 36 |
- double score = match_positions(search, choice, &positions[0]); |
|
| 37 |
- |
|
| 38 |
- size_t maxwidth = tty_getwidth(tty); |
|
| 39 |
- |
|
| 40 |
- if (options->show_scores) |
|
| 41 |
- tty_printf(tty, "(%5.2f) ", score); |
|
| 42 |
- |
|
| 43 |
- if (selected) |
|
| 44 |
- tty_setinvert(tty); |
|
| 45 |
- |
|
| 46 |
- for (size_t i = 0, p = 0; choice[i] != '\0'; i++) {
|
|
| 47 |
- if (i + 1 < maxwidth) {
|
|
| 48 |
- if (positions[p] == i) {
|
|
| 49 |
- tty_setfg(tty, TTY_COLOR_HIGHLIGHT); |
|
| 50 |
- p++; |
|
| 51 |
- } else {
|
|
| 52 |
- tty_setfg(tty, TTY_COLOR_NORMAL); |
|
| 53 |
- } |
|
| 54 |
- tty_printf(tty, "%c", choice[i]); |
|
| 55 |
- } else {
|
|
| 56 |
- tty_printf(tty, "$"); |
|
| 57 |
- break; |
|
| 58 |
- } |
|
| 59 |
- } |
|
| 60 |
- tty_setnormal(tty); |
|
| 61 |
-} |
|
| 62 |
- |
|
| 63 |
-static void draw(tty_t *tty, choices_t *choices, options_t *options) {
|
|
| 64 |
- unsigned int num_lines = options->num_lines; |
|
| 65 |
- size_t start = 0; |
|
| 66 |
- size_t current_selection = choices->selection; |
|
| 67 |
- if (current_selection + options->scrolloff >= num_lines) {
|
|
| 68 |
- start = current_selection + options->scrolloff - num_lines + 1; |
|
| 69 |
- if (start + num_lines >= choices_available(choices)) {
|
|
| 70 |
- start = choices_available(choices) - num_lines; |
|
| 71 |
- } |
|
| 72 |
- } |
|
| 73 |
- tty_setcol(tty, 0); |
|
| 74 |
- tty_printf(tty, "%s%s", options->prompt, search); |
|
| 75 |
- tty_clearline(tty); |
|
| 76 |
- for (size_t i = start; i < start + num_lines; i++) {
|
|
| 77 |
- tty_printf(tty, "\n"); |
|
| 78 |
- tty_clearline(tty); |
|
| 79 |
- const char *choice = choices_get(choices, i); |
|
| 80 |
- if (choice) {
|
|
| 81 |
- draw_match(tty, choice, i == choices->selection, options); |
|
| 82 |
- } |
|
| 83 |
- } |
|
| 84 |
- tty_moveup(tty, num_lines); |
|
| 85 |
- tty_setcol(tty, strlen(options->prompt) + strlen(search)); |
|
| 86 |
- tty_flush(tty); |
|
| 87 |
-} |
|
| 88 |
- |
|
| 89 |
-static void emit(choices_t *choices) {
|
|
| 90 |
- const char *selection = choices_get(choices, choices->selection); |
|
| 91 |
- if (selection) {
|
|
| 92 |
- /* output the selected result */ |
|
| 93 |
- printf("%s\n", selection);
|
|
| 94 |
- } else {
|
|
| 95 |
- /* No match, output the query instead */ |
|
| 96 |
- printf("%s\n", search);
|
|
| 97 |
- } |
|
| 98 |
-} |
|
| 99 |
- |
|
| 100 |
-#define KEY_CTRL(key) ((key) - ('@'))
|
|
| 101 |
-#define KEY_DEL 127 |
|
| 102 |
-#define KEY_ESC 27 |
|
| 103 |
- |
|
| 104 |
-static void run(tty_t *tty, choices_t *choices, options_t *options) {
|
|
| 105 |
- choices_search(choices, search); |
|
| 106 |
- char ch; |
|
| 107 |
- do {
|
|
| 108 |
- draw(tty, choices, options); |
|
| 109 |
- ch = tty_getchar(tty); |
|
| 110 |
- size_t search_size = strlen(search); |
|
| 111 |
- if (isprint(ch)) {
|
|
| 112 |
- if (search_size < SEARCH_SIZE_MAX) {
|
|
| 113 |
- search[search_size++] = ch; |
|
| 114 |
- search[search_size] = '\0'; |
|
| 115 |
- choices_search(choices, search); |
|
| 116 |
- } |
|
| 117 |
- } else if (ch == KEY_DEL || ch == KEY_CTRL('H')) { /* DEL || Backspace (C-H) */
|
|
| 118 |
- if (search_size) |
|
| 119 |
- search[--search_size] = '\0'; |
|
| 120 |
- choices_search(choices, search); |
|
| 121 |
- } else if (ch == KEY_CTRL('U')) { /* C-U */
|
|
| 122 |
- search_size = 0; |
|
| 123 |
- search[0] = '\0'; |
|
| 124 |
- choices_search(choices, search); |
|
| 125 |
- } else if (ch == KEY_CTRL('W')) { /* C-W */
|
|
| 126 |
- if (search_size) |
|
| 127 |
- search[--search_size] = '\0'; |
|
| 128 |
- while (search_size && !isspace(search[--search_size])) |
|
| 129 |
- search[search_size] = '\0'; |
|
| 130 |
- choices_search(choices, search); |
|
| 131 |
- } else if (ch == KEY_CTRL('N')) { /* C-N */
|
|
| 132 |
- choices_next(choices); |
|
| 133 |
- } else if (ch == KEY_CTRL('P')) { /* C-P */
|
|
| 134 |
- choices_prev(choices); |
|
| 135 |
- } else if (ch == KEY_CTRL('I')) { /* TAB (C-I) */
|
|
| 136 |
- strncpy(search, choices_get(choices, choices->selection), SEARCH_SIZE_MAX); |
|
| 137 |
- choices_search(choices, search); |
|
| 138 |
- } else if (ch == KEY_CTRL('C') || ch == KEY_CTRL('D')) { /* ^C || ^D */
|
|
| 139 |
- clear(tty, options); |
|
| 140 |
- tty_close(tty); |
|
| 141 |
- exit(EXIT_FAILURE); |
|
| 142 |
- } else if (ch == KEY_CTRL('M')) { /* CR */
|
|
| 143 |
- clear(tty, options); |
|
| 144 |
- |
|
| 145 |
- /* ttyout should be flushed before outputting on stdout */ |
|
| 146 |
- tty_close(tty); |
|
| 147 |
- |
|
| 148 |
- emit(choices); |
|
| 149 |
- |
|
| 150 |
- /* Return to eventually exit successfully */ |
|
| 151 |
- return; |
|
| 152 |
- } else if (ch == KEY_ESC) { /* ESC */
|
|
| 153 |
- ch = tty_getchar(tty); |
|
| 154 |
- if (ch == '[' || ch == 'O') {
|
|
| 155 |
- ch = tty_getchar(tty); |
|
| 156 |
- if (ch == 'A') { /* UP ARROW */
|
|
| 157 |
- choices_prev(choices); |
|
| 158 |
- } else if (ch == 'B') { /* DOWN ARROW */
|
|
| 159 |
- choices_next(choices); |
|
| 160 |
- } |
|
| 161 |
- } |
|
| 162 |
- } |
|
| 163 |
- } while (1); |
|
| 164 |
-} |
|
| 165 |
- |
|
| 166 | 17 |
int main(int argc, char *argv[]) {
|
| 167 | 18 |
options_parse(&options, argc, argv); |
| 168 | 19 |
|
| ... | ... |
@@ -195,10 +46,7 @@ int main(int argc, char *argv[]) {
|
| 195 | 46 |
if (options.num_lines + 1 > tty_getheight(&tty)) |
| 196 | 47 |
options.num_lines = tty_getheight(&tty) - 1; |
| 197 | 48 |
|
| 198 |
- if (options.init_search) |
|
| 199 |
- strncpy(search, options.init_search, SEARCH_SIZE_MAX); |
|
| 200 |
- |
|
| 201 |
- run(&tty, &choices, &options); |
|
| 49 |
+ tty_interface_run(&tty, &choices, &options); |
|
| 202 | 50 |
} |
| 203 | 51 |
|
| 204 | 52 |
choices_destroy(&choices); |
| ... | ... |
@@ -16,10 +16,10 @@ options_t options; |
| 16 | 16 |
#define SEARCH_SIZE_MAX 4096 |
| 17 | 17 |
static char search[SEARCH_SIZE_MAX + 1] = {0};
|
| 18 | 18 |
|
| 19 |
-static void clear(tty_t *tty) {
|
|
| 19 |
+static void clear(tty_t *tty, options_t *options) {
|
|
| 20 | 20 |
tty_setcol(tty, 0); |
| 21 | 21 |
size_t line = 0; |
| 22 |
- while (line++ < options.num_lines) {
|
|
| 22 |
+ while (line++ < options->num_lines) {
|
|
| 23 | 23 |
tty_newline(tty); |
| 24 | 24 |
} |
| 25 | 25 |
tty_clearline(tty); |
| ... | ... |
@@ -27,7 +27,7 @@ static void clear(tty_t *tty) {
|
| 27 | 27 |
tty_flush(tty); |
| 28 | 28 |
} |
| 29 | 29 |
|
| 30 |
-static void draw_match(tty_t *tty, const char *choice, int selected) {
|
|
| 30 |
+static void draw_match(tty_t *tty, const char *choice, int selected, options_t *options) {
|
|
| 31 | 31 |
int n = strlen(search); |
| 32 | 32 |
size_t positions[n + 1]; |
| 33 | 33 |
for (int i = 0; i < n + 1; i++) |
| ... | ... |
@@ -37,7 +37,7 @@ static void draw_match(tty_t *tty, const char *choice, int selected) {
|
| 37 | 37 |
|
| 38 | 38 |
size_t maxwidth = tty_getwidth(tty); |
| 39 | 39 |
|
| 40 |
- if (options.show_scores) |
|
| 40 |
+ if (options->show_scores) |
|
| 41 | 41 |
tty_printf(tty, "(%5.2f) ", score); |
| 42 | 42 |
|
| 43 | 43 |
if (selected) |
| ... | ... |
@@ -60,29 +60,29 @@ static void draw_match(tty_t *tty, const char *choice, int selected) {
|
| 60 | 60 |
tty_setnormal(tty); |
| 61 | 61 |
} |
| 62 | 62 |
|
| 63 |
-static void draw(tty_t *tty, choices_t *choices) {
|
|
| 64 |
- unsigned int num_lines = options.num_lines; |
|
| 63 |
+static void draw(tty_t *tty, choices_t *choices, options_t *options) {
|
|
| 64 |
+ unsigned int num_lines = options->num_lines; |
|
| 65 | 65 |
size_t start = 0; |
| 66 | 66 |
size_t current_selection = choices->selection; |
| 67 |
- if (current_selection + options.scrolloff >= num_lines) {
|
|
| 68 |
- start = current_selection + options.scrolloff - num_lines + 1; |
|
| 67 |
+ if (current_selection + options->scrolloff >= num_lines) {
|
|
| 68 |
+ start = current_selection + options->scrolloff - num_lines + 1; |
|
| 69 | 69 |
if (start + num_lines >= choices_available(choices)) {
|
| 70 | 70 |
start = choices_available(choices) - num_lines; |
| 71 | 71 |
} |
| 72 | 72 |
} |
| 73 | 73 |
tty_setcol(tty, 0); |
| 74 |
- tty_printf(tty, "%s%s", options.prompt, search); |
|
| 74 |
+ tty_printf(tty, "%s%s", options->prompt, search); |
|
| 75 | 75 |
tty_clearline(tty); |
| 76 | 76 |
for (size_t i = start; i < start + num_lines; i++) {
|
| 77 | 77 |
tty_printf(tty, "\n"); |
| 78 | 78 |
tty_clearline(tty); |
| 79 | 79 |
const char *choice = choices_get(choices, i); |
| 80 | 80 |
if (choice) {
|
| 81 |
- draw_match(tty, choice, i == choices->selection); |
|
| 81 |
+ draw_match(tty, choice, i == choices->selection, options); |
|
| 82 | 82 |
} |
| 83 | 83 |
} |
| 84 | 84 |
tty_moveup(tty, num_lines); |
| 85 |
- tty_setcol(tty, strlen(options.prompt) + strlen(search)); |
|
| 85 |
+ tty_setcol(tty, strlen(options->prompt) + strlen(search)); |
|
| 86 | 86 |
tty_flush(tty); |
| 87 | 87 |
} |
| 88 | 88 |
|
| ... | ... |
@@ -101,11 +101,11 @@ static void emit(choices_t *choices) {
|
| 101 | 101 |
#define KEY_DEL 127 |
| 102 | 102 |
#define KEY_ESC 27 |
| 103 | 103 |
|
| 104 |
-static void run(tty_t *tty, choices_t *choices) {
|
|
| 104 |
+static void run(tty_t *tty, choices_t *choices, options_t *options) {
|
|
| 105 | 105 |
choices_search(choices, search); |
| 106 | 106 |
char ch; |
| 107 | 107 |
do {
|
| 108 |
- draw(tty, choices); |
|
| 108 |
+ draw(tty, choices, options); |
|
| 109 | 109 |
ch = tty_getchar(tty); |
| 110 | 110 |
size_t search_size = strlen(search); |
| 111 | 111 |
if (isprint(ch)) {
|
| ... | ... |
@@ -136,11 +136,11 @@ static void run(tty_t *tty, choices_t *choices) {
|
| 136 | 136 |
strncpy(search, choices_get(choices, choices->selection), SEARCH_SIZE_MAX); |
| 137 | 137 |
choices_search(choices, search); |
| 138 | 138 |
} else if (ch == KEY_CTRL('C') || ch == KEY_CTRL('D')) { /* ^C || ^D */
|
| 139 |
- clear(tty); |
|
| 139 |
+ clear(tty, options); |
|
| 140 | 140 |
tty_close(tty); |
| 141 | 141 |
exit(EXIT_FAILURE); |
| 142 | 142 |
} else if (ch == KEY_CTRL('M')) { /* CR */
|
| 143 |
- clear(tty); |
|
| 143 |
+ clear(tty, options); |
|
| 144 | 144 |
|
| 145 | 145 |
/* ttyout should be flushed before outputting on stdout */ |
| 146 | 146 |
tty_close(tty); |
| ... | ... |
@@ -198,7 +198,7 @@ int main(int argc, char *argv[]) {
|
| 198 | 198 |
if (options.init_search) |
| 199 | 199 |
strncpy(search, options.init_search, SEARCH_SIZE_MAX); |
| 200 | 200 |
|
| 201 |
- run(&tty, &choices); |
|
| 201 |
+ run(&tty, &choices, &options); |
|
| 202 | 202 |
} |
| 203 | 203 |
|
| 204 | 204 |
choices_destroy(&choices); |
| ... | ... |
@@ -2,21 +2,16 @@ |
| 2 | 2 |
#include <string.h> |
| 3 | 3 |
#include <stdlib.h> |
| 4 | 4 |
#include <ctype.h> |
| 5 |
-#include <getopt.h> |
|
| 6 | 5 |
#include <limits.h> |
| 7 | 6 |
|
| 8 | 7 |
#include "match.h" |
| 9 | 8 |
#include "tty.h" |
| 10 | 9 |
#include "choices.h" |
| 10 |
+#include "options.h" |
|
| 11 | 11 |
|
| 12 | 12 |
#include "../config.h" |
| 13 | 13 |
|
| 14 |
-static int flag_show_scores = 0; |
|
| 15 |
- |
|
| 16 |
-static size_t num_lines = 10; |
|
| 17 |
-static size_t scrolloff = 1; |
|
| 18 |
- |
|
| 19 |
-static const char *prompt = "> "; |
|
| 14 |
+options_t options; |
|
| 20 | 15 |
|
| 21 | 16 |
#define SEARCH_SIZE_MAX 4096 |
| 22 | 17 |
static char search[SEARCH_SIZE_MAX + 1] = {0};
|
| ... | ... |
@@ -24,7 +19,7 @@ static char search[SEARCH_SIZE_MAX + 1] = {0};
|
| 24 | 19 |
static void clear(tty_t *tty) {
|
| 25 | 20 |
tty_setcol(tty, 0); |
| 26 | 21 |
size_t line = 0; |
| 27 |
- while (line++ < num_lines) {
|
|
| 22 |
+ while (line++ < options.num_lines) {
|
|
| 28 | 23 |
tty_newline(tty); |
| 29 | 24 |
} |
| 30 | 25 |
tty_clearline(tty); |
| ... | ... |
@@ -42,7 +37,7 @@ static void draw_match(tty_t *tty, const char *choice, int selected) {
|
| 42 | 37 |
|
| 43 | 38 |
size_t maxwidth = tty_getwidth(tty); |
| 44 | 39 |
|
| 45 |
- if (flag_show_scores) |
|
| 40 |
+ if (options.show_scores) |
|
| 46 | 41 |
tty_printf(tty, "(%5.2f) ", score); |
| 47 | 42 |
|
| 48 | 43 |
if (selected) |
| ... | ... |
@@ -66,16 +61,17 @@ static void draw_match(tty_t *tty, const char *choice, int selected) {
|
| 66 | 61 |
} |
| 67 | 62 |
|
| 68 | 63 |
static void draw(tty_t *tty, choices_t *choices) {
|
| 64 |
+ unsigned int num_lines = options.num_lines; |
|
| 69 | 65 |
size_t start = 0; |
| 70 | 66 |
size_t current_selection = choices->selection; |
| 71 |
- if (current_selection + scrolloff >= num_lines) {
|
|
| 72 |
- start = current_selection + scrolloff - num_lines + 1; |
|
| 67 |
+ if (current_selection + options.scrolloff >= num_lines) {
|
|
| 68 |
+ start = current_selection + options.scrolloff - num_lines + 1; |
|
| 73 | 69 |
if (start + num_lines >= choices_available(choices)) {
|
| 74 | 70 |
start = choices_available(choices) - num_lines; |
| 75 | 71 |
} |
| 76 | 72 |
} |
| 77 | 73 |
tty_setcol(tty, 0); |
| 78 |
- tty_printf(tty, "%s%s", prompt, search); |
|
| 74 |
+ tty_printf(tty, "%s%s", options.prompt, search); |
|
| 79 | 75 |
tty_clearline(tty); |
| 80 | 76 |
for (size_t i = start; i < start + num_lines; i++) {
|
| 81 | 77 |
tty_printf(tty, "\n"); |
| ... | ... |
@@ -86,7 +82,7 @@ static void draw(tty_t *tty, choices_t *choices) {
|
| 86 | 82 |
} |
| 87 | 83 |
} |
| 88 | 84 |
tty_moveup(tty, num_lines); |
| 89 |
- tty_setcol(tty, strlen(prompt) + strlen(search)); |
|
| 85 |
+ tty_setcol(tty, strlen(options.prompt) + strlen(search)); |
|
| 90 | 86 |
tty_flush(tty); |
| 91 | 87 |
} |
| 92 | 88 |
|
| ... | ... |
@@ -167,119 +163,40 @@ static void run(tty_t *tty, choices_t *choices) {
|
| 167 | 163 |
} while (1); |
| 168 | 164 |
} |
| 169 | 165 |
|
| 170 |
-static const char *usage_str = |
|
| 171 |
- "" |
|
| 172 |
- "Usage: fzy [OPTION]...\n" |
|
| 173 |
- " -l, --lines=LINES Specify how many lines of results to show (default 10)\n" |
|
| 174 |
- " -p, --prompt=PROMPT Input prompt (default '> ')\n" |
|
| 175 |
- " -q, --query=QUERY Use QUERY as the initial search string\n" |
|
| 176 |
- " -e, --show-matches=QUERY Output the sorted matches of QUERY\n" |
|
| 177 |
- " -t, --tty=TTY Specify file to use as TTY device (default /dev/tty)\n" |
|
| 178 |
- " -s, --show-scores Show the scores of each match\n" |
|
| 179 |
- " -h, --help Display this help and exit\n" |
|
| 180 |
- " -v, --version Output version information and exit\n"; |
|
| 181 |
- |
|
| 182 |
-static void usage(const char *argv0) {
|
|
| 183 |
- fprintf(stderr, usage_str, argv0); |
|
| 184 |
-} |
|
| 185 |
- |
|
| 186 |
-static struct option longopts[] = {{"show-matches", required_argument, NULL, 'e'},
|
|
| 187 |
- {"query", required_argument, NULL, 'q'},
|
|
| 188 |
- {"lines", required_argument, NULL, 'l'},
|
|
| 189 |
- {"tty", required_argument, NULL, 't'},
|
|
| 190 |
- {"prompt", required_argument, NULL, 'p'},
|
|
| 191 |
- {"show-scores", no_argument, NULL, 's'},
|
|
| 192 |
- {"version", no_argument, NULL, 'v'},
|
|
| 193 |
- {"benchmark", optional_argument, NULL, 'b'},
|
|
| 194 |
- {"help", no_argument, NULL, 'h'},
|
|
| 195 |
- {NULL, 0, NULL, 0}};
|
|
| 196 |
- |
|
| 197 | 166 |
int main(int argc, char *argv[]) {
|
| 198 |
- int benchmark = 0; |
|
| 199 |
- const char *filter = NULL; |
|
| 200 |
- const char *tty_filename = "/dev/tty"; |
|
| 201 |
- char c; |
|
| 202 |
- while ((c = getopt_long(argc, argv, "vhse:q:l:t:p:", longopts, NULL)) != -1) {
|
|
| 203 |
- switch (c) {
|
|
| 204 |
- case 'v': |
|
| 205 |
- printf("%s " VERSION " (c) 2014 John Hawthorn\n", argv[0]);
|
|
| 206 |
- exit(EXIT_SUCCESS); |
|
| 207 |
- case 's': |
|
| 208 |
- flag_show_scores = 1; |
|
| 209 |
- break; |
|
| 210 |
- case 'q': |
|
| 211 |
- strncpy(search, optarg, SEARCH_SIZE_MAX); |
|
| 212 |
- break; |
|
| 213 |
- case 'e': |
|
| 214 |
- filter = optarg; |
|
| 215 |
- break; |
|
| 216 |
- case 'b': |
|
| 217 |
- if (optarg) {
|
|
| 218 |
- if (sscanf(optarg, "%d", &benchmark) != 1) {
|
|
| 219 |
- usage(argv[0]); |
|
| 220 |
- exit(EXIT_FAILURE); |
|
| 221 |
- } |
|
| 222 |
- } else {
|
|
| 223 |
- benchmark = 100; |
|
| 224 |
- } |
|
| 225 |
- break; |
|
| 226 |
- case 't': |
|
| 227 |
- tty_filename = optarg; |
|
| 228 |
- break; |
|
| 229 |
- case 'p': |
|
| 230 |
- prompt = optarg; |
|
| 231 |
- break; |
|
| 232 |
- case 'l': {
|
|
| 233 |
- int l; |
|
| 234 |
- if (!strcmp(optarg, "max")) {
|
|
| 235 |
- l = INT_MAX; |
|
| 236 |
- } else if (sscanf(optarg, "%d", &l) != 1 || l < 3) {
|
|
| 237 |
- fprintf(stderr, "Invalid format for --lines: %s\n", optarg); |
|
| 238 |
- fprintf(stderr, "Must be integer in range 3..\n"); |
|
| 239 |
- usage(argv[0]); |
|
| 240 |
- exit(EXIT_FAILURE); |
|
| 241 |
- } |
|
| 242 |
- num_lines = l; |
|
| 243 |
- } break; |
|
| 244 |
- case 'h': |
|
| 245 |
- default: |
|
| 246 |
- usage(argv[0]); |
|
| 247 |
- exit(EXIT_SUCCESS); |
|
| 248 |
- } |
|
| 249 |
- } |
|
| 250 |
- if (optind != argc) {
|
|
| 251 |
- usage(argv[0]); |
|
| 252 |
- exit(EXIT_FAILURE); |
|
| 253 |
- } |
|
| 167 |
+ options_parse(&options, argc, argv); |
|
| 254 | 168 |
|
| 255 | 169 |
choices_t choices; |
| 256 | 170 |
choices_init(&choices); |
| 257 | 171 |
choices_fread(&choices, stdin); |
| 258 | 172 |
|
| 259 |
- if (benchmark) {
|
|
| 260 |
- if (!filter) {
|
|
| 173 |
+ if (options.benchmark) {
|
|
| 174 |
+ if (!options.filter) {
|
|
| 261 | 175 |
fprintf(stderr, "Must specify -e/--show-matches with --benchmark\n"); |
| 262 | 176 |
exit(EXIT_FAILURE); |
| 263 | 177 |
} |
| 264 |
- for (int i = 0; i < benchmark; i++) |
|
| 265 |
- choices_search(&choices, filter); |
|
| 266 |
- } else if (filter) {
|
|
| 267 |
- choices_search(&choices, filter); |
|
| 178 |
+ for (int i = 0; i < options.benchmark; i++) |
|
| 179 |
+ choices_search(&choices, options.filter); |
|
| 180 |
+ } else if (options.filter) {
|
|
| 181 |
+ choices_search(&choices, options.filter); |
|
| 268 | 182 |
for (size_t i = 0; i < choices_available(&choices); i++) {
|
| 269 |
- if (flag_show_scores) |
|
| 183 |
+ if (options.show_scores) |
|
| 270 | 184 |
printf("%f\t", choices_getscore(&choices, i));
|
| 271 | 185 |
printf("%s\n", choices_get(&choices, i));
|
| 272 | 186 |
} |
| 273 | 187 |
} else {
|
| 274 | 188 |
/* interactive */ |
| 275 | 189 |
tty_t tty; |
| 276 |
- tty_init(&tty, tty_filename); |
|
| 190 |
+ tty_init(&tty, options.tty_filename); |
|
| 191 |
+ |
|
| 192 |
+ if (options.num_lines > choices.size) |
|
| 193 |
+ options.num_lines = choices.size; |
|
| 277 | 194 |
|
| 278 |
- if (num_lines > choices.size) |
|
| 279 |
- num_lines = choices.size; |
|
| 195 |
+ if (options.num_lines + 1 > tty_getheight(&tty)) |
|
| 196 |
+ options.num_lines = tty_getheight(&tty) - 1; |
|
| 280 | 197 |
|
| 281 |
- if (num_lines + 1 > tty_getheight(&tty)) |
|
| 282 |
- num_lines = tty_getheight(&tty) - 1; |
|
| 198 |
+ if (options.init_search) |
|
| 199 |
+ strncpy(search, options.init_search, SEARCH_SIZE_MAX); |
|
| 283 | 200 |
|
| 284 | 201 |
run(&tty, &choices); |
| 285 | 202 |
} |
| 1 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,290 @@ |
| 1 |
+#include <stdio.h> |
|
| 2 |
+#include <string.h> |
|
| 3 |
+#include <stdlib.h> |
|
| 4 |
+#include <ctype.h> |
|
| 5 |
+#include <getopt.h> |
|
| 6 |
+#include <limits.h> |
|
| 7 |
+ |
|
| 8 |
+#include "match.h" |
|
| 9 |
+#include "tty.h" |
|
| 10 |
+#include "choices.h" |
|
| 11 |
+ |
|
| 12 |
+#include "../config.h" |
|
| 13 |
+ |
|
| 14 |
+static int flag_show_scores = 0; |
|
| 15 |
+ |
|
| 16 |
+static size_t num_lines = 10; |
|
| 17 |
+static size_t scrolloff = 1; |
|
| 18 |
+ |
|
| 19 |
+static const char *prompt = "> "; |
|
| 20 |
+ |
|
| 21 |
+#define SEARCH_SIZE_MAX 4096 |
|
| 22 |
+static char search[SEARCH_SIZE_MAX + 1] = {0};
|
|
| 23 |
+ |
|
| 24 |
+static void clear(tty_t *tty) {
|
|
| 25 |
+ tty_setcol(tty, 0); |
|
| 26 |
+ size_t line = 0; |
|
| 27 |
+ while (line++ < num_lines) {
|
|
| 28 |
+ tty_newline(tty); |
|
| 29 |
+ } |
|
| 30 |
+ tty_clearline(tty); |
|
| 31 |
+ tty_moveup(tty, line - 1); |
|
| 32 |
+ tty_flush(tty); |
|
| 33 |
+} |
|
| 34 |
+ |
|
| 35 |
+static void draw_match(tty_t *tty, const char *choice, int selected) {
|
|
| 36 |
+ int n = strlen(search); |
|
| 37 |
+ size_t positions[n + 1]; |
|
| 38 |
+ for (int i = 0; i < n + 1; i++) |
|
| 39 |
+ positions[i] = -1; |
|
| 40 |
+ |
|
| 41 |
+ double score = match_positions(search, choice, &positions[0]); |
|
| 42 |
+ |
|
| 43 |
+ size_t maxwidth = tty_getwidth(tty); |
|
| 44 |
+ |
|
| 45 |
+ if (flag_show_scores) |
|
| 46 |
+ tty_printf(tty, "(%5.2f) ", score); |
|
| 47 |
+ |
|
| 48 |
+ if (selected) |
|
| 49 |
+ tty_setinvert(tty); |
|
| 50 |
+ |
|
| 51 |
+ for (size_t i = 0, p = 0; choice[i] != '\0'; i++) {
|
|
| 52 |
+ if (i + 1 < maxwidth) {
|
|
| 53 |
+ if (positions[p] == i) {
|
|
| 54 |
+ tty_setfg(tty, TTY_COLOR_HIGHLIGHT); |
|
| 55 |
+ p++; |
|
| 56 |
+ } else {
|
|
| 57 |
+ tty_setfg(tty, TTY_COLOR_NORMAL); |
|
| 58 |
+ } |
|
| 59 |
+ tty_printf(tty, "%c", choice[i]); |
|
| 60 |
+ } else {
|
|
| 61 |
+ tty_printf(tty, "$"); |
|
| 62 |
+ break; |
|
| 63 |
+ } |
|
| 64 |
+ } |
|
| 65 |
+ tty_setnormal(tty); |
|
| 66 |
+} |
|
| 67 |
+ |
|
| 68 |
+static void draw(tty_t *tty, choices_t *choices) {
|
|
| 69 |
+ size_t start = 0; |
|
| 70 |
+ size_t current_selection = choices->selection; |
|
| 71 |
+ if (current_selection + scrolloff >= num_lines) {
|
|
| 72 |
+ start = current_selection + scrolloff - num_lines + 1; |
|
| 73 |
+ if (start + num_lines >= choices_available(choices)) {
|
|
| 74 |
+ start = choices_available(choices) - num_lines; |
|
| 75 |
+ } |
|
| 76 |
+ } |
|
| 77 |
+ tty_setcol(tty, 0); |
|
| 78 |
+ tty_printf(tty, "%s%s", prompt, search); |
|
| 79 |
+ tty_clearline(tty); |
|
| 80 |
+ for (size_t i = start; i < start + num_lines; i++) {
|
|
| 81 |
+ tty_printf(tty, "\n"); |
|
| 82 |
+ tty_clearline(tty); |
|
| 83 |
+ const char *choice = choices_get(choices, i); |
|
| 84 |
+ if (choice) {
|
|
| 85 |
+ draw_match(tty, choice, i == choices->selection); |
|
| 86 |
+ } |
|
| 87 |
+ } |
|
| 88 |
+ tty_moveup(tty, num_lines); |
|
| 89 |
+ tty_setcol(tty, strlen(prompt) + strlen(search)); |
|
| 90 |
+ tty_flush(tty); |
|
| 91 |
+} |
|
| 92 |
+ |
|
| 93 |
+static void emit(choices_t *choices) {
|
|
| 94 |
+ const char *selection = choices_get(choices, choices->selection); |
|
| 95 |
+ if (selection) {
|
|
| 96 |
+ /* output the selected result */ |
|
| 97 |
+ printf("%s\n", selection);
|
|
| 98 |
+ } else {
|
|
| 99 |
+ /* No match, output the query instead */ |
|
| 100 |
+ printf("%s\n", search);
|
|
| 101 |
+ } |
|
| 102 |
+} |
|
| 103 |
+ |
|
| 104 |
+#define KEY_CTRL(key) ((key) - ('@'))
|
|
| 105 |
+#define KEY_DEL 127 |
|
| 106 |
+#define KEY_ESC 27 |
|
| 107 |
+ |
|
| 108 |
+static void run(tty_t *tty, choices_t *choices) {
|
|
| 109 |
+ choices_search(choices, search); |
|
| 110 |
+ char ch; |
|
| 111 |
+ do {
|
|
| 112 |
+ draw(tty, choices); |
|
| 113 |
+ ch = tty_getchar(tty); |
|
| 114 |
+ size_t search_size = strlen(search); |
|
| 115 |
+ if (isprint(ch)) {
|
|
| 116 |
+ if (search_size < SEARCH_SIZE_MAX) {
|
|
| 117 |
+ search[search_size++] = ch; |
|
| 118 |
+ search[search_size] = '\0'; |
|
| 119 |
+ choices_search(choices, search); |
|
| 120 |
+ } |
|
| 121 |
+ } else if (ch == KEY_DEL || ch == KEY_CTRL('H')) { /* DEL || Backspace (C-H) */
|
|
| 122 |
+ if (search_size) |
|
| 123 |
+ search[--search_size] = '\0'; |
|
| 124 |
+ choices_search(choices, search); |
|
| 125 |
+ } else if (ch == KEY_CTRL('U')) { /* C-U */
|
|
| 126 |
+ search_size = 0; |
|
| 127 |
+ search[0] = '\0'; |
|
| 128 |
+ choices_search(choices, search); |
|
| 129 |
+ } else if (ch == KEY_CTRL('W')) { /* C-W */
|
|
| 130 |
+ if (search_size) |
|
| 131 |
+ search[--search_size] = '\0'; |
|
| 132 |
+ while (search_size && !isspace(search[--search_size])) |
|
| 133 |
+ search[search_size] = '\0'; |
|
| 134 |
+ choices_search(choices, search); |
|
| 135 |
+ } else if (ch == KEY_CTRL('N')) { /* C-N */
|
|
| 136 |
+ choices_next(choices); |
|
| 137 |
+ } else if (ch == KEY_CTRL('P')) { /* C-P */
|
|
| 138 |
+ choices_prev(choices); |
|
| 139 |
+ } else if (ch == KEY_CTRL('I')) { /* TAB (C-I) */
|
|
| 140 |
+ strncpy(search, choices_get(choices, choices->selection), SEARCH_SIZE_MAX); |
|
| 141 |
+ choices_search(choices, search); |
|
| 142 |
+ } else if (ch == KEY_CTRL('C') || ch == KEY_CTRL('D')) { /* ^C || ^D */
|
|
| 143 |
+ clear(tty); |
|
| 144 |
+ tty_close(tty); |
|
| 145 |
+ exit(EXIT_FAILURE); |
|
| 146 |
+ } else if (ch == KEY_CTRL('M')) { /* CR */
|
|
| 147 |
+ clear(tty); |
|
| 148 |
+ |
|
| 149 |
+ /* ttyout should be flushed before outputting on stdout */ |
|
| 150 |
+ tty_close(tty); |
|
| 151 |
+ |
|
| 152 |
+ emit(choices); |
|
| 153 |
+ |
|
| 154 |
+ /* Return to eventually exit successfully */ |
|
| 155 |
+ return; |
|
| 156 |
+ } else if (ch == KEY_ESC) { /* ESC */
|
|
| 157 |
+ ch = tty_getchar(tty); |
|
| 158 |
+ if (ch == '[' || ch == 'O') {
|
|
| 159 |
+ ch = tty_getchar(tty); |
|
| 160 |
+ if (ch == 'A') { /* UP ARROW */
|
|
| 161 |
+ choices_prev(choices); |
|
| 162 |
+ } else if (ch == 'B') { /* DOWN ARROW */
|
|
| 163 |
+ choices_next(choices); |
|
| 164 |
+ } |
|
| 165 |
+ } |
|
| 166 |
+ } |
|
| 167 |
+ } while (1); |
|
| 168 |
+} |
|
| 169 |
+ |
|
| 170 |
+static const char *usage_str = |
|
| 171 |
+ "" |
|
| 172 |
+ "Usage: fzy [OPTION]...\n" |
|
| 173 |
+ " -l, --lines=LINES Specify how many lines of results to show (default 10)\n" |
|
| 174 |
+ " -p, --prompt=PROMPT Input prompt (default '> ')\n" |
|
| 175 |
+ " -q, --query=QUERY Use QUERY as the initial search string\n" |
|
| 176 |
+ " -e, --show-matches=QUERY Output the sorted matches of QUERY\n" |
|
| 177 |
+ " -t, --tty=TTY Specify file to use as TTY device (default /dev/tty)\n" |
|
| 178 |
+ " -s, --show-scores Show the scores of each match\n" |
|
| 179 |
+ " -h, --help Display this help and exit\n" |
|
| 180 |
+ " -v, --version Output version information and exit\n"; |
|
| 181 |
+ |
|
| 182 |
+static void usage(const char *argv0) {
|
|
| 183 |
+ fprintf(stderr, usage_str, argv0); |
|
| 184 |
+} |
|
| 185 |
+ |
|
| 186 |
+static struct option longopts[] = {{"show-matches", required_argument, NULL, 'e'},
|
|
| 187 |
+ {"query", required_argument, NULL, 'q'},
|
|
| 188 |
+ {"lines", required_argument, NULL, 'l'},
|
|
| 189 |
+ {"tty", required_argument, NULL, 't'},
|
|
| 190 |
+ {"prompt", required_argument, NULL, 'p'},
|
|
| 191 |
+ {"show-scores", no_argument, NULL, 's'},
|
|
| 192 |
+ {"version", no_argument, NULL, 'v'},
|
|
| 193 |
+ {"benchmark", optional_argument, NULL, 'b'},
|
|
| 194 |
+ {"help", no_argument, NULL, 'h'},
|
|
| 195 |
+ {NULL, 0, NULL, 0}};
|
|
| 196 |
+ |
|
| 197 |
+int main(int argc, char *argv[]) {
|
|
| 198 |
+ int benchmark = 0; |
|
| 199 |
+ const char *filter = NULL; |
|
| 200 |
+ const char *tty_filename = "/dev/tty"; |
|
| 201 |
+ char c; |
|
| 202 |
+ while ((c = getopt_long(argc, argv, "vhse:q:l:t:p:", longopts, NULL)) != -1) {
|
|
| 203 |
+ switch (c) {
|
|
| 204 |
+ case 'v': |
|
| 205 |
+ printf("%s " VERSION " (c) 2014 John Hawthorn\n", argv[0]);
|
|
| 206 |
+ exit(EXIT_SUCCESS); |
|
| 207 |
+ case 's': |
|
| 208 |
+ flag_show_scores = 1; |
|
| 209 |
+ break; |
|
| 210 |
+ case 'q': |
|
| 211 |
+ strncpy(search, optarg, SEARCH_SIZE_MAX); |
|
| 212 |
+ break; |
|
| 213 |
+ case 'e': |
|
| 214 |
+ filter = optarg; |
|
| 215 |
+ break; |
|
| 216 |
+ case 'b': |
|
| 217 |
+ if (optarg) {
|
|
| 218 |
+ if (sscanf(optarg, "%d", &benchmark) != 1) {
|
|
| 219 |
+ usage(argv[0]); |
|
| 220 |
+ exit(EXIT_FAILURE); |
|
| 221 |
+ } |
|
| 222 |
+ } else {
|
|
| 223 |
+ benchmark = 100; |
|
| 224 |
+ } |
|
| 225 |
+ break; |
|
| 226 |
+ case 't': |
|
| 227 |
+ tty_filename = optarg; |
|
| 228 |
+ break; |
|
| 229 |
+ case 'p': |
|
| 230 |
+ prompt = optarg; |
|
| 231 |
+ break; |
|
| 232 |
+ case 'l': {
|
|
| 233 |
+ int l; |
|
| 234 |
+ if (!strcmp(optarg, "max")) {
|
|
| 235 |
+ l = INT_MAX; |
|
| 236 |
+ } else if (sscanf(optarg, "%d", &l) != 1 || l < 3) {
|
|
| 237 |
+ fprintf(stderr, "Invalid format for --lines: %s\n", optarg); |
|
| 238 |
+ fprintf(stderr, "Must be integer in range 3..\n"); |
|
| 239 |
+ usage(argv[0]); |
|
| 240 |
+ exit(EXIT_FAILURE); |
|
| 241 |
+ } |
|
| 242 |
+ num_lines = l; |
|
| 243 |
+ } break; |
|
| 244 |
+ case 'h': |
|
| 245 |
+ default: |
|
| 246 |
+ usage(argv[0]); |
|
| 247 |
+ exit(EXIT_SUCCESS); |
|
| 248 |
+ } |
|
| 249 |
+ } |
|
| 250 |
+ if (optind != argc) {
|
|
| 251 |
+ usage(argv[0]); |
|
| 252 |
+ exit(EXIT_FAILURE); |
|
| 253 |
+ } |
|
| 254 |
+ |
|
| 255 |
+ choices_t choices; |
|
| 256 |
+ choices_init(&choices); |
|
| 257 |
+ choices_fread(&choices, stdin); |
|
| 258 |
+ |
|
| 259 |
+ if (benchmark) {
|
|
| 260 |
+ if (!filter) {
|
|
| 261 |
+ fprintf(stderr, "Must specify -e/--show-matches with --benchmark\n"); |
|
| 262 |
+ exit(EXIT_FAILURE); |
|
| 263 |
+ } |
|
| 264 |
+ for (int i = 0; i < benchmark; i++) |
|
| 265 |
+ choices_search(&choices, filter); |
|
| 266 |
+ } else if (filter) {
|
|
| 267 |
+ choices_search(&choices, filter); |
|
| 268 |
+ for (size_t i = 0; i < choices_available(&choices); i++) {
|
|
| 269 |
+ if (flag_show_scores) |
|
| 270 |
+ printf("%f\t", choices_getscore(&choices, i));
|
|
| 271 |
+ printf("%s\n", choices_get(&choices, i));
|
|
| 272 |
+ } |
|
| 273 |
+ } else {
|
|
| 274 |
+ /* interactive */ |
|
| 275 |
+ tty_t tty; |
|
| 276 |
+ tty_init(&tty, tty_filename); |
|
| 277 |
+ |
|
| 278 |
+ if (num_lines > choices.size) |
|
| 279 |
+ num_lines = choices.size; |
|
| 280 |
+ |
|
| 281 |
+ if (num_lines + 1 > tty_getheight(&tty)) |
|
| 282 |
+ num_lines = tty_getheight(&tty) - 1; |
|
| 283 |
+ |
|
| 284 |
+ run(&tty, &choices); |
|
| 285 |
+ } |
|
| 286 |
+ |
|
| 287 |
+ choices_destroy(&choices); |
|
| 288 |
+ |
|
| 289 |
+ return 0; |
|
| 290 |
+} |