1

zsh 异步生成提示符

 2 years ago
source link: https://blog.lilydjwg.me/2014/2/19/asynchronously-update-zsh-prompt.42906.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

zsh 异步生成提示符

本文来自依云's Blog,转载请注明。

为什么要异步?当然是因为慢了。比如 Arch 核心仓库 git 版挺大的,第一次进去时显示个 git 分支名要等好一会儿。今天在 zsh-users 列表中看到 Bart Schaefer 给出了一个使用 coprocess 的解决方案,眼前一亮,立即照葫芦画瓢给自己的 zsh 用上了。以下是整个提示符设置部分的代码:

if [[ -n $commands[git] ]]; then
_nogit_dir=()
for p in $nogit_dir; do
[[ -d $p ]] && _nogit_dir+=$(realpath $p)
done
unset p
typeset -g _current_branch= vcs_info_fd=
zmodload zsh/zselect 2>/dev/null
_vcs_update_info () {
eval $(read -rE -u$1)
zle -F $1
exec {1}>&-
zle reset-prompt
}
_set_current_branch () {
cwd=$(pwd -P)
for p in $_nogit_dir; do
if [[ $cwd == $p* ]]; then
return
fi
done
setopt localoptions no_monitor
coproc {
_br=$(git branch --no-color 2>/dev/null)
if [[ $? -eq 0 ]]; then
_current_branch=$(echo $_br|awk '{if($1 == "*"){print "%{\x1b[33m%} (" substr($0, 3) ")"}}')
fi
# always gives something for reading, or _vcs_update_info won't be
# called, fd not closed
typeset -p _current_branch
}
disown %{\ _br
exec {vcs_info_fd}<&p
# wait 0.1 seconds before showing up to avoid unnecessary double update
# precmd functions are called *after* prompt is expanded, and we can't call
# zle reset-prompt outside zle, so turn to zselect
zselect -r -t 10 $vcs_info_fd 2>/dev/null
zle -F $vcs_info_fd _vcs_update_info
}
typeset -gaU precmd_functions
precmd_functions+=_set_current_branch
setopt PROMPT_SUBST
fi
[[ -n $ZSH_PS_HOST && $ZSH_PS_HOST != \(*\)\  ]] && ZSH_PS_HOST="($ZSH_PS_HOST) "
E=$'\x1b'
PS1="%{${E}[2m%}%h $ZSH_PS_HOST%(?..%{${E}[1;31m%}%?%{${E}[0m%} )%{${E}[32m%}%~\$_current_branch
%(!.%{${E}[0;31m%}###.%{${E}[1;34m%}>>>)%{${E}[0m%} "

比较坑的是使用chpwd_functions的话只能在目录改变时显示一次,再随便执行个什么命令分支提示就没了。又想到目录不改变的时候分支也可以变化(切换分支了嘛),所以使用precmd_functions,每次显示提示符前(单纯的重绘除外)都执行一次。另外,为了避免每次显示提示符时都明显地分为两步干扰视线,所以在那个_set_current_branch函数里等了 0.1 秒,超时才会不管分支名显示先继续了。

2014年2月24日更新:注意,直到 zsh 5.0.5(就是当前最新版本)有个 bug,在显示提示符之后、用户输入之前,上述代码会经常出现「忙等待」的情况浪费 CPU。这里有个补丁可以修复。

发送到 Kindle

Category: shell | Tags: linux Git zsh | Read Count: 10428

评论 (3)
unclebill 说:
7 年前

给oh-my-zsh写个patch吧。

依云 说:
7 年前

我从来没了解过 oh-my-zsh 呢。

unclebill 说:
7 年前

有很多可以自由选择加载的插件
https://github.com/robbyrussell/oh-my-zsh/tree/master/plugins
还有很多主题,还有很方便的alias(比如1,2,3...分别是cd -,cd -2, cd -3),但也显得臃肿。

[取消回复评论]

昵称 登录 E-mail: *
Web:
Twitter:
当有新评论通过 E-mail 通知我

loading captcha image...
(输入验证码)

or Ctrl+Enter


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK