Some overhaul and refactoring. bbstartup.sh and bindings.bb have been

moved into scripts/bbstartup and scripts/bbbindkeys alongside the other
scripts. Some minor bugs have been fixed as well, and a few bindings
added.
This commit is contained in:
Bruce Hill 2020-04-08 23:58:37 -07:00
parent adcb0a43e0
commit e0a30fe02b
8 changed files with 347 additions and 240 deletions

View File

@ -25,7 +25,7 @@ install: $(NAME)
[ ! "$$prefix" ] && prefix="/usr/local"; \
[ ! "$$sysconfdir" ] && sysconfdir=/etc; \
mkdir -pv -m 755 "$$prefix/share/man/man1" "$$prefix/bin" "$$sysconfdir/xdg/bb" \
&& cp -rv bindings.bb scripts/* "$$sysconfdir/xdg/bb/" \
&& cp -rv scripts/* "$$sysconfdir/xdg/bb/" \
&& cp -v bb.1 bbcmd.1 "$$prefix/share/man/man1/" \
&& rm -f "$$prefix/bin/$(NAME)" \
&& cp -v $(NAME) "$$prefix/bin/"
@ -42,3 +42,4 @@ uninstall:
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\n"
.PHONY: all, clean, install, uninstall

View File

@ -51,7 +51,7 @@ The core idea behind `bb` is that `bb` is a file **browser**, not a file
to the filesystem (passing selected files as arguments), rather than
reinventing the wheel by hard-coding operations like `rm`, `mv`, `cp`, `touch`,
and so on. Shell scripts can be bound to keypresses in
`~/.config/bb/bindings.bb`. For example, `D` is bound to a script that prints a
`~/.config/bb/bbbindkeys`. For example, `D` is bound to a script that prints a
confirmation message, then runs `rm -rf "$@" && bbcmd deselect refresh`,
which means selecting `file1` and `file2`, then pressing `D` will cause `bb` to
run the shell command `rm -rf file1 file2` and then tell `bb` to deselect all
@ -59,20 +59,18 @@ run the shell command `rm -rf file1 file2` and then tell `bb` to deselect all
## Customizing bb
`bb` runs a script at startup (by default [bbstartup.sh](bbstartup.sh), installed
to `/etc/xdg/bb/bbstartup.sh`) that sets up `bb`'s key bindings and a few other
minor things. You can override this with your own custom startup script by creating
a file at `~/.config/bb/bbstartup.sh`. The default startup script loads key bindings
from (in order) `/etc/xdg/bb/bindings.bb` and `~/.config/bb/bindings.bb` (or if
neither exists, from the local directory).
When `bb` launches, it first updates `bb`'s `$PATH` environment variable to
include, in order, `~/.config/bb` and `/etc/xdg/bb`. Then, `bb` will run the
command `bbstartup` (the default implementation is found at
[scripts/bbstartup](scripts/bbstartup), along with other default `bb` commands).
`bbstartup` will call `bbbindkeys` and may also set up configuration options like
which columns to display and what sort order to use. All of these behaviors can
be customized by creating custom local versions of these files in `~/.config/bb/`.
The default versions can be found in `/etc/xdg/bb/`.
`bb` comes with a bunch of pre-defined bindings for basic actions in
[bindings.bb](bindings.bb) (installed to `/etc/xdg/bb/bindings.bb`). It's very
easy to add new bindings for whatever custom scripts you want to run, just
create a file called `~/.config/bb/bindings.bb` and put your bindings there.
You can also create bindings at runtime by hitting `Ctrl-b`, pressing the key
you want to bind, and then entering in a script to run (in case you want to set
up an easy way to repeat some custom workflow).
You can also create temporary bindings at runtime by hitting `Ctrl-b`, pressing
the key you want to bind, and then entering in a script to run (in case you
want to set up an easy way to repeat some custom workflow).
### API

16
bb.c
View File

@ -534,6 +534,7 @@ void print_bindings(int fd)
*/
void run_bbcmd(bb_t *bb, const char *cmd)
{
while (*cmd == ' ' || *cmd == '\n') ++cmd;
if (strncmp(cmd, "bbcmd ", strlen("bbcmd ")) == 0) cmd = &cmd[strlen("bbcmd ")];
const char *value = strchr(cmd, ':');
if (value) ++value;
@ -563,8 +564,15 @@ void run_bbcmd(bb_t *bb, const char *cmd)
for (size_t i = 0; i < sizeof(bindings)/sizeof(bindings[0]); i++) {
if (bindings[i].script && (bindings[i].key != keyval || is_section))
continue;
binding_t binding = {keyval, memcheck(strdup(script)),
memcheck(strdup(description))};
char *script2;
if (is_simple_bbcmd(script)) {
script2 = memcheck(strdup(script));
} else {
const char *prefix = "set -e\n";
script2 = memcheck(calloc(strlen(prefix) + strlen(script) + 1, 1));
sprintf(script2, "%s%s", prefix, script);
}
binding_t binding = {keyval, script2, memcheck(strdup(description))};
if (bindings[i].key == keyval) {
free(bindings[i].description);
free(bindings[i].script);
@ -1194,9 +1202,9 @@ int main(int argc, char *argv[])
struct sigaction sa_winch = {.sa_handler = &update_term_size};
sigaction(SIGWINCH, &sa_winch, NULL);
update_term_size(0);
// Wait 10ms at a time for terminal to initialize if necessary
// Wait 100us at a time for terminal to initialize if necessary
while (winsize.ws_row == 0)
usleep(10000);
usleep(100);
// Set up environment variables
// Default values

2
bb.h
View File

@ -26,7 +26,7 @@
#include "bterm.h"
// Macros:
#define BB_VERSION "0.26.0"
#define BB_VERSION "0.27.0"
#ifndef PATH_MAX
#define PATH_MAX 4096

View File

@ -1,215 +0,0 @@
# This file defines the key bindings for bb
# The format is: <key>(,<key>)*:[ ]*#<description>(\n[ ]+script)+
Section: BB Commands
?,F1: # Show Help menu
bbcmd help
q,Q: # Quit
bbcmd quit
Ctrl-c: # Send interrupt signal
kill -INT $PPID
Ctrl-z: # Suspend
kill -TSTP $PPID
Ctrl-\: # Quit and generate core dump
kill -QUIT $PPID
Section: File Navigation
j,Down: # Next file
bbcmd move:+1
k,Up: # Previous file
bbcmd move:-1
h,Left: # Parent directory
bbcmd cd:..
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' | bbpick "Find: "
)" && bbcmd goto:"$file"
/: # Pick a file
file="$(printf "%s\0" $BBGLOB | bbpick "Pick: ")" || exit
bbcmd goto:"$file"
*: # Set the glob
glob="$(bbask "Show files matching: ")" && bbcmd glob:"$glob"
Ctrl-g: # Go to directory
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
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' | bbpick "Jump to: ")" &&
bbcmd cd:"$(readlink -f "$XDG_CONFIG_HOME"/bb/marks/"$mark")"
-,Backspace: # Go to previous directory
[ "$BBPREVPATH" ] && bbcmd cd:"$BBPREVPATH"
;: # Show selected files
bbcmd cd:'<selection>'
0: # Go to intitial directory
bbcmd cd:"$BBINITIALPATH"
g,Home: # Go to first file
bbcmd move:0
G,End: # Go to last file
bbcmd move:100%n
PgDn: # Page down
bbcmd scroll:+100%
PgUp: # Page up
bbcmd scroll:-100%
Ctrl-d: # Half page down
bbcmd scroll:+50%
Ctrl-u: # Half page up
bbcmd scroll:-50%
Mouse wheel down: # Scroll down
bbcmd scroll:+3
Mouse wheel up: # Scroll up
bbcmd scroll:-3
Section: File Selection
v,V,Space: # Toggle selection at cursor
bbcmd toggle:"$BBCURSOR"
Escape: # Clear selection
bbcmd deselect
S: # Select pattern
patt="$(bbask "Select: ")" && bbcmd select: $patt
U: # Unselect pattern
patt="$(bbask "Unselect: ")" && bbcmd deselect: $patt
Ctrl-s: # Save the selection
[ $# -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 ] && ! 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
K: # Spread selection up
bbcmd spread:-1
Shift-Home: # Spread the selection to the top
bbcmd spread:0
Shift-End: # Spread the selection to the bottom
bbcmd spread:100%n
Ctrl-a: # Select all files here
bbcmd select
Section: File Actions
Left click: # Move cursor to file
if [ "$BBCLICKED" = "<column label>" ]; then
bbcmd sort:"~$BBMOUSECOL"
elif [ "$BBCLICKED" -a "$BBMOUSECOL" = "*" ]; then
bbcmd toggle:"$BBCLICKED"
elif [ "$BBCLICKED" ]; then
bbcmd goto:"$BBCLICKED"
fi
Enter,Double left click: # Open file/directory
if [ -d "$BBCURSOR" ]; then bbcmd cd:"$BBCURSOR"
elif [ "$(uname)" = "Darwin" ]; then
if expr "$(file -bI "$BBCURSOR")" : '\(text/\|inode/empty\)' >/dev/null; then $EDITOR "$BBCURSOR"
else open "$BBCURSOR"; fi
else
if expr "$(file -bi "$BBCURSOR")" : '\(text/\|inode/x-empty\)' >/dev/null; then $EDITOR "$BBCURSOR"
else xdg-open "$BBCURSOR"; fi
fi
e: # Edit file in $EDITOR
$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" | 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
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 | bbpick "Create new: ")" in
File)
name="$(bbask "New File: ")" && touch -- "$name"
;;
Directory)
name="$(bbask "New Directory: ")" && mkdir -- "$name"
;;
*) exit
;;
esac && bbcmd goto:"$name" refresh || bbpause
p: # Page through a file with `less`
less -XK "$BBCURSOR"
r,F2: # Rename files
case "$(bbtargets "$BBCURSOR" "$@")" in
cursor) set -- "$BBCURSOR";;
both) set -- "$BBCURSOR" "$@";;
esac
for f; do
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 "
&& bbconfirm && { rm -rf "$r" || { bbpause; exit; }; }
mv "$f" "$r" || { bbpause; exit; }
bbcmd deselect:"$f" select:"$r"
[ "$f" = "$BBCURSOR" ] && bbcmd goto:"$r"
done
bbcmd refresh
~: # Regex rename files
if ! command -v rename >/dev/null; then
printf '\033[31;1mThe `rename` command is not installed. Please install it to use this key binding.\033[0m\n'
bbpause; exit 1
fi
if [ $# -eq 0 ]; then set -- $BBGLOB; fi
set -e
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
if [ $# -eq 0 ]; then set -- *; [ -e "$1" ] || exit 1; fi
rename -i "$patt" "$rep" "$@"
bbcmd deselect refresh
Section: Shell Commands
:: # Run a command
cmd="$(bbask ':')" && sh -c "$cmd" -- "$@"; bbcmd refresh; bbpause
|: # Pipe selected files to a command
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
bbcmd fg
Section: Viewing Options
s: # Sort by...
sort="$(bbask -1 "Sort (n)ame (s)ize (m)odification (c)reation (a)ccess (r)andom (p)ermissions: ")" &&
bbcmd sort:"~$sort"
---,#: # Set columns
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
bbcmd glob:"*"
else
bbcmd glob:".* *"
fi
i: # Toggle interleaving files and directories
bbcmd interleave
F5,Ctrl-l: # Refresh view
bbcmd refresh
Ctrl-b: # Bind a key to a script
key="$(bbask -1 "Press key to bind...")" && echo && script="$(bbask "Bind script: ")" &&
bbcmd bind:"$key":"{ $script; } || bbpause" || bbpause
Section: User Bindings

View File

@ -118,6 +118,7 @@ static keyname_t key_names[] = {
{KEY_CTRL_2, "Ctrl-2"}, {KEY_CTRL_3, "Ctrl-3"}, {KEY_CTRL_4, "Ctrl-4"},
{KEY_CTRL_5, "Ctrl-5"}, {KEY_CTRL_6, "Ctrl-6"}, {KEY_CTRL_7, "Ctrl-7"},
{KEY_CTRL_5, "Ctrl-8"}, {KEY_CTRL_6, "Ctrl-9"},
{':', "Colon"},
};
int bgetkey(FILE *in, int *mouse_x, int *mouse_y);

318
scripts/bbbindkeys Executable file
View File

@ -0,0 +1,318 @@
#!/bin/sh
# This file defines the key bindings for bb. It works by a very hacky script on
# the line below that prints out the rest of this file, converted into `bbcmd
# bind:` commands. Thanks to the hackiness, the code below is also valid shell
# code, so syntax highlighting should work normally.
#
# The format is: ## <key>(,<key>)*:[ ]+<description>(\n script)+
#
# May God have mercy on my soul for creating this abomination:
sed '1,'$LINENO'd; /^$/d; s/^## \(.*\): \(.*\)/\x00bind:\1:# \2/; $a\\x00' "$0" | bbcmd; exit
## Section: BB Commands
## ?,F1: Show Help menu
bbcmd help
## q,Q: Quit
bbcmd quit
## Ctrl-c: Send interrupt signal
kill -INT $PPID
## Ctrl-z: Suspend
kill -TSTP $PPID
## Ctrl-\: Quit and generate core dump
kill -QUIT $PPID
## Section: File Navigation
## j,Down: Next file
bbcmd move:+1
## k,Up: Previous file
bbcmd move:-1
## h,Left: Parent directory
bbcmd cd:..
## 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' | bbpick "Find: ")"
bbcmd goto:"$file"
## /: Pick a file
file="$(printf "%s\0" $BBGLOB | bbpick "Pick: ")"
bbcmd goto:"$file"
## *: Set the glob
glob="$(bbask "Show files matching: ")"
bbcmd glob:"$glob"
## Ctrl-g: Go to directory
dir="$(bbask "Go to directory: ")"
bbcmd cd:"$dir"
## m: Mark this directory
mkdir -p "$XDG_CONFIG_HOME/bb/marks"
ln -sT "$2" "$XDG_CONFIG_HOME/bb/marks/$1" 2>/dev/null
mark="$(bbask "Mark: ")"
ln -s "$PWD" "$XDG_CONFIG_HOME"/bb/marks/"$mark"
## ': Go to a marked directory
[ -d "$XDG_CONFIG_HOME"/bb/marks ]
mark="$(find "$XDG_CONFIG_HOME"/bb/marks/ -mindepth 1 -type l -printf '%P\0' | bbpick "Jump to: ")"
mark="$(readlink -f "$XDG_CONFIG_HOME"/bb/marks/"$mark")"
bbcmd cd:"$mark"
## -,Backspace: Go to previous directory
[ "$BBPREVPATH" ] && bbcmd cd:"$BBPREVPATH"
## ;: Show selected files
bbcmd cd:'<selection>'
## 0: Go to intitial directory
bbcmd cd:"$BBINITIALPATH"
## g,Home: Go to first file
bbcmd move:0
## G,End: Go to last file
bbcmd move:100%n
## PgDn: Page down
bbcmd scroll:+100%
## PgUp: Page up
bbcmd scroll:-100%
## Ctrl-d: Half page down
bbcmd scroll:+50%
## Ctrl-u: Half page up
bbcmd scroll:-50%
## Mouse wheel down: Scroll down
bbcmd scroll:+3
## Mouse wheel up: Scroll up
bbcmd scroll:-3
## Section: File Selection
## v,V,Space: Toggle selection at cursor
bbcmd toggle:"$BBCURSOR"
## Escape: Clear selection
bbcmd deselect
## S: Select pattern
patt="$(bbask "Select: ")"
bbcmd select: $patt
## U: Unselect pattern
patt="$(bbask "Unselect: ")"
bbcmd deselect: $patt
## Ctrl-s: Save the selection
[ $# -gt 0 ]
savename="$(bbask "Save selection as: ")"
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 ]
[ $# -gt 0 ] && bbconfirm "The current selection will be discarded. "
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
## K: Spread selection up
bbcmd spread:-1
## Shift-Home: Spread the selection to the top
bbcmd spread:0
## Shift-End: Spread the selection to the bottom
bbcmd spread:100%n
## Ctrl-a: Select all files here
bbcmd select
## Section: File Actions
## Left click: Move cursor to file
if [ "$BBCLICKED" = "<column label>" ]; then
bbcmd sort:"~$BBMOUSECOL"
elif [ "$BBCLICKED" -a "$BBMOUSECOL" = "*" ]; then
bbcmd toggle:"$BBCLICKED"
elif [ "$BBCLICKED" ]; then
bbcmd goto:"$BBCLICKED"
fi
## Enter,Double left click: Open file/directory
if [ -d "$BBCURSOR" ]; then bbcmd cd:"$BBCURSOR"
elif [ "$(uname)" = "Darwin" ]; then
if expr "$(file -bI "$BBCURSOR")" : '\(text/\|inode/empty\)' >/dev/null; then $EDITOR "$BBCURSOR"
else open "$BBCURSOR"; fi
else
if expr "$(file -bi "$BBCURSOR")" : '\(text/\|inode/x-empty\)' >/dev/null; then $EDITOR "$BBCURSOR"
else xdg-open "$BBCURSOR"; fi
fi
## e: Edit file in $EDITOR
$EDITOR "$BBCURSOR"
## 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" | 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
case "$(bbtargets "$BBCURSOR" "$@")" in
cursor) set -- "$BBCURSOR";;
both) set -- "$BBCURSOR" "$@";;
esac
[ $# -gt 0 ]
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 | bbpick "Create new: ")" in
File)
name="$(bbask "New File: ")" && touch -- "$name"
;;
Directory)
name="$(bbask "New Directory: ")" && mkdir -- "$name"
;;
*) exit
;;
esac
bbcmd goto:"$name" refresh
## p: Page through a file with `less`
less -XK "$BBCURSOR"
## r,F2: Rename files
case "$(bbtargets "$BBCURSOR" "$@")" in
cursor) set -- "$BBCURSOR";;
both) set -- "$BBCURSOR" "$@";;
esac
for f; do
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 "
&& bbconfirm && { rm -rf "$r" || { bbpause; exit; }; }
mv "$f" "$r" || { bbpause; exit; }
bbcmd deselect:"$f" select:"$r"
[ "$f" = "$BBCURSOR" ] && bbcmd goto:"$r"
done
bbcmd refresh
## ~: Regex rename files
if ! command -v rename >/dev/null; then
printf '\033[31;1mThe `rename` command is not installed. Please install it to use this key binding.\033[0m\n'
bbpause; exit 1
fi
if [ $# -eq 0 ]; then set -- $BBGLOB; fi
patt="$(bbask "Replace pattern: ")"
rep="$(bbask "Replacement: ")"
printf "\033[1mRenaming:\n\033[33m$(rename -nv "$patt" "$rep" "$@")\033[0m" | bbunscroll | more
bbconfirm
rename -i "$patt" "$rep" "$@"
bbcmd deselect refresh
## Section: Shell Commands
## Colon: Run a command
cmd="$(bbask ':')"
sh -c "$cmd" -- "$@" || true
bbpause
bbcmd refresh
## |: Pipe selected files to a command
cmd="$(bbask '|')"
if [ $# -eq 0 ]; then set -- "$BBCURSOR"; fi
printf '%s\n' "$@" | sh -c "$cmd" || true
bbpause
bbcmd refresh
## @: Pass selected files as args to a command
cmd="$(bbask '@')"
if [ $# -eq 0 ]; then set -- "$BBCURSOR"; fi
sh -c "$cmd \"\$@\"" -- "$@" || true
bbpause
bbcmd refresh
## $: Pass the cursor as an argument to a command
cmd="$(bbask '$')"
sh -c "$cmd \"\$1\"" -- "$BBCURSOR" || true
bbpause
bbcmd refresh
## >: Open a shell
tput rmcup; tput cvvis
$SHELL || true
bbcmd refresh
## f: Resume suspended process
bbcmd fg
## Section: Viewing Options
## s: Sort by...
sort="$(bbask -1 "Sort (n)ame (s)ize (m)odification (c)reation (a)ccess (r)andom (p)ermissions: ")"
bbcmd sort:"~$sort"
## ---,#: Set columns
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
bbcmd glob:"*"
else
bbcmd glob:".* *"
fi
## i: Toggle interleaving files and directories
bbcmd interleave
## F5,Ctrl-l: Refresh view
bbcmd refresh
## Ctrl-b: Bind a key to a script
key="$(bbask -1 "Press key to bind...")"
echo
script="$(bbask "Bind script: ")"
bbcmd bind:"$key":"{ $script; } || bbpause"
## Section: User Bindings

View File

@ -4,11 +4,7 @@
[ ! -d "$XDG_DATA_HOME/bb" ] && mkdir -p "$XDG_DATA_HOME/bb"
# Load key bindings
if [ "$BBPATH" ]; then
cat "$BBPATH/bindings.bb" "$XDG_CONFIG_HOME/bb/bindings.bb"
else
cat "$sysconfdir/xdg/bb/bindings.bb" "$XDG_CONFIG_HOME/bb/bindings.bb"
fi 2>/dev/null | awk '/^#/ {next} /^[^ ]/ {printf "\0bind:"} {print $0} END {printf "\0"}' >> "$BBCMD"
bbbindkeys
if [ -e "$XDG_DATA_HOME/bb/settings.sh" ]; then
. "$XDG_DATA_HOME/bb/settings.sh"