indica se l'ultimo comando era vuoto in PROMPT_COMMAND


12

In bash, dall'interno di PROMPT_COMMAND, c'è un modo per dire se l'utente ha appena premuto 'return' e non ha inserito un comando?

Risposte:


7

Controlla se il numero di cronologia è stato incrementato. Un prompt annullato o un prompt in cui l'utente ha appena premuto Enternon incrementa il numero della cronologia.

Il numero di cronologia è disponibile nella variabile HISTCMD, ma questo non è disponibile in PROMPT_COMMAND(perché ciò che si desidera è in realtà il numero di cronologia del comando precedente; il comando che si esegue da PROMPT_COMMANDsolo non ha un numero di cronologia). È possibile ottenere il numero dall'output di 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'

Nota che se hai attivato la compressione dei duplicati nella cronologia ( HISTCONTROL=ignoredupso HISTCONTROL=erasedups), questo riporterà erroneamente un comando vuoto dopo aver eseguito successivamente due comandi identici.


Grazie Gilles. Mi manca qualcosa qui. Questo non sembra mai funzionare, come mettere 'ciao echo' sulla prima riga della funzione letterale non funziona, sebbene PROMPT_COMMAND = 'ciao echo'. Ho pensato che potesse essere il problema HISTCMD_previous vs HISTCMD_PREVIOUS, ma nessun dado. Continuerò a frugare, ma sto commentando perché il tuo fu bash è chiaramente leghe oltre il mio.
utente

@utente Ho corretto più errori di battitura, in particolare il ${HISTCMD_previous%%$'[\t ]'*}bit mancava $'…'e alla fine si è troncato dopo `, t` o spazio anziché dopo tab o spazio, ma bash stampa una scheda.
Gilles 'SO- smetti di essere malvagio' il

1
Questa soluzione si basa sul presupposto che i duplicati siano salvati nella cronologia (che è OFF per me). Quindi questa soluzione non funziona come previsto per i comandi ripetuti mentre i duplicati non vengono salvati nella cronologia.
schlimmchen,

4

C'è una soluzione alternativa, ma ha alcuni requisiti:

È necessario impostare $HISTCONTROLper salvare TUTTI i comandi, anche i duplicati e gli spazi. Quindi impostare:

HISTCONTROL=

Ora definisci una funzione da chiamare come $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"
}

Ora imposta la $PROMPT_COMMANDvariabile:

PROMPT_COMMAND="isnewline"

Vedi l'output:

user@host:~$ true
user@host:~$ <return>
User hit return
user@host:~$ <space><return>
user@host:~$ 

Non capisco perché stai usando un file temporaneo qui. La variabile lastviene conservata da un richiamo isnewlineal successivo (scegli solo un nome meno generico come prompt_command__isnewline__lastper evitare scontri).
Gilles 'SO- smetti di essere malvagio' il

@Gilles Hai ragione, l'ho cambiato, grazie per il tuo suggerimento
caos

Grazie, caos. Ho usato la stessa idea per quanto segue, che è un po 'più facile da analizzare. 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
utente

1

Non conosco un modo per farlo, di per sé . Ma puoi ottenere lo stesso effetto usando

trap debug some_command_or_function

Questo farà sì some_command_or_functionche venga chiamato ogni volta che si esegue un comando. La cosa difficile è che non verrà chiamato se colpisci semplicemente Enter- a meno che tu non abbia definito un PROMPT_COMMAND, nel qual caso colpire Enterinvoca il PROMPT_COMMAND, che, a sua volta, attiva la trappola.

Forse il modo più semplice per ottenere il risultato desiderato è definire una funzione trap di debug invece di utilizzare un PROMPT_COMMAND. Ma non posso dirlo, perché non so quale risultato desideri. Se vuoi che accada qualcosa quando hai appena colpito Entere qualcosa di diverso / aggiuntivo accade quando digiti un comando, allora (AFAIK) devi usare una trap di debug e un PROMPT_COMMAND. Vedi questa rispostaquesta per un modo per far funzionare bene i due meccanismi insieme.


0

(Questo sarebbe stato un commento alla risposta accettata se mi fosse stato permesso di aggiungere commenti ...) @schlimmen, potresti impostare HISTTIMEFORMATqualcosa di simile HISTTIMEFORMAT='%F %T 'e quindi salvare e confrontare history 1. È perché con le cancellazioni almeno il timestamp dell'ultimo (possibilmente ripetuto) ultimo comando cambia ogni volta --- e con un'impostazione HISSTIMEFORMATappropriata, history 1visualizzerà il timestamp (a differenza di fc), e quindi differisce anche tra i comandi ripetuti.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.