cleaner page next/prev and global window dimension property - iomenu - interactive terminal-based selection menu
(HTM) git clone git://bitreich.org/iomenu git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/iomenu
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) Tags
(DIR) README
(DIR) LICENSE
---
(DIR) commit 62853eb76762d6adfac4bd5cbcc410e96ebc955f
(DIR) parent a74019ac53549e4017a2aa36bd377c1e0c2c9fc7
(HTM) Author: Josuah Demangeonā ā µ <mail@josuah.net>
Date: Sun, 19 Mar 2017 11:49:25 +0100
cleaner page next/prev and global window dimension property
Diffstat:
M iomenu.c | 199 ++++++++++++++++---------------
1 file changed, 103 insertions(+), 96 deletions(-)
---
(DIR) diff --git a/iomenu.c b/iomenu.c
@@ -17,15 +17,18 @@
#define MAX(X, Y) (((X) > (Y)) ? (X) : (Y))
-char input[BUFSIZ];
-int current = 0, offset = 0, prev = 0, next = 0;
-int linec = 0, matchc = 0;
-char **linev = NULL, **matchv = NULL;
-char *opt_prompt = "";
-int opt_lines = 0;
+static struct winsize winsize;
+static struct termios termios;
+static char input[BUFSIZ];
+static int current = 0, offset = 0, prev = 0, next = 0;
+static int linec = 0, matchc = 0;
+static char **linev = NULL, **matchv = NULL;
+static char *opt_prompt = "";
+static int opt_lines = 0;
-void
+
+static void
free_v(char **v, int c)
{
for (; c > 0; c--)
@@ -35,7 +38,7 @@ free_v(char **v, int c)
}
-void
+static void
die(const char *s)
{
/* tcsetattr(STDIN_FILENO, TCSANOW, &termio_old); */
@@ -44,25 +47,21 @@ die(const char *s)
}
-struct termios
+static void
set_terminal(int tty_fd)
{
- struct termios termio_old;
- struct termios termio_new;
-
- if (tcgetattr(tty_fd, &termio_old) < 0)
- die("Can not get terminal attributes with tcgetattr().");
-
- termio_new = termio_old;
- termio_new.c_lflag &= ~(ICANON | ECHO | IGNBRK);
+ if (tcgetattr(tty_fd, &termios) < 0) {
+ perror("tcgetattr");
+ exit(EXIT_FAILURE);
+ }
- tcsetattr(tty_fd, TCSANOW, &termio_new);
+ termios.c_lflag &= ~(ICANON | ECHO | IGNBRK);
- return termio_old;
+ tcsetattr(tty_fd, TCSANOW, &termios);
}
-void
+static void
read_lines(void)
{
char buffer[BUFSIZ];
@@ -99,7 +98,7 @@ read_lines(void)
}
-int
+static int
match_line(char *line, char **tokv, int tokc)
{
for (int i = 0; i < tokc; i++)
@@ -110,38 +109,7 @@ match_line(char *line, char **tokv, int tokc)
}
-void
-filter_lines(void)
-{
- char **tokv = NULL, *s, buffer[sizeof (input)];
- int tokc = 0, n = 0;
-
- current = offset = prev = next = 0;
-
- /* tokenize input from space characters, this comes from dmenu */
- strcpy(buffer, input);
- for (s = strtok(buffer, " "); s; s = strtok(NULL, " "), tokc++) {
-
- if (tokc >= n) {
- tokv = realloc(tokv, ++n * sizeof (*tokv));
-
- if (tokv == NULL)
- die("realloc");
- }
-
- tokv[tokc] = s;
- }
-
- matchc = 0;
- for (int i = 0; i < linec; i++)
- if (match_line(linev[i], tokv, tokc))
- matchv[matchc++] = linev[i];
-
- free(tokv);
-}
-
-
-void
+static void
print_string(char *str, int current)
{
fputs(current ? "\033[30;47m" : "", stderr);
@@ -150,8 +118,8 @@ print_string(char *str, int current)
}
-void
-print_lines(int count, int cols)
+static void
+print_lines(int count)
{
int p = 0; /* amount of lines printed */
offset = current / count * count;
@@ -166,86 +134,92 @@ print_lines(int count, int cols)
}
-void
-update_pages(int pos, int cols)
+static int
+prev_page(int pos, int cols)
{
- int col;
+ pos--;
+ for (int col = 0; pos > 0; pos--)
+ if ((col += strlen(matchv[pos]) + 2) > cols)
+ return pos + 1;
- for (prev = pos, col = 0; prev > 0; prev--)
- if ((col += strlen(matchv[prev]) + 2) > cols)
- break;
+ return pos;
+}
- for (next = pos, col = 0; next <= matchc; next++)
- if ((col += strlen(matchv[next]) + 2) > cols)
- break;
- next++;
- next--;
+static int
+next_page(int pos, int cols)
+{
+ for (int col = 0; pos < matchc; pos++)
+ if ((col += strlen(matchv[pos]) + 2) > cols)
+ return pos - 1;
+
+ return pos;
}
-void
-print_columns(int cols)
+static void
+print_columns(void)
{
if (current < offset) {
+ next = offset;
offset = prev;
- update_pages(offset, cols - 30 - 1);
+ prev = prev_page(offset, winsize.ws_col - 30 - 1);
} else if (current >= next) {
+ prev = offset;
offset = next;
- update_pages(offset, cols - 30 - 1);
+ next = next_page(offset, winsize.ws_col - 30 - 1);
}
+ fputs(offset > 0 ? "< " : " ", stderr);
+
for (int i = offset; i < next && i < matchc; i++)
print_string(matchv[i], i == current);
-
if (next < matchc)
- fprintf(stderr, "\033[%dC>", cols);
+ fprintf(stderr, "\033[%dC>", winsize.ws_col - 30);
}
-void
-print_prompt(int cols)
+static void
+print_prompt(void)
{
- int limit = opt_lines ? cols : 30;
+ int limit = opt_lines ? winsize.ws_col : 30 - 2;
fputc('\r', stderr);
- for (int i = 0; i < limit - 2; i++)
+ for (int i = 0; i < limit; i++)
fputc(' ', stderr);
- fputs(offset > 0 ? "< " : " ", stderr);
-
fprintf(stderr, "\r%s %s", opt_prompt, input);
}
-void
+static void
print_screen(int tty_fd)
{
- struct winsize w;
int count;
- if (ioctl(tty_fd, TIOCGWINSZ, &w) < 0)
- die("could not get terminal size");
+ if (ioctl(tty_fd, TIOCGWINSZ, &winsize) < 0)
+ die("ioctl");
- count = MIN(opt_lines, w.ws_row - 2);
+ count = MIN(opt_lines, winsize.ws_row - 2);
fputs("\r\033[K", stderr);
if (opt_lines) {
- print_lines(count, w.ws_col);
+ print_lines(count);
fprintf(stderr, "\033[%dA", count + 1);
+
} else {
fputs("\033[30C", stderr);
- print_columns(w.ws_col);
+ print_columns();
}
- print_prompt(w.ws_col);
+ print_prompt();
}
-void
+static void
print_clear(int lines)
{
for (int i = 0; i < lines + 1; i++)
@@ -254,7 +228,40 @@ print_clear(int lines)
}
-void
+static void
+filter_lines(void)
+{
+ char **tokv = NULL, *s, buffer[sizeof (input)];
+ int tokc = 0, n = 0;
+
+ current = offset = prev = next = 0;
+
+ strcpy(buffer, input);
+
+ for (s = strtok(buffer, " "); s; s = strtok(NULL, " "), tokc++) {
+
+ if (tokc >= n) {
+ tokv = realloc(tokv, ++n * sizeof (*tokv));
+
+ if (tokv == NULL)
+ die("realloc");
+ }
+
+ tokv[tokc] = s;
+ }
+
+ matchc = 0;
+ for (int i = 0; i < linec; i++)
+ if (match_line(linev[i], tokv, tokc))
+ matchv[matchc++] = linev[i];
+
+ free(tokv);
+
+ next = next_page(0, winsize.ws_col - 30 - 1);
+}
+
+
+static void
remove_word_input()
{
int len = strlen(input) - 1;
@@ -270,7 +277,7 @@ remove_word_input()
}
-void
+static void
add_character(char key)
{
int len = strlen(input);
@@ -287,7 +294,7 @@ add_character(char key)
/*
* Send the selection to stdout.
*/
-void
+static void
print_selection(void)
{
fputs("\r\033[K", stderr);
@@ -303,7 +310,7 @@ print_selection(void)
/*
* Perform action associated with key
*/
-int
+static int
input_key(FILE *tty_fp)
{
char key = fgetc(tty_fp);
@@ -359,20 +366,20 @@ input_key(FILE *tty_fp)
/*
* Listen for the user input and call the appropriate functions.
*/
-int
+static int
input_get(int tty_fd)
{
FILE *tty_fp = fopen("/dev/tty", "r");
int exit_code;
- struct termios termio_old = set_terminal(tty_fd);
input[0] = '\0';
+ set_terminal(tty_fd);
+
while ((exit_code = input_key(tty_fp)) == CONTINUE)
print_screen(tty_fd);
- /* resets the terminal to the previous state. */
- tcsetattr(tty_fd, TCSANOW, &termio_old);
+ set_terminal(tty_fd);
fclose(tty_fp);
@@ -380,7 +387,7 @@ input_get(int tty_fd)
}
-void
+static void
usage(void)
{
fputs("usage: iomenu [-l lines] [-p prompt]\n", stderr);