Zsh

出自 ArchWiki

Zsh 是一个强大的 shell,既可以作为交互式 shell 运行,也可以作为脚本语言解释器运行。虽然它与 POSIX sh 兼容(默认情况下不兼容,只有在执行 emulate sh 时才兼容),但它提供了诸如改进的 tab 补全globbing 等优点。

Zsh 常见问题解答 提供了更多使用 Zsh 的理由。

安装

在开始之前,用户可能需要查看当前正在使用的 shell

$ echo $SHELL

安装 zsh 软件包。为了获得额外的补全定义,也请安装 zsh-completions 软件包。

初始配置

通过在终端中运行以下命令,确保 Zsh 已正确安装

$ zsh

现在您应该看到 zsh-newuser-install,它将引导您完成一些基本配置。如果您想跳过此步骤,请按 q。如果您没有看到它,可以使用以下命令手动调用它

$ autoload -Uz zsh-newuser-install
$ zsh-newuser-install -f
注意: 确保您的终端尺寸至少为 72×15,否则 zsh-newuser-install 将不会运行。

将 Zsh 设置为默认 Shell

将您的 shell 更改为 /usr/bin/zsh。请参阅 命令行 shell#更改您的默认 shell

提示: 如果替换 bash,用户可能需要将一些代码从 ~/.bashrc 移动到 ~/.zshrc(例如提示符和 别名),以及从 ~/.bash_profile 移动到 ~/.zprofile(例如 启动 X Window 系统的代码)。

启动/关闭文件

