added -s option - 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 173b8e981c29a274af7398f08c76b9e07562e6de
(DIR) parent f85d89ea704e25328a41b5c4ba3d115d1c997131
(HTM) 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))