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:
parent
adcb0a43e0
commit
e0a30fe02b
3
Makefile
3
Makefile
@ -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
|
||||
|
26
README.md
26
README.md
@ -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
16
bb.c
@ -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
2
bb.h
@ -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
|
||||
|
215
bindings.bb
215
bindings.bb
@ -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
|
1
bterm.h
1
bterm.h
@ -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
318
scripts/bbbindkeys
Executable 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
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user