Sagen Sie, ob der letzte Befehl in PROMPT_COMMAND leer war

11

Gibt es in bash innerhalb von PROMPT_COMMAND eine Möglichkeit, festzustellen, ob der Benutzer nur die Eingabetaste gedrückt und keinen Befehl eingegeben hat?

Benutzer
quelle

Antworten:

7

Überprüfen Sie, ob die Verlaufsnummer erhöht wurde. Eine abgebrochene Eingabeaufforderung oder eine Eingabeaufforderung, bei der der Benutzer gerade gedrückt hatEnter , erhöht die Verlaufsnummer nicht.

Die Verlaufsnummer ist in der Variablen verfügbar HISTCMD, diese ist jedoch in nicht verfügbar PROMPT_COMMAND(da Sie tatsächlich die Verlaufsnummer des vorherigen Befehls wünschen; der Befehl, der sich PROMPT_COMMANDselbst ausführt , hat keine Verlaufsnummer). Sie können die Nummer aus der Ausgabe von erhalten 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'

Beachten Sie, dass, wenn Sie das Quetschen von Duplikaten im Verlauf ( HISTCONTROL=ignoredupsoder HISTCONTROL=erasedups) aktiviert haben , fälschlicherweise ein leerer Befehl gemeldet wird, nachdem zwei identische Befehle nacheinander ausgeführt wurden.

Gilles 'SO - hör auf böse zu sein'
quelle
Danke, Gilles. Mir fehlt hier etwas. Dies scheint nie zu funktionieren, da das Setzen von 'echo hello' in die erste Zeile der Literalfunktion nicht funktioniert, obwohl PROMPT_COMMAND = 'echo hello' dies tut. Ich dachte, es könnte das Problem HISTCMD_previous vs HISTCMD_PREVIOUS sein, aber keine Würfel. Ich werde weiter stochern, aber ich kommentiere, da Ihr Bash Fu eindeutig weit über meinem liegt.
Benutzer
@user Ich habe mehr Tippfehler behoben, insbesondere ${HISTCMD_previous%%$'[\t ]'*}fehlte das Bit $'…'und wurde nach `, t` oder Leerzeichen anstatt nach Tabulator oder Leerzeichen abgeschnitten, aber Bash druckt einen Tabulator.
Gilles 'SO - hör auf böse zu sein'
1
Diese Lösung basiert auf der Annahme, dass Duplikate im Verlauf gespeichert werden (was für mich AUS ist). Daher funktioniert diese Lösung bei wiederholten Befehlen nicht wie erwartet, während Duplikate nicht im Verlauf gespeichert werden.
schlimmchen
4

Es gibt eine Problemumgehung, die jedoch einige Anforderungen erfüllt:

Sie müssen festlegen $HISTCONTROL, dass ALLE Befehle sowie Duplikate und Leerzeichen gespeichert werden. Also setzen Sie:

HISTCONTROL=

Definieren Sie nun eine aufzurufende Funktion als $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"
}

Stellen Sie nun die $PROMPT_COMMANDVariable ein:

PROMPT_COMMAND="isnewline"

Siehe die Ausgabe:

user@host:~$ true
user@host:~$ <return>
User hit return
user@host:~$ <space><return>
user@host:~$ 
Chaos
quelle
Ich verstehe nicht, warum Sie hier eine temporäre Datei verwenden. Die Variable lastbleibt von einem Aufruf isnewlinezum nächsten erhalten (wählen Sie nur einen weniger generischen Namen prompt_command__isnewline__last, um Konflikte zu vermeiden).
Gilles 'SO - hör auf böse zu sein'
@ Gilles Du hast recht, ich habe es geändert, danke für deinen Vorschlag
Chaos
Danke, Chaos. Ich habe die gleiche Idee für das Folgende verwendet, was etwas einfacher zu analysieren ist. 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
Benutzer
0

Ich kenne per se keinen Weg, das zu tun . Mit können Sie jedoch den gleichen Effekt erzielen

Trap some_command_or_function Debug

Dadurch wird der some_command_or_functionjedes Mal aufgerufen, wenn Sie einen Befehl ausführen. Das Knifflige ist, dass es nicht aufgerufen wird, wenn Sie nur Enterdrücken - es sei denn, Sie haben ein PROMPT_COMMAND definiert. In diesem Fall Enterruft das Schlagen das PROMPT_COMMAND auf, was wiederum die Falle auslöst.

Der einfachste Weg, um das gewünschte Ergebnis zu erzielen, besteht darin, eine Debug-Trap-Funktion zu definieren, anstatt PROMPT_COMMAND zu verwenden. Aber ich kann es nicht sagen, weil ich nicht weiß, welches Ergebnis Sie wollen. Wenn Sie möchten, dass etwas passiert, wenn Sie nur drücken Enter, und etwas anderes / zusätzliches passiert, wenn Sie einen Befehl eingeben, müssen Sie (AFAIK) einen Debug-Trap und ein PROMPT_COMMAND verwenden. In dieser Antwort finden Sie eine Möglichkeit, die beiden Mechanismen gut zusammenspielen zu lassen.

Scott
quelle
0

(Dies wäre ein Kommentar zu der akzeptierten Antwort gewesen, wenn ich Kommentare hätte hinzufügen dürfen ...) @schlimmen, Sie können HISTTIMEFORMATetwas wie einstellen HISTTIMEFORMAT='%F %T 'und dann speichern und vergleichen history 1. Dies liegt daran, dass bei Löschvorgängen mindestens der Zeitstempel des (möglicherweise wiederholten) letzten Befehls jedes Mal geändert wird - und bei HISSTIMEFORMATentsprechender Einstellung history 1der Zeitstempel (im Gegensatz zu fc) angezeigt wird und sich daher auch zwischen den wiederholten Befehlen unterscheidet.

Pavel Smerk
quelle