Elliot Reed
Elliot Reed

Reputation: 749

Stop command when key no longer being pressed in Bash

Thought this would have been more obvious, but I need to run a command whilst a key is being pressed, and stop the command (SIGINT) when it's no longer pressed.

For example:

#!/bin/bash

while [ F5 is being pressed ] ; do

    arecord -f cd -t wav

done

Upvotes: 1

Views: 75

Answers (1)

konsolebox
konsolebox

Reputation: 75548

Forwarding from PlayShell's keys.sh you can have:

#!/bin/bash

shopt -s extglob

KEYS_F5=$'\e[[E'
KEYS_XTERM_F5=$'\e[15~'

function keys_readonce {
    __V0='' __V1=''

    local A K
    local -a KEY=() S=() T=()

    for A; do
        case "$A" in
        +([[:digit:]]))
            T=(-t "$A")
            ;;
        -q|--quiet)
            S=(-s)
            ;;
        *)
            echo "Invalid argument: $A"
            exit 1
            ;;
        esac
    done

    local IFS=''

    if read -rn 1 -d '' "${T[@]}" "${S[@]}" K; then
        KEY[0]=$K

        if [[ $K == $'\e' ]]; then
            if [[ BASH_VERSINFO -ge 4 ]]; then
                T=(-t 0.05)
            else
                T=(-t 1)
            fi

            if read -rn 1 -d '' "${T[@]}" "${S[@]}" K; then
                case "$K" in
                \[)
                    KEY[1]=$K

                    local -i I=2

                    while
                        read -rn 1 -d '' "${T[@]}" "${S[@]}" "KEY[$I]" && \
                        [[ ${KEY[I]} != [[:upper:]~] ]]
                    do
                        (( ++I ))
                    done
                    ;;
                O)
                    KEY[1]=$K
                    read -rn 1 -d '' "${T[@]}" 'KEY[2]'
                    ;;
                [[:print:]]|$'\t'|$'\e')
                    KEY[1]=$K
                    ;;
                *)
                    __V1=$K
                    ;;
                esac
            fi
        fi

        __V0="${KEY[*]}"

        return 0
    fi

    return 1
}

while keys_readonce 5 && [[ $__V0 == "$KEYS_F5" || $__V0 == "$KEYS_XTERM_F5" ]]; do  ## 5 secs. timeout is optional
    # Do something
    :
done

Upvotes: 1

Related Questions