Major update: instead of defining all the helper functions as static
C-strings prefixed to commands (modified by the Makefile), the helper functions are now standalone scripts in the helpers/ dir, which gets added to "$PATH" when running bb.
This commit is contained in:
parent
a8fd174319
commit
865092c656
26
API.md
26
API.md
@ -9,18 +9,18 @@ internal state.
|
||||
|
||||
## Helper Functions
|
||||
|
||||
- `bb`: used for modifying `bb`'s internal state (see BB Commands).
|
||||
- `ask`: get user input in a standardized and customizable way. The first
|
||||
argument is a variable where the value is stored. The second argument is
|
||||
a prompt. A third optional argument can provide a default value (may be
|
||||
ignored).
|
||||
- `ask1`: get a single character of user input. The first argument is a variable
|
||||
where the input will be stored and the second argument is a prompt.
|
||||
- `pause`: Display a "press any key to continue" message and wait for a keypress.
|
||||
- `confirm`: Display a "Is this okay? [y/N]" prompt and exit with failure if
|
||||
the user does not press 'y'.
|
||||
- `spin`: Display a spinning icon while a slow command executes in the background.
|
||||
(e.g. `spin sleep 5`).
|
||||
- `bbask [-1] [prompt [initial]]`: get user input in a standardized and
|
||||
customizable way and output it to `STDOUT`.
|
||||
- `bbcmd <cmd>*`: used for modifying `bb`'s internal state (see BB Commands).
|
||||
- `bbconfirm [prompt]`: Display a "Is this okay? [y/N]" prompt and exit with
|
||||
failure if the user does not press 'y'.
|
||||
- `bbpause`: Display a "press any key to continue" message and wait for a keypress.
|
||||
- `bbpick [prompt]`: Select one of `NULL`-delimited multiple inputs and print it.
|
||||
- `bbtargets "$BBCMD" "$@"`: If `$BBCURSOR` is not currently among `$@` (the
|
||||
selected files), this script prompts the user to ask whether they want to
|
||||
perform an action on the selected files, or on the cursor. The result is
|
||||
printed as `cursor` or `selected`.
|
||||
- `bbunscroll`: Print text to the screen *above* the cursor instead of below it.
|
||||
|
||||
## Environment Variables
|
||||
|
||||
@ -80,7 +80,7 @@ glob is available in `$BBGLOB`, which can be used in scripts if left unquoted.
|
||||
|
||||
## Final Notes
|
||||
|
||||
Internally, `bbcmd` writes the commands (NUL terminated) to a file whose path is
|
||||
Internally, `bbcmd` writes the commands (`NULL` terminated) to a file whose path is
|
||||
in`$BBCMD` and `bb` reads from that file when it resumes. These commands can also
|
||||
be passed to `bb` at startup as command line arugments starting with `+`, and
|
||||
will run immediately. E.g. `bbcmd +'col:n' +'sort:+r' .` will launch `bb` only
|
||||
|
49
Makefile
49
Makefile
@ -8,49 +8,6 @@ CWARN=-Wall -Wpedantic -Wextra -Wno-unknown-pragmas -Wno-missing-field-initializ
|
||||
#CFLAGS += -fsanitize=address -fno-omit-frame-pointer
|
||||
G=
|
||||
|
||||
ifeq ($(shell uname),Darwin)
|
||||
CFLAGS += -D_DARWIN_C_SOURCE
|
||||
endif
|
||||
|
||||
ifneq (, $(SH))
|
||||
CFLAGS += -D'SH="$(SH)"'
|
||||
endif
|
||||
|
||||
PICKER_FLAG=
|
||||
ifeq (, $(PICKER))
|
||||
PICKER=$(shell sh -c "(which fzf >/dev/null 2>/dev/null && echo 'fzf') || (which fzy >/dev/null 2>/dev/null && echo 'fzy') || (which pick >/dev/null 2>/dev/null && echo 'pick') || (which ask >/dev/null 2>/dev/null && echo 'ask')")
|
||||
endif
|
||||
ifneq (, $(PICKER))
|
||||
PICKER_FLAG=-D"PICK=\"$(PICKER) --prompt=\\\"$$1\\\"\""
|
||||
ifeq ($(shell which $(PICKER)),$(shell which fzf 2>/dev/null || echo '<none>'))
|
||||
PICKER_FLAG=-D'PICK="printf \"\\033[3A\\033[?25h\" >/dev/tty; fzf --read0 --height=4 --prompt=\"$$1\""'
|
||||
endif
|
||||
ifeq ($(shell which $(PICKER)),$(shell which fzy 2>/dev/null || echo '<none>'))
|
||||
PICKER_FLAG=-D'PICK="printf \"\\033[3A\\033[?25h\" >/dev/tty; tr "\\0" "\\n" | fzy --lines=3 --prompt=\"\033[1m$$1\033[0m\""'
|
||||
endif
|
||||
ifeq ($(shell which $(PICKER)),$(shell which ask 2>/dev/null || echo '<none>'))
|
||||
PICKER_FLAG=-D'PICK="/usr/bin/env ask --read0 --prompt=\"$$1\033[?25h\""'
|
||||
endif
|
||||
ifeq ($(shell which $(PICKER)),$(shell which pick 2>/dev/null || echo '<none>'))
|
||||
PICKER_FLAG=-D'PICK="printf \"\\033[?25h\" >/dev/tty; tr "\\0" "\\n" | pick"'
|
||||
endif
|
||||
ifeq ($(shell which $(PICKER)),$(shell which dmenu 2>/dev/null || echo '<none>'))
|
||||
PICKER_FLAG=-D'PICK="tr "\\0" "\\n" | dmenu -i -l 10 -p \"$$1\""'
|
||||
endif
|
||||
endif
|
||||
CFLAGS += $(PICKER_FLAG)
|
||||
|
||||
ifneq (, $(ASKER))
|
||||
PERCENT := %
|
||||
ifeq ($(shell which $(ASKER)),$(shell which ask 2>/dev/null || echo '<none>'))
|
||||
CFLAGS += -D'ASK="eval \"$$1=\\$$(/usr/bin/env ask --history=bb.hist --prompt=\\\"$$2\033[?25h\\\" --query=\\\"$$3\\\")\""'
|
||||
CFLAGS += -D'CONFIRM="/usr/bin/env ask -n \"$$1Is that okay?\033[?25h\""'
|
||||
endif
|
||||
ifeq ($(shell which $(ASKER)),$(shell which dmenu 2>/dev/null || echo '<none>'))
|
||||
CFLAGS += -D'ASK="eval \"$$1=\\$$(echo \"$$3\" | dmenu -p \"$$2\")\""'
|
||||
endif
|
||||
endif
|
||||
|
||||
all: $(NAME)
|
||||
|
||||
clean:
|
||||
@ -67,8 +24,8 @@ install: $(NAME)
|
||||
fi; \
|
||||
[ ! "$$prefix" ] && prefix="/usr/local"; \
|
||||
[ ! "$$sysconfdir" ] && sysconfdir=/etc; \
|
||||
mkdir -pv -m 755 "$$prefix/share/man/man1" "$$prefix/bin" "$$sysconfdir/xdg/bb" \
|
||||
&& cp -v bbstartup.sh bindings.bb "$$sysconfdir/xdg/bb/" \
|
||||
mkdir -pv -m 755 "$$prefix/share/man/man1" "$$prefix/bin" "$$sysconfdir/xdg/bb" "$$sysconfdir/xdg/bb/helpers" \
|
||||
&& cp -rv bbstartup.sh bindings.bb helpers "$$sysconfdir/xdg/bb/" \
|
||||
&& cp -v bb.1 bbcmd.1 "$$prefix/share/man/man1/" \
|
||||
&& rm -f "$$prefix/bin/$(NAME)" \
|
||||
&& cp -v $(NAME) "$$prefix/bin/"
|
||||
@ -83,5 +40,5 @@ uninstall:
|
||||
[ ! "$$sysconfdir" ] && sysconfdir=/etc; \
|
||||
echo "Deleting..."; \
|
||||
rm -rvf "$$prefix/bin/$(NAME)" "$$prefix/share/man/man1/bb.1" "$$prefix/share/man/man1/bbcmd.1" "$$sysconfdir/xdg/bb"; \
|
||||
printf "\033[1mIf you created any config files in ~/.config/bb, you may want to delete them manually.\033[0m"
|
||||
printf "\033[1mIf you created any config files in ~/.config/bb, you may want to delete them manually.\033[0m\n"
|
||||
|
||||
|
2
bb.1
2
bb.1
@ -1,6 +1,6 @@
|
||||
.\" Manpage for bb.
|
||||
.\" Contact bruce@bruce-hill.com to correct errors or typos.
|
||||
.TH man 1 "23 Feb 2020" "0.24" "bb manual page"
|
||||
.TH man 1 "23 Feb 2020" "0.25" "bb manual page"
|
||||
.SH NAME
|
||||
bb \- A bitty browser for command line file management
|
||||
.SH SYNOPSIS
|
||||
|
14
bb.c
14
bb.c
@ -904,12 +904,9 @@ int run_script(bb_t *bb, const char *cmd)
|
||||
err("Couldn't set pgrp");
|
||||
char **args = memcheck(calloc(4 + (size_t)bb->nselected + 1, sizeof(char*)));
|
||||
int i = 0;
|
||||
args[i++] = SH;
|
||||
args[i++] = "sh";
|
||||
args[i++] = "-c";
|
||||
char *fullcmd = calloc(strlen(cmd) + strlen(bbcmdfn) + 1, sizeof(char));
|
||||
strcpy(fullcmd, bbcmdfn);
|
||||
strcat(fullcmd, cmd);
|
||||
args[i++] = fullcmd;
|
||||
args[i++] = (char*)cmd;
|
||||
args[i++] = "--"; // ensure files like "-i" are not interpreted as flags for sh
|
||||
// bb->selected is in most-recent order, so populate args in reverse to make sure
|
||||
// that $1 is the first selected, etc.
|
||||
@ -924,7 +921,7 @@ int run_script(bb_t *bb, const char *cmd)
|
||||
ttyin = open("/dev/tty", O_RDONLY);
|
||||
dup2(ttyout, STDOUT_FILENO);
|
||||
dup2(ttyin, STDIN_FILENO);
|
||||
execvp(SH, args);
|
||||
execvp(args[0], args);
|
||||
err("Failed to execute command: '%s'", cmd);
|
||||
return -1;
|
||||
}
|
||||
@ -1195,6 +1192,10 @@ int main(int argc, char *argv[])
|
||||
sprintf(xdg_data_home, "%s/.local/share", getenv("HOME"));
|
||||
setenv("XDG_DATA_HOME", xdg_data_home, 0);
|
||||
setenv("sysconfdir", "/etc", 0);
|
||||
char *newpath;
|
||||
if (asprintf(&newpath, "%s/xdg/bb/helpers:%s/bb/helpers:%s", getenv("sysconfdir"), getenv("XDG_CONFIG_HOME"), getenv("PATH")) < 0)
|
||||
err("Could not allocate memory");
|
||||
setenv("PATH", newpath, 1);
|
||||
setenv("SHELL", "bash", 0);
|
||||
setenv("EDITOR", "nano", 0);
|
||||
char *curdepth = getenv("BBDEPTH");
|
||||
@ -1202,7 +1203,6 @@ int main(int argc, char *argv[])
|
||||
char depthstr[16];
|
||||
sprintf(depthstr, "%d", depth + 1);
|
||||
setenv("BBDEPTH", depthstr, 1);
|
||||
setenv("BBSHELLFUNC", bbcmdfn, 1);
|
||||
char full_initial_path[PATH_MAX];
|
||||
getcwd(full_initial_path, PATH_MAX);
|
||||
normalize_path(full_initial_path, initial_path, full_initial_path);
|
||||
|
76
bb.h
76
bb.h
@ -26,7 +26,7 @@
|
||||
#include "bterm.h"
|
||||
|
||||
// Macros:
|
||||
#define BB_VERSION "0.24.0"
|
||||
#define BB_VERSION "0.25.0"
|
||||
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX 4096
|
||||
@ -243,80 +243,6 @@ static const struct termios default_termios = {
|
||||
static const char *description_str = "bb - an itty bitty console TUI file browser\n";
|
||||
static const char *usage_str = "Usage: bb (-h/--help | -v/--version | -s | -d | -0 | +command)* [[--] directory]\n";
|
||||
|
||||
// Shell functions
|
||||
static const char *bbcmdfn = "bbcmd() {\n"
|
||||
" if test $# -eq 0; then cat >> $BBCMD; return; fi\n"
|
||||
" for arg; do\n"
|
||||
" shift;\n"
|
||||
" if expr \"$arg\" : \"^[^:]*:$\" >/dev/null; then\n"
|
||||
" if test $# -gt 0; then printf \"$arg%s\\0\" \"$@\" >> $BBCMD;\n"
|
||||
" else sed \"s/\\([^\\x00]\\+\\)/$arg\\1/g\" >> $BBCMD; fi;\n"
|
||||
" return;\n"
|
||||
" fi;\n"
|
||||
" printf \"%s\\0\" \"$arg\" >> $BBCMD;\n"
|
||||
" done;\n"
|
||||
"}\n"
|
||||
// This shell function overwrites the lines above the cursor instead of scrolling the screen
|
||||
"unscroll() {\n"
|
||||
" input=\"$(cat)\"\n"
|
||||
" printf \"\\033[$(echo \"$input\" | wc -l)A\\033[J\" >/dev/tty\n"
|
||||
" echo \"$input\"\n"
|
||||
"}\n"
|
||||
"ask() {\n"
|
||||
#ifdef ASK
|
||||
ASK ";\n"
|
||||
#else
|
||||
" [ $# -lt 2 ] && printf '\033[31;1mNot enough args to ask!\033[0m\n' && return 1;\n"
|
||||
" printf \"\033[1m%s\033[0m\" \"$2\" >/dev/tty;\n"
|
||||
" tput cvvis >/dev/tty;\n"
|
||||
#ifdef __APPLE__
|
||||
" read -e $1 </dev/tty >/dev/tty;\n"
|
||||
#else
|
||||
" read $1 </dev/tty >/dev/tty;\n"
|
||||
#endif
|
||||
#endif
|
||||
"}\n"
|
||||
"ask1() {\n"
|
||||
#ifdef ASK1
|
||||
ASK1 ";\n"
|
||||
#else
|
||||
" tput civis >/dev/tty;\n"
|
||||
" printf \"\033[1m%s\033[0m\" \"$2\" >/dev/tty;\n"
|
||||
" stty -icanon -echo >/dev/tty 2>/dev/tty;\n"
|
||||
#ifdef __APPLE__
|
||||
" read -n 1 $1 </dev/tty >/dev/tty;\n"
|
||||
#else
|
||||
" eval \"$1=\\$(dd bs=1 count=1 2>/dev/null </dev/tty)\";\n"
|
||||
#endif
|
||||
" stty icanon echo >/dev/tty 2>/dev/tty;\n"
|
||||
" tput cvvis >/dev/tty;\n"
|
||||
#endif
|
||||
"}\n"
|
||||
"confirm() {\n"
|
||||
#ifdef CONFIRM
|
||||
CONFIRM ";\n"
|
||||
#else
|
||||
" ask1 REPLY \"$1\033[0;1mIs that okay? [y/N] \" && [ \"$REPLY\" = 'y' ];\n"
|
||||
#endif
|
||||
"}\n"
|
||||
"pause() {\n"
|
||||
" ask1 REPLY \"\033[0;2m Press any key to continue...\033[0m\";"
|
||||
"}\n"
|
||||
"pick() {\n"
|
||||
#ifdef PICK
|
||||
PICK ";\n"
|
||||
#else
|
||||
" ask query \"$1\" && awk '{print length, $1}' | sort -n | cut -d' ' -f2- |\n"
|
||||
" grep -i -m1 \"$(echo \"$query\" | sed 's;.;[^/&]*[&];g')\";\n"
|
||||
#endif
|
||||
"}\n"
|
||||
#ifdef SH
|
||||
"alias sh="SH";\n"
|
||||
#else
|
||||
#define SH "sh"
|
||||
#endif
|
||||
;
|
||||
|
||||
static const char *runstartup =
|
||||
"for path in \"$XDG_CONFIG_HOME/bb\" \"$sysconfdir/xdg/bb\" .; do\n"
|
||||
" if [ -e \"$path/bbstartup.sh\" ]; then\n"
|
||||
|
2
bbcmd.1
2
bbcmd.1
@ -1,6 +1,6 @@
|
||||
.\" Manpage for bbcmd.
|
||||
.\" Contact bruce@bruce-hill.com to correct errors or typos.
|
||||
.TH man 1 "23 Feb 2020" "0.24" "bbcmd manual page"
|
||||
.TH man 1 "23 Feb 2020" "0.25" "bbcmd manual page"
|
||||
|
||||
.de TPx
|
||||
. TP 4n
|
||||
|
111
bindings.bb
111
bindings.bb
@ -23,23 +23,22 @@ l,Right: # Enter directory
|
||||
if [ -d "$BBCURSOR" ]; then bbcmd cd:"$BBCURSOR"; fi
|
||||
Ctrl-f: # Search for file
|
||||
file="$(
|
||||
find $BBGLOB -mindepth 1 -printf '%P\0' | pick "Find: "
|
||||
find $BBGLOB -mindepth 1 -printf '%P\0' | bbpick "Find: "
|
||||
)" && bbcmd goto:"$file"
|
||||
/: # Pick a file
|
||||
file="$(printf "%s\0" $BBGLOB | pick "Pick: ")" || exit
|
||||
file="$(printf "%s\0" $BBGLOB | bbpick "Pick: ")" || exit
|
||||
bbcmd goto:"$file"
|
||||
*: # Set the glob
|
||||
ask BBGLOB "Show files matching: "
|
||||
bbcmd glob:"$BBGLOB"
|
||||
glob="$(bbask "Show files matching: ")" && bbcmd glob:"$glob"
|
||||
Ctrl-g: # Go to directory
|
||||
ask goto "Go to directory: " && bbcmd cd:"$goto"
|
||||
cd="$(bbask "Go to directory: ")" && bbcmd cd:"$cd"
|
||||
m: # Mark this directory
|
||||
mkdir -p "$XDG_CONFIG_HOME/bb/marks"
|
||||
ln -sT "$2" "$XDG_CONFIG_HOME/bb/marks/$1" 2>/dev/null
|
||||
ask mark "Mark: " && ln -s "$PWD" "$XDG_CONFIG_HOME"/bb/marks/"$mark"
|
||||
mark="$(bbask "Mark: ") && ln -s "$PWD" "$XDG_CONFIG_HOME"/bb/marks/"$mark"
|
||||
': # Go to a marked directory
|
||||
[ -d "$XDG_CONFIG_HOME"/bb/marks ] || exit
|
||||
mark="$(find "$XDG_CONFIG_HOME"/bb/marks/ -mindepth 1 -type l -printf '%P\0' | pick "Jump to: ")" &&
|
||||
mark="$(find "$XDG_CONFIG_HOME"/bb/marks/ -mindepth 1 -type l -printf '%P\0' | bbpick "Jump to: ")" &&
|
||||
bbcmd cd:"$(readlink -f "$XDG_CONFIG_HOME"/bb/marks/"$mark")"
|
||||
-,Backspace: # Go to previous directory
|
||||
[ "$BBPREVPATH" ] && bbcmd cd:"$BBPREVPATH"
|
||||
@ -70,18 +69,18 @@ v,V,Space: # Toggle selection at cursor
|
||||
Escape: # Clear selection
|
||||
bbcmd deselect
|
||||
S: # Select pattern
|
||||
ask patt "Select: " && bbcmd select: $patt
|
||||
patt="$(bbask "Select: ")" && bbcmd select: $patt
|
||||
U: # Unselect pattern
|
||||
ask patt "Unselect: " && eval bbcmd deselect: "$patt"
|
||||
patt="$(bbask "Unselect: ")" && bbcmd deselect: $patt
|
||||
Ctrl-s: # Save the selection
|
||||
[ $# -gt 0 ] && ask savename "Save selection as: " || exit 1
|
||||
[ $# -gt 0 ] && savename="$(bbask "Save selection as: ")" || exit 1
|
||||
mkdir -p "$XDG_DATA_HOME"/bb
|
||||
if ! expr "$savename" : ".*\.sel" >/dev/null; then savename="$savename.sel"; fi
|
||||
printf '%s\0' "$@" > "$XDG_DATA_HOME"/bb/"$savename"
|
||||
Ctrl-o: # Open a saved selection
|
||||
[ -d "$XDG_DATA_HOME"/bb ] || exit
|
||||
[ $# -gt 0 ] && ! confirm "The current selection will be discarded. " && exit 1
|
||||
loadpath="$(find "$XDG_DATA_HOME"/bb/ -mindepth 1 -name '*.sel' -printf '%P\0' | pick "Load selection: ")" &&
|
||||
[ $# -gt 0 ] && ! bbconfirm "The current selection will be discarded. " && exit 1
|
||||
loadpath="$(find "$XDG_DATA_HOME"/bb/ -mindepth 1 -name '*.sel' -printf '%P\0' | bbpick "Load selection: ")" &&
|
||||
cat "$XDG_DATA_HOME"/bb/"$loadpath" | bbcmd deselect select:
|
||||
J: # Spread selection down
|
||||
bbcmd spread:+1
|
||||
@ -113,77 +112,79 @@ Enter,Double left click: # Open file/directory
|
||||
else xdg-open "$BBCURSOR"; fi
|
||||
fi
|
||||
e: # Edit file in $EDITOR
|
||||
$EDITOR "$BBCURSOR" || pause
|
||||
d,Delete: # Delete a file
|
||||
printf "\033[1mDeleting \033[33m$BBCURSOR\033[0;1m...\033[0m " && confirm &&
|
||||
rm -rf "$BBCURSOR" && bbcmd deselect:"$BBCURSOR" refresh
|
||||
D: # Delete all selected files
|
||||
[ $# -gt 0 ] && printf "\033[1mDeleting the following:\n\033[33m$(printf ' %s\n' "$@")\033[0m" | unscroll | more &&
|
||||
confirm && rm -rf "$@" && bbcmd deselect refresh
|
||||
$EDITOR "$BBCURSOR" || bbpause
|
||||
d,Delete: # Delete
|
||||
case "$(bbtargets "$BBCURSOR" "$@")" in
|
||||
cursor) set -- "$BBCURSOR" ;;
|
||||
both) set -- "$BBCURSOR" "$@" ;;
|
||||
esac
|
||||
printf "\033[1mDeleting the following:\n\033[33m$(printf ' %s\n' "$@")\033[0m" | bbunscroll | more &&
|
||||
bbconfirm && rm -rf "$@" && bbcmd deselect refresh
|
||||
Ctrl-v: # Move files here
|
||||
printf "\033[1mMoving the following to here:\n\033[33m$(printf ' %s\n' "$@")\033[0m" | unscroll | more &&
|
||||
confirm && printf "\033[1G\033[KMoving..." && mv -i "$@" . && printf "done." &&
|
||||
printf "\033[1mMoving the following to here:\n\033[33m$(printf ' %s\n' "$@")\033[0m" | bbunscroll | more &&
|
||||
bbconfirm && printf "\033[1G\033[KMoving..." && mv -i "$@" . && printf "done." &&
|
||||
bbcmd deselect refresh && for f; do bbcmd sel:"$(basename "$f")"; done
|
||||
c: # Copy a file
|
||||
printf "\033[1mCreating copy of \033[33m$BBCURSOR\033[0;1m...\033[0m " &&
|
||||
confirm && cp -ri "$BBCURSOR" "$BBCURSOR.copy" && bbcmd refresh
|
||||
C: # Copy all selected files here
|
||||
[ $# -gt 0 ] && printf "\033[1mCopying the following to here:\n\033[33m$(printf ' %s\n' "$@")\033[0m" | unscroll | more &&
|
||||
confirm && printf "\033[1G\033[KCopying..." &&
|
||||
case "$(bbtargets "$BBCURSOR" "$@")" in
|
||||
cursor) set -- "$BBCURSOR";;
|
||||
both) set -- "$BBCURSOR" "$@";;
|
||||
esac
|
||||
[ $# -gt 0 ] || exit
|
||||
printf "\033[1mCopying the following to here:\n\033[33m$(printf ' %s\n' "$@")\033[0m" | bbunscroll | more
|
||||
bbconfirm && printf "\033[1G\033[KCopying..." &&
|
||||
for f; do if [ "./$(basename "$f")" -ef "$f" ]; then
|
||||
cp -ri "$f" "$f.copy" || break;
|
||||
else cp -ri "$f" . || break; fi; done; printf 'done.' && bbcmd refresh
|
||||
Ctrl-n: # New file/directory
|
||||
case "$(printf '%s\0' File Directory | pick "Create new: ")" in
|
||||
case "$(printf '%s\0' File Directory | bbpick "Create new: ")" in
|
||||
File)
|
||||
ask name "New File: " || exit
|
||||
touch -- "$name"
|
||||
name="$(bbask "New File: ")" && touch -- "$name"
|
||||
;;
|
||||
Directory)
|
||||
ask name "New Directory: " || exit
|
||||
mkdir -- "$name"
|
||||
name="$(bbask "New Directory: ")" && mkdir -- "$name"
|
||||
;;
|
||||
*) exit
|
||||
;;
|
||||
esac && bbcmd goto:"$name" refresh || pause
|
||||
esac && bbcmd goto:"$name" refresh || bbpause
|
||||
p: # Page through a file with `less`
|
||||
less -XK "$BBCURSOR"
|
||||
r,F2: # Rename a file
|
||||
ask newname "Rename $(printf "\033[33m%s\033[39m" "$(basename "$BBCURSOR")"): " "$(basename "$BBCURSOR")" || exit
|
||||
r="$(dirname "$BBCURSOR")/$newname" || exit
|
||||
[ "$r" = "$BBCURSOR" ] && exit
|
||||
[ -e "$r" ] && printf "\033[31;1m$r already exists! It will be overwritten.\033[0m " &&
|
||||
confirm && { rm -rf "$r" || { pause; exit; }; }
|
||||
mv "$BBCURSOR" "$r" && bbcmd refresh &&
|
||||
while [ $# -gt 0 ]; do "$1" = "$BBCURSOR" && bbcmd deselect:"$BBCURSOR" select:"$r"; shift; done &&
|
||||
bbcmd goto:"$r" || { pause; exit; }
|
||||
R: # Rename all selected files
|
||||
r,F2: # Rename files
|
||||
case "$(bbtargets "$BBCURSOR" "$@")" in
|
||||
cursor) set -- "$BBCURSOR";;
|
||||
both) set -- "$BBCURSOR" "$@";;
|
||||
esac
|
||||
for f; do
|
||||
ask newname "Rename $(printf "\033[33m%s\033[39m" "$(basename "$f")"): " "$(basename "$f")" || break;
|
||||
newname="$(bbask "Rename $(printf "\033[33m%s\033[39m" "$(basename "$f")"): " "$(basename "$f")")" || break;
|
||||
r="$(dirname "$f")/$newname";
|
||||
[ "$r" = "$f" ] && continue;
|
||||
[ -e "$r" ] && printf "\033[31;1m$r already exists! It will be overwritten.\033[0m "
|
||||
&& confirm && { rm -rf "$r" || { pause; exit; }; }
|
||||
mv "$f" "$r" || { pause; exit; }
|
||||
&& bbconfirm && { rm -rf "$r" || { bbpause; exit; }; }
|
||||
mv "$f" "$r" || { bbpause; exit; }
|
||||
bbcmd deselect:"$f" select:"$r";
|
||||
[ "$f" = "$BBCURSOR" ] && bbcmd goto:"$r";
|
||||
done;
|
||||
bbcmd refresh
|
||||
Ctrl-r: # Regex rename files
|
||||
case "$(bbtargets "$BBCURSOR" "$@")" in
|
||||
cursor) set -- "$BBCURSOR";;
|
||||
both) set -- "$BBCURSOR" "$@";;
|
||||
esac
|
||||
command -v rename >/dev/null ||
|
||||
{ printf '\033[31;1mThe `rename` command is not installed. Please install it to use this key binding.\033[0m\n'; pause; exit; };
|
||||
ask patt "Replace pattern: " && ask rep "Replacement: " &&
|
||||
printf "\033[1mRenaming:\n\033[33m$(if [ $# -gt 0 ]; then rename -nv "$patt" "$rep" "$@"; else rename -nv "$patt" "$rep" *; fi)\033[0m" | unscroll | more &&
|
||||
confirm || exit 1
|
||||
{ printf '\033[31;1mThe `rename` command is not installed. Please install it to use this key binding.\033[0m\n'; bbpause; exit; };
|
||||
patt="$(bbask "Replace pattern: ") && rep="$(bbask "Replacement: ")" &&
|
||||
printf "\033[1mRenaming:\n\033[33m$(if [ $# -gt 0 ]; then rename -nv "$patt" "$rep" "$@"; else rename -nv "$patt" "$rep" *; fi)\033[0m" | bbunscroll | more &&
|
||||
bbconfirm || exit 1
|
||||
if [ $# -eq 0 ]; then set -- *; ! [ -e "$1" ] && exit; fi
|
||||
rename -i "$patt" "$rep" "$@"
|
||||
bbcmd deselect refresh
|
||||
|
||||
Section: Shell Commands
|
||||
:: # Run a command
|
||||
ask cmd ':' && sh -c "$BBSHELLFUNC$cmd" -- "$@"; bbcmd refresh; pause
|
||||
cmd="$(bbask ':')" && sh -c "$cmd" -- "$@"; bbcmd refresh; bbpause
|
||||
|: # Pipe selected files to a command
|
||||
ask cmd '|' && printf '%s\n' "$@" | sh -c "$BBSHELLFUNC$cmd"; bbcmd refresh; pause
|
||||
cmd="$(bbask '|')" && printf '%s\n' "$@" | sh -c "$cmd"; bbcmd refresh; bbpause
|
||||
@: # Pipe selected files to a command
|
||||
cmd="$(bbask '@')" && sh -c "$cmd \"$$@\"" -- "$@"; bbcmd refresh; bbpause
|
||||
>: # Open a shell
|
||||
tput rmcup; tput cvvis; $SHELL; bbcmd refresh
|
||||
f: # Resume suspended process
|
||||
@ -191,10 +192,10 @@ f: # Resume suspended process
|
||||
|
||||
Section: Viewing Options
|
||||
s: # Sort by...
|
||||
ask1 sort "Sort (n)ame (s)ize (m)odification (c)reation (a)ccess (r)andom (p)ermissions: " &&
|
||||
sort="$(bbask -1 "Sort (n)ame (s)ize (m)odification (c)reation (a)ccess (r)andom (p)ermissions: ")" &&
|
||||
bbcmd sort:"~$sort"
|
||||
---,#: # Set columns
|
||||
ask columns "Set columns (*)selected (a)ccessed (c)reated (m)odified (n)ame (p)ermissions (r)andom (s)ize: " &&
|
||||
columns="$(bbask "Set columns (*)selected (a)ccessed (c)reated (m)odified (n)ame (p)ermissions (r)andom (s)ize: ")" &&
|
||||
bbcmd col:"$columns"
|
||||
.: # Toggle dotfile visibility
|
||||
if [ "$BBGLOB" = ".* *" ]; then
|
||||
@ -207,7 +208,7 @@ i: # Toggle interleaving files and directories
|
||||
F5,Ctrl-l: # Refresh view
|
||||
bbcmd refresh
|
||||
Ctrl-b: # Bind a key to a script
|
||||
ask1 key "Press key to bind..." && echo && ask script "Bind script: " &&
|
||||
bbcmd bind:"$key":"{ $script; } || pause" || pause
|
||||
key="$(bbask -1 "Press key to bind...")" && echo && script="$(bbask "Bind script: ")" &&
|
||||
bbcmd bind:"$key":"{ $script; } || bbpause" || bbpause
|
||||
|
||||
Section: User Bindings
|
||||
|
31
helpers/bbask
Executable file
31
helpers/bbask
Executable file
@ -0,0 +1,31 @@
|
||||
#!/bin/sh
|
||||
# A simple user-input asker. Result is output to stdout.
|
||||
# Usage: ask [-1] [prompt [initial query]]
|
||||
if [ "$1" = '-1' ]; then
|
||||
# Get one character of input
|
||||
tput civis >/dev/tty;
|
||||
printf '\033[1m%s\033[0m' "$2" >/dev/tty;
|
||||
stty -icanon -echo >/dev/tty 2>/dev/tty;
|
||||
if [ "$(uname)" = "Darwin" ]; then
|
||||
read -n 1 REPLY </dev/tty >/dev/tty;
|
||||
echo $REPLY
|
||||
else
|
||||
dd bs=1 count=1 2>/dev/null </dev/tty
|
||||
fi
|
||||
stty icanon echo >/dev/tty 2>/dev/tty
|
||||
tput cvvis >/dev/tty
|
||||
else
|
||||
# Get a line of input
|
||||
if command -v ask >/dev/null; then
|
||||
ask --history=bb.hist --prompt="$(printf '%s\033[?25h' "$1")" --query="$2"
|
||||
else
|
||||
printf "\033[1m%s\033[0m" "$1" >/dev/tty
|
||||
tput cvvis >/dev/tty
|
||||
if [ "$(uname)" = "Darwin" ]; then
|
||||
read -e REPLY </dev/tty >/dev/tty
|
||||
else
|
||||
read REPLY </dev/tty >/dev/tty
|
||||
fi
|
||||
echo $REPLY
|
||||
fi
|
||||
fi
|
11
helpers/bbcmd
Executable file
11
helpers/bbcmd
Executable file
@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
if [ $# -eq 0 ]; then cat >> $BBCMD; exit; fi
|
||||
for arg; do
|
||||
shift
|
||||
if expr "$arg" : '^[^:]*:$' >/dev/null; then
|
||||
if [ $# -gt 0 ]; then printf "$arg%s\\0" "$@" >> $BBCMD
|
||||
else sed "s/\([^\\x00]\+\)/$arg\1/g" >> $BBCMD; fi
|
||||
exit
|
||||
fi
|
||||
printf "%s\\0" "$arg" >> $BBCMD
|
||||
done
|
9
helpers/bbconfirm
Executable file
9
helpers/bbconfirm
Executable file
@ -0,0 +1,9 @@
|
||||
#!/bin/sh
|
||||
# Ask for user confirmation
|
||||
set -e
|
||||
if command -v ask >/dev/null; then
|
||||
ask -n "$(printf "$1Is that okay?\033[?25h")"
|
||||
else
|
||||
reply="$(bbask -1 "$(printf "$1\033[0;1mIs that okay? [y/N] ")")"
|
||||
[ "$reply" != 'y' ]
|
||||
fi
|
4
helpers/bbpause
Executable file
4
helpers/bbpause
Executable file
@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
# Pause before continuing
|
||||
printf '\033[0;2m Press any key to continue...\033[0m' >/dev/tty
|
||||
bbask -1 >/dev/null
|
39
helpers/bbpick
Executable file
39
helpers/bbpick
Executable file
@ -0,0 +1,39 @@
|
||||
#!/bin/sh
|
||||
# Pick from the provided input
|
||||
if [ -z "$PICKER" ]; then
|
||||
if command -v fzf >/dev/null; then
|
||||
PICKER=fzf
|
||||
elif command -v fzy >/dev/null; then
|
||||
PICKER=fzy
|
||||
elif command -v ask >/dev/null; then
|
||||
PICKER=ask
|
||||
elif command -v dmenu >/dev/null; then
|
||||
PICKER=dmenu
|
||||
elif command -v pick >/dev/null; then
|
||||
PICKER=pick
|
||||
fi
|
||||
fi
|
||||
|
||||
case "$PICKER" in
|
||||
fzf)
|
||||
printf '\033[3A\033[?25h' >/dev/tty
|
||||
fzf --read0 --height=4 --prompt="$(printf "$1")"
|
||||
;;
|
||||
fzy)
|
||||
printf '\033[3A\033[?25h' >/dev/tty
|
||||
tr '\0' '\n' | fzy --lines=3 --prompt="$(printf "\033[1m$1\033[0m")"
|
||||
;;
|
||||
ask)
|
||||
ask --read0 --prompt="$(printf "$1\033[?25h")"
|
||||
;;
|
||||
dmenu)
|
||||
tr '\0' '\n' | dmenu -i -l 10 -p "$(printf "$1")"
|
||||
;;
|
||||
pick)
|
||||
printf '\033[?25h' >/dev/tty
|
||||
tr '\0' '\n' | pick
|
||||
;;
|
||||
*)
|
||||
query="$(bbask "$1")" && grep -i -m1 "$(echo "$query" | sed 's;.;[^/&]*[&];g')"
|
||||
;;
|
||||
esac
|
25
helpers/bbtargets
Executable file
25
helpers/bbtargets
Executable file
@ -0,0 +1,25 @@
|
||||
#!/bin/sh
|
||||
# If the user is doing something ambiguous, like selecting a bunch of files,
|
||||
# moving the cursor off of those files, then doing an action, this will ask
|
||||
# what they mean to target, then output either 'cursor' or 'selected'.
|
||||
# Usage: targets "$BBCURSOR" "$@"
|
||||
cursor="$1"
|
||||
shift
|
||||
if [ $# -gt 0 ]; then
|
||||
for f in "$@"; do
|
||||
if [ "$f" = "$cursor" ]; then
|
||||
intended='Selected files'
|
||||
break
|
||||
fi
|
||||
done
|
||||
else
|
||||
intended='Cursor file'
|
||||
fi
|
||||
|
||||
[ -z "$intended" ] && intended="$(printf '%s\0' 'Cursor file' 'Selected files' 'Both' | bbpick 'Which do you want to delete? ')"
|
||||
|
||||
case "$intended" in
|
||||
Cursor*) echo cursor ;;
|
||||
Selected*) echo selected ;;
|
||||
Both) echo both ;;
|
||||
esac
|
5
helpers/bbunscroll
Executable file
5
helpers/bbunscroll
Executable file
@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
# Display text from the current line upward (instead of downward)
|
||||
input="$(cat)"
|
||||
printf "\\033[$(echo "$input" | wc -l)A\\033[J" >/dev/tty
|
||||
echo "$input"
|
Loading…
Reference in New Issue
Block a user