summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hawthorn <john.hawthorn@gmail.com>2016-06-19 23:08:00 -0700
committerJohn Hawthorn <john.hawthorn@gmail.com>2016-06-19 23:08:00 -0700
commit52f091dfd559ba6f4ad9ddeb40411423c4914cd4 (patch)
tree4de7747cda29f1408feb0fa28d4a745b0a6917fa /src
parentfbf5f7a2d388a1fe9f4f8386e5db006bd7acf8c6 (diff)
Extract tty interface to own file
Diffstat (limited to 'src')
-rw-r--r--src/fzy.c156
-rw-r--r--src/tty_interface.c160
-rw-r--r--src/tty_interface.h12
3 files changed, 174 insertions, 154 deletions
diff --git a/src/fzy.c b/src/fzy.c
index ef4a0de..544afbe 100644
--- a/src/fzy.c
+++ b/src/fzy.c
@@ -8,161 +8,12 @@
#include "tty.h"
#include "choices.h"
#include "options.h"
+#include "tty_interface.h"
#include "../config.h"
options_t options;
-#define SEARCH_SIZE_MAX 4096
-static char search[SEARCH_SIZE_MAX + 1] = {0};
-
-static void clear(tty_t *tty, options_t *options) {
- tty_setcol(tty, 0);
- size_t line = 0;
- while (line++ < options->num_lines) {
- tty_newline(tty);
- }
- tty_clearline(tty);
- tty_moveup(tty, line - 1);
- tty_flush(tty);
-}
-
-static void draw_match(tty_t *tty, const char *choice, int selected, options_t *options) {
- int n = strlen(search);
- size_t positions[n + 1];
- for (int i = 0; i < n + 1; i++)
- positions[i] = -1;
-
- double score = match_positions(search, choice, &positions[0]);
-
- size_t maxwidth = tty_getwidth(tty);
-
- if (options->show_scores)
- tty_printf(tty, "(%5.2f) ", score);
-
- if (selected)
- tty_setinvert(tty);
-
- for (size_t i = 0, p = 0; choice[i] != '\0'; i++) {
- if (i + 1 < maxwidth) {
- if (positions[p] == i) {
- tty_setfg(tty, TTY_COLOR_HIGHLIGHT);
- p++;
- } else {
- tty_setfg(tty, TTY_COLOR_NORMAL);
- }
- tty_printf(tty, "%c", choice[i]);
- } else {
- tty_printf(tty, "$");
- break;
- }
- }
- tty_setnormal(tty);
-}
-
-static void draw(tty_t *tty, choices_t *choices, options_t *options) {
- unsigned int num_lines = options->num_lines;
- size_t start = 0;
- size_t current_selection = choices->selection;
- if (current_selection + options->scrolloff >= num_lines) {
- start = current_selection + options->scrolloff - num_lines + 1;
- if (start + num_lines >= choices_available(choices)) {
- start = choices_available(choices) - num_lines;
- }
- }
- tty_setcol(tty, 0);
- tty_printf(tty, "%s%s", options->prompt, search);
- tty_clearline(tty);
- for (size_t i = start; i < start + num_lines; i++) {
- tty_printf(tty, "\n");
- tty_clearline(tty);
- const char *choice = choices_get(choices, i);
- if (choice) {
- draw_match(tty, choice, i == choices->selection, options);
- }
- }
- tty_moveup(tty, num_lines);
- tty_setcol(tty, strlen(options->prompt) + strlen(search));
- tty_flush(tty);
-}
-
-static void emit(choices_t *choices) {
- const char *selection = choices_get(choices, choices->selection);
- if (selection) {
- /* output the selected result */
- printf("%s\n", selection);
- } else {
- /* No match, output the query instead */
- printf("%s\n", search);
- }
-}
-
-#define KEY_CTRL(key) ((key) - ('@'))
-#define KEY_DEL 127
-#define KEY_ESC 27
-
-static void run(tty_t *tty, choices_t *choices, options_t *options) {
- choices_search(choices, search);
- char ch;
- do {
- draw(tty, choices, options);
- ch = tty_getchar(tty);
- size_t search_size = strlen(search);
- if (isprint(ch)) {
- if (search_size < SEARCH_SIZE_MAX) {
- search[search_size++] = ch;
- search[search_size] = '\0';
- choices_search(choices, search);
- }
- } else if (ch == KEY_DEL || ch == KEY_CTRL('H')) { /* DEL || Backspace (C-H) */
- if (search_size)
- search[--search_size] = '\0';
- choices_search(choices, search);
- } else if (ch == KEY_CTRL('U')) { /* C-U */
- search_size = 0;
- search[0] = '\0';
- choices_search(choices, search);
- } else if (ch == KEY_CTRL('W')) { /* C-W */
- if (search_size)
- search[--search_size] = '\0';
- while (search_size && !isspace(search[--search_size]))
- search[search_size] = '\0';
- choices_search(choices, search);
- } else if (ch == KEY_CTRL('N')) { /* C-N */
- choices_next(choices);
- } else if (ch == KEY_CTRL('P')) { /* C-P */
- choices_prev(choices);
- } else if (ch == KEY_CTRL('I')) { /* TAB (C-I) */
- strncpy(search, choices_get(choices, choices->selection), SEARCH_SIZE_MAX);
- choices_search(choices, search);
- } else if (ch == KEY_CTRL('C') || ch == KEY_CTRL('D')) { /* ^C || ^D */
- clear(tty, options);
- tty_close(tty);
- exit(EXIT_FAILURE);
- } else if (ch == KEY_CTRL('M')) { /* CR */
- clear(tty, options);
-
- /* ttyout should be flushed before outputting on stdout */
- tty_close(tty);
-
- emit(choices);
-
- /* Return to eventually exit successfully */
- return;
- } else if (ch == KEY_ESC) { /* ESC */
- ch = tty_getchar(tty);
- if (ch == '[' || ch == 'O') {
- ch = tty_getchar(tty);
- if (ch == 'A') { /* UP ARROW */
- choices_prev(choices);
- } else if (ch == 'B') { /* DOWN ARROW */
- choices_next(choices);
- }
- }
- }
- } while (1);
-}
-
int main(int argc, char *argv[]) {
options_parse(&options, argc, argv);
@@ -195,10 +46,7 @@ int main(int argc, char *argv[]) {
if (options.num_lines + 1 > tty_getheight(&tty))
options.num_lines = tty_getheight(&tty) - 1;
- if (options.init_search)
- strncpy(search, options.init_search, SEARCH_SIZE_MAX);
-
- run(&tty, &choices, &options);
+ tty_interface_run(&tty, &choices, &options);
}
choices_destroy(&choices);
diff --git a/src/tty_interface.c b/src/tty_interface.c
new file mode 100644
index 0000000..69c3ab1
--- /dev/null
+++ b/src/tty_interface.c
@@ -0,0 +1,160 @@
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "match.h"
+#include "tty_interface.h"
+#include "../config.h"
+
+static char search[SEARCH_SIZE_MAX + 1];
+
+static void clear(tty_t *tty, options_t *options) {
+ tty_setcol(tty, 0);
+ size_t line = 0;
+ while (line++ < options->num_lines) {
+ tty_newline(tty);
+ }
+ tty_clearline(tty);
+ tty_moveup(tty, line - 1);
+ tty_flush(tty);
+}
+
+static void draw_match(tty_t *tty, const char *choice, int selected, options_t *options) {
+ int n = strlen(search);
+ size_t positions[n + 1];
+ for (int i = 0; i < n + 1; i++)
+ positions[i] = -1;
+
+ double score = match_positions(search, choice, &positions[0]);
+
+ size_t maxwidth = tty_getwidth(tty);
+
+ if (options->show_scores)
+ tty_printf(tty, "(%5.2f) ", score);
+
+ if (selected)
+ tty_setinvert(tty);
+
+ for (size_t i = 0, p = 0; choice[i] != '\0'; i++) {
+ if (i + 1 < maxwidth) {
+ if (positions[p] == i) {
+ tty_setfg(tty, TTY_COLOR_HIGHLIGHT);
+ p++;
+ } else {
+ tty_setfg(tty, TTY_COLOR_NORMAL);
+ }
+ tty_printf(tty, "%c", choice[i]);
+ } else {
+ tty_printf(tty, "$");
+ break;
+ }
+ }
+ tty_setnormal(tty);
+}
+
+static void draw(tty_t *tty, choices_t *choices, options_t *options) {
+ unsigned int num_lines = options->num_lines;
+ size_t start = 0;
+ size_t current_selection = choices->selection;
+ if (current_selection + options->scrolloff >= num_lines) {
+ start = current_selection + options->scrolloff - num_lines + 1;
+ if (start + num_lines >= choices_available(choices)) {
+ start = choices_available(choices) - num_lines;
+ }
+ }
+ tty_setcol(tty, 0);
+ tty_printf(tty, "%s%s", options->prompt, search);
+ tty_clearline(tty);
+ for (size_t i = start; i < start + num_lines; i++) {
+ tty_printf(tty, "\n");
+ tty_clearline(tty);
+ const char *choice = choices_get(choices, i);
+ if (choice) {
+ draw_match(tty, choice, i == choices->selection, options);
+ }
+ }
+ tty_moveup(tty, num_lines);
+ tty_setcol(tty, strlen(options->prompt) + strlen(search));
+ tty_flush(tty);
+}
+
+static void emit(choices_t *choices) {
+ const char *selection = choices_get(choices, choices->selection);
+ if (selection) {
+ /* output the selected result */
+ printf("%s\n", selection);
+ } else {
+ /* No match, output the query instead */
+ printf("%s\n", search);
+ }
+}
+
+#define KEY_CTRL(key) ((key) - ('@'))
+#define KEY_DEL 127
+#define KEY_ESC 27
+
+void tty_interface_run(tty_t *tty, choices_t *choices, options_t *options) {
+ if (options->init_search)
+ strncpy(search, options->init_search, SEARCH_SIZE_MAX);
+
+ choices_search(choices, search);
+ char ch;
+ do {
+ draw(tty, choices, options);
+ ch = tty_getchar(tty);
+ size_t search_size = strlen(search);
+ if (isprint(ch)) {
+ if (search_size < SEARCH_SIZE_MAX) {
+ search[search_size++] = ch;
+ search[search_size] = '\0';
+ choices_search(choices, search);
+ }
+ } else if (ch == KEY_DEL || ch == KEY_CTRL('H')) { /* DEL || Backspace (C-H) */
+ if (search_size)
+ search[--search_size] = '\0';
+ choices_search(choices, search);
+ } else if (ch == KEY_CTRL('U')) { /* C-U */
+ search_size = 0;
+ search[0] = '\0';
+ choices_search(choices, search);
+ } else if (ch == KEY_CTRL('W')) { /* C-W */
+ if (search_size)
+ search[--search_size] = '\0';
+ while (search_size && !isspace(search[--search_size]))
+ search[search_size] = '\0';
+ choices_search(choices, search);
+ } else if (ch == KEY_CTRL('N')) { /* C-N */
+ choices_next(choices);
+ } else if (ch == KEY_CTRL('P')) { /* C-P */
+ choices_prev(choices);
+ } else if (ch == KEY_CTRL('I')) { /* TAB (C-I) */
+ strncpy(search, choices_get(choices, choices->selection), SEARCH_SIZE_MAX);
+ choices_search(choices, search);
+ } else if (ch == KEY_CTRL('C') || ch == KEY_CTRL('D')) { /* ^C || ^D */
+ clear(tty, options);
+ tty_close(tty);
+ exit(EXIT_FAILURE);
+ } else if (ch == KEY_CTRL('M')) { /* CR */
+ clear(tty, options);
+
+ /* ttyout should be flushed before outputting on stdout */
+ tty_close(tty);
+
+ emit(choices);
+
+ /* Return to eventually exit successfully */
+ return;
+ } else if (ch == KEY_ESC) { /* ESC */
+ ch = tty_getchar(tty);
+ if (ch == '[' || ch == 'O') {
+ ch = tty_getchar(tty);
+ if (ch == 'A') { /* UP ARROW */
+ choices_prev(choices);
+ } else if (ch == 'B') { /* DOWN ARROW */
+ choices_next(choices);
+ }
+ }
+ }
+ } while (1);
+}
diff --git a/src/tty_interface.h b/src/tty_interface.h
new file mode 100644
index 0000000..e1240c3
--- /dev/null
+++ b/src/tty_interface.h
@@ -0,0 +1,12 @@
+#ifndef TTY_INTERFACE_H
+#define TTY_INTERFACE_H TTY_INTERFACE_H
+
+#include "choices.h"
+#include "options.h"
+#include "tty.h"
+
+#define SEARCH_SIZE_MAX 4096
+
+void tty_interface_run(tty_t *tty, choices_t *choices, options_t *options);
+
+#endif