4

For my powerlevel10k custom prompt, I currently have this function to display the seconds since the epoch, comma separated. I display it under the current time so I always have a cue to remember roughly what the current epoch time is.

function prompt_epoch() {
  MYEPOCH=$(/bin/date +%s | sed ':a;s/\B[0-9]\{3\}\>/,&/;ta')
  p10k segment -f 66 -t ${MYEPOCH}
}

My prompt looks like this: prompt example screenshot

I've been told I can do this without the forked processes using these commands:

$ zmodload -F zsh/datetime p:EPOCHSECONDS
$ printf "%'d" $EPOCHSECONDS
1,648,943,504

But I'm not sure how to do that without the forking. I know to add the zmodload line in my ~/.zshrc before my powerlevel10k is sourced, but formatting ${EPOCHSECONDS} isn't something I know how to do without a fork.

If I were doing it the way I know, this is what I'd do:

function prompt_epoch() {
  MYEPOCH=$(printf "%'d" ${EPOCHSECONDS})
  p10k segment -f 66 -t ${MYEPOCH}
}

But as far as I understand it, that's still forking a process every time the prompt is called, correct? Am I misunderstanding the advice given because I don't think I can see a way to get the latest epoch seconds without running some sort of process, which requires a fork, correct?

1

2 Answers 2

7

The printf utility in both bash and zsh has a -v option that allows you to "print into a variable":

printf -v MYEPOCH "%'d" ${EPOCHSECONDS}

The actual result of the above command may well be dependent on the current locale.

2
  • I was looking in completely the wrong place, thank you very much for a great answer. I really appreciate your help, you're the best!
    – acjca2
    Apr 3, 2022 at 12:07
  • The function printf in zsh is documented here.
    – acjca2
    Apr 3, 2022 at 13:25
3

FWIW, you can also do:

zmodload zsh/datetime
set -o histsubstpattern -o promptsubst -o extendedglob
RPS1='$EPOCHSECONDS:fs/%(#b)([^,])([^,](#c3)(|,*))/$match[1],$match[2]'

To get something like 1,648,989,768 in your right prompt without forking a process nor relying on the locale for the value of the thousands separator.

${param:fs/left/right} uses the substitute history modifier like in csh, while the f one repeats it as long as it changes something, achieving something similar to your GNU sed approach.

With the histsubstpattern option enabled, left can be a pattern, so $param:s/left/right behaves like ksh93's ${param/pattern/replacement} except we can combine it with that f modifier which makes it more useful here.

Like with ksh93's ${param/pattern/replacement}, the pattern can be preceded by % to match only at the end of the subject. With extendedglob, we can enable back-references with (#b) or use (#c3) to match 3 of the preceding atom like ERE's {3}.

Note that beside $EPOCHSECONDS (for which you need to load the zsh/datetime module), the epoch time can also be obtained with the %D{%s} prompt expansion. To be able to apply a modifier on it, you'd have to have it be expanded as part of parameter expansion though. That can be done with the % parameter expansion flag:

set -o histsubstpattern -o promptsubst -o extendedglob
RPS1='${${(%):-"%D{%s}"}:fs/%(#b)([^,])([^,](#c3)(|,*))/$match[1],$match[2]}'
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .