En bash, depuis l'intérieur de PROMPT_COMMAND, existe-t-il un moyen de savoir si l'utilisateur vient d'appuyer sur 'return' et n'a pas entré de commande?
En bash, depuis l'intérieur de PROMPT_COMMAND, existe-t-il un moyen de savoir si l'utilisateur vient d'appuyer sur 'return' et n'a pas entré de commande?
Réponses:
Vérifiez si le numéro d'historique a été incrémenté. Une invite annulée ou une invite où l'utilisateur vient d'appuyer Entern'augmentera pas le numéro d'historique.
Le numéro d'historique est disponible dans la variable HISTCMD
, mais il n'est pas disponible dans PROMPT_COMMAND
(car ce que vous voulez, c'est en fait le numéro d'historique de la commande précédente; la commande qui s'exécute PROMPT_COMMAND
elle-même n'a pas de numéro d'historique). Vous pouvez obtenir le nombre à partir de la sortie 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'
Notez que si vous avez activé l'écrasement des doublons dans l'historique ( HISTCONTROL=ignoredups
ou HISTCONTROL=erasedups
), cela signalera par erreur une commande vide après avoir exécuté deux commandes identiques successivement.
${HISTCMD_previous%%$'[\t ]'*}
bit manquait le $'…'
et `,
j'ai fini par tronquer après t` ou espace au lieu de après tab ou espace, mais bash imprime un onglet.
Il existe une solution de contournement, mais elle a certaines exigences:
Vous devez définir $HISTCONTROL
pour enregistrer TOUTES les commandes, ainsi que les doublons et les espaces. Alors définissez:
HISTCONTROL=
Définissez maintenant une fonction à appeler $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"
}
Maintenant, définissez la $PROMPT_COMMAND
variable:
PROMPT_COMMAND="isnewline"
Voir la sortie:
user@host:~$ true
user@host:~$ <return>
User hit return
user@host:~$ <space><return>
user@host:~$
last
est conservée d'une invocation de isnewline
à la suivante (choisissez seulement un nom moins générique comme prompt_command__isnewline__last
pour éviter les conflits).
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
Je ne connais aucun moyen de le faire, en soi . Mais vous pouvez obtenir le même effet en utilisant
piège le débogage de some_command_or_function
Cela entraînera l' some_command_or_function
appel à chaque fois que vous exécutez une commande. La chose délicate est qu'elle ne sera pas appelée si vous appuyez simplement sur Enter- sauf si vous avez défini un PROMPT_COMMAND, auquel cas frapper Enterinvoque le PROMPT_COMMAND, qui, à son tour, déclenche le piège.
La façon la plus simple d'obtenir le résultat souhaité est peut-être de définir une fonction d'interruption de débogage au lieu d'utiliser un PROMPT_COMMAND. Mais je ne peux pas le dire, car je ne sais pas quel résultat tu veux. Si vous voulez que quelque chose se produise lorsque vous venez de frapper Enteret que quelque chose de différent / supplémentaire se produise lorsque vous tapez une commande, alors (AFAIK) vous devez utiliser une interruption de débogage et une PROMPT_COMMAND. Voir cette réponse et celle-ci pour un moyen de faire en sorte que les deux mécanismes fonctionnent bien ensemble.
(Cela aurait été un commentaire à la réponse acceptée si j'avais été autorisé à ajouter des commentaires ...) @schlimmen, vous pouvez définir HISTTIMEFORMAT
quelque chose comme HISTTIMEFORMAT='%F %T '
, puis enregistrer et comparer history 1
. C'est parce qu'avec les effacements, au moins l'horodatage de la dernière commande (éventuellement répétée) change à chaque fois --- et avec HISSTIMEFORMAT
un réglage approprié, history 1
affichera l'horodatage (contrairement fc
), et différera donc même entre les commandes répétées.