Bind makes bash faster

bind is a bash builtin used for displaying and setting readline mappings.

simple use

With it you can map keys like:

bind '"\C-gr": "ssh remote@192.168.1.102"'

This will type into your terminal ssh remote@192.168.1.102 whenever you type Ctrl-g+r. If you want it to execute immedietly after typing just use

bind '"\C-gr": "ssh remote@192.168.1.102\n"'

If you won't quote the second part it will be treated as readline command or function.

bind '",": print-last-kbd-macro'

key syntax

Mapped keys can have special keys like \C- which represents the pressing Ctrl with key, and \e which represents pressing meta key (alt) with key (there is no dash in between). You can make combinations like '",e": "echo "', '"\C-xC-b": "vim ~/.bashrc\n"', '"\e\C-t": "transmission-remote -l"' (Ctrl-Alt-t).

If you type keys partially and wait over 500ms or type one wrong character the mapping will be ignored and previously typed keys will be typed to the terminal normally. This can be used to define mapping based on normal characters that are not common like , you can create many easy to type bindings for common commands like ",t": "transmission-remote -l\n" with practically no cost.

Even if characters used are not rare they might be an easy to type gibberish like "cPp": "cd $PROJECTS/python\n" which you won't have to even worry about when typing as you just never type such things normally, and when you do you can just wait a little.

Above that you can use

set keyseq-timeout 500

in your ~/.inputrc to change key sequence timeout (in miliseconds) to your preference.

Finding other special keys

