1

I want to read in bash when any key is pressed, be it arrow key, number, letter, or punctuation, without pressing enter.

This is the closest that I have come up with, besides that when an escaped key is pressed, it spills over into the next input. Also, escaped keys will read but not echo.

#!/bin/bash

read -r -n 1 -d $'\n' -p 'input> ' line
echo -en "\n"
echo "$line"
Blue Ice
  • 7,888
  • 6
  • 32
  • 52

1 Answers1

1

A bit hacky/dirty way, but should work for user interactive shells...

read -n1 -s -p 'input> ' line; read -t 0.1 -n2 -s line2
line="$line$line2"

Now, it's up to you to convert <ESC>[A to string <UP> or not.

NOTE: It would most likely fail, if the stdin is redirected (say, from pipe/file...)

anishsane
  • 20,270
  • 5
  • 40
  • 73
  • "hacky/dirty"... Almost perfect. – Blue Ice Mar 31 '13 at 14:50
  • Just realized that similar approach is already given at TLDP : http://tldp.org/LDP/abs/html/escapingsection.html#BASHEK – anishsane Apr 10 '13 at 04:41
  • Yes. This example will not work on OS X, however, because the read times on a Mac need to be positive integers. The only way the TLDP program works is if there can be very short read times following the first read time. – Blue Ice Apr 10 '13 at 12:33
  • ^^ Correct. as I said, it would only work for interactive shells, when the user is going to press a key, manually. & as you found out, it would not work for OSX. But on OSX, you can still compile a custom binary `myread` & use it as `line=\`myread\``... – anishsane Apr 10 '13 at 13:26
  • What about long escape sequences? (For instance, my Ctrl-F2 key generates "\e[O1;5Q". And what about really really fast typers? I am pretty sure that sometimes more than one key gets pressed within 0.1 seconds. – Alfe Sep 06 '13 at 10:15
  • @alfe: For first question, you can extend the above logic, `$line1` for simple character, `$line1$line2` for arrow keys, `$line1$line2$line3` for ctrl+F2 like combination. – anishsane Sep 06 '13 at 10:38
  • For 2nd question, you can alter the delay. But, for 5-95 %le people, _hopefully_ this will work. – anishsane Sep 06 '13 at 10:38
  • Consider pasted long text. Consider strange terminals which create escape sequences of various lengths. What we really need is a function which states of a received escape sequence whether it is complete or unfinished. Then we can continue reading as long as it is unfinished. I'm still searching for such a thing. `terminfo` and `tput` are starting points, but I'm not successful yet. – Alfe Sep 06 '13 at 10:52