You are not logged in.
Hi, I'm trying to create a zsh prompt. Best to show what I would like with an example:
~ user@hostname
> cd documents
~/documents user@hostname
> cd secret_project
~/documents/secret_project user@hostname
>Notice that the current directory takes up a fixed width, and if the string is shorter than that width then it is padded with spaces.
I have not been able to achieve fixed width with padding. I have tried the following:
P_CURDIR=$(printf "%-30s" "%~")
PROMPT=$P_CURDIR
PROMPT+=%M(note that %~ and %M are expanded by zsh into the working directory and hostname, respectively).
But this pads the working directory with 30 spaces always, rather than padding it with the correct number of spaces to ensure constant width. Like this:
~ user@hostname
> cd documents
~/documents user@hostname
> cd secret_project
~/documents/secret_project user@hostname
>Does anybody have any idea on how to achieve a prompt like the first example, as opposed to the second one?
Last edited by karkhaz (2014-03-16 19:50:19)
Offline
may be way off but have you tried replacing "%-30s" with "%-(30-%)s" I dont use zsh so I am not sure if it would read that as I would want it to.
Offline
may be way off but have you tried replacing "%-30s" with "%-(30-%)s"
'fraid not, that gives me .zshrc:printf:56: %-(: invalid directive. If it works on bash then it should work on zsh, as the printf command is a bash thing.
I'm going to mark this as solved, as I've found a hacky solution. If somebody has something more elegant, please do share. Else, I hope this is useful to somebody.
PROMPT=%~
DIR_WIDTH=40
for i in {0..$DIR_WIDTH}
do
PROMPT+=%$DIR_WIDTH(l.. )
done
PROMPT+=%MExplanation: the construct %n(l.x.y) prints out x if at least n characters have already been printed on the current line; else, it prints y. Thus, in the true case I print nothing, and in the false case I print out a space. Repeating this 40 times after I have already printed out the working directory gives the correct result. More explanation in section 13.3 on this page.
Edit: Just to be clear, the character to the right of the left paren in %$DIR_WIDTH(l.. ) is a lower-case leter 'el', not a number one.
Last edited by karkhaz (2014-03-16 19:52:19)
Offline
printf is not a bash built-in, but it is a zsh built-in. Try referring to the printf binary, /usr/bin/printf.
Offline
I don't use zsh, so I'm only speculating, but I believe that the "%~" doesn't get expanded during
P_CURDIR=$(printf "%-30s" "%~")Thus P_CURDIR contains the literal string "%~ " after that line is executed. The expansion is performed when you assign P_CURDIR to PROMPT.
Also, printf won't truncate the string to 30 characters. If %~ expands to more than 30 chars, you will get them all - which may not be what you want.
I believe you can use the 'print' zsh builtin to do what you want. Try this:
P_CURDIR=$(print -P -f "%-30s %s" %~ %M)
PROMPT=$P_CURDIRIf you want the directory name to be a maximum of 30 characters, you could truncate yourself. It all depends on which end you want to cut off. To have only the trailing 30 characters, do
P_CURDIR=$(print -P -f "%-30s" %~)
P_CURDIR=${P_CURDIR: -30}
PROMPT="$P_CURDIR %M"Note that you need the space between the : and the - in 'P_CURDIR=${P_CURDIR: -30}'.
If you want the leading 30 characters, try
P_CURDIR=$(print -P -f "%-30s" %~)
P_CURDIR=${P_CURDIR:0:30}
PROMPT="$P_CURDIR %M"Offline