The simplest approach to emulate bash's $PROMPT_COMMAND
which comes to my mind is to use the precmd
hook, as you already figured out. Define it as
precmd() { eval "$PROMPT_COMMAND" }
and you can do something like that:
$ PROMPT_COMMAND='echo Hello, it is now $(date)'
Hello, it is now Mon, Mar 31, 2014 7:08:00 PM
$ whoami
user
Hello, it is now Mon, Mar 31, 2014 7:08:21 PM
$
Please note the single quotes in that example, otherwise $(date)
will get expanded too early, i.e. already when defining $PROMPT_COMMAND
and not when called before the prompt.
If you want to preserve (and don't want to alter) the existing definition, you can use that approach:
$ prmptcmd() { eval "$PROMPT_COMMAND" }
$ precmd_functions=(prmptcmd)
With that the prmptcmd
functions is executed after the existing precmd()
function.
Finally, here is a way which is suitable for use in a program package, which neither should modify user or system files nor can enter the commands interactive.
An example to spawn a bash session could be
PROMPT_COMMAND="echo foo" bash
To spawn zsh you can use
ZDOTDIR=/program/dir zsh
which causes /program/dir/.zshrc
to be sourced. In this file the precmd()
hook can be defined as explained above. If you want the user's settings in addition include source $HOME/.zshrc
etc. in the program's .zshrc, too.
This setup is maintainable, as no files outside the program directory are modified.
As a last addition, here is a proof of concept how to keep the newuser welcome, too. Use the following code in your /program/dir/.zshenv
rc config file:
echo define precmd, traps, etc.
autoload -Uz zsh-newuser-install
if [[ ! -e "$HOME/.zshrc" ]]; then
zsh-newuser-install -f
mv $ZDOTDIR/.zshrc $HOME/.zshrc
else
builtin source $HOME/.zshrc
fi
Truth to be told, I need a post-interactive-command-execution hook, but neither shell provides one so I have to resort to pre-prompt hooks - they seem to be as close as I can get. – Shnatsel – 2014-03-31T02:13:42.207
1Hm, I am wondering, what the difference between post-interactive-command-execution and pre-prompt is. Apart from a conceptual difference, where do you observe actually a difference. (Let's omit the commands
exit
andexec
, ok;)
) – mpy – 2014-03-31T17:21:54.110@mpy there's a difference when running a background job, because background jobs are independent from the prompt sequence. – Shnatsel – 2014-03-31T19:52:00.603
1Ok, I got that point. So, how about something like that:
start() { eval "$@"; echo post-command-code }
and then use a zle-binding to execute the command line withstart
prepended? – mpy – 2014-03-31T20:14:49.853@mpy Actually there might be an even better way, here's what I found in shell options: "DEBUG_BEFORE_CMD Run the DEBUG trap before each command; otherwise it is run after each command." Looks like this is exactly what I need! – Shnatsel – 2014-04-02T23:50:48.260
1The
DEBUG
trap is a nice find, but you still have the problem how to define it. I've extended my answer once more, but I leave it to you to write your own answer regarding the DEBUG trap solution.:)
– mpy – 2014-04-03T17:23:34.413