zsh not re-computing my shell prompt

2019-02-21 08:40发布

This might be a bit fringe, but I recently moved to zsh and am having a problem customizing my shell prompt.

Part of my .zshrc looks like this:

# keeping this simple right now by just printing the date, but imagine this function would look for something specific when moving to a new directory each time
function parse_special {
    print $(date)
}

autoload -U colors && colors
PS1="%{$fg[green]%}%n@%m %{$fg[blue]%}%c %{$fg[yellow]%}%{$(parse_special)%} %{$reset_color%}%# "

When I launch terminal, everything looks good; my prompt is what I expect:

me@someHost ~ Wed Aug 8 22:56:22 PDT 2012 %

But when I cd to another directory, it appears my parse_special function is not called again to recompute my custom prompt (notice the date is not changing):

me@someHost ~ Wed Aug 8 22:56:22 PDT 2012 % cd .ssh 
me@someHost .ssh Wed Aug 8 22:56:22 PDT 2012 % cd ../workspace 
me@someHost workspace Wed Aug 8 22:56:22 PDT 2012 % 

Is there any way I can tell zsh to recompute the prompt each time it is about to show it?

thanks a lot for any suggestions.


reply to cjhveal

It seems like PS1 does not like to get set by single quoted values. I tried the following:

local tp1="%{$fg[green]%}%n@%m%{$reset_color%}"
PS1="${tp1}"
print "PS1 set by tp1: ${PS1}"
local tp2='%{$fg[green]%}%n@%m%{$reset_color%}'
PS1="${tp2}"
print "PS1 set by tp2: ${PS1}"

And got this output

#inner stuff was green
PS1 set by tp1: %{%}%n@%m%{%}
#everything was uncolored
PS1 set by tp2: %{$fg[green]%}%n@%m%{$reset_color%}

I should also add, based on cjhveal's suggestion, here is what I literally tried. Again, the single quotes seem to be messing things up

function parse_special {    
    print $(date)
}

autoload -U colors && colors
local prompt_user='%{$fg[green]%}%n@%m%{$reset_color%}'
local prompt_root='%{$fg[red]%}%n@%m%{$reset_color%}'
local prompt_dir='%{$fg[blue]%}%c%{$reset_color%}'
local prompt_special='%{$fg[yellow]%}%{$(parse_special)%}%{$reset_color%}'
PS1="${prompt_user} ${prompt_dir}${prompt_special}%# "

2条回答
贼婆χ
2楼-- · 2019-02-21 09:15

You are half the way to solving this problem:

PS1='$(date)'

will show you prompt $(date), but

PS1='$(date)'
setopt promptsubst

will show you prompt Thu Aug 9 21:01:53 MSK 2012 (depends on $LANG and $LC_TIME, of course).

By the way, in the newest zsh you don’t need to use %{$fg[blue]%} anymore, there is nos %F{blue} for foreground, %K{blue} for background, %f%k for resetting them and a few others, see man zshmisc, section EXPANSION OF PROMPT SEQUENCES.

查看更多
Bombasti
3楼-- · 2019-02-21 09:19

I ran into the same problem while customizing my prompt in zsh.

I believe this happens because the shell interpolates the value into the string once, when the prompt is initialized. Subsequent reloads have the constant string in your prompt, not the subshell interpolation.

Instead, put any lines that involve subshells into a variable defined with single quotes. Then interpolate that variable instead.

autoload -U colors && colors

local parse_special='%{$fg[yellow]%}$(date)%{$reset_color%}'

PS1="%{$fg[green]%}%n@%m %{$fg[blue]%}%c ${parse_special} %# "

Update: Adding this from ZyX's answer to make a complete solution for this. You also need to add this:

setopt promptsubst

In fact, I would suggest extracting each part of your prompt into a variable like this, including a reset_color on each. Doing so lets you change the order of prompt components without changing their implementation.

查看更多
登录 后发表回答