No bash, de dentro do PROMPT_COMMAND, existe uma maneira de saber se o usuário pressionou 'return' e não inseriu um comando?
No bash, de dentro do PROMPT_COMMAND, existe uma maneira de saber se o usuário pressionou 'return' e não inseriu um comando?
Respostas:
Verifique se o número do histórico foi incrementado. Um prompt cancelado ou um prompt em que o usuário acabou de pressionar Enternão aumentará o número do histórico.
O número do histórico está disponível na variável HISTCMD
, mas não está disponível em PROMPT_COMMAND
(porque o que você deseja é, de fato, o número do histórico do comando anterior; o comando que se executa por PROMPT_COMMAND
si mesmo não tem número do histórico). Você pode obter o número da saída de fc
.
prompt_command () {
HISTCMD_previous=$(fc -l -1); HISTCMD_previous=${HISTCMD_previous%%$'[\t ]'*}
if [[ -z $HISTCMD_before_last ]]; then
# initial prompt
elif [[ $HISTCMD_before_last = "$HISTCMD_previous" ]]; then
# cancelled prompt
else
# a command was run
fi
HISTCMD_before_last=$HISTCMD_previous
}
PROMPT_COMMAND='prompt_command'
Observe que, se você ativou o esmagamento de duplicatas no histórico ( HISTCONTROL=ignoredups
ou HISTCONTROL=erasedups
), isso reportará por engano um comando vazio após executar dois comandos idênticos sucessivamente.
${HISTCMD_previous%%$'[\t ]'*}
bit estava ausente $'…'
e acabou truncando após `,
t` ou espaço em vez de após tab ou espaço, mas o bash imprime uma tab.
Existe uma solução alternativa, mas ela tem alguns requisitos:
Você precisa definir $HISTCONTROL
para salvar TODOS os comandos, também duplicatas e espaços. Então defina:
HISTCONTROL=
Agora defina uma função para chamar como $PROMPT_COMMAND
:
isnewline () {
# read the last history number
prompt_command__isnewline__last="$prompt_command__isnewline__curr"
# get the current history number
prompt_command__isnewline__curr="$(history 1 | grep -oP '^\ +\K[0-9]+')"
[ "$prompt_command__isnewline__curr" = "$prompt_command__isnewline__last" ] && \
echo "User hit return"
}
Agora, defina a $PROMPT_COMMAND
variável:
PROMPT_COMMAND="isnewline"
Veja a saída:
user@host:~$ true
user@host:~$ <return>
User hit return
user@host:~$ <space><return>
user@host:~$
last
é preservada de uma chamada isnewline
para a próxima (escolha apenas um nome menos genérico prompt_command__isnewline__last
para evitar conflitos).
HISTCONTROL="" function last_was_blank { local last_command="$(history 1)" if [[ "$last_was_blank_PREVIOUS_LINE" = "$last_command" ]] ; then echo "true" else echo "false" fi export last_was_blank_PREVIOUS_LINE="$last_command" } PROMPT_COMMAND=last_was_blank
Não sei como, por si só . Mas você pode obter o mesmo efeito usando
interceptação some_command_or_function debug
Isso fará com some_command_or_function
que seja chamado sempre que você executar um comando. O mais complicado é que não será chamado se você apenas pressionar Enter- a menos que você tenha um PROMPT_COMMAND definido; nesse caso, pressionar Enterinvoca o PROMPT_COMMAND, que, por sua vez, aciona a armadilha.
Talvez a maneira mais simples de obter o resultado desejado seja definir uma função de interceptação de depuração em vez de usar um PROMPT_COMMAND. Mas não sei dizer, porque não sei qual resultado você deseja. Se você deseja que algo aconteça quando você apenas pressiona Enter, e algo diferente / adicional aconteça ao digitar um comando, (AFAIK), você precisa usar uma interceptação de depuração e um PROMPT_COMMAND. Veja esta resposta e esta como uma maneira de fazer com que os dois mecanismos funcionem bem juntos.
(Isso teria sido um comentário para a resposta aceita se eu tivesse permissão para adicionar comentários ...) @schlimmen, você pode definir HISTTIMEFORMAT
algo como isso HISTTIMEFORMAT='%F %T '
e depois salvar e comparar history 1
. Isso ocorre porque, com as cópias apagadas, pelo menos o registro de data e hora do último comando (possivelmente repetido) muda sempre - e, com HISSTIMEFORMAT
o ajuste apropriado, history 1
exibirá o registro de data e hora (diferente de fc
) e, portanto, difere mesmo entre os comandos repetidos.