提示: 有关交互式 shell 和登录 shell 的解释,以及在启动文件中放入什么内容,请参阅 Z-Shell 用户指南
注意
  • 如果未设置 $ZDOTDIR,则使用 $HOME 代替。
  • 如果在任何文件中取消设置选项 RCS,则在该文件之后将不会读取任何配置文件。
  • 如果在任何文件中取消设置选项 GLOBAL_RCS,则在该文件之后将不会读取任何全局配置文件 (/etc/zsh/*)。

启动时,默认情况下 Zsh 将按以下顺序从以下文件中读取命令(如果这些文件存在)。

  • /etc/zsh/zshenv 用于为所有用户设置 环境变量;它不应包含产生输出或假定 shell 连接到 TTY 的命令。当此文件存在时,它将始终被读取,这无法被覆盖。
  • $ZDOTDIR/.zshenv 用于设置用户的环境变量;它不应包含产生输出或假定 shell 连接到 TTY 的命令。当此文件存在时,它将始终被读取。
  • /etc/zsh/zprofile 用于在启动时为所有用户执行命令,当作为登录 shell启动时将被读取。请注意,在 Arch Linux 上,默认情况下它包含 一行,该行会 source /etc/profile。在想要删除它之前,请参阅下面的警告!
    • /etc/profile 此文件应在登录时由所有 POSIX sh 兼容的 shell source:它在登录时设置 $PATH 和其他环境变量以及应用程序特定的 (/etc/profile.d/*.sh) 设置。
  • $ZDOTDIR/.zprofile 用于在启动时执行用户的命令,当作为登录 shell启动时将被读取。通常用于自动启动图形会话和设置会话范围的环境变量。
  • /etc/zsh/zshrc 用于为所有用户设置交互式 shell 配置和执行命令,当作为交互式 shell启动时将被读取。
  • $ZDOTDIR/.zshrc 用于设置用户的交互式 shell 配置和执行命令,当作为交互式 shell启动时将被读取。
  • /etc/zsh/zlogin 用于在初始进度结束时为所有用户执行命令,当作为登录 shell启动时将被读取。
  • $ZDOTDIR/.zlogin 用于在初始进度结束时执行用户的命令,当作为登录 shell启动时将被读取。通常用于自动启动命令行实用程序。不应用于自动启动图形会话,因为此时会话可能包含仅用于交互式 shell 的配置。
  • $ZDOTDIR/.zlogout 用于在登录 shell 退出时执行命令。
  • /etc/zsh/zlogout 用于在登录 shell 退出时为所有用户执行命令。

请参阅 图形表示

注意: $HOME/.profile 不是 Zsh 启动文件的一部分,并且 不会被 source,除非 Zsh 作为 shksh 调用并作为登录 shell 启动。有关 sh 和 ksh 兼容模式的更多详细信息,请参阅 zsh(1) § COMPATIBILITY
警告: 请勿删除 /etc/zsh/zprofile 中的默认 一行,否则会破坏其他软件包的完整性,这些软件包在 /etc/profile.d/ 中提供了一些脚本。

配置 Zsh

尽管 Zsh 开箱即用,但几乎可以肯定它没有按照大多数用户希望的方式进行设置。但是由于 Zsh 中可用的自定义量非常大,因此配置 Zsh 可能是一项令人畏惧且耗时的体验。有关自动配置,请参阅 #第三方扩展

简单的 .zshrc

下面包含一个示例配置文件。它提供了一组不错的默认选项,并提供了许多 Zsh 可以自定义的方式的示例。为了使用此配置,请将其另存为名为 .zshrc 的文件。

提示: 无需注销然后重新登录即可应用更改,方法是运行 source ~/.zshrc

这是一个简单的 .zshrc

~/.zshrc
autoload -Uz compinit promptinit
compinit
promptinit

# This will set the default prompt to the walters theme
prompt walters

有关提示符主题系统的更多详细信息,请参阅 #提示符主题

配置 $PATH

Zsh 将 PATH 变量绑定到 path 数组。这允许您通过简单地修改 path 数组来操作 PATH。有关详细信息,请参阅 Z-Shell 用户指南

要将 ~/.local/bin/ 添加到 PATH

~/.zshenv
typeset -U path PATH
path=(~/.local/bin $path)
export PATH

命令补全

也许 Zsh 最引人注目的功能是其高级自动补全功能。至少,在 .zshrc 中启用自动补全。要启用自动补全,请将以下内容添加到您的 ~/.zshrc

~/.zshrc
autoload -Uz compinit
compinit

上述配置包括 ssh/scp/sftp 主机名补全,但为了使此功能起作用,用户不得启用 ssh 的主机名哈希(即 ssh 客户端配置中的选项 HashKnownHosts)。

对于带有箭头键驱动界面的自动补全,请将以下内容添加到

~/.zshrc
zstyle ':completion:*' menu select

要激活菜单,请按 Tab 键两次。

为了在特权命令中启用特权环境的自动补全(例如,如果您完成以 sudo 开头的命令,补全脚本也会尝试使用 sudo 确定您的补全),请包含

~/.zshrc
zstyle ':completion::complete:*' gain-privileges 1
警告: 这将让 Zsh 补全脚本以 sudo 权限运行命令。如果您使用不受信任的自动补全脚本,则不应启用此功能。
注意: 这种特殊的上下文感知补全仅适用于少量命令。

自定义补全

您可以自行编写自定义补全。如果您这样做,可以参考 zshcompsys(1) 手册页。

请注意,官方文档可能难以阅读。您可以考虑尝试更简单的 zsh-completion-howto 教程,以便轻松入门。

快捷键绑定

Zsh 不使用 readline,而是使用自己的更强大的 Zsh 行编辑器 (ZLE)。它不读取 /etc/inputrc~/.inputrc。阅读 更深入地了解 zsh 行编辑器和创建自定义小部件,以了解 ZLE 配置的入门知识。

ZLE 具有 Emacs 模式和 vi 模式。如果 VISUALEDITOR 环境变量 之一包含字符串 vi,则将使用 vi 模式;否则,它将默认为 Emacs 模式。分别使用 bindkey -ebindkey -v 为 Emacs 模式或 vi 模式显式设置模式。vi 模式中按 Esc 键的延迟默认为 0.4 秒,您可以使用 export KEYTIMEOUT=5 将其缩短(0.05 秒)。

快捷键绑定通过将与按键匹配的转义序列映射到 ZLE 小部件来分配。可用的窗口小部件及其操作说明和默认快捷键绑定在 zshzle(1) § STANDARD WIDGETSzshcontrib(1) § ZLE FUNCTIONS 中列出。

在 Zsh 中设置快捷键绑定的推荐方法是使用 terminfo(5) 中的字符串功能。例如[1][2]

~/.zshrc
# create a zkbd compatible hash;
# to add other keys to this hash, see: man 5 terminfo
typeset -g -A key

key[Home]="${terminfo[khome]}"
key[End]="${terminfo[kend]}"
key[Insert]="${terminfo[kich1]}"
key[Backspace]="${terminfo[kbs]}"
key[Delete]="${terminfo[kdch1]}"
key[Up]="${terminfo[kcuu1]}"
key[Down]="${terminfo[kcud1]}"
key[Left]="${terminfo[kcub1]}"
key[Right]="${terminfo[kcuf1]}"
key[PageUp]="${terminfo[kpp]}"
key[PageDown]="${terminfo[knp]}"
key[Shift-Tab]="${terminfo[kcbt]}"

# setup key accordingly
[[ -n "${key[Home]}"      ]] && bindkey -- "${key[Home]}"       beginning-of-line
[[ -n "${key[End]}"       ]] && bindkey -- "${key[End]}"        end-of-line
[[ -n "${key[Insert]}"    ]] && bindkey -- "${key[Insert]}"     overwrite-mode
[[ -n "${key[Backspace]}" ]] && bindkey -- "${key[Backspace]}"  backward-delete-char
[[ -n "${key[Delete]}"    ]] && bindkey -- "${key[Delete]}"     delete-char
[[ -n "${key[Up]}"        ]] && bindkey -- "${key[Up]}"         up-line-or-history
[[ -n "${key[Down]}"      ]] && bindkey -- "${key[Down]}"       down-line-or-history
[[ -n "${key[Left]}"      ]] && bindkey -- "${key[Left]}"       backward-char
[[ -n "${key[Right]}"     ]] && bindkey -- "${key[Right]}"      forward-char
[[ -n "${key[PageUp]}"    ]] && bindkey -- "${key[PageUp]}"     beginning-of-buffer-or-history
[[ -n "${key[PageDown]}"  ]] && bindkey -- "${key[PageDown]}"   end-of-buffer-or-history
[[ -n "${key[Shift-Tab]}" ]] && bindkey -- "${key[Shift-Tab]}"  reverse-menu-complete

# Finally, make sure the terminal is in application mode, when zle is
# active. Only then are the values from $terminfo valid.
if (( ${+terminfo[smkx]} && ${+terminfo[rmkx]} )); then
	autoload -Uz add-zle-hook-widget
	function zle_application_mode_start { echoti smkx }
	function zle_application_mode_stop { echoti rmkx }
	add-zle-hook-widget -Uz zle-line-init zle_application_mode_start
	add-zle-hook-widget -Uz zle-line-finish zle_application_mode_stop
fi

历史记录搜索

您需要设置 key 数组并确保 ZLE 进入应用程序模式才能使用以下说明;请参阅 #快捷键绑定

要启用历史记录搜索,请将以下行添加到 .zshrc 文件

~/.zshrc
autoload -Uz up-line-or-beginning-search down-line-or-beginning-search
zle -N up-line-or-beginning-search
zle -N down-line-or-beginning-search

[[ -n "${key[Up]}"   ]] && bindkey -- "${key[Up]}"   up-line-or-beginning-search
[[ -n "${key[Down]}" ]] && bindkey -- "${key[Down]}" down-line-or-beginning-search

这样做后,当按下 UpDown 键时,将仅显示与当前行(直到当前光标位置)匹配的过去命令。

Shift、Alt、Ctrl 和 Meta 修饰键

与 xterm 兼容的终端可以使用来自 user_caps(5) 的扩展快捷键定义。这些是 ShiftAltCtrlMetaUpDownLeftRightPageUpPageDownHomeEndDel 的组合。有关修饰键和按键组合的推荐名称列表,请参阅 zkbd 源代码

例如,对于 Ctrl+Left 移动到上一个单词的开头,Ctrl+Right 移动到下一个单词的开头

~/.zshrc
key[Control-Left]="${terminfo[kLFT5]}"
key[Control-Right]="${terminfo[kRIT5]}"

[[ -n "${key[Control-Left]}"  ]] && bindkey -- "${key[Control-Left]}"  backward-word
[[ -n "${key[Control-Right]}" ]] && bindkey -- "${key[Control-Right]}" forward-word

提示符

Zsh 提供了使用提示符主题的选项,或者对于对主题不满意(或想要扩展其用途)的用户,可以选择构建自定义提示符。

提示符主题

提示符主题是在 Zsh 中设置彩色提示符的快速简便方法。有关提示符主题以及如何编写自己的主题的信息,请参阅 zshcontrib(1) § PROMPT THEMES

要使用主题,请确保提示符主题系统设置为在 .zshrc 中自动加载。这可以通过将以下行添加到

~/.zshrc
autoload -Uz promptinit
promptinit

通过运行以下命令列出可用的提示符主题

$ prompt -l

例如,要使用 walters 主题,请输入

$ prompt walters

要预览所有可用的主题,请使用此命令

$ prompt -p
手动安装提示符主题

可以手动安装主题,而无需外部配置管理器工具。对于本地安装,首先创建一个文件夹并将其添加到 fpath 数组,例如

$ mkdir ~/.zprompts
$ fpath=("$HOME/.zprompts" "$fpath[@]")

现在在此文件夹中创建主题文件的符号链接

$ ln -s mytheme.zsh ~/.zprompts/prompt_mytheme_setup

如果您希望全局安装主题,请执行

# ln -s mytheme.zsh /usr/share/zsh/functions/Prompts/prompt_mytheme_setup

现在您应该可以使用以下命令激活它

$ prompt mytheme

如果一切正常,您可以相应地编辑您的 .zshrc

在没有单独文件的情况下添加提示符主题

除了通过其自身的文件添加提示符主题外,还可以从另一个文件(如您的 .zshrc)中添加主题,例如

~/.zshrc
# Load promptinit
autoload -Uz promptinit && promptinit

# Define the theme
prompt_mytheme_setup() {
  PS1="%~%# "
}

# Add the theme to promptsys
prompt_themes+=( mytheme )

# Load the theme
prompt mytheme

自定义提示符

除了所有 shell 通用的主左侧提示符 PS1 (PROMPT, prompt) 之外,Zsh 还支持右侧提示符 RPS1 (RPROMPT)。这两个变量是您想要设置为自定义值的变量。

其他特殊用途的提示符,例如 PS2 (PROMPT2)、PS3 (PROMPT3)、PS4 (PROMPT4)、RPS1 (RPROMPT)、RPS2 (RPROMPT2) 和 SPROMPT,在 zshparam(1) § PARAMETERS USED BY THE SHELL 中进行了解释。

所有提示符都可以使用提示符转义符进行自定义。可用的提示符转义符在 zshmisc(1) § EXPANSION OF PROMPT SEQUENCES 中列出。

颜色

Zsh 设置颜色的方式与 Bash 不同;您不需要使用大量的 ANSI 转义序列或来自 terminfo(5) 的终端功能。Zsh 提供了方便的提示符转义符来设置前景色、背景色和其他视觉效果;有关它们的列表及其说明,请参阅 zshmisc(1) § Visual effects

可以使用十进制整数、八种最广泛支持的颜色之一的名称或以 # 开头后跟十六进制格式的 RGB 三元组来指定颜色。有关更多详细信息,请参阅 zshzle(1) § CHARACTER HIGHLIGHTING 中 fg=colour 的描述。

大多数终端按名称支持以下颜色

名称 编号
黑色 0
红色 1
绿色 2
黄色 3
蓝色 4
品红色 5
青色 6
白色 7

与 xterm 256 色兼容的终端模拟器的颜色编号 0-255 可以在 xterm-256color 图表中找到。

使用正确设置的 TERM 环境变量,可以从 terminfo(5) 数据库中使用 echoti colors 找到终端支持的最大颜色数。在 24 位颜色的情况下,还要使用 print $COLORTERM 检查 COLORTERM 环境变量。如果它返回 24bittruecolor,则即使 terminfo 显示的数字较小,您的终端也支持 16777216 (224) 种颜色。

注意
  • 颜色 0-15 在终端模拟器及其使用的配色方案之间可能有所不同。
  • 许多终端模拟器以更亮的颜色显示粗体。
提示
  • 可以使用命令 print -P "提示符转义符" 测试提示符转义符,例如
    $ print -P '%B%F{red}co%F{green}lo%F{blue}rs%f%b'
  • 如果您使用 24 位颜色,您可能需要在不支持它们的终端中加载 zsh/nearcolor 模块。例如
    [[ "$COLORTERM" == (24bit|truecolor) || "${terminfo[colors]}" -eq '16777216' ]] || zmodload zsh/nearcolor
    有关 zsh/nearcolor 模块的详细信息,请参阅 zshmodules(1) § THE ZSH/NEARCOLOR MODULE
示例

一个简单的无色提示符示例

PROMPT='%n@%m %~ %# '

它将如何显示

username@host ~ %

这是一个带有颜色的双侧提示符示例

PROMPT='%F{green}%n%f@%F{magenta}%m%f %F{blue}%B%~%b%f %# '
RPROMPT='[%F{yellow}%?%f]'

这是它的显示方式

username@host ~ % [0]

要使用 16-255 范围内的颜色和 24 位真彩色,您可以使用分配给所需颜色的 0 到 255 的数字及其十六进制颜色代码,分别

PROMPT='%F{2}%n%f@%F{5}%m%f %F{4}%B%~%b%f %# '
RPROMPT='[%F{3}%?%f]'
PROMPT='%F{#c0c0c0}%n%f@%F{#008000}%m%f %F{#800080}%B%~%b%f %# '
RPROMPT='[%F{#0000ff}%?%f]'

.zshrc 示例文件

有关更多信息,请参阅 dotfiles#用户仓库

技巧与窍门

登录时自动启动 X

请参阅 xinit#登录时自动启动 X

程序异常退出后恢复终端设置

许多程序会更改终端状态,并且通常在异常退出时(例如,崩溃或遇到 SIGINT 时)不恢复终端设置。

这通常可以通过执行 reset(1) 来解决

$ reset

以下部分描述了避免手动重置终端的需求的方法。

ttyctl 命令

ttyctl 命令可用于“冻结/解冻”终端。要在启动时冻结交互式 shell,请使用以下命令

~/.zshrc
ttyctl -f

使用转义序列重置终端

备用划线字符集 可能会以 ttyctl 无法阻止的方式搞乱终端。

一个简单的解决方案是从 precmd 钩子函数输出重置终端的转义序列,以便在每次绘制提示符之前执行它们。例如,使用 转义序列 \e[0m\e(B\e)0\017\e[?5l\e7\e[0;0r\e8

~/.zshrc
autoload -Uz add-zsh-hook

function reset_broken_terminal () {
	printf '%b' '\e[0m\e(B\e)0\017\e[?5l\e7\e[0;0r\e8'
}

add-zsh-hook -Uz precmd reset_broken_terminal

要测试它是否有效,请运行

$ print '\e(0\e)B'

记住最近的目录

Dirstack

可以将 Zsh 配置为记住 DIRSTACKSIZE 最近访问的文件夹。然后可以使用它来非常快速地 cd 到它们。您需要向您的配置文件添加一些行

~/.zshrc
autoload -Uz add-zsh-hook

DIRSTACKFILE="${XDG_CACHE_HOME:-$HOME/.cache}/zsh/dirs"
if [[ -f "$DIRSTACKFILE" ]] && (( ${#dirstack} == 0 )); then
	dirstack=("${(@f)"$(< "$DIRSTACKFILE")"}")
	[[ -d "${dirstack[1]}" ]] && cd -- "${dirstack[1]}"
fi
chpwd_dirstack() {
	print -l -- "$PWD" "${(u)dirstack[@]}" > "$DIRSTACKFILE"
}
add-zsh-hook -Uz chpwd chpwd_dirstack

DIRSTACKSIZE='20'

setopt AUTO_PUSHD PUSHD_SILENT PUSHD_TO_HOME

## Remove duplicate entries
setopt PUSHD_IGNORE_DUPS

## This reverts the +/- operators.
setopt PUSHD_MINUS

现在使用

$ dirs -v

来打印 dirstack。使用 cd -<NUM> 返回到访问过的文件夹。在破折号后使用自动补全。如果使用自动补全菜单,这将非常方便。

注意
  • 如果您打开了多个 zsh 会话,并且尝试 cd,由于两个会话都写入同一个文件时发生冲突,这将不起作用。
  • 您可能需要创建 $HOME/.cache/zsh 目录,以避免出现 no such file or directory 错误。

cdr

cdr 允许您将工作目录更改为自动维护的列表中的先前工作目录。它将所有条目存储在跨会话和(默认情况下)当前会话中的终端模拟器之间维护的文件中。

有关设置说明,请参阅 zshcontrib(1) § REMEMBERING RECENT DIRECTORIES

zoxide

zoxide 是一个更智能的 cd 命令,可让您仅需按几下按键即可导航到任何位置。它会记住您经常使用的目录,并使用评分机制来猜测您想去哪里。

帮助命令

Bash 不同,Zsh 不启用内置的 help 命令,而是提供 run-help。默认情况下,run-helpman 的别名,可以通过在命令前加上它来手动执行,也可以使用键盘快捷键 Alt+hEsc h 为当前键入的命令调用它。

由于默认情况下它只是 man 的别名,因此它仅适用于外部命令。为了提高其功能,使其适用于 shell 内置命令和其他 shell 功能,您需要使用 run-help 函数。有关 run-help 及其辅助函数的更多信息,请参阅 zshcontrib(1)

首先加载 run-help 函数,然后删除现有的 run-help 别名。为方便起见,可以将 help 别名为 run-help。例如,将以下内容添加到您的 zshrc

autoload -Uz run-help
(( ${+aliases[run-help]} )) && unalias run-help
alias help=run-help

辅助函数必须单独启用

autoload -Uz run-help-git run-help-ip run-help-openssl run-help-p4 run-help-sudo run-help-svk run-help-svn

例如,run-help git commit 命令现在将打开 手册页 git-commit(1) 而不是 git(1)

持久化重哈希

通常,compinit 不会自动在 $PATH 中查找新的可执行文件。例如,在您安装新软件包后,/usr/bin/ 中的文件不会立即或自动包含在补全中。因此,为了包含这些新的可执行文件,需要运行

$ rehash

可以将此“重哈希”设置为自动发生。[3] 只需在您的 zshrc 中包含以下内容

~/.zshrc
zstyle ':completion:*' rehash true

按需重哈希

如上所述,但是 pacman 可以配置 hooks 以自动请求 rehash,这不会像上面的持续重哈希那样产生性能损失。要启用此功能,请创建 /etc/pacman.d/hooks 目录和 /var/cache/zsh 目录,然后创建一个 hook 文件

/etc/pacman.d/hooks/zsh.hook
[Trigger]
Operation = Install
Operation = Upgrade
Operation = Remove
Type = Path
Target = usr/bin/*
[Action]
Depends = zsh
When = PostTransaction
Exec = /usr/bin/install -Dm644 /dev/null /var/cache/zsh/pacman

这使文件 /var/cache/zsh/pacman 的修改日期与上次安装、升级或删除软件包的时间保持一致。然后,必须哄骗 zsh 在其命令缓存过时时重新哈希其命令缓存,方法是在您的 ~/.zshrc 中添加

~/.zshrc
zshcache_time="$(date +%s%N)"

autoload -Uz add-zsh-hook

rehash_precmd() {
  if [[ -a /var/cache/zsh/pacman ]]; then
    local paccache_time="$(date -r /var/cache/zsh/pacman +%s%N)"
    if (( zshcache_time < paccache_time )); then
      rehash
      zshcache_time="$paccache_time"
    fi
  fi
}

add-zsh-hook -Uz precmd rehash_precmd

如果在 /var/cache/zsh/pacman 更新之前触发了 precmd 钩子,则补全可能无法工作,直到启动新的提示符。运行空命令(例如按 enter 键)应该就足够了。

使用 SIGUSR1 的替代按需重哈希

如上所述,但是 hook 文件如下所示

/etc/pacman.d/hooks/zsh-rehash.hook
[Trigger]
Operation = Install
Operation = Upgrade
Operation = Remove
Type = Path
Target = usr/bin/*

[Action]
Depends = zsh
Depends = procps-ng
When = PostTransaction
Exec = /usr/bin/pkill zsh --signal=USR1
警告: 这会将 SIGUSR1 发送到所有正在运行的 zsh 实例。请注意,SIGUSR1 的默认行为是终止,因此当您首次配置此项时,如果所有用户(包括登录 shell)的所有正在运行的 zsh 实例都没有 source 下面的陷阱,则它们将被终止。
~/.zshrc
TRAPUSR1() { rehash }

上面的函数陷阱可以用列表陷阱 trap 'rehash' USR1 替换。有关陷阱类型之间的差异,请参阅 zshmisc(1) § Trap Functions

此方法将立即 rehash 所有 zsh 实例,无需按 Enter 键即可触发 precmd

将按键绑定到 ncurses 应用程序

将 ncurses 应用程序绑定到按键,但它不会接受交互。使用 BUFFER 变量使其工作。以下示例允许用户使用 Alt+\ 打开 ncmpcpp

~/.zshrc
ncmpcppShow() {
  BUFFER="ncmpcpp"
  zle accept-line
}
zle -N ncmpcppShow
bindkey '^[\' ncmpcppShow

另一种方法,它将保留您在调用应用程序之前在行中输入的所有内容

~/.zshrc
ncmpcppShow() {
  ncmpcpp <$TTY
  zle redisplay
}
zle -N ncmpcppShow
bindkey '^[\' ncmpcppShow

文件管理器快捷键绑定

文件管理器快捷键绑定(如图形文件管理器中使用的快捷键绑定)可能会派上用场。第一个快捷键返回目录历史记录 (Alt+Left),第二个快捷键让用户转到父目录 (Alt+Up)。它们还会显示目录内容。

~/.zshrc
cdUndoKey() {
  popd
  zle       reset-prompt
  print
  ls
  zle       reset-prompt
}

cdParentKey() {
  pushd ..
  zle      reset-prompt
  print
  ls
  zle       reset-prompt
}

zle -N                 cdParentKey
zle -N                 cdUndoKey
bindkey '^[[1;3A'      cdParentKey
bindkey '^[[1;3D'      cdUndoKey

xterm 标题

如果您的终端模拟器支持,您可以从 Zsh 设置其标题。这允许动态更改标题以显示有关 shell 状态的相关信息,例如显示用户名和当前目录或当前正在执行的命令。

xterm 标题使用 xterm 控制序列操作系统命令 \e]2;\a\e]2;\e\\ 设置。例如

$ print -n '\e]2;My xterm title\a'

将标题设置为

My xterm title

获得动态标题的简单方法是在 precmdpreexec 钩子函数中设置标题。有关可用钩子函数及其说明的列表,请参阅 zshmisc(1) § Hook Functions

通过使用 print -P,您还可以利用 Zsh 的提示符转义符。

提示
  • 标题打印可以拆分为多个命令,只要它们是顺序的即可。
  • GNU Screen 将 xterm 标题发送到硬状态 (%h)。如果您想使用 Screen 的 字符串转义符(例如,用于颜色),则应使用 \e_\e\\ 转义序列设置硬状态。否则,如果在 \e]2;\a 中使用了字符串转义符,则终端模拟器将获得乱码标题,因为它无法解释 Screen 的字符串转义符。
注意
  • 打印变量时,请勿使用 print-P 选项,以防止它们被解析为提示符转义符。
  • 使用 q 参数展开标志 打印变量时,防止它们被解析为转义序列。
~/.zshrc
autoload -Uz add-zsh-hook

function xterm_title_precmd () {
	print -Pn -- '\e]2;%n@%m %~\a'
	[[ "$TERM" == 'screen'* ]] && print -Pn -- '\e_\005{2}%n\005{-}@\005{5}%m\005{-} \005{+b 4}%~\005{-}\e\\'
}

function xterm_title_preexec () {
	print -Pn -- '\e]2;%n@%m %~ %# ' && print -n -- "${(q)1}\a"
	[[ "$TERM" == 'screen'* ]] && { print -Pn -- '\e_\005{2}%n\005{-}@\005{5}%m\005{-} \005{+b 4}%~\005{-} %# ' && print -n -- "${(q)1}\e\\"; }
}

if [[ "$TERM" == (Eterm*|alacritty*|aterm*|foot*|gnome*|konsole*|kterm*|putty*|rxvt*|screen*|wezterm*|tmux*|xterm*) ]]; then
	add-zsh-hook -Uz precmd xterm_title_precmd
	add-zsh-hook -Uz preexec xterm_title_preexec
fi

终端模拟器标签页标题

一些终端模拟器和多路复用器支持设置标签页的标题。 转义序列取决于终端类型

终端 转义序列 描述
GNU Screen \ek\e\\ Screen 的窗口标题 (%t)。
Konsole \e]30;\a Konsole 的标签页标题。

Shell 环境检测

请参阅 关于 shell 环境检测的仓库,以获取检测 shell 环境的测试。 这包括登录/交互式 shell、Xorg 会话、TTY 和 SSH 会话。

/dev/tcp 等效项:ztcp

使用 zsh/net/tcp 模块

$ zmodload zsh/net/tcp

您现在可以建立 TCP 连接

$ ztcp example.com 80

更多详情请见 zshmodules(1) § THE_ZSH/NET/TCP_MODULEzshtcpsys(1)

部分命令行上退出 shell 的快捷方式

默认情况下,如果命令行已填充,Ctrl+d 不会关闭您的 shell,此修复了该问题

.zshrc
exit_zsh() { exit }
zle -N exit_zsh
bindkey '^D' exit_zsh

pacman -F "command not found" 处理程序

pacman 包含搜索包含文件的软件包的功能。 以下 command-not-found 处理程序将直接使用 pacman 来搜索匹配的软件包,当执行未知命令时。

~/.zshrc
...
function command_not_found_handler {
    local purple='\e[1;35m' bright='\e[0;1m' green='\e[1;32m' reset='\e[0m'
    printf 'zsh: command not found: %s\n' "$1"
    local entries=(
        ${(f)"$(/usr/bin/pacman -F --machinereadable -- "/usr/bin/$1")"}
    )
    if (( ${#entries[@]} ))
    then
        printf "${bright}$1${reset} may be found in the following packages:\n"
        local pkg
        for entry in "${entries[@]}"
        do
            # (repo package version file)
            local fields=(
                ${(0)entry}
            )
            if [[ "$pkg" != "${fields[2]}" ]]
            then
                printf "${purple}%s/${bright}%s ${green}%s${reset}\n" "${fields[1]}" "${fields[2]}" "${fields[3]}"
            fi
            printf '    /%s\n' "${fields[4]}"
            pkg="${fields[2]}"
        done
    fi
    return 127
}
...
注意: pacman 的文件数据库与正常的同步数据库是分开的,它需要使用 pacman -Fy 获取。 有关详细信息,请参阅 pacman#搜索包含特定文件的软件包

有关使用 pkgfile 的替代方案,请参阅 #pkgfile "command not found" 处理程序

使用快捷键清除回滚缓冲区

默认情况下,清除屏幕的快捷键不会清除大多数终端模拟器上的回滚缓冲区(您需要向上滚动才能看到的部分)。 以下是解决此问题的一种可能方案。

~/.zshrc
...
function clear-screen-and-scrollback() {
    printf '\x1Bc'
    zle clear-screen
}

zle -N clear-screen-and-scrollback
bindkey '^L' clear-screen-and-scrollback
...

第三方扩展

配置框架

注意: 框架引入了抽象和复杂性。 它们可能,并且经常会,引入未定义的行为。 如果 shell 崩溃,首要 调试步骤应该是恢复到纯 shell。
  • oh-my-posh — Oh My Posh 是一个自定义提示符引擎,适用于任何能够使用函数或变量调整提示符字符串的 shell。
https://github.com/JanDeDobbeleer/oh-my-posh || oh-my-poshAUR
  • oh-my-zsh — 一个流行的、社区驱动的框架,用于管理您的 Zsh 配置。 它捆绑了大量有用的函数、助手、插件、主题。
https://github.com/ohmyzsh/ohmyzsh || oh-my-zsh-gitAUR
  • Prezto — 一个 Zsh 的配置框架。 它带有模块,通过合理的默认设置、别名、函数、自动补全和提示符主题来丰富命令行界面环境。
https://github.com/sorin-ionescu/prezto || prezto-gitAUR
  • ZIM — 一个配置框架,具有极快的速度和模块化扩展。 Zim 非常容易自定义,并且附带了丰富的功能模块,且不影响速度或功能。
https://github.com/zimfw/zimfw || zsh-zim-gitAUR

插件管理器

  • Antidote — 传统 Antibody 插件管理器的功能完整的 Zsh 实现。
https://github.com/mattmc3/antidote || zsh-antidoteAUR
  • zinit (之前为 "zplugin") — 灵活的 Zsh 插件管理器,具有干净的 fpath、报告、补全管理、加速模式 已恢复
https://github.com/zdharma-continuum/zinit || zinitAUR
  • zi (之前为 "zplugin") — zplugin 的替代分支,旨在扩展原始项目,而不是像 zinit 那样保留和维护原始项目。
https://github.com/z-shell/zi || 未打包? 在 AUR 中搜索
  • sheldon — 快速、可配置的 shell 插件管理器,用 Rust 编写 [4]
https://github.com/rossmacarthur/sheldon || sheldon
  • Antigen — 一个 Zsh 插件管理器,灵感来自 oh-my-zsh 和 vundle。 已废弃
https://github.com/zsh-users/antigen || antigen-gitAUR
  • zgen — 一个轻量级且简单的 Zsh 插件管理器。 已废弃
https://github.com/tarjoilija/zgen || zgen-gitAUR
  • zplug — 下一代 Zsh 插件管理器。 已废弃
https://github.com/zplug/zplug || zplugAUR

类似 Fish 的语法高亮和自动建议

Fish 提供了非常强大的 shell 语法高亮和自动建议。 要在 Zsh 中同时使用两者,您可以安装 zsh-syntax-highlightingzsh-autosuggestions,最后 source 从您的 zshrc 中获取一个或两个提供的脚本

~/.zshrc
source /usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
source /usr/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh

pkgfile "command not found" 处理程序

pkgfile 包含一个 Zsh 脚本文件,该文件提供了一个 command_not_found_handler 函数,用于在输入无法识别的命令时自动搜索 pkgfile 数据库。

您需要 source 该脚本以启用它。 例如

~/.zshrc
source /usr/share/doc/pkgfile/command-not-found.zsh
注意: pkgfile 数据库可能需要更新后才能工作。 有关详细信息,请参阅 pkgfile#安装

有关使用 pacman 原生功能的替代方案,请参阅 #pacman -F "command not found" 处理程序

另请参阅