ZSH: change prompt just before command is run

4

3

I would like to have a two-line prompt in zsh, but collapse it to a very small one just after pressing ENTER, so that it doesn't show up in the terminal scroll history. After typing two commands, the terminal should look like this while typing the third:

> echo Command 1
Command 1
> echo Command 2
Command 2
+------------ Long prompt ----------+
`> echo typing a new command here…

I tried getting something with the preexec hook and zle reset prompt, but I get the error widgets can only be called when ZLE is active:

$ autoload -U add-zsh-hook
$ hook_function() { OLD_PROMPT="$PROMPT"; export PROMPT="> "; zle reset-prompt; export PROMPT="$OLD_PROMPT"; }
$ PROMPT=$'+------------ Long prompt ----------+\n\`> '
+------------ Long prompt ----------+
`> add-zsh-hook preexec hook_function
+------------ Long prompt ----------+
`> echo Test
hook_function:zle: widgets can only be called when ZLE is active
Test
+------------ Long prompt ----------+
`> 

Suzanne Dupéron

Posted 2016-01-18T13:32:19.787

Reputation: 407

Answers

6

When the preexec function is called, zle is already finished and hence, zle widgets can't be used any more.

So, you have to intercept the pressing of the ENTER key before zle terminates. By default ENTER is bound to accept-line, but this might depend on other tricks you already use;

$ bindkey | grep '\^M'
"^M" accept-line

We now write a new widget we want to bind to ENTER instead:

del-prompt-accept-line() {
    OLD_PROMPT="$PROMPT"
    PROMPT="> "
    zle reset-prompt
    PROMPT="$OLD_PROMPT"
    zle accept-line
}

The logic is taken from your approach. In the last line we call the accept-line widget or anything else which was executed on pressing ENTER.

Finally we introduce the new widget to zle and bind it to ENTER:

zle -N del-prompt-accept-line
bindkey "^M" del-prompt-accept-line

Et voilà:

> echo foo bar
foo bar
+------------ Long prompt ----------+
`> echo this is my new command... not pressed ENTER, yet!

mpy

Posted 2016-01-18T13:32:19.787

Reputation: 20 866

very cool. i used this and added a timestamp and path which suited my work well. – Mike D – 2019-03-16T18:06:06.517