jotapdiez
jotapdiez

Reputation: 1466

handle user input on background

I want to handle user input, but in the background, like in a new thread.

For example, show a progress bar, and when the user hits R, the progress bar resets, or if the user hits Q, the script exits.

I don't want the script to wait for user input. Just render everything and if the user hits any key do something.

Is it posible in bash?

Thanks in advance.

EDIT: I need the script ALWAYS read user input but do not interrupt the execution of main loop.Complicated I make myself understood in English

_handle_keys()
{
    read -sn1 a
    test "$a" == `echo -en "\e"` || continue
    read -sn1 a
    test "$a" == "[" || break
    read -sn1 a

    case "$a" in
        C) # Derecha
            if [ $PALETTE_X -lt $(($COLUMNS-$PALETTE_SIZE)) ] ; then
                PALETTE_X=$(($PALETTE_X+1))
            fi
        ;; 
        D) # Izquierda
            if [ $PALETTE_X -gt 0 ] ; then
                PALETTE_X=$(($PALETTE_X-1))
            fi
        ;;
    esac
}
render()
{
    clear
    printf "\033[2;0f BALL (X:${BALL_X} | Y:${BALL_Y})"
    _palette_render # Actualiza la paleta
    _ball_render
}

while true
do
    LINES=`tput lines`
    COLUMNS=`tput cols`

    render
    _handle_keys
done

In my script, the ball moves (render>_ball_render) only when a key is pressed because _handle_keys wait for user input.

I made a ugly solution with read -t0.1 but don't like this

PD: Sorry for my last comment, the time edit finish in the middle of my editing

Upvotes: 5

Views: 4121

Answers (2)

Rado
Rado

Reputation: 66

You might also add "reset" to the end of the script to reset the terminal into original state, or it might look locked. It will clear the screen as well, so one might want to add a pause before executing the command.

Upvotes: 1

Andy
Andy

Reputation: 4866

Here is a technique that seems to work. I am basing this on Sam Hocevar's answer to Bash: How to end infinite loop with any key pressed?.

#!/bin/bash

if [ ! -t 0 ]; then
  echo "This script must be run from a terminal"
  exit 1
fi

stty -echo -icanon time 0 min 0

count=0
keypress=''
while true; do
  let count+=1
  echo -ne $count'\r'

  # This stuff goes in _handle_keys
  read keypress
  case $keypress in
  # This case is for no keypress
  "")
    ;;
  $'\e[C')
    echo "derecha"
    ;;
  $'\e[D')
    echo "izquierda"
    ;;
  # If you want to do something for unknown keys, otherwise leave this out
  *)
    echo "unknown input $keypress"
    ;;
  esac
  # End _handle_keys
done

stty sane

If the stty sane is missed (e.g. because the script gets killed with Ctrl-C), the terminal will be left in a weird state. You may want to look at the trap statement to address this.

Upvotes: 9

Related Questions