Key binding to go up by one directory (in Bash)
You can do that.
It's not as elegant or straight forward as with zsh but it's doable in bash using bind
.
You can not only bind built in Readline functions (listed with bind -l
) but other macros and shell functions too.
bind -m emacs -x '"\C-i":"cd .."'
will bind a shell command (cd ..
) to the keys (Ctrl+i) in emacs mode (the default mode). (Ctrl+i is unbound by default, u isn't)
Note that your prompt will probably not reflect the change.
If you leave out -x
the string will instead be typed out for you so "cd ..\n"
achieves the same result.
Edit: bind
is how you bind keys and macros can accomplish what you want even though no built in thing exists.
If you end your PS1 prompt with \033[K
(erase to eol) and can use bind -m emacs '"\C-i":" cd ..&&echo -e \"\\033[2A\"\n"'
to do what you want.
This will first print cd ..
then control chars to move the cursor up and run it (with \n
).
The end of your PS1 prevents it from showing. This is a hack but it shows that it's doable.
In bash, how do I bind a function key to a command?
You can determine the character sequence emitted by a key by pressing Ctrl-v at the command line, then pressing the key you're interested in. On my system for F12, I get ^[[24~
. The ^[
represents Esc. Different types of terminals or terminal emulators can emit different codes for the same key.
At a Bash prompt you can enter a command like this to enable the key macro so you can try it out.
bind '"\e[24~":"foobar"'
Now, when you press F12, you'll get "foobar" on the command line ready for further editing. If you wanted a keystroke to enter a command immediately, you can add a newline:
bind '"\e[24~":"pwd\n"'
Now when you press F12, you'll get the current directory displayed without having to press Enter. What if you've already typed something on the line and you use this which automatically executes? It could get messy. However, you could clear the line as part of your macro:
bind '"\e[24~":"\C-k \C-upwd\n"'
The space makes sure that the Ctrl-u has something to delete to keep the bell from ringing.
Once you've gotten the macro working the way you want, you can make it persistent by adding it to your ~/.inputrc
file. There's no need for the bind
command or the outer set of single quotes:
"\e[24~":"\C-k \C-upwd\n"
Edit:
You can also create a key binding that will execute something without disturbing the current command line.
bind -x '"\eW":"who"'
Then while you're typing a command that requires a username, for example, and you need to know the names of user who are logged in, you can press Alt-Shift-W and the output of who
will be displayed and the prompt will be re-issued with your partial command intact and the cursor in the same position in the line.
Unfortunately, this doesn't work properly for keys such as F12 which output more than two characters. In some cases this can be worked around.
The command (who
in this case) could be any executable - a program, script or function.
Complex keybinding in bash
The trick to this is to call functions which rebinds your keys. In my example I'll use C-b to insert text and to call menu-complete, instead of C-x. You'll have to sacrifice a key, in my example C-t
In .bashrc, or a bash file to be sourced
set_Cb_to_insert_text() {
bind '"\C-m": accept-line'
bind '"\C-b":"ls \C-t1"'
bind -x '"\C-t1":set_Cb_to_complete'
}
set_Cb_to_complete() {
bind '"\C-m":"\C-t2\C-t3"'
bind '"\C-b": menu-complete'
bind '"\C-t2": accept-line'
bind -x '"\C-t3":set_Cb_to_insert_text'
}
set_Cb_to_insert_text
How this works:
With bind
, you can bind keys to do one of three things, but no combination of them:
- Execute a readline command:
bind '"key": command'
- Execute a series of keystrokes:
bind '"key":"keystrokes"'
- Execute a shell command:
bind -x '"key": shell-command'
So if you want to combine these three things, you'll need to bind them each to a separate combination of keystrokes (in my example C-t{1,2,3}) and bind a key to execute all these keystrokes.
In the example:
C-b first inserts ls
and 'presses' C-t1, which executes set_Cb_to_complete
, which in turn rebinds C-b to menu-complete
. It also rebinds C-m, carriage return, or Enter, because it now needs to do two things: Accept the line, and reset C-b to insert ls
, by calling the set_Cb_to_insert_text
function, which also resets Enter to it's normal use.
The reason I said that C-t had to be "sacrificed", is that if you press C-t, readline will wait to see if you are going to press 1, or 2, or any of the bound key sequences, before it takes any action. But when you first have put C-t to this use, you can use it as an initial key for a huge amount of keystrokes to cover all your readline trickery.
Piece of advice: While you are writing and testing these, bind an alternate key to accept-line
, because suddenly something breaks the chain at the wrong place, and you are stuck in a terminal without a way to execute commands :)
In a bash script, how can I bind a key to a function?
Key bindings using bind
only affect the interactive text input (the readline library). When running a program (even a built-in while
) the terminal is switched to standard "cooked" mode and input is given to the currently running program (in this case, sleep
would receive the input).
You can read the keys manually:
read -N 1 input
echo "Read '$input'"
However, if you want to run the while
loop and read input at the same time, you will have to do it in separate processes (bash does not support threads). Since variables are local to a process, the end result will have to be fairly complicated.
Bash bind command
Have you tried this?
bind '"R":self-insert'
or this, if you can't type "R":
bind '"'`echo -e '\x52'`'":self-insert'
How to make bash's bind commands completely invisible?
This should work for you:
stty susp undef
bind -x '"\C-z":"fg >/dev/null 2>&1"'
Keep in mind though that this might not be such a good idea, since it'll prevent you from suspending most other programs.
Related Topics
Sed Replacement Not Working When Using Variables
Limit on File Name Length in Bash
Linux Tool to Send Raw Data to a Tcp Server
Move Files to Directories Based on Extension
How to Access an Environment Variable in a .Desktop File's Exec Line
Why Disabling Interrupts Disables Kernel Preemption and How Spin Lock Disables Preemption
Pass Output as an Argument for Cp in Bash
Changing Location of Core Dump
Unix: Differencebetween Source and Export
How to Find Files Modified in Last X Minutes (Find -Mmin Does Not Work as Expected)
Maximum Number of Files/Directories on Linux
How Use Qt in Visual Studio Code
What's the Meaning of a ! Before a Command in the Shell
How to Enable Bash in Windows 10 Developer Preview
Why Can Back-Quotes and $() for Command Substitution Result in Different Output
How to Increase the Scrollback Buffer in a Running Screen Session