saber si el último comando estaba vacío en PROMPT_COMMAND

12

En bash, desde PROMPT_COMMAND, ¿hay alguna forma de saber si el usuario simplemente presionó 'regresar' y no ingresó un comando?

usuario
fuente

Respuestas:

7

Compruebe si el número de historial se incrementó. Un aviso cancelado o un aviso donde el usuario acaba de presionar Enterno incrementará el número del historial.

El número de historial está disponible en la variable HISTCMD, pero no está disponible en PROMPT_COMMAND(porque lo que desea allí es, de hecho, el número de historial del comando anterior; el comando que se ejecuta PROMPT_COMMANDsolo no tiene número de historial). Puede obtener el número de la salida 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'

Tenga en cuenta que si ha activado el aplastamiento de duplicados en el historial ( HISTCONTROL=ignoredupso HISTCONTROL=erasedups), esto informará erróneamente un comando vacío después de ejecutar dos comandos idénticos sucesivamente.

Gilles 'SO- deja de ser malvado'
fuente
Gracias Gilles Me falta algo aquí. Esto nunca parece ejecutarse, ya que poner 'echo hello' en la primera línea de la función literal no funciona, aunque PROMPT_COMMAND = 'echo hello' sí funciona. Pensé que podría ser el problema HISTCMD_previous vs HISTCMD_PREVIOUS, pero no dados. Seguiré hurgando, pero estoy comentando ya que tu bash fu es claramente ligas más allá de la mía.
usuario
@user Arreglé más errores tipográficos, en particular, ${HISTCMD_previous%%$'[\t ]'*}faltaba el bit $'…'y terminó truncado después de `, t` o espacio en lugar de después de tabulación o espacio, pero bash imprime una ficha.
Gilles 'SO- deja de ser malvado'
1
Esta solución se basa en el supuesto de que los duplicados se guardan en el historial (que está desactivado para mí). Por lo tanto, esta solución no funciona como se esperaba para los comandos repetidos, mientras que los duplicados no se guardan en el historial.
schlimmchen
4

Hay una solución alternativa, pero tiene algunos requisitos:

Debe configurar $HISTCONTROLpara guardar TODOS los comandos, también duplicados y espacios. Entonces establece:

HISTCONTROL=

Ahora defina una función para llamar 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"
}

Ahora, establezca la $PROMPT_COMMANDvariable:

PROMPT_COMMAND="isnewline"

Ver la salida:

user@host:~$ true
user@host:~$ <return>
User hit return
user@host:~$ <space><return>
user@host:~$ 
caos
fuente
No entiendo por qué estás usando un archivo temporal aquí. La variable lastse conserva de una invocación isnewlinea la siguiente (solo elija un nombre menos genérico prompt_command__isnewline__lastpara evitar conflictos).
Gilles 'SO- deja de ser malvado'
@Gilles Tienes razón, lo cambié, gracias por tu sugerencia
caos
Gracias caos. Utilicé la misma idea para lo siguiente, que es un poco más fácil de analizar. 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
usuario
1

No sé de una manera de hacer eso, per se . Pero puedes obtener el mismo efecto usando

atrapar algún_comando_o_función de depuración

Esto hará some_command_or_functionque se invoque cada vez que ejecute un comando. Lo complicado es que no se Enterinvocará si solo golpeas , a menos que tengas un PROMPT_COMMAND definido, en cuyo caso golpear Enterinvoca PROMPT_COMMAND, que, a su vez, activa la trampa.

Quizás la forma más sencilla de lograr el resultado que desea es definir una función de captura de depuración en lugar de utilizar un PROMPT_COMMAND. Pero no puedo decirlo, porque no sé qué resultado quieres. Si desea que algo suceda cuando presiona Enter, y que suceda algo diferente / adicional cuando escribe un comando, (AFAIK) debe usar una trampa de depuración y un PROMPT_COMMAND. Vea esta respuestaesta para una forma de hacer que los dos mecanismos jueguen bien juntos.

Scott
fuente
0

(Esto habría sido un comentario a la respuesta aceptada si me hubieran permitido agregar comentarios ...) @schlimmen, puede configurar HISTTIMEFORMATalgo así HISTTIMEFORMAT='%F %T 'y luego guardar y comparar history 1. Es porque con borrados al menos la marca de tiempo del último comando (posiblemente repetido) cambia cada vez --- y con HISSTIMEFORMATel ajuste apropiado, history 1mostrará la marca de tiempo (a diferencia fc) y, por lo tanto, diferirá incluso entre los comandos repetidos.

Pavel Smerk
fuente