[TOC]
前言
Zinit 是一个灵活快速的 zsh 插件管理器,它可以自动安装 Github 或者其他网站上的 zsh 插件。
特性
-
Zinit 会打印插件加载时设置的
aliases
,functions
,bindkeys
,Zle widgets
,zstyles
,completeions
,variables
,PATH
和FPATH
。这使得用户可以更快熟悉新插件同时在不同的场合下,提供了丰富且易于显示信息等有用功能。 -
支持插件
unloading
和罗列功能,支持安装/卸载,有选择的禁止/启用插件补全功能。 -
Zinit 支持加载 Oh-My-Zsh 和 Prezto 插件和库,但是其实现不基于特定框架,不会让插件管理器膨胀这类代码(更多该部分内容,可查看:Introduction)。
-
系统不使用
$FPATH
,加载拥有相同入口的多个插件时,不会混乱$FPATH
。设置选项通常会引起兼容性问题,除了KSH_ARRAYS
。 -
Zinit 支持特殊,专用的为用户卸载冗长复杂命令的
packages
。 -
Zinit 提供了特殊的 Zinit 扩展:annexes,通过 annexes 可以为插件管理器设置新的命令,URL 预处理器,安装后(
post-install
)/更新后(post-update
)钩子...。
安装
Zinit 提供了自动安装和手动安装两种方法:
-
自动安装:方法如下:(推荐)
sh -c "$(curl -fsSL https://raw.githubusercontent.com/zdharma/zinit/master/doc/install.sh)"
-
手动安装:步骤如下:
- 下载源码到
~/.zinit/bin
:
mkdir ~/.zinit git clone https://github.com/zdharma/zinit.git ~/.zinit/bin
- 添加如下内容到
~/.zshrc
最顶端:
source ~/.zinit/bin/zinit.zsh
- 重新加载
~/.zshrc
:
source ~/.zshrc
- 下载源码到
核心功能
Zinit 的涉及到的内容很多,完全了解 Zinit 提供的功能其实没有必要,我们只需理解 Zinit 最核心的一些功能点即可。
以下是本人认为的 Zinit 的核心功能,掌握下列内容,应当就可以基本使用 Zinit:
-
插件下载及加载:作为一个 zsh 的插件管理器,其基本功能就是插件下载及加载。插件的下载 / 加载基本使用方法如下:
zinit load zdharma/history-search-multi-word zinit light zsh-users/zsh-syntax-highlighting
以上两个命令是 Zinit 提供的两个基础插件加载配置,其中:
-
load
:表示使能插件追踪功能。使用该关键字后,Zinit 会记录相关插件启动的信息,并提供如下功能:-
zinit report {plugin-spec}
:查看插件信息 -
zinit unload {plugin-spec}
:卸载插件
-
-
light
:表示关闭插件追踪功能。当使用该关键字后,Zinit 不会对插件加载信息进行追踪,也就不具备查看和卸载插件的功能,但正如其名称一致,它提供了一个轻量级插件加载功能,加载插件速度会非常快。
注:在 Turbo 模式下,
load
引起的插件追踪导致的加载缓慢几乎是微不足道的。 -
-
ice 修饰符(Ice-Modifiers):Zinit 内置了很多
ice
修饰符用于为下一条zinit
命令添加额外的描述信息。
见名知意,所谓ice
,表示的就是添加一些东西(比如往饮料里添加冰块(ice)),同时冰块(ice)易融化,表示使用ice
修饰的信息仅仅只对下一条zinit
命令起作用。ice
修饰符提供的额外信息描述可分为如下几大项:-
下载选项(Cloning Options):涵盖的描述符有:
proto
,from
,ver
,bpick
,depth
,cloneopts
,svn
。 -
文件选择(Selection of Files):涵盖的描述符有:
pick
,src
,multisrc
。 -
加载限定(Conditional Loading):涵盖的描述符有:
wait
,load
,unload
,cloneonly
,if
,has
,subscribe / on-update-of
,trigger-load
。 -
插件输出(Plugin Output):涵盖的描述符有:
silent
,lucid
,notify
。 -
补全(Completions):涵盖的描述符有:
blockf
,nocompletions
。 -
下载 / 更新 / 加载时的命令执行(Command Execution After Cloning, Updating or Loading):涵盖的描述符有:
mv
,cp
,atclone
,atpull
,atinit
,atload
,run-atpull
,nocd
,make
,countdown
,reset
。 -
Shell 仿真(Sticky-Emulation Of Other Shells):涵盖的描述符有:
sh / !sh
,bash / !bash
,ksh / !ksh
,csh / !csh
。 -
其他(Others):
as
,id-as
,compile
,nocompile
,service
,reset-prompt
,bindmap
,trackbinds
,wrap-track
,aliases
,light-mode
,extract
。
完整的
ice
描述符相关内容可查看:Ice Modifiers。以下简单对几个较常用的
ice
修饰符进行介绍:-
as
:表示下载插件的意图,通常有如下 3 个选项:-
as"progrma"
:也可以写为as"command"
,就是将下载的插件作为命令使用。当插件下载完成后,会自动将插件脚本/命令(通常由pick
指定)自动添加到系统环境变量$PATH
中。 -
as"completion"
:表示将插件或者单文件脚本(以下划线_*
开始的文件)作为补全文件。 -
as"null"
:即pick"/dev/null" nocompletions
的简写,表示取消默认的source
操作和自动补全安装。
-
-
from
:指定插件下载网址。支持的网址有:from"github"
(默认),..."github-rel"
,..."gitlab"
,..."bitbucket"
,..."notabug"
(其各自对应的简写为:gh
,gh-r
,gl
,bb
,nb
),也可以是一个完整的域名。比如:zinit ice from"gh-r" as"program" zinit load junegunn/fzf-bin
上述命令会到 Github-release 页面下载
junegunn/fzf-bin
的可执行文件,并自动解压。注:
from
不支持 snippet 操作。 -
bpick
:用于指定在 GitHub Releases 页面下载的具体文件(依据正则表达式进行选取)。比如:zinit ice from"gh-r" as"program" bpick"*linux*" zinit load docker/compose
上述命令会在 Github-release 页面下载名称符合
*linux*
的文件(也就是 Linux 版本的安装文件),并自动进行解压。注:通常无需自己指定
bpick
选项,因为 Zinit 会自动根据当前操作系统及其 CPU 架构自动下载合适的文件。
注:bpick
不支持 snippet 操作。 -
pick
:选择要进行source
或者作为命令的文件(当使用snippet --command
或as"program"
时)。pick
选项使用正则匹配,对下载并解压完成的文件夹内的所有文件按字母表顺序进行排序,第一个符合条件的文件即为匹配文件。比如:zinit ice pick"powerless.zsh" zinit light martinrotter/powerless
上述命令会下载插件
martinrotter/powerless
,pick
指定了下载完成后会自动进行source powerless.zsh
操作。pick
还有另一个更常用的操作就是结合as"porgram"
/as"command"
操作,表示将pick
指定的文件增加+x
权限并添加到系统环境变量$PATH
中。比如:zinit ice as"program" pick"httpstat.sh" zinit light b4b4r07/httpstat
上述命令会下载插件
b4b4r07/httpstat
,由于指定了as"program"
,所以会将pick
选项指定的文件作为可执行文件,此时 Zinit 会自动将httpstat.sh
所在的目录添加到$PATH
中。注:使用
as"program"
时,对pick
执行的文件,就不会进行source
操作,而是作为命令使用,因此,通常会结合mv
/cp
等选项将可执行文件重命名,方便终端简化命令调用,比如对上述代码进行修改为如下:zinit ice as"program" cp"httpstat.sh -> httpstat" pick"httpstat" zinit light b4b4r07/httpstat
当下载完成后,会首先进行
cp
操作,将插件根目录的httpstat.sh
复制一份为httpstat
,然后pick
选项生效,为httpstat
添加可执行权限并添加到$PATH
中。如此终端就可以直接使用httpstat
命令了。 -
src
:指定额外文件进行source
。当pick
指定的主文件source
完成或添加到$PATH
后,会对src
指定的文件进行source
操作。zinit ice pick"powerless.zsh" src"utilities.zsh" zinit light martinrotter/powerless
上述命令在
powerless.zsh
进行source
操作后,还会执行source utilities.zsh
操作。注:
src
不支持正则匹配,而是直接以原意进行匹配。 -
multisrc
:支持指定多个文件进行source
操作。多个文件以空格进行分割,或者以大括号进行分割。比如:zinit ice svn pick"completion.zsh" multisrc'git.zsh \ functions.zsh {history,grep}.zsh' zinit snippet OMZ::lib
上述命令在下载完成 Oh-My-Zsh 的
lib
插件后,会先进行source completion.zsh
操作,然后还会对git.zsh
,functions.zsh
,history.zsh
和grep.zsh
进行source
操作。注:
multisrc
支持正则匹配。 -
load
:当满足条件时,加载插件。插件只会加载一次,当下次条件再次满足时,不会触发再次加载(除非插件已被卸载unload
)。 -
unload
:当满足条件时,卸载插件。插件只会卸载一次,当下次条件再次满足时,不会触发再次卸载(除非插件已被再次加载load
)。# Load when in ~/tmp zinit ice load'![[ $PWD = */tmp* ]]' unload'![[ $PWD != */tmp* ]]' \ atload"!promptinit; prompt sprint3" zinit load psprint/zprompts # Load when NOT in ~/tmp zinit ice load'![[ $PWD != */tmp* ]]' unload'![[ $PWD = */tmp* ]]' zinit load russjohnson/angry-fly-zsh
-
插件生命周期(life-cycle):Zinit 中,插件加载会经历四个生命周期:下载(clone)-> 更新(update)-> 初始化(init)-> 加载(load)。每个周期 Zinit 都为我们提供了相应的钩子(hook)方便我们在相应的插件生命周期内执行一些额外命令,具体钩子如下:
-
atclone
:插件下载完成(git clone
)后,执行相应的命令。 -
atpull
:插件更新完成(git pull
)后,执行相应的命令。 -
atinit
:插件加载前,执行初始化命令。 -
atload
:插件加载完成后,执行相应的命令。如果采用zinit load
方式加载插件,则此时atload"!{command}"
会对插件加载过程进行检测。
zinit ice from"gh-r" as"program" bpick"*amd64*.deb" pick"usr/bin/bat" \ atclone"echo clone" \ atpull"echo update" \ atinit"echo init" \ atload"echo load" zinit light sharkdp/bat
-
-
mv
:在下载(git clone
)或者更新(git pull
)完成后,进行mv
操作。比如:mv "fzf-* -> fzf"
-
cp
:在下载(git clone
)或者更新(git pull
)完成后,进行cp
操作。比如:cp "docker-c* -> dcompose"
-
make
:在下载(git clone
)/ 更新(git pull
)完成后,以及mv
,cp
,atpull
,atclone
操作完成后,执行make
命令,编译源码。make
选项可添加参数信息,比如:make"install PREFIX=/opt"
。如果make
选项以!
开头(make'!'
),那么其会先于atclone
/atpull
运行。
zinit ice as"program" atclone"rm -f src/auto/config.cache; ./configure" \ atpull"%atclone" make pick"src/vim" zinit light vim/vim
上述命令使用 Zinit 下载 Vim 源码并进行编译安装。当插件
vim/vim
下载完成后,会触发atclone
钩子,此时会执行rm -f src/auto/config.cache; ./configure
操作,然后执行make
操作,编译 Vim 源码,此时src
文件就会生成可执行文件vim
,最后通过pick
选项将make
生成的vim
添加到$PATH
中。当插件更新完成后,会触发atpull
操作,%atclone
表示执行的命令与atclone
一致,最后会再次触发make
操作,对更新后的源码进行编译。-
reset
:在插件更新(git pull
)前,执行git reset --hard HEAD
(或者svn revert
)操作,将插件恢复到上一次初始状态,目的是为了避免插件更新引起的可能冲突(conflict)。对于使用gh-r
下载的插件,会执行rm -rf *
操作,直接删除所有旧文件。 -
wait
:用于插件(或脚本文件)延迟加载。其使用有如下几种方式:-
wait'<number>'
:表示在控制台启动number
毫秒后,加载插件。比如:zinit ice wait'1' zinit light wfxr/forgit
上述命令表示在控制台(prompt)启动 1s 后,加载插件
wfxr/forgit
。注:不附带数值的
wait
相当于wait'0'
,表示控制台启动后立即加载插件。 -
wait’[[ ... ]]‘
/wait'(( ... ))'
:当满足条件时,加载插件。比如:zinit ice wait'[[ $PWD = */github || $PWD = */github/* ]]' zinit load unixorn/git-extra-commands '
上述命令在用户进入
github
目录时,会自动加载插件unixorn/git-extra-commands
。 -
wait'!...'
:!
表示当加载插件完成后,重置控制台。通常用于主题插件的加载。
-
注:zsh 在使用
wait
描述符延迟加载插件后,其启动速度可提升 80%。 -
下载选项(Cloning Options):涵盖的描述符有:
注:ice
描述符的执行顺序为:atinit
-> atpull!
-> make'!!'
-> mv
-> cp
-> make!
-> atclone
/atpull
-> make
-> (plugin script loading)
-> src
-> multisrc
-> atload
'
-
Turbo Mode (Zsh >= 5.3):Zinit 中所谓的 Turbo Mode,其实就是插件延迟加载功能,更确切的说,就是使用
ice
修饰符的wait
选项进行插件加载。比如:PS1="READY > " zinit ice wait'!0' zinit load halfo/lambda-mod-zsh-theme
上述命令表示终端在加载完成
.zshrc
文件并成功显示第一个控制台时,加载插件halfo/lambda-mod-zsh-theme
。实际上插件真正进行加载大约是在提示符READY >
出现后的 1ms 内。
我们一般不会用以上方法加载提示符,但此处作为直接观察 Turbo 模式却是一个不错的方法。 -
Zinit 命令(Zinit Commands):Zinit 提供了在终端进行操作的一些命令,比如:
# 加载插件 $ zinit load {plg-spec} # 加载插件,不打印加载信息 $ zinit light [-b] {plg-spec} # 加载单文件,-f 表示不使用缓存,即强制重新下载 $ zinit snippet [-f] {url} # 卸载插件,-q 表示 quiet $ zinit unload [-q] {plg-spec} # 显示插件加载时间,以插件加载顺序排序。-s 表示以秒进行显示(默认毫秒),-m 表示显示插件加载时刻 $ zinit times [-s] [-m] # 显示 Zinit 状态 $ zinit zstatus # 显示插件加载状态,--all 表示显示所有插件 $ zinit report {plg-spec} | --all # 显示已加载的插件(使用关键字进行过滤) $ zinit loaded [keyword],list [keyword] # 显示每个插件的设置的按键绑定 $ zinit bindkeys # 编译插件 $ zinit compile {plg-spec} | --all # 移除已编译的插件 $ zinit uncompile {plg-spec} | --all # 显示已编译的插件 $ zinit compiled # 更新 Zinit $ zinit self-update # 更新插件/脚本,--all 表示更新所有插件/脚本,-q 表示静默更新,-r | --reset 更新前执行 git reset --hard / svn revert $ zinit update [-q] [-r] {plg-spec} | URL | --all # 为下一条 zinit 命令添加 ice 描述符 $ zinit ice <ice specification> # 磁盘删除插件/脚本,--all 表示清除,--clean 表示删除未加载的插件/脚本 $ zinit delete {plg-spec} | URL | --clean | --all # 进入插件目录 $ zinit cd {plg-spec}
更多 Zinit 内置命令,请参考:zinit-commands
其他
以下是 Zinit 提供的另外一些有用的特性以及一些本人觉得好用的操作:
zinit snippet 'https://github.com/robbyrussell/oh-my-zsh/raw/master/plugins/git/git.plugin.zsh'
zinit snippet 'https://github.com/sorin-ionescu/prezto/blob/master/modules/helper/init.zsh'
snippet
表示通过curl
,wget
下载的单文件脚本。
对于 Oh-My-Zsh 和 Prezto,Zinit 提供了相应的简写方式:
# OMZ:: 表示 Oh My Zsh 插件
zinit snippet OMZ::plugins/git/git.plugin.zsh
# PZT:: 表示 Prezto 插件
zinit snippet PZT::modules/helper/init.zsh
-
多文件加载:
snippet
支持Subversion
协议,Github 同样也支持该协议。因此,如果使用的是Subversion
协议,那么snippet
则支持 多文件加载(比如,一个 Prezto 模块可以包含两个或以上文件,比如init.zsh
,alias.zsh
)。默认会进行加载的文件为:*.plugin.zsh
,init.zsh
,*.zsh-theme
:
# URL points to directory
zinit ice svn
zinit snippet PZT::modules/docker
-
附件(Annexes):Zinit 附件即 Zinit 扩展(Zinit Extensions),其作用是为 Zinit 增加一些子命令(subcommand),增加更多新的
ice
修饰符选项以及注册atclone
,atpull
,atinit
和atload
钩子函数...比如:
# Load a few important annexes, without Turbo
# (this is currently required for annexes)
zinit light-mode for \
zinit-zsh/z-a-patch-dl \
zinit-zsh/z-a-as-monitor \
zinit-zsh/z-a-bin-gem-node
上述命令就安装了 3 个比较重要的附件:z-a-patch-dl
,z-a-as-monitor
和z-a-bin-gen-node
。
-
For 语法(The For-Syntax):相对于经典的
ice
语法,For 语法提供了更加紧凑,优化的语法结构。比如:
zinit as"null" wait"3" lucid for \
sbin"recall" Fakerr/git-recall \
sbin paulirish/git-open \
sbin paulirish/git-recent \
sbin davidosomething/git-my \
make"PREFIX=$ZPFX install" iwata/git-now \
make"PREFIX=$ZPFX" tj/git-extras
上述单一一条命令就安装了 6 个插件,并且所有插件共享基础ice
选项:as"null
,wait"3"
,lucid
,可以看到,For 语法确实简洁许多。
注:sbin
描述符是由附件 z-a-bin-gem-node 提供的,sbin
选项的作用在于无需更改$PATH
就可以在命令行中直接使用其指定的命令。如果命令与插件名称相同,可省略不写。
-
atpull"…"
:atpull
属性在插件更新的时候会被触发。通常在更新插件的时候,拷贝文件是安全操作:因为仓库初始文件是不会被修改的,因此 Git 不会报告冲突。但是,移动mv
文件就不一定了,此时,就可结合atpull
属性:zinit ice as"program" mv"httpstat.sh -> httpstat" \ pick"httpstat" atpull'!git reset --hard' zinit light b4b4r07/httpstat
-
无冲突更新:如果
atpull
以感叹号开头,那么它会在git pull
和mv
命令执行之前运行。但是,atpull
,mv
,cp
只在抓取到新提交commit
的时候才会运行。
因此,对于上述命令,如果用户执行zinit update b4b4r07/httpstat
命令更新插件,如果该插件抓取到新的commit
,那么首先就会执行git reset --hard
,重新恢复初始文件httpstat.sh
,然后就执行git pull
,拉取新commit
(使用fast-forward
模式),成功后就会执行mv
命令,将httpstat.sh
修改为httpstat
。以这种方式就可以在无须阻塞git
更新的同时,使用mv
命令永久更新插件内容。
-
脚本命令(Snippets-Commands):可以将脚本的命令直接添加到
$PATH
中:
zinit ice mv"httpstat.sh -> httpstat" \
pick"httpstat" as"program"
zinit snippet \
https://github.com/b4b4r07/httpstat/blob/master/httpstat.sh
-
编译程序(Compiling Programs):典型的场景就是从 github 下载源码进行编译,比如运行
./configure
/make
等命令,则此时可以使用ice
修饰符,通过pick
选择需要添加到$PATH
的二进制程序,通过make
选项执行 make 操作...例子如下:
zinit ice as"program" atclone"rm -f src/auto/config.cache; ./configure" \
atpull"%atclone" make pick"src/vim"
zinit light vim/vim
上述命令中的各个参数含义如下:
-
as"program"
:表示结果为一个可执行文件(命令),因此不会进行source
操作,而是直接把 Zinit 会把pick
指定的二进制文件添加到$PATH
中。 -
atclone"..."
:表示下载(git clone
)完成后,需要执行的命令。 -
atpull"%atclone"
:表示更新(git pull
)完成后,执行atclone''
指定的命令。 -
make
:在atclone
和atpull
操作后,执行make
操作(注:如果是make '!'
,那么表示的是在进行atclone
或atpull
之前先执行make
操作)。 -
pick"src/vim"
:表示编译完成后生成的可执行文件为src/vim
,则意味着 Zinit 会把src
目录添加到$PATH
中。
如果需要执行的是make install
操作,则只需将make
修改为make"all install"
如果编译(make
)完成后,需要进行source
操作,则使用src
选项,比如:
zinit ice as"program" make'!' atclone'./direnv hook zsh > zhook.zsh' \
atpull'%atclone' src"zhook.zsh"
zinit light direnv/direnv
上述命令在git clone
和git pull
完成之前会先执行make
操作,然后执行./direnv hook zsh > zhook.zsh
,生成zhook.zsh
目标文件,最后再进行source zhook.zsh
操作。这样子就确保了命令./direnv hook zsh
只在git clone
和git pull
时才执行,其他情况不响应,因此 zsh 可以更快启动。
-
脚本补全(Snippets-Completions):通过使用
as"completion"
,可以让snippet
命令直接加载一个补全文件:
zinit ice as"completion"
zinit snippet https://github.com/docker/cli/blob/master/contrib/completion/zsh/_docker
- 补全管理(Completion Management):Zinit 允许为每个插件指定各自补全的禁止/启用。比如安装一个流行的提供补全的插件:
zinit ice blockf
zinit light zsh-users/zsh-completions
第一条命令中的blockf
指令会阻断传统的补全添加方式,Zinit 会使用自己的方式(基于符号链接而不是添加多个目录到$fpath
)。
Zinit 会自动安装新下载插件的补全。如果要卸载补全然后再重新安装,方法如下:
zinit cuninstall zsh-users/zsh-completions # uninstall
zinit creinstall zsh-users/zsh-completions # install
- 列举补全(Listing Completions):查看所有插件提供的补全,方法如下:
zi clist
默认情况下,上述命令每行会显示插件的 3 个补全,也可以通过为clist
添加参数指定补全显示个数,比如:
zi clist 6 # 每行显示 6 个补全
- 启用/禁用补全(Enabling and Disabling Completions):启用/禁止补全只需提供补全的名字:
$ zi cdisable cmake
Disabled cmake completion belonging to zsh-users/zsh-completions
$ zi cenable cmake
Enabled cmake completion belonging to zsh-users/zsh-completions
-
补全搜索:
zinit csearch
命令会对所有插件目录进行补全搜索,列举所有可用补全,并显示其安装状态。
-
子目录 SVN 支持(Subversion for Subdirectories):通常,如果要使用 Github 项目的某个子目录作为 snippet,那么可以为 URL 添加
/trunk/{path-to-dir}
,比如:
zinit ice svn
zinit snippet https://github.com/zsh-users/zsh-completions/trunk/src
# For Oh My Zsh and Prezto, the OMZ:: and PZT:: prefixes work
# without the need to add the `/trunk/` infix (however the path
# should point to a directory, not to a file):
zinit ice svn; zinit snippet PZT::modules/docker
snippet 也会像插件下载一样,自动安装其补全。
-
使用 Oh-My-Zsh 主题:Zinit 并没有直接提供加载 Oh-My-Zsh 框架的功能,但是我们可以通过
snippet
命令来加载单独的插件。
Oh-My-Zsh 的部分插件 / 主题会依赖 Oh-My-Zsh 本身提供的一些功能,比如常用的 git 库和 git 插件,则在.zshrc
中进行如下配置即可:
如果想使用 Oh-My-Zsh 主题,由于 OMZ 大多数主题都要求# Load OMZ Git library zinit snippet OMZL::git.zsh # Load Git plugin from OMZ zinit snippet OMZP::git
promptsubst
选项,否则可能出现类似... $(build_prompt) ...
的错误,因此,还需配置如下内容:
如果想禁止 OMZ 的 git 插件提供的补全信息,可进行如下配置:setopt promptsubst
综上,如果想使用 Oh-My-Zsh 主题,完整的配置如下:zinit cdclear -q
# Load OMZ Git library zinit snippet OMZL::git.zsh # Load Git plugin from OMZ zinit snippet OMZP::git zinit cdclear -q # <- forget completions provided up to this moment setopt promptsubst # Load theme from OMZ # zinit snippet OMZT::gnzh # Load normal GitHub plugin with theme depending on OMZ Git library # zinit light NicoSantangelo/Alpharized
网友评论