Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bind a key to command that reads stdin

Tags:

bash

I have a script that reads a line from stdin and perform some operations based on the line's contents. I need to bind a key to that script so it can be called simply by typing Ctrl-t. When I call the script by its name it works as expected, but when I hit the key binding it hangs. In fact the shell hangs and I have to kill it. The script uses read -r line. I tried with cat with same results.

Script looks like this (file name read.sh):

#!/bin/bash

echo -n '  > '
read -r buf
echo "you typed $buf"

Bind like this:

bind -x '"\C-t" : "read.sh"'
like image 781
Tihomir Mitkov Avatar asked Oct 31 '22 05:10

Tihomir Mitkov


1 Answers

Your terminal settings are different when you press Ctrl+t versus when you just launch the script through the terminal. If you add the following line to read.sh, it'll print your terminal settings:

echo Terminal settings: "$(stty -a)"

Now run the script by itself, and then run it by pressing Ctrl+t. You'll notice a few differences, the biggest of which are the additions of -echo and -icrnl, which turn off echo and change newline handling. This gives the appearance of the script hanging.

You can fix this problem inside the script by forcing the tty back into canonical mode, and re-adding echo. Before making any stty changes, you'll want to save the settings and restore them when the script exits. You can use trap for that.

#!/bin/bash
# Save the tty settings and restore them on exit.
SAVED_TERM_SETTINGS="$(stty -g)"
trap "stty \"${SAVED_TERM_SETTINGS}\"" EXIT

# Force the tty (back) into canonical line-reading mode.
stty cooked echo

# Read lines and do stuff.
echo -n '  > '
read -r buf
echo "you typed $buf"
like image 86
indiv Avatar answered Nov 11 '22 19:11

indiv