k-a-v
k-a-v

Reputation: 347

Bash - hide terminal arrow keys ("^[[A")

I wrote the following bash script.

#!/bin/bash

coordx=0
coordy=0

while true; do
    read -r -sn1 t
    case $t in
        A) 
            ((coordy--))
            tput cup $coordy $coordx
            printf "test"
        ;;
        B) 
            ((coordy++)) 
            tput cup $coordy $coordx
        ;;
        C)
            ((coordx++))
            tput cup $coordy $coordx
        ;;
        D) 
            ((coordx--))
            tput cup $coordy $coordx
        ;;
    esac
done

It moves the terminal cursor when arrow keys are pressed. However, when the keys are held down, the following happens:

gif

At random intervals, the terminal code for each of the arrow keys is displayed. How can I hide these so that the terminal doesn't display them but is still able to print out content?

Upvotes: 0

Views: 1435

Answers (1)

Léa Gris
Léa Gris

Reputation: 19625

Try with:

 -N nchars    return only after reading exactly NCHARS characters, unless
              EOF is encountered or read times out, ignoring any
              delimiter

Read all 3 characters of the arrow keys:

  • ESC[A,
  • ESC[B,
  • ESC[C,
  • ESC[D
    read -r -sN3 t
    t="${t:2:1}"

Played a bit expanding your code

#!/usr/bin/env bash

typeset -i \
  coordx=0 coordy=0 \
  pcoordx=0 pcoordy=0 \
  cols=$(tput cols) lines=$(tput lines)
typeset -i \
  maxcol=$((cols - 1)) \
  maxline=$((lines - 1))

while true; do
  read -r -sN3 t
  case "${t:2:1}" in
    A)
      ((coordy > 0 ? coordy-- : 0))
      if [ $pcoordy -ne $coordy ]; then
        tput cup $coordy $coordx
        pcoordy=$coordy
      else
        tput bel
      fi
      ;;
    B)
      ((coordy < maxline ? coordy++ : lines))
      if [ $pcoordy -ne $coordy ]; then
        tput cup $coordy $coordx
        pcoordy=$coordy
      else
        tput bel
      fi
      ;;
    C)
      ((coordx < maxcol ? coordx++ : cols))
      if [ $pcoordx -ne $coordx ]; then
        tput cup $coordy $coordx
        pcoordx=$coordx
      else
        tput bel
      fi
      ;;
    D)
      ((coordx > 0 ? coordx-- : 0))
      if [ $pcoordx -ne $coordx ]; then
        tput cup $coordy $coordx
        pcoordx=$coordx
      else
        tput bel
      fi
      ;;
  esac
done

Upvotes: 2

Related Questions