If you want to use functional keys like F11 you can press Ctrl-v + F11 which will give you ^[[23~ and this sequence can be used directly as part of a key.

Ctrl-v + Del -> ^[[P

Ctrl-v + Ctrl-F11 -> ^[[23;2~

Ctrl-v + Ctrl-a -> ^A

Ctrl-v + Alt-a -> ^[a

Ctrl-v + a -> a

-x

This option specifies command to be executed, contrary to previous examples this option makes binded value executed as a command and it's not just typed.

Current path and previously typed keys will not be affected nor will be the cursor position.

Executed command isn't saved to history, and is working in current session so all functions and variables defined are available, also all changes to them are saved.

For example

bind -x '"\C-gm": exit'

will exit the current shell.

-x '"\C-gm": "cd /; ls"' will not change current directory but will print ls at /.

-x '"\C-gm": "x=2"' will set x to 2 without any visible changes in the terminal.

This option works great for seamlessly opening files, opening your file manager or listing information while writing commands.

It can also be used for avoiding of adding your bindings to history.

This option also sets some special variables, more on in copying current/last command.

main key

Assuming you use the default emacs style keybinding you really don't have much space to add your own Ctrl bindings without changing everything or mapping everything with Ctrl+Alt.

But there exists a key binding that serves no purpose and that's \C-g which is binded to abort. When was the last time that you have used this? Were you even aware of it's existance? The only time i've used it was to cancel the \C-r history search, and even after remapping it seems to be working for that.

g is in the middle of the keyboard so it's a very accessible key and I encourage you to use it similar to vim leader key.

You could go with the , as the leader but why not both.

removing key bindings

If you want to change default key binding you can use the -r option

bind -r '\C-y'

This will delete all mapping to \C-y

listing your mappings

Bind has a lot of options but 80% of them is just for listing currently set mappings.

-l all of readline functions.

-P same as previous but with their binded keys.

-p same as previous but can be used as input for .inputrc.

-S key sequences bound to macros (things you set).

-s same as previous but can be used as input for .inputrc.

-V readline variable names and their values.

-v same as previous but can be used as input for .inputrc.

-X everything set with -x option.

-f FILENAME exports all set things for .inputrc.

my bindings

I hope you'll find inspiration in here.

quick moving between directories and opening files

fcd() { jaP="$(find "$1" -type d | fzf)"; [ -n "$jaP" ] && cd "$jaP"; }
frf() { t="$1"; shift; jaP="$(find -type f | fzf)"; [ -n "$jaP" ] && "$@" "$jaP"; }
frd() { t="$1"; shift; jaP="$(find -type d | fzf)"; [ -n "$jaP" ] && "$@" "$jaP"; }

bind -x '"\C-gm": frf . mpv'
bind -x '"\C-gs": frd . sxiv -r'
bind -x '"\C-gz": frf . zathura'
bind -x '"\C-gU": frf . nvim'
bind '"\C-gc": "fcd .\n"'

It's better to define complex things in functions.

file manager switching

bind -x '"\C-gg": csas'

With this even if you are halfway in writing a complex line you can open your file manager and come back to the same state. I use csas but you can use ranger or lf.

bind -x '"\C-gg": ranger'

copying current/last command

This one is very useful and quite special. The -x option sets additional variables about the current state of the edited line.

READLINE_ARGUMENT holds argument to keys ( set with Alt-1, ... , Alt-9 key binding).

READLINE_MARK holds position of mark ( set with \C-@ key binding).

READLINE_LINE holds edited line.

READLINE_POINT holds position in edited line.

Changing any of them also changes state e.g.

bind -r '\C-a'

go_to_beginning() {
    READLINE_POINT=0
}
bind -x '"\C-a": go_to_beginning'

This will completely emulate the default \C-a mapping.

copylastcomm(){
    if [ -n "$READLINE_LINE" ]
    then
        tr -d '\n' <<< "$READLINE_LINE" | xclip -sel clip
    else
        history 1 | sed 's/^ *[0-9]\+ *//;q' | tr -d '\n' | xclip -sel clip
    fi
}

bind -x '"\C-g1": copylastcomm'

This wonderful shortcut copies current line if it's not empty, or last typed command into clipboard.

SSH/mounting directories

I have a convention of starting ssh connection with e letter and mounting remote directories with E (I have a lot of old computers).

bind '"\C-gem": "ssh maisto@192.168.1.103\n"'
bind '"\C-geM": "ssh maisto@192.168.1.59\n"'
bind '"\C-geu": "ssh natka@192.168.1.4\n"'
bind '"\C-gen": "ssh nanar@192.168.5.135\n"'

bind '"\C-gep": "ssh pi@rasp.ves\n"'
bind '"\C-geP": "ssh -p 7822 pi@127.0.0.1\n"'
bind '"\C-gea": "ssh -p 8022 192.168.34.155\n"'
bind '"\C-geA": "ssh -p 8022 192.168.1.37\n"'
bind '"\C-gec": "ssh -p 8022 192.168.5.68\n"'
bind '"\C-gel": "sshpass -p/6248 ssh user1@192.168.5.65\n"'
bind '"\C-gev": "ssh vereo@192.168.1.240\n"'

bind '"\C-gEm": "sshfs maisto@192.168.1.103:/home/maisto/"'
bind '"\C-gEkm": "sshfs maisto@192.168.1.103:/home/maisto/ktc1/ ~/ktc1/\n"'
bind '"\C-gEhm": "sshfs maisto@192.168.1.103:/home/maisto/hre/ ~/hre/\n"'
bind '"\C-gEzm": "sshfs maisto@192.168.1.103:/home/maisto/zeh/ ~/zeh/\n"'
bind '"\C-gEM": "sshfs maisto@192.168.1.103:/home/maisto/"'
bind '"\C-gEkM": "sshfs maisto@192.168.1.103:/home/maisto/ktc1/ ~/ktc1/\n"'
bind '"\C-gEhM": "sshfs maisto@192.168.1.103:/home/maisto/hre/ ~/hre/\n"'
bind '"\C-gEzM": "sshfs maisto@192.168.1.103:/home/maisto/zeh/ ~/zeh/\n"'
bind '"\C-gEv": "sshfs vereo@192.168.1.240:/home/vereo/ "'

torrents

This one quickly shows me the current state of my torrents

bind '"\C-gt": "transmission-remote -l\n"'

And this one calls my script for adding torrents on input from clipboard

bind '"\C-ga": "transadd \"$(xclip -o -sel clip)\"\n"'

screen/tmux

Allows for choice to which session to reattach

bind '"\C-gi": "screen -r "'

Starts new session

bind '"\C-gI": "screen\n"'

translation

I have an alias to translate-shell, I've stopped using these binding because i've made a better dmenu script.

bind '"\C-gTs": "trans -s spa -t en "'
bind '"\C-gTe": "trans -s en -t spa "'

editing files

I have convention of starting these with u letter.

bind '"\C-gus": "$EDITOR ~/.config/sunt\n"'
bind '"\C-guu": "$EDITOR ~/.config/newsboat/urls\n"'
bind '"\C-gux": "$EDITOR ~/.config/Xresources\n"'
bind '"\C-gue": "$EDITOR $G/eng\n"'
bind '"\C-gug": "$EDITOR $G/g\n"'
bind '"\C-gul": "$EDITOR $G/linux\n"'
bind '"\C-guf": "$EDITOR $G/f\n"'
bind '"\C-gub": "$EDITOR ~/.bashrc\n"'
bind '"\C-guv": "$EDITOR ~/.config/vars\n"'
bind '"\C-gud": "$EDITOR ~/.config/dirshortcuts\n"'
bind '"\C-gun": "$EDITOR ~/.config/nvim/init.vim\n"'
bind '"\C-guN": "$EDITOR $G/notes\n"'
bind '"\C-guc": "$EDITOR ~/.config/csasrc\n"'
bind '"\C-gum": "$EDITOR $TO/magnets\n"'
bind '"\C-gup": "$EDITOR $PR/sh/pugna-arch\n"'

changing directory

I actually generate them automatically for bash and my file manager with a script.

bind '"\C-gh": "cd $HOME\n"'

#movies, shows, etc
bind '"\C-gff": "cd $FIL\n"'
bind '"\C-gfv": "cd $FILV\n"'
bind '"\C-gfs": "cd $FILS\n"'
bind '"\C-gfy": "cd $FILY\n"'
bind '"\C-gfc": "cd $FILC\n"'
bind '"\C-gfa": "cd $FILA\n"'
bind '"\C-gf0": "cd $FILY/000\n"'

#folder for archiving
bind '"\C-gC": "cd $CB\n"'
bind '"\C-gfFs": "cd $CB/fil/s\n"'
bind '"\C-gfFa": "cd $CB/fil/a\n"'
bind '"\C-gfFv": "cd $CB/fil/v\n"'
bind '"\C-gfFc": "cd $CB/fil/c\n"'

bind '"\C-gfm": "cd $MUSIC\n"'
bind '"\C-gfk": "cd $BOOKS\n"'
bind '"\C-gG": "cd $G\n"'
bind '"\C-gD": "cd $DOWNLOADS\n"'
bind '"\C-gFf": "cd $FILES\n"'
bind '"\C-gFF": "cd $FILES\n"'
bind '"\C-gFd": "cd $DATASETS\n"'
bind '"\C-gFx": "cd $XF\n"'
bind '"\C-gFi": "cd $IV\n"'
bind '"\C-gFm": "cd $FILES/mirrors\n"'
bind '"\C-gFs": "cd $FILES/shots\n"'

#projects
bind '"\C-gpp": "cd $PR\n"'
bind '"\C-gpa": "cd $PR/asm\n"'
bind '"\C-gpc": "cd $PR/c\n"'
bind '"\C-gpx": "cd $PR/c/x86_64\n"'
bind '"\C-gpm": "cd $PR/c/msp430\n"'
bind '"\C-gpq": "cd $PR/quickc\n"'
bind '"\C-gps": "cd $PR/sh\n"'
bind '"\C-gpP": "cd $PR/python\n"'
bind '"\C-gpj": "cd $PR/js\n"'

bind '"\C-gS": "cd $SYSISO\n"'
bind '"\C-gk": "cd $KPP\n"'
bind '"\C-gM": "cd $MEMES\n"'
bind '"\C-gdd": "cd $HOME/Downloads\n"'

#~/.local/bin - my script folder
bind '"\C-gL": "cd $LBIN\n"'

more about bind

If you want to learn about bind in depth you can run info bash bind or go to https://www.computerhope.com/unix/bash/bind.htm.

I also recommend reading about readline and looking at bash bindings with

info bash -n bind