This handles the formatting by calculation - so, while it does expand several times, it doesn't do any subshells or pipes.
It just treats
$PS1 as an array and uses the higher indices to store/calculate any/all necessary state between prompts. No other shell state is affected.
00:00:43:[mikeserv@desktop tmp]$ sleep 10
00:00:33:[mikeserv@desktop tmp]$ sleep 10
I can break it down a little maybe...
First, save the current value of
$PS1 to be self-recursive in a way that will always set the right values to
$PS1[1-3] while simultaneously self-referencing. To get this part you have to consider the order in which shell-math expressions are evaluated. Most importantly, shell-math is always the last order of business for shell-math. Before all else, the shell expands values. In this way you can reference an old-value for a shell-variable in a math expression after assigning it by using
Here is a simple example first:
x=10; echo "$(((x+=5)+$x+x))" "$x"
The shell will evaluate that statement by first substituting the value of
$x wherever the
$ dollar-sign reference is used, and so the expression becomes:
...then the shell adds 5 to the value of
$x and afterward expands the whole expression to
x+10+x, while retaining only the actually assigned value in the reference variable. And so the math expression's expanded value is 40, but the ultimate value of
$x is 15.
That is largely how the
$PS1 equation works as well, except that there is a further level of math expansion/evaluation exploited in the array indices.
I'm not really sure why I chose to use
PS1=!1 there - I guess it was probably just silly aesthetics - but this assigns 0 to
$PS1 while expanding it for parameter substitution. The value of a bitwise AND for 0 and anything else will always be 0, but it doesn't short-circuit as a boolean
&& does when the left-most primary is 0 and so the parenthetical expression still gets evaluated every time. That is important, of course, because that first elipsis is where the initial values for
$PS1[2,3] are set.
$PS1 is here assured to be 0 even if it is tampered w/ between prompt draws. Within the parentheses there...
$PS1 is assigned the difference of
$PS1 is assigned the quotient of that value and 3600. All values are here initialized. And so:
...if there are at least two digits in
$PS1 then the inner expansion there is null, and because we know
$PS1 is 0 then if
$PS1 can be substituted away to nothing, so also is
$PS1 else it is expanded to its value. In this way only single digit values for each iteration of
$PS1 assignments will expand a leading zero, and
$PS1 is itself expanded modulo 60 immediately thereafter while being concurrently assigned the next successively smaller value for each of hours, minutes, seconds.
Rinse and repeat, until the last iteration when
$PS1 is overwritten w/ the current value of
$SECONDS so that it may be compared to
$SECONDS once more when the prompt is next drawn.