1

I wrote a bash script, which has "buttons" similar to "mc" or Norton Commander. Right now, I use the number keys (1-0) to simulate the buttons being pressed. However, I would rather have the F-keys (F1-F10) to do it.

I saw this question and answers, but I am not certain this can be used in a script to trigger a function (e.g. by using "read").

Does bash support it? If so, is there a fairly easy way to implement it?

UPDATE

The script is kind of a dash, which needs to be refreshed in order to keep the contents current. However, at the same time I would like to keep the "channel" open to allow user input (therefore sleep would not be adequate).

The read line currently in use to get the user input looks like this:

read -n 1 -s -t "${iRefresh}" sReturnVar.

Here "iRefresh" is set to 2 seconds in order to time out when no input is given to refresh the display and return to the read line thereafter. In essence the read line doubles as a content refresher while waiting for user input.

Phoenix
  • 186
  • 9
  • What about https://stackoverflow.com/questions/37948079/read-a-key-combination-with-bash-script ? – vdavid Jun 10 '21 at 11:03

1 Answers1

5

This will dynamically determine the values for F1-F24, then use them in the context you're looking for. My system coopts F11, so I did not show that. This is somewhat brittle in that it depends on terminfo and sane terminal codes -- YMMV.

#!/usr/bin/env bash

read_key_press() {
  if read -sN1 key_press; then
    while read -sN1 -t 0.001 ; do
      key_press+="${REPLY}"
    done
  fi
}

declare -a fnkey
for x in {1..24}; do
    raw=$(tput kf$x | cat -A)
    fnkey[$x]=${raw#^[}
done

while read_key_press; do
  case "${key_press}" in
    $'\e'${fnkey[1]})   echo 'F1';;
    $'\e'${fnkey[2]})   echo 'F2';;
    $'\e'${fnkey[3]})   echo 'F3';;
    $'\e'${fnkey[4]})   echo 'F4';;
    $'\e'${fnkey[5]})   echo 'F5';;
    $'\e'${fnkey[6]})   echo 'F6';;
    $'\e'${fnkey[7]})   echo 'F7';;
    $'\e'${fnkey[8]})   echo 'F8';;
    $'\e'${fnkey[9]})   echo 'F9';;
    $'\e'${fnkey[10]})   echo 'F10';;
    $'\e'${fnkey[11]})   echo 'F11';;
    $'\e'${fnkey[12]})   echo 'F12';;
    $'\e'${fnkey[13]})   echo 'F13';;
    $'\e'${fnkey[14]})   echo 'F14';;
    $'\e'${fnkey[15]})   echo 'F15';;
    $'\e'${fnkey[16]})   echo 'F16';;
    $'\e'${fnkey[17]})   echo 'F17';;
    $'\e'${fnkey[18]})   echo 'F18';;
    $'\e'${fnkey[19]})   echo 'F19';;
    $'\e'${fnkey[20]})   echo 'F20';;
    $'\e'${fnkey[21]})   echo 'F21';;
    $'\e'${fnkey[22]})   echo 'F22';;
    $'\e'${fnkey[23]})   echo 'F23';;
    $'\e'${fnkey[24]})   echo 'F24';;
    ^D) exit ;;    # note: this is a real <ctrl>-<d>
    *) echo    "Key pressed: ${key_press}";;
  esac
done

For me, this produces:

<~> $ /tmp/so8897.sh
Key pressed: q
Key pressed: w
Key pressed: e
Key pressed: r
Key pressed: t
Key pressed: y
F1
F2
F3
F4
F5
F6
F7
F8
F9
F10
F12
F13
F14
F15
F16
F17
F18
F19
F20
F21
F22
F23
F24
Joe Casadonte
  • 15,888
  • 11
  • 45
  • 57
  • This looks like a great way to implement it. I just realized, however, that I use the timeout ability `-t 2` to regularly update the displayed content of the script every two seconds when no option was pressed. Is there a way to combine that (to get the script to update the displayed content every two seconds, but still allow input from extended keys like the F-keys)? – Phoenix Jun 11 '21 at 07:59
  • You'd have to post a code snippet. In general, though, the above should easily integrated into whatever you already have to read "normal" keys; there's anything special in the way I'm reading input, so just add the above escape codes into whatever you have for processing your keys already, and now you can process function keys, too. – Joe Casadonte Jun 11 '21 at 11:42
  • 1
    I must apologize. Heavy time constraints prohibited me from properly look at your code and due to that missed the `if read -sN1 key_press; then` line above the one I focused on. After revisiting it today, I was now successful to implement this and it worked as outlined. A big THANKS from me! – Phoenix Jun 19 '21 at 11:53