BASH question: usando read, posso capturar uma única tecla de seta char (em keyup)

3

Então aqui está o meu negócio: trabalhando no BASH, eu já construí uma função que funciona muito bem, que aceita um array ou qualquer número de parâmetros, e cospe um menu interativo, navegável por setas para cima ou para baixo e concluindo com o usuário pressionando enter, tendo destacado o item de menu desejado (cuja saída é o índice ou o valor do item de menu, dependendo de como o menu é iniciado):

Tudoissoestáfuncionandobem;Eurenderizoomenue,emseguida,respondoaoseventosanalisadosapartirdaentradadousuárioparaopromptinvisíveldeumcomandoread(disparadoautomaticamenteapósacoletade3caracteres):%código%Asaída,tendosidoalimentadaemumavariávelread-s-n3key2>/dev/null>&2,éexecutadapormeiodeumainstrução$keyavaliandoasentradasaceitáveisprevistas:case(up)3[A(abaixo)3[A(enter)queporsuavezdisparamoscomportamentosdesejados.

Noentanto,percebiquecomaintroduçãodemaisde7itensdemenu(podemospressuporquenãodeveexceder10)seriabomdeixarousuáriotocarnaentradanuméricadoitemdemenudesejado,oqueseriarealceoitememquestãosemenviá-lo.

Meuproblemaéeste:Euconseguiquefuncionemuitobemtambém,MASousuário,tendodigitadoateclanuméricadesejada(5nocasodesteexemplo)éentãoobrigadoapressionaratecla"" para a declaração enter ativar seu efeito, cortesia de meus sinalizadores read modifier no meu -n 3 . Isso é contrário ao modelo de usabilidade já estabelecido, a menos, é claro, que eles atinjam sua seleção numérica três vezes, desencadeando o requisito mínimo de 3 caracteres (o que é igualmente contra-intuitivo).

O problema é que read é tratado como 3 caracteres, sendo necessário o 3[A . 0-9 são tratados como SINGLE characters (ou seja, se eu alterar isso para um -n 3 , eles se comportam como esperado, mas agora as teclas de seta falham, coletando apenas o caractere de escape).

Então, eu acho que o que eu estou querendo saber é: existe uma maneira de ouvir um -n 1 ? Eu não consigo enviar um -n 1 {OR} 3 (whichever comes first) ou \n ou similar, como até que o \r tenha resolvido, eles não terão nenhum efeito (significando que não encontrei nenhum meio de simplesmente deixar o read durante a execução de um processo paralelo para verificar se o valor digitado é 0-9 caso ele prove um único caractere).

NÃO SE JUNTO a esta abordagem. Eu estou bem com o uso de -n 3 ou awk , ou mesmo sed (embora esse último eu esteja confuso ainda). Eu não me importo se é um expect que faz a coleta.

Editar:

SOLUÇÃO

read -n1 c
case "$c" in
    (1) echo One. ;;
    (2) echo Two. ;;
    ($'3') 
        read -t.001 -n2 r
        case "$r" in
            ('[A') echo Up. ;;
            ('[B') echo Down. ;;
        esac
esac

Status: resolvido

@choroba para o resgate!

Explicação da solução

Eu farei o meu melhor para parafrasear:

Sua solução envolveu aninhamento as duas declarações read (eu as estava experimentando sequencialmente) Foi isso, junto com o read (definindo assim um tempo limite quase instantâneo na função ) que permitiu que o carryover fosse lido.

Meu problema era que as chaves de escape que eu monitorava tinham 3 caracteres de comprimento (por isso, eu defini o -t.001 flag). Foi só depois que me ocorreu que aceitar certas entradas de único -caracteres também seria vantajoso.

Sua solução foi sugerir um caso -n3 :

Basicamente

  1. 'Ao ler o caractere de escape ...' ( **($'3') )
  2. **($'3') read '' (desta vez aguardando DOIS caracteres) e definido como timeout após um nanossegundo e impedindo barras invertidas em caracteres de escape.

Como o comportamento de Create another aparentemente é "transbordar" a entrada restante na instrução próximo read , a instrução mencionada iniciou sua contagem regressiva para o tempo limite com o valor procurado já tendo sido semeado. Como isso atendeu aos sinalizadores de requisito definidos para o read , tornou-se uma simples questão testar o segundo conjunto de caracteres para o resultado do caso (e como a função de inicialização ainda está recebendo a resposta esperada, embora a partir de uma instrução diferente, o programa continua como se tivesse conseguido os resultados que eu estava tentando encontrar em primeiro lugar.

    
por ZenAtWork 06.11.2018 / 11:41

1 resposta

4

Você pode ler por -n 1 e ler os dois seguintes se o primeiro for 3 e reagir de acordo. Caso contrário, manipule o número diretamente.

#!/bin/bash

read -n1 c
case "$c" in
    (1) echo One. ;;
    (2) echo Two. ;;
    ($'3') 
        read -t.001 -n2 r
        case "$r" in
            ('[A') echo Up. ;;
            ('[B') echo Down. ;;
        esac
esac
    
por 06.11.2018 / 12:13