Each shell has its own way of expanding the prompt. OpenBSD's ksh is pdksh. See its prompt settings in the manual, under the PS1
parameter.
The way ksh works is that it performs parameter substitution, command substitution and arithmetic substitution (all the $
expansions) on the value of PS1
before printing the prompt. So you set PS1
once and for all, but the value is regenerated each time. (You can do that in bash too, if you put shopt -s promptvars
in your .bashrc
.)
OpenBSD's ksh supports backslash escapes similar to bash. With other versions of ksh, you'd need to translate the bash prompt escape sequences into $
substitutions as well.
PS1='$(if (($? == 0)); then print -n "\\033[32m"; else print -n "\\033[31m"; fi)'
PS1="$PS1"'[\u@\h \w]'$(print '\033')'[0m '
The simple translation above has a few defects:
- It forks a process each time, to analyze
$?
. There is a way to avoid this, but it's hackish in ksh88.
- It causes redrawing bugs, because of the zero-width control sequences. This can be avoided with the gross hack documented in the manual.
Here's some more complex code that uses arithmetic to avoid spawning a subshell and takes care of delimiting non-printable sequences.
escape=$(print '\033')
ctrla=$(print '\001')
PS1=$(print '\001\015')
PS1=$PS1$ctrla$escape'[$(($? ? 31 : 32))m'$ctrla
PS1=$PS1'[\u@\h \w]'
PS1=$PS1$ctrla$escape'[0m'$ctrla' '
PS1
does not need to be exported since I don't know of any programs besides interactive shells that use it, and interactive shells get their value ofPS1
from the relevantrc
file already. The reason I mention this is environment variables take up space inARG_MAX
which means you generally don't want a huge environment, or else you will run into "argument list too long" errors more frequently.