URI: 
       added -s option - iomenu - interactive terminal-based selection menu
  HTML git clone git://bitreich.org/iomenu git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/iomenu
   DIR Log
   DIR Files
   DIR Refs
   DIR Tags
   DIR README
   DIR LICENSE
       ---
   DIR commit 173b8e981c29a274af7398f08c76b9e07562e6de
   DIR parent f85d89ea704e25328a41b5c4ba3d115d1c997131
  HTML Author: Josuah Demangeon <mail@josuah.net>
       Date:   Tue, 11 Apr 2017 23:51:22 +0200
       
       added -s option
       
       Diffstat:
         M iomenu.1                            |      47 +++++++++++++++++++++++++++++--
         M iomenu.c                            |      65 +++++++++++++++++++++++++------
       
       2 files changed, 99 insertions(+), 13 deletions(-)
       ---
   DIR diff --git a/iomenu.1 b/iomenu.1
       @@ -2,24 +2,33 @@
        .Dt IOMENU 1
        .Os
        .
       +.
        .Sh NAME
        .
       +.
        .Nm iomenu
        .Nd interactive selection menu
        .
       +.
        .Sh SYNOPSIS
        .
       +.
        .Nm
        .Op Fl l Ar lines
        .Op Fl p Ar prompt
        .Op Fl b
       +.Op Fl s
        .Op Fl t
        .
       +.
        .Sh DESCRIPTION
        .
       +.
        .Nm
        is an interactive filtering and selection tool for the terminal.
       +.
        .Pp
       +.
        It reads lines from standard input, and prompt for a selection.
        The selected line(s) is(are) printed to standard output.
        .Bl -tag -width XXXXXXXXXXXXXXXX
       @@ -39,8 +48,16 @@ lines.
        Set the prompt to display at the beginning of the input to
        .Ar prompt .
        .
       +.It Fl t
       +If a line starts with
       +.Li # ,
       +.Nm
       +will interprete it as a header, which always matches, and can not be
       +printed.
       +.
        .It Fl t / Fl b
       -Print the menu at the top / bottom rather than at current cursor position.
       +Print the menu at the top / bottom rather than at current cursor
       +position.
        Reset the cursor postition afterward.
        .El
        .
       @@ -82,56 +99,82 @@ Remove the whole input string.
        Fill the input with current selection.
        .El
        .
       +.
        .Sh EXIT STATUS
        .
       +.
        .Ex -std
        .
       +.
        .Sh EXAMPLES
        .
       +.
        Open a bookmark from a list in a text file:
       +.
        .Bd -literal -offset XX
        iomenu < bookmarks-urls.txt | xargs firefox
        .Ed
       +.
        .Pp
       +.
        Go to a subdirectory:
       +.
        .Bd -literal -offset XX
        cd "$(find . -type d | iomenu)"
        .Ed
       +.
        .Pp
       +.
        Edit a file located in
        .Ev HOME :
       +.
        .Bd -literal -offset XX
        EDITOR "$(find "$HOME" -type f | iomenu -l 255)"
        .Ed
       +.
        .Pp
       +.
        Play an audio file:
       +.
        .Bd -literal -offset XX
        mplayer "$(find ~/Music | iomenu)"
        .Ed
       +.
        .Pp
       +.
        Select a background job to attach to:
       +.
        .Bd -literal -offset XX
        fg "%$(jobs | iomenu | cut -c 2)"
        .Ed
       +.
        .Pp
       +.
        Filter "ps" output and print a process ID
       +.
        .Bd -literal -offset XX
       -ps ax | tail -n +2 | iomenu -l 255 | sed -r 's/ *([0-9]*).*/\1/'
       +{ printf '# '; ps ax; } | iomenu -l 255 -s | sed -r 's/ *([0-9]*).*/\1/'
        .Ed
        .
       +.
        .Sh SEE ALSO
        .
       +.
        .Xr dmenu 1 ,
        .Xr slmenu 1 ,
        .Xr vis-menu 1
        .
       +.
        .Sh BUGS
        .
       +.
        .Nm
        currently only support ASCII characters.
        .
       +.
        .Sh AUTORS
        .
       +.
        .Nm
        was written from scratch by
        .An Josuah Demangeon Aq Mt mail@josuah.net
   DIR diff --git a/iomenu.c b/iomenu.c
       @@ -17,7 +17,6 @@
        #define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
        #define MAX(X, Y) (((X) > (Y)) ? (X) : (Y))
        
       -
        static struct winsize ws;
        static struct termios termios;
        int   tty_fd;
       @@ -27,7 +26,7 @@ static int     linec = 0,      matchc = 0;
        static char  **linev = NULL, **matchv = NULL;
        static char    input[BUFSIZ], formatted[BUFSIZ * 8];
        static int     opt_l = 0, opt_tb = 0;
       -static char   *opt_p = "";
       +static char   *opt_p = "", opt_s = '\0';
        
        
        static void
       @@ -130,7 +129,7 @@ read_lines(void)
                                        die("realloc");
                        }
        
       -                linev[linec] = matchv[matchc] = malloc(len);
       +                linev[linec] = matchv[matchc] = malloc(len + 1);
                        if (linev[linec] == NULL)
                                die("malloc");
        
       @@ -165,8 +164,12 @@ format(char *str, int cols)
                        if (str[i] == '\t') {
                                for (int t = (j + 7) % 8 + 1; t > 0 && j < cols; t--)
                                        formatted[j++] = ' ';
       -                } else {
       +
       +                } else if (isprint(str[i])) {
                                formatted[j++] = str[i];
       +
       +                } else {
       +                        formatted[j++] = '?';
                        }
                }
        
       @@ -177,10 +180,17 @@ format(char *str, int cols)
        
        
        static void
       -print_string(char *str, int current)
       +print_string(char *str, int iscurrent)
        {
       -        fputs(current   ? "\033[30;47m" : "", stderr);
       +        extern int opt_l;
       +        extern char opt_s;
       +
       +        fputs(iscurrent ? "\033[30;47m" : "", stderr);
                fputs(opt_l ? "\033[K " : " ", stderr);
       +
       +        if (opt_s && str[0] == '#')
       +                fputs("\033[1;30m", stderr);
       +
                fputs(format(str, ws.ws_col - 2), stderr);
                fputs(" \033[m", stderr);
        }
       @@ -289,6 +299,9 @@ print_screen(void)
        static int
        match_line(char *line, char **tokv, int tokc)
        {
       +        if (opt_s && line[0] == opt_s)
       +                return 2;
       +
                for (int i = 0; i < tokc; i++)
                        if (strstr(line, tokv[i]) == NULL)
                                return 0;
       @@ -298,6 +311,21 @@ match_line(char *line, char **tokv, int tokc)
        
        
        static void
       +move_line(signed int count)
       +{
       +        extern int    current;
       +        extern char **matchv;
       +
       +        for (int i = current + count; 0 <= i && i < matchc; i += count) {
       +                if (!opt_s || matchv[i][0] != opt_s) {
       +                        current = i;
       +                        break;
       +                }
       +        }
       +}
       +
       +
       +static void
        filter_lines(void)
        {
                char **tokv = NULL, *s, buffer[sizeof (input)];
       @@ -325,6 +353,9 @@ filter_lines(void)
                                matchv[matchc++] = linev[i];
        
                free(tokv);
       +
       +        if (opt_s && matchv[current][0] == opt_s)
       +                move_line(+1);
        }
        
        
       @@ -361,9 +392,16 @@ add_character(char key)
        static void
        print_selection(void)
        {
       +        extern int    current;
       +        extern char **matchv, input[BUFSIZ];
       +
                fputs("\r\033[K", stderr);
       -        fputs(matchc > 0 ? matchv[current] : input, stdout);
       -        fputc('\n', stdout);
       +
       +        if (matchc == 0 || (opt_s && matchv[current][0] == opt_s)) {
       +                puts(input);
       +        } else {
       +                puts(matchv[current]);
       +        }
        }
        
        
       @@ -393,11 +431,11 @@ input_key(void)
                        break;
        
                case CONTROL('N'):
       -                current += current < matchc - 1 ? 1 : 0;
       +                move_line(+1);
                        break;
        
                case CONTROL('P'):
       -                current -= current > 0 ? 1 : 0;
       +                move_line(-1);
                        break;
        
                case CONTROL('I'):  /* tab */
       @@ -446,7 +484,7 @@ input_get(void)
        static void
        usage(void)
        {
       -        fputs("usage: iomenu [-b] [-t] [-l lines] [-p prompt]\n", stderr);
       +        fputs("usage: iomenu [-b] [-t] [-s] [-l lines] [-p prompt]\n", stderr);
        
                exit(EXIT_FAILURE);
        }
       @@ -478,6 +516,10 @@ main(int argc, char *argv[])
                                opt_p = argv[i];
                                break;
        
       +                case 's':
       +                        opt_s = '#';
       +                        break;
       +
                        default:
                                usage();
                        }
       @@ -485,6 +527,7 @@ main(int argc, char *argv[])
        
                setlocale(LC_ALL, "");
                read_lines();
       +        filter_lines();
        
                if (!freopen("/dev/tty", "r", stdin) ||
                    !freopen("/dev/tty", "w", stderr))