Removed breadline() and switched to use ask
when possible, defaulting
to `read` and `fzy`
This commit is contained in:
parent
470caf1d60
commit
32b414e555
13
Makefile
13
Makefile
@ -1,16 +1,21 @@
|
||||
PREFIX=
|
||||
CC=gcc
|
||||
CFLAGS=-O0 -std=gnu99 -D_XOPEN_SOURCE=500 -D_GNU_SOURCE -D_POSIX_C_SOURCE=200809L \
|
||||
-Wall -Wpedantic -Wno-unknown-pragmas -fsanitize=address -fno-omit-frame-pointer
|
||||
CFLAGS=-O0 -std=gnu99 -D_XOPEN_SOURCE=500 -D_GNU_SOURCE -D_POSIX_C_SOURCE=200809L
|
||||
CWARN= -Wall -Wpedantic -Wno-unknown-pragmas -fsanitize=address -fno-omit-frame-pointer
|
||||
UNAME := $(shell uname)
|
||||
ifeq ($(UNAME),Darwin)
|
||||
CFLAGS += -D_DARWIN_C_SOURCE -Weverything -Wno-missing-field-initializers -Wno-padded\
|
||||
CFLAGS += -D_DARWIN_C_SOURCE
|
||||
CWARN += -Weverything -Wno-missing-field-initializers -Wno-padded\
|
||||
-Wno-missing-noreturn -Wno-cast-qual
|
||||
endif
|
||||
LIBS=
|
||||
NAME=bb
|
||||
G=-g
|
||||
|
||||
ifneq (, $(shell which ask))
|
||||
CFLAGS += -D'ASKECHO(prompt)="ask \"" prompt "\""' -D'FUZZY(prompt)="ask \"" prompt "\""'
|
||||
endif
|
||||
|
||||
all: $(NAME)
|
||||
|
||||
clean:
|
||||
@ -20,7 +25,7 @@ config.h:
|
||||
cp config.def.h config.h
|
||||
|
||||
$(NAME): $(NAME).c bterm.h config.h
|
||||
$(CC) $(NAME).c $(LIBS) $(CFLAGS) $(G) -o $(NAME)
|
||||
$(CC) $(NAME).c $(LIBS) $(CFLAGS) $(CWARN) $(G) -o $(NAME)
|
||||
|
||||
install: $(NAME)
|
||||
@prefix="$(PREFIX)"; \
|
||||
|
12
bb.c
12
bb.c
@ -1411,18 +1411,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
int i;
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (argv[i][0] == '?') {
|
||||
if (cmdfd != -1)
|
||||
close(cmdfd);
|
||||
init_term();
|
||||
char *line = breadline(tty_in, tty_out, argv[i] + 1, argv[i+1]);
|
||||
close_term();
|
||||
if (!line) return 1;
|
||||
fputs(line, stdout);
|
||||
free(line);
|
||||
fflush(stdout);
|
||||
return 0;
|
||||
}
|
||||
if (argv[i][0] == '+') {
|
||||
write(cmdfd, argv[i]+1, strlen(argv[i]+1)+1);
|
||||
continue;
|
||||
|
125
bterm.h
125
bterm.h
@ -109,7 +109,6 @@
|
||||
|
||||
int bgetkey(FILE *in, int *mouse_x, int *mouse_y, int timeout);
|
||||
const char *bkeyname(int key);
|
||||
char *breadline(FILE *in, FILE *out, const char *prompt, const char *initial);
|
||||
|
||||
static inline int nextchar(int fd, int timeout)
|
||||
{
|
||||
@ -302,129 +301,5 @@ const char *bkeyname(int key)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* A basic readline implementation. No history, but all the normal editing
|
||||
* key bindings like Ctrl-U to clear to the beginning of the line, backspace,
|
||||
* arrow keys, etc.
|
||||
*
|
||||
* Takes an input file and output file, and an optional prompt and returns
|
||||
* a malloc'd string containing the user's input or NULL if an error occurred
|
||||
* or if the user hit Escape or Ctrl-c.
|
||||
*/
|
||||
char *breadline(FILE *in, FILE *out, const char *prompt, const char *initial)
|
||||
{
|
||||
size_t cap = initial ? strlen(initial) + 100 : 100;
|
||||
char *buf = calloc(cap, 1);
|
||||
if (!buf) return NULL;
|
||||
int i = 0, len = 0;
|
||||
if (prompt) {
|
||||
fputs("\033[1G\033[K\033[37;1m", out);
|
||||
fputs(prompt, out);
|
||||
fputs("\033[0m", out);
|
||||
}
|
||||
if (initial) {
|
||||
strcpy(buf, initial);
|
||||
len = (int)strlen(initial);
|
||||
i = len;
|
||||
fputs(initial, out);
|
||||
}
|
||||
// Show cursor and set to blinking line:
|
||||
fputs("\033[?25h\033[5 q", out);
|
||||
while (1) {
|
||||
fflush(out);
|
||||
int key = bgetkey(in, NULL, NULL, -1);
|
||||
switch (key) {
|
||||
case -1: case -2: case -3: continue;
|
||||
case '\r':
|
||||
// TODO: support backslash-enter
|
||||
goto finished;
|
||||
case KEY_CTRL_C: case KEY_ESC:
|
||||
free(buf);
|
||||
buf = NULL;
|
||||
goto finished;
|
||||
case KEY_CTRL_A:
|
||||
if (i > 0) {
|
||||
fprintf(out, "\033[%dD", i);
|
||||
i = 0;
|
||||
}
|
||||
break;
|
||||
case KEY_CTRL_E:
|
||||
if (i < len) {
|
||||
fprintf(out, "\033[%dC", len-i);
|
||||
i = len;
|
||||
}
|
||||
break;
|
||||
case KEY_CTRL_U: {
|
||||
int to_clear = i;
|
||||
if (to_clear) {
|
||||
memmove(buf, buf+i, (size_t)(len-i));
|
||||
buf[len -= i] = 0;
|
||||
i = 0;
|
||||
fprintf(out, "\033[%dD\033[K", to_clear);
|
||||
if (len > 0)
|
||||
fprintf(out, "%s\033[%dD", buf, len);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case KEY_CTRL_K:
|
||||
if (i < len) {
|
||||
buf[len = i] = 0;
|
||||
fputs("\033[K", out);
|
||||
}
|
||||
break;
|
||||
case KEY_BACKSPACE: case KEY_BACKSPACE2:
|
||||
if (i > 0) {
|
||||
--i;
|
||||
memmove(buf+i, buf+i+1, (size_t)(len-i));
|
||||
buf[--len] = 0;
|
||||
if (i == len) fputs("\033[D \033[D", out);
|
||||
else fprintf(out, "\033[D%s\033[K\033[%dD", buf+i, len-i);
|
||||
}
|
||||
break;
|
||||
case KEY_DELETE: case KEY_CTRL_D:
|
||||
if (i < len) {
|
||||
memmove(buf+i, buf+i+1, (size_t)(len-i));
|
||||
buf[--len] = 0;
|
||||
if (i == len) fputs(" \033[D", out);
|
||||
else fprintf(out, "%s\033[K\033[%dD", buf+i, len-i);
|
||||
}
|
||||
break;
|
||||
case KEY_ARROW_LEFT: case KEY_CTRL_B:
|
||||
if (i > 0) {
|
||||
--i;
|
||||
fputs("\033[D", out);
|
||||
}
|
||||
break;
|
||||
case KEY_ARROW_RIGHT: case KEY_CTRL_F:
|
||||
if (i < len) {
|
||||
++i;
|
||||
fputs("\033[C", out);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (' ' <= key && key <= '~') {
|
||||
if (len + 1 >= (int)cap) {
|
||||
cap += 100;
|
||||
buf = realloc(buf, cap);
|
||||
if (!buf) goto finished;
|
||||
}
|
||||
if (i < len)
|
||||
memmove(buf+i+1, buf+i, (size_t)(len-i+1));
|
||||
buf[i++] = (char)key;
|
||||
buf[++len] = 0;
|
||||
if (i == len)
|
||||
fputc(key, out);
|
||||
else
|
||||
fprintf(out, "%c%s\033[%dD", (char)key, buf+i, len-i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
finished:
|
||||
// Reset cursor to block
|
||||
fputs("\033[1G\033[1 q\033[2K", out);
|
||||
return buf;
|
||||
}
|
||||
|
||||
#endif
|
||||
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1
|
||||
|
45
config.def.h
45
config.def.h
@ -76,6 +76,22 @@
|
||||
|
||||
#define PAUSE " read -n1 -p '\033[2mPress any key to continue...\033[0m\033[?25l'"
|
||||
|
||||
#ifndef FUZZY
|
||||
#define FUZZY(prompt) "fzy --prompt=\"" prompt "\""
|
||||
#endif
|
||||
|
||||
#ifndef ASK
|
||||
#ifdef ASKECHO
|
||||
#define ASK(var, prompt) var "=\"$(" ASKECHO(prompt) ")\""
|
||||
#else
|
||||
#define ASK(var, prompt) "read -p \"" prompt "\" " var
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ASKECHO
|
||||
#define ASKECHO(prompt) ASK("REPLY", prompt) " && echo \"$REPLY\""
|
||||
#endif
|
||||
|
||||
#define NORMAL_TERM (1<<0)
|
||||
#define AT_CURSOR (1<<1)
|
||||
|
||||
@ -163,19 +179,20 @@ binding_t bindings[] = {
|
||||
{{' ','v','V'}, "+toggle", B("Toggle")" selection"},
|
||||
{{KEY_ESC}, "+deselect:*", B("Clear")" selection"},
|
||||
{{'e'}, "$EDITOR \"$@\"", B("Edit")" file in $EDITOR", NORMAL_TERM},
|
||||
{{KEY_CTRL_F}, "bb \"+g:`fzf`\"", B("Fuzzy search")" for file", NORMAL_TERM},
|
||||
{{'/'}, "bb \"+g:`ls -a|fzf`\"", B("Fuzzy select")" file", NORMAL_TERM},
|
||||
{{KEY_CTRL_F}, "bb \"+g:`find | "FUZZY("Find: ")"`\" +r", B("Fuzzy search")" for file"},
|
||||
{{'/'}, "bb \"+g:`ls -a | " FUZZY("Pick: ") "`\" +r", B("Fuzzy pick")" file"},
|
||||
{{'d', KEY_DELETE}, "rm -rfi \"$@\"; bb '+de:*' +r", B("Delete")" files", AT_CURSOR},
|
||||
{{'D'}, "rm -rf \"$@\"; bb '+de:*' +r", B("Delete")" files (without confirmation)"},
|
||||
{{'M'}, "mv -i \"$@\" .; bb '+de:*' +r; for f; do bb \"+sel:`pwd`/`basename \"$f\"`\"; done",
|
||||
B("Move")" files to current directory"},
|
||||
{{'c'}, "cp -i \"$@\" .; bb +r", B("Copy")" files to current directory"},
|
||||
{{'C'}, "bb '+de:*'; for f; do cp \"$f\" \"$f.copy\" && bb \"+sel:$f.copy\"; done; bb +r", B("Clone")" files"},
|
||||
{{'n'}, "name=`bb '?New file: '` && touch \"$name\"; bb +r \"+goto:$name\"", B("New file")},
|
||||
{{'N'}, "name=`bb '?New dir: '` && mkdir \"$name\"; bb +r \"+goto:$name\"", B("New directory")},
|
||||
{{'|'}, "cmd=`bb '?|'` && printf '%s\\n' \"$@\" | sh -c \"$cmd\"; " PAUSE "; bb +r",
|
||||
{{'n'}, ASK("name", "New file: ")" && touch \"$name\"; bb +r \"+goto:$name\"", B("New file")},
|
||||
{{'N'}, ASK("name", "New dir: ")" && mkdir \"$name\"; bb +r \"+goto:$name\"", B("New directory")},
|
||||
{{KEY_CTRL_G}, "bb \"+cd:`" ASKECHO("Go to directory: ") "`\" +r", B("Go to")" directory"},
|
||||
{{'|'}, ASK("cmd", "|") " && printf '%s\\n' \"$@\" | sh -c \"$cmd\"; " PAUSE "; bb +r",
|
||||
B("Pipe")" selected files to a command"},
|
||||
{{':'}, "sh -c \"`bb '?:'`\" -- \"$@\"; " PAUSE "; bb +refresh",
|
||||
{{':'}, "sh -c \"`" ASKECHO(":") "`\" -- \"$@\"; " PAUSE "; bb +refresh",
|
||||
B("Run")" a command"},
|
||||
{{'>'}, "$SHELL", "Open a "B("shell"), NORMAL_TERM},
|
||||
{{'m'}, "read -n1 -p 'Mark: ' m && bb \"+mark:$m;$PWD\"", "Set "B("mark")},
|
||||
@ -185,7 +202,7 @@ binding_t bindings[] = {
|
||||
QUOTE(
|
||||
bb '+deselect:*' +refresh;
|
||||
for f; do
|
||||
if renamed="$(dirname "$f")/$(bb '?Rename: ' "$(basename "$f")")" &&
|
||||
if renamed="$(dirname "$f")/$(ask --initial="$(basename "$f")" 'Rename: ')" &&
|
||||
test "$f" != "$renamed" && mv -i "$f" "$renamed"; then
|
||||
test $BBSELECTED && bb "+select:$renamed";
|
||||
elif test $BBSELECTED; then bb "+select:$f"; fi
|
||||
@ -194,7 +211,7 @@ binding_t bindings[] = {
|
||||
|
||||
{{'R'},
|
||||
QUOTE(
|
||||
if patt="`bb '?Rename pattern: ' 's/'`"; then true; else bb +r; exit; fi;
|
||||
if patt="`ask --initial='s/' 'Rename pattern: '`"; then true; else bb +r; exit; fi;
|
||||
if sed -E "$patt" </dev/null; then true; else read -p 'Press any key to continue...' -n1; bb +r; exit; fi;
|
||||
bb '+deselect:*' +refresh;
|
||||
for f; do
|
||||
@ -207,21 +224,21 @@ binding_t bindings[] = {
|
||||
|
||||
{{'P'},
|
||||
QUOTE(
|
||||
patt=`bb '?Select pattern: '` &&
|
||||
for f; do echo "$f" | grep "$patt" >/dev/null 2>/dev/null && bb "+sel:$f"; done
|
||||
patt=`ask 'Select pattern: '` &&
|
||||
for f in *; do echo "$f" | grep "$patt" >/dev/null 2>/dev/null && bb "+sel:$f"; done
|
||||
)/*ENDQUOTE*/,
|
||||
B("Regex select")" files"},
|
||||
|
||||
{{'J'}, "+spread:+1", B("Spread")" selection down"},
|
||||
{{'K'}, "+spread:-1", B("Spread")" selection up"},
|
||||
{{'b'}, "bb \"+`bb '?bb +'`\"", "Run a "B("bb command")},
|
||||
{{'b'}, "bb \"+`"ASKECHO("bb +")"`\"", "Run a "B("bb command")},
|
||||
{{'s'},
|
||||
("read -n1 -p 'Sort "B("(a)")"lphabetic "B("(s)")"ize "B("(m)")"odification "
|
||||
B("(c)")"creation "B("(a)")"access "B("(r)")"andom "B("(p)")"ermissions:\033[0m ' sort "
|
||||
("sort=\"$(ask -q 'Sort (n)ame (s)ize (m)odification (c)reation (a)ccess (r)andom "
|
||||
"(p)ermissions: ' n s m c a r p)\""
|
||||
"&& bb \"+sort:+$sort\""),
|
||||
B("Sort")" by..."},
|
||||
|
||||
{{'#'}, "bb \"+col:`bb '?Set columns: '`\"", "Set "B("columns")},
|
||||
{{'#'}, "bb \"+col:`"ASKECHO("Set columns: ")"`\"", "Set "B("columns")},
|
||||
{{'.'}, "bb +dotfiles", "Toggle "B("dotfiles")},
|
||||
{{'g', KEY_HOME}, "+move:0", "Go to "B("first")" file"},
|
||||
{{'G', KEY_END}, "+move:100%n", "Go to "B("last")" file"},
|
||||
|
Loading…
Reference in New Issue
Block a user