Added support for page up and down with Ctrl/Alt + v - 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 422bb3cf75123ac36aed39c370de89dfbe55dd78
 (DIR) parent e2db9fd49d5351986d5803604bed7e2680545621
 (HTM) Author: Josuah Demangeon <josuah.demangeon@gandi.net>
       Date:   Mon, 21 Aug 2017 09:04:18 +0200
       
       Added support for page up and down with Ctrl/Alt + v
       
       Diffstat:
         M README                              |      34 ++++++++++++++++++-------------
         M iomenu.1                            |      24 +++++++++++++++---------
         M iomenu.c                            |      51 +++++++++++++++++++------------
       
       3 files changed, 66 insertions(+), 43 deletions(-)
       ---
 (DIR) diff --git a/README b/README
       @@ -1,7 +1,7 @@
       -IOMENU(1)                   General Commands Manual                  IOMENU(1)
       +IOMENU(1)               FreeBSD General Commands Manual              IOMENU(1)
        
        NAME
       -     iomenu – interactive selection menu
       +     iomenu - interactive selection menu
        
        SYNOPSIS
             iomenu [-#] [-l lines] [-p prompt]
       @@ -22,28 +22,34 @@ DESCRIPTION
             -#                If a line starts with #, iomenu will interprete it as a
                               header, which always matches, and can not be printed.
        
       -   Selection control
       +   Selection keybindings
             An active selection is highlighted, and can be controlled with
             keybindings.
        
       -     ^P, ^N           Move selection to the previous/next item.
       +     Ctrl + p, Ctrl + n
       +                      Move selection to the previous/next item.
        
       -     ^M, ^J, Enter    Print the selection to the standard output, and exit 0.
       +     Ctrl + v Ns, Alt + v
       +                      Move one page up or down.
        
       -   Input handling
       -     As printable keys are entered, the selection is filtered to match every
       -     word from the input.
       +     Ctrl + m, Ctrl + j, Enter
       +                      Print the selection to the standard output, and exit 0.
        
       -     ^H, Bakcspace    Remove last character from current input.
       +Text input
       +     As printable keys are entered, the lines are filtered to match each word
       +     from the input.
        
       -     ^W               Remove last word from current input.
       +     Ctrl + h, Bakcspace
       +                      Remove last character from current input.
        
       -     ^U               Remove the whole input string.
       +     Ctrl + w         Remove last word from current input.
        
       -     ^I, Tab          Fill the input with current selection.
       +     Ctrl + u         Remove the whole input string.
       +
       +     Ctrl + i, Tab    Fill the input with current selection.
        
        EXIT STATUS
       -     The iomenu utility exits 0 on success, and >0 if an error occurs.
       +     The iomenu utility exits 0 on success, and >0 if an error occurs.
        
        EXAMPLES
             Open a bookmark from a list in a text file:
       @@ -80,4 +86,4 @@ AUTORS
             iomenu was written from scratch by Josuah Demangeon <mail@josuah.net>
             with the help of dmenu(1) and vis-menu(1) as models.
        
       -Void Linux                      August 21, 2017                     Void Linux
       +FreeBSD 11.0-RELEASE-p1         August 21, 2017        FreeBSD 11.0-RELEASE-p1
 (DIR) diff --git a/iomenu.1 b/iomenu.1
       @@ -54,36 +54,42 @@ will interprete it as a header, which always matches, and can not be
        printed.
        .
        .
       -.Ss Selection control
       +.Ss Selection keybindings
        .
        An active selection is highlighted, and can be controlled with keybindings.
        .Bl -tag -width XXXXXXXXXXXXXXX
        .
       -.It Ic ^P Ns , Ic ^N
       +.It Ic Ctrl + p Ns , Ic Ctrl + n
        Move selection to the previous/next item.
        .
       -.It Ic ^M Ns , Ic ^J Ns , Ic Enter
       +.It Ic Ctrl + v Ns, Ic Alt + v
       +Move one page up or down.
       +.
       +.It Ic Ctrl + m Ns , Ic Ctrl + j Ns , Ic Enter
        Print the selection to the standard output, and exit 0.
        .
        .El
        .
       -.Ss Input handling
        .
       -As printable keys are entered, the selection is filtered to match every
       +.Sh Text input
       +.
       +As printable keys are entered, the lines are filtered to match each
        word from the input.
       +.
        .Bl -tag -width XXXXXXXXXXXXXXX
        .
       -.It Ic ^H Ns , Ic Bakcspace
       +.It Ic Ctrl + h Ns , Ic Bakcspace
        Remove last character from current input.
        .
       -.It Ic ^W
       +.It Ic Ctrl + w
        Remove last word from current input.
        .
       -.It Ic ^U
       +.It Ic Ctrl + u
        Remove the whole input string.
        .
       -.It Ic ^I Ns , Ic Tab
       +.It Ic Ctrl + i Ns , Ic Tab
        Fill the input with current selection.
       +.
        .El
        .
        .
 (DIR) diff --git a/iomenu.c b/iomenu.c
       @@ -18,13 +18,13 @@
        
        static struct winsize ws;
        static struct termios termios;
       -static int    ttyfd;
       -static int    current = 0, offset = 0, prev = 0, next = 0;
       -static int    linec = 0,      matchc = 0;
       -static char **linev = NULL, **matchv = NULL;
       -static char   input[BUFSIZ], formatted[BUFSIZ * 8];
       -static int    opt[128];
       -static char  *prompt = "";
       +static int            ttyfd;
       +static int            current = 0, offset = 0, prev = 0, next = 0;
       +static int            linec = 0,      matchc = 0;
       +static char         **linev = NULL, **matchv = NULL;
       +static char           input[BUFSIZ], formatted[BUFSIZ * 8];
       +static int            opt[128], rows = 0;
       +static char          *prompt = "";
        
        static void
        freelines(void)
       @@ -145,11 +145,11 @@ format(char *str, int cols)
        }
        
        static void
       -printlines(int count)
       +printlines(void)
        {
       -        int printed = 0, i = current / count * count;
       +        int printed = 0, i = current - current % rows;
        
       -        while (printed < count && i < matchc) {
       +        while (printed < rows && i < matchc) {
        
                        char *s = format(matchv[i], ws.ws_col - 1);
        
       @@ -163,7 +163,7 @@ printlines(int count)
                        i++; printed++;
                }
        
       -        while (printed++ < count)
       +        while (printed++ < rows)
                        fputs("\n\033[K", stderr);
        }
        
       @@ -171,12 +171,11 @@ static void
        printscreen(void)
        {
                int cols = ws.ws_col - 1;
       -        int count = MIN(opt['l'], ws.ws_row - 1);
        
                fputs("\r\033[K", stderr);
        
       -        printlines(count);
       -        fprintf(stderr, "\033[%dA\r", count);
       +        printlines();
       +        fprintf(stderr, "\033[%dA\r", rows);
        
                if (*prompt) {
                        format(prompt, cols - 2);
       @@ -204,11 +203,11 @@ matchline(char *line, char **tokv, int tokc)
        }
        
        static void
       -move(signed int n)
       +move(signed int sign)
        {
                int i;
        
       -        for (i = current + n; 0 <= i && i < matchc; i += n) {
       +        for (i = current + sign; 0 <= i && i < matchc; i += sign) {
                        if (!opt['#'] || matchv[i][0] != '#') {
                                current = i;
                                break;
       @@ -217,6 +216,18 @@ move(signed int n)
        }
        
        static void
       +movepg(signed int sign)
       +{
       +        int i = current - current % rows + rows * sign;
       +
       +        if (0 > i || i > matchc)
       +                return;
       +
       +        current = i - 1;
       +        move(+1);
       +}
       +
       +static void
        filter(void)
        {
                char **tokv = NULL, *s, buffer[sizeof (input)];
       @@ -280,7 +291,6 @@ addchar(char key)
        static void
        printselection(void)
        {
       -        /* header */
                if (opt['#']) {
                        char **match = matchv + current;
        
       @@ -294,7 +304,6 @@ printselection(void)
                        putchar('\t');
                }
        
       -        /* input or selection */
                if (matchc == 0 || (opt['#'] && matchv[current][0] == '#')) {
                        puts(input);
                } else {
       @@ -339,11 +348,11 @@ top:
                        break;
        
                case CONTROL('V'):
       -                move(ws.ws_row - 1);
       +                movepg(+1);
                        break;
        
                case ALT('v'):
       -                move(-ws.ws_row + 1);
       +                movepg(-1);
                        break;
        
                case CONTROL('I'):  /* tab */
       @@ -373,6 +382,8 @@ sigwinch()
        {
                if (ioctl(ttyfd, TIOCGWINSZ, &ws) < 0)
                        die("ioctl");
       +
       +        rows = MIN(opt['l'], ws.ws_row - 1);
                printscreen();
        
                signal(SIGWINCH, sigwinch);