Pressionar as teclas de leitura no shell usando sinais trap e Unix

3

Estou com dificuldade para entender a finalidade de trap e as várias invocações de stty no snippet abaixo.

Eu estava esperando que alguém pudesse me dar um resumo do que está acontecendo.

getkey() {
  local stty="$(stty -g)"
  trap "stty $stty; trap SIGINT; return 128" SIGINT
  stty cbreak -echo 
  local key
  while true; do
    key=$(dd count=1 2>/dev/null) || return $?
    if [ -z "$1" ] || [[ "$key" == [$1] ]]; then
      break
    fi
  done
  stty $stty
  echo "$key"
  return 0
}
    
por Jorge Bucaran 15.05.2015 / 22:25

1 resposta

4
local stty="$(stty -g)"

Salve as configurações atuais do terminal. stty $stty , que é executado quando a função retorna normalmente e no SIGINT, restaura essas configurações.

trap "stty $stty; trap SIGINT; return 128" SIGINT

Se a função for interrompida por SIGINT (o sinal enviado pressionando Ctrl + C ), restaure as configurações do terminal e retorne 128. (Por que 128? Pergunto-me. Normalmente, o status de saída em um sinal seria de 128 + número de sinal.)

stty cbreak -echo 

Desative a funcionalidade de edição bruta do terminal (caractere / palavra / apagamento de linha) e desative o eco dos caracteres à medida que eles são digitados.

  key=$(dd count=1 2>/dev/null) || return $?

Leia até 512 bytes do terminal ( count é um número de blocos e o tamanho padrão do bloco é de 512 bytes). Isso é um pouco estranho: acho que a intenção era ler um byte. Como dd retornará assim que pelo menos um byte estiver disponível, isso retornará um único byte na prática se um usuário estiver digitando, mas se um programa estiver alimentando as teclas pressionadas ou se o sistema estiver lento, isso poderá ler mais bytes. O código tem o benefício de que, se o usuário digitar um caractere multibyte, todos os bytes que compõem o caractere serão provavelmente (mas não garantidos) lidos na iteração do loop.

Se dd retornar um status diferente de zero, isso indica um erro de leitura ou um sinal; a função retorna imediatamente. As configurações do terminal não são restauradas, o que é um bug, embora na maioria das vezes o erro seja o usuário pressionar Ctrl + C , nesse caso as configurações do terminal são restaurados, ou que o terminal desapareceu, caso em que o ponto é discutível.

  if [ -z "$1" ] || [[ "$key" == [$1] ]]; then
    break
  fi

Sair do loop se o (s) byte (s) lido (s) for um dos caracteres no argumento da função. Se o argumento estiver vazio, qualquer caractere terminará o loop. O argumento não é exatamente uma lista de caracteres, está em curinga sintaxe do conjunto de caracteres: um ^ ou ! inicial inverte o conjunto, um sinal de menos na maioria das posições é analisado como um intervalo (por exemplo, 0-9 ), [:…:] e [.….] denotam classes de caracteres e símbolos de agrupamento respectivamente e uma barra invertida cita o próximo \ , [ , ] ou - .

    
por 16.05.2015 / 02:36