6.2 增强工具

除了像 Bash-it 和 Oh My Zsh 这种大而全的 Shell 配置框架外,市面上也包括一些单独的工具。利用这些工具,我们不仅能够增强 Shell 的功能,而且可以达到更加愉悦的 Shell 使用体验。下面,我们就来介绍既实用又有意思的第三方增强工具。

6.2.1 快速路径切换:z.lua

z.lua 是一个使用 Lua 编程语言实现的类似 z.sh、autojump、fasd 等功能的快速路径切换工具。其特点包括:

  • 对所有访问路径进行跟踪,具备学习功能,使用正则匹配从而能够更加准确的带你到想去的地方;
  • 与 z.sh、autojump、fasd 相比,速度更快;
  • 支持广泛的 shell,包含 bash、zsh、fish 等等。

6.2.1.1 安装 z.lua

因为 z.lua 是通过 Lua 编程语言实现的,所以在安装它之前,确保我们的系统中已经包含 lua

xiaodong@codeland:~$ which lua lua5.1 lua5.2 lua5.3

z.lua 支持 Lua 5.1、5.2、5.3 以上版本,上述命令只要有一个正确输出便可。

接下来,我们将 z.lua 的源代码克隆到用户主目录的 ~/.z.lua 子目录:

xiaodong@codeland:~$ git clone \
https://github.com/skywind3000/z.lua.git \
~/.z.lua

待克隆完毕,我们将 z.lua 的初始化语句添加到相应的 Shell 配置文件。

对 bash 来说,将下面这行追加到 ~/.bashrc 配置文件中:

eval "$(lua ~/.z.lua/z.lua --init bash)

若是 zsh,则添加以下内容到 ~/.zshrc 配置文件:

eval "$(lua ~/.z.lua/z.lua --init zsh)

另外,我们也可以在 --init 选项后面添加 once enhanced 参数,以便执行增强匹配模式。我们推荐使用这种匹配模式,从而让 z.lua 更准确的切换到我们想去的路径。

保存编辑后,分别执行下列命令以便使 z.lua 即时生效:

xiaodong@codeland:~$ source ~/.bashrc # bash
xiaodong@codeland:~$ source ~/.zshrc  # zsh

6.2.1.2 使用 z.lua

z.lua 在安装成功后会创建一个名为 z 的别名。让我们先用 z 来切换一些目录:

xiaodong@codeland:~$ z cli
xiaodong@codeland:~/cli$ z ~/prj
xiaodong@codeland:~/prj$ z usingcli
xiaodong@codeland:~/prj/usingcli$ z ~/tmp
xiaodong@codeland:~/tmp$ z ~/.z.lua
xiaodong@codeland:~/.z.lua$

在默认设置下,z.lua 将所有访问的路径都保存到了 ~/.zlua 文件中。我们可以用 cat 来查看它的内容:

xiaodong@codeland:~$ cat ~/.zlua
/home/xiaodong/cli|6|1551946470
/home/xiaodong/.z.lua|3|1551946500
/home/xiaodong/prj|8|1551944681
/home/xiaodong/tmp|3|1551944599
/home/xiaodong/prj/usingcli|1|1551944549

从上面命令的输出中,我们可以看到每个访问路径的次数和时间都有记录。它们使用 | 分隔。z.lua 正是通过这个访问路径数据库来帮助我们快速切换到想去的目录。

另外,我们也可以直接执行 z,这将使 z.lua 列出所访问的路径条目:

xiaodong@codeland:~$ z
6          /home/xiaodong/.z.lua
12         /home/xiaodong/cli/1.15.8/src/event/modules
12         /home/xiaodong/cli/1.15.8/src/event
16         /home/xiaodong/prj/usingcli
20         /home/xiaodong/cli/1.15.8/src
28         /home/xiaodong/tmp
32         /home/xiaodong/cli
52         /home/xiaodong/prj

其中,开头的数字为每个访问路径的权重,该权重由 z.lua 根据算法计算得到。

了解了 z.lua 的基本原理,下面我们就来进行实战:

xiaodong@codeland:~$ z p
xiaodong@codeland:~/prj$

在执行该命令后,z.lua 通过参数 p 匹配到了我们先前访问的路径:

/home/xiaodong/prj

并转到了该目录。

我们再来试试:

xiaodong@codeland:~/prj$ z p us
xiaodong@codeland:~/prj/usingcli$

这次,z.lua 将我们带到了下面的目录:

/home/xiaodong/prj/usingcli

在这种情况下,z.lua 必须同时匹配 p(匹配 prj)和 us(匹配 usingcli),只有两个条件都满足,才会转到相应的目录。

此外,z 命令还包含一些选项以实现其它的功能。比如:

  • -i:交互模式,如果有多个匹配结果的话,那么 z.lua 将展示一个列表:

      xiaodong@codeland:~$ z -i p
      2:  24         /home/xiaodong/tmp
      1:  48         /home/xiaodong/prj
      >

    从列表中,我们可以看到有两个路径条目,中间列为权重。在提示符 > 后输入编号,z.lua 将带我们到相应的目录。直接按回车键将不进行跳转。

  • -b:这个选项在深层次目录中跳转特别有用,它可以将我们快速带回某一级的父目录:

      xiaodong@codeland:~$ z mod
      xiaodong@codeland:~/cli/1.15.8/src/event/modules$ z -b sr
      xiaodong@codeland:~/cli/1.15.8/src$

    第一次,z.lua 跳转到了以下目录:

      ~/cli/1.15.8/src/event/modules

    在添加 -b 选项后,z.lua 根据给定的匹配关键字 sr 匹配到了 src 这级父目录,并跳转到了该目录:

      ~/cli/1.15.8/src

值得一提的是,z.lua 还支持自动补全。如果我们在执行 z p 时按 Tab 键,z.lua 则会显示一个列表:

xiaodong@codeland:~$ z p<Tab>
xiaodong@codeland:~$ z /home/xiaodong/prj
/home/xiaodong/prj  /home/xiaodong/tmp

经过一段时间的使用,我们认为 z.lua 确实是相当不错的路径切换工具,每一个使用命令行的用户都应当将其纳入自己的工具箱。

6.2.2 高效查询 Shell 历史:HSTR

虽然在 bash 和 zsh 中,我们可以使用 Ctrl + r 来搜索历史命令列表,但是它还不够高效。为此,程序员又开发出了比 Ctrl + r 更好用的工具:HSTR。我们可以把 HSTR 看作 Ctrl + r 的增强版本,它使用起来也更加方便。

6.2.2.1 安装 HSTR

HSTR 支持 bash 和 zsh,其本身是使用 C 编写而成,在使用它之前,我们必须先安装它。HSTR 为常见的 Linux 发行版都提供有二进制包,包括 Debian、Ubuntu、Fedora、CentOS 等等。

在 Debian 和 Ubuntu 中,可按如下方式安装:

xiaodong@codeland:~$ sudo -i
root@codeland:~# echo -e "\ndeb https://www.mindforger.com/debian \
      stretch main" >> /etc/apt/sources.list
root@codeland:~# wget -qO - https://www.mindforger.com/gpgpubkey.txt \
      | apt-key add -
root@codeland:~# apt update && apt install hstr

如果要在 Fedora 和 CentOS 中安装 HSTR,那么可以执行:

xiaodong@codeland:~$ sudo yum install hstr

Arch Linux 可从 AUR 安装 HSTR。

6.2.2.2 配置 HSTR

一旦安装完毕 HSTR,我们便可通过 hstr 命令来调用它。不过,在此之前,我们需要先对其进行配置。

对 bash 来说,执行以下命令:

xiaodong@codeland:~$ hstr -s
alias hh=hstr                    # hh to be alias for hstr
export HSTR_CONFIG=hicolor       # get more colors
shopt -s histappend              # append new history items to
                                 # .bash_history
export HISTCONTROL=ignorespace   # leading space hides commands
                                 # from history
export HISTFILESIZE=10000        # increase history file size
                                 # (default is 500)
export HISTSIZE=${HISTFILESIZE}  # increase history size
                                 # (default is 500)
# ensure synchronization between Bash memory and history file
export PROMPT_COMMAND="history -a; history -n; ${PROMPT_COMMAND}"
# if this is interactive shell, then bind hstr to Ctrl-r
# (for Vi mode check doc)
if [[ $- =~ .*i.* ]]; then bind '"\C-r": "\C-a hstr -- \C-j"'; fi
# if this is interactive shell, then bind 'kill last command' to
# Ctrl-x k
if [[ $- =~ .*i.* ]]; then bind '"\C-xk": "\C-a hstr -k \C-j"'; fi
xiaodong@codeland:~$ hstr -s >> ~/.bashrc

如果是 zsh,则执行:

xiaodong@codeland:~$ hstr -z
alias hh=hstr                  # hh to be alias for hstr
export HISTFILE=~/.zsh_history # ensure history file visibility
export HSTR_CONFIG=hicolor     # get more colors
bindkey -s "\C-r" "\eqhstr\n"  # bind hstr to Ctrl-r
                               # (for Vi mode check doc)
xiaodong@codeland:~$ hstr -z >> ~/.zshrc

这段配置不仅为 HSTR 定义了别名 hh,而且为其绑定了快捷键 Ctrl + r。为了使其生效,分别重新载入 bash 和 zsh 的配置文件:

xiaodong@codeland:~$ source ~/.bashrc
xiaodong@codeland:~$ source ~/.zshrc

6.2.2.3 HSTR 的用法

HSTR 已经准备就绪,现在我们可以开始使用它了。有两种启动 HSTR 的方式,一种是执行命令,另一种是按快捷键。下面,我们分别对其进行介绍。

首先,我们来看看如何通过命令的方式来启动 HSTR。前面在配置 HSTR 时,我们为其定义了别名 hh。所以我们在命令行直接输入 hh 并按回车键

xiaodong@codeland:~$ cd ~/cli
xiaodong@codeland:~/cli$ hh

HSTR 为我们呈现了一个可以交互的文本界面,如图 6.16 所示。该界面大致可以分为 4 个部分,从上往下依次为:

  1. 命令输入行:我们输入命令,或者查询关键字的地方。
  2. 使用提示行:包含如何使用的说明以及按键的作用。
  3. 当前状态行:显示当前视图的排列方式、关键字的匹配方法、以及是否区分大小写等信息。
  4. 历史命令列表:根据视图的排列方式展示历史命令。
HSTR 的界面

图 6.16: HSTR 的界面

让我们在命令输入行输入一些字符看看:

xiaodong@codeland$ vag # vagrant

我们每输入一个字符,HSTR 都会进行搜索,并将列表中匹配的命令用高亮颜色显示。如果输错了,则按退格键Ctrl + u删除。然后,再重新输入。

现在,根据我们的需要,我们可以进行如下选择:

  • 直接按回车键,这将执行列表中的第一行命令。
  • 如果想要对命令进行编辑,那么我们可以按Tab 键
  • 或者,按Ctrl + g取消本次操作。

在执行 hh 的时候,我们也可以带一个查询关键字参数。这样,HSTR 启动时就会直接将过滤结果展示给我们,如图 6.17 所示。

xiaodong@codeland:~/cli$ hh nvim
执行 hh nvim 的结果

图 6.17: 执行 hh nvim 的结果

除了执行命令外,HSTR 还支持通过快捷键启动。我们只需要按Ctrl + r即可。

6.2.2.3.1 列表操作

前面我们只提到了如何使用列表中的第一条命令,如果我们想要使用其它命令,那么又该如何操作呢?

首先,在 HSTR 的交互文本界面中,我们可以通过下面的快捷键来上下移动:

  • 下方向键Ctrl + n:向下移动一行
  • 上方向键Ctrl + p:往上移动一行

一旦选定某行命令,除了执行我们先前介绍的操作之外,我们还能够将其加入收藏夹,或者删除不再需要的命令。

  • Ctrl + f:将命令添加到收藏夹
  • Delete 键:删除命令,根据提示按y将确认删除
6.2.2.3.2 控制选项

在 HSTR 的交互文本界面中,我们可以通过更改它的控制选项,从而改变其行为。HSTR 的控制选项主要包括以下 3 种:

  1. 视图排序方式:包含按 HSTR 的排名算法排序、历史顺序、以及收藏夹。按Ctrl + /可以在这 3 中视图方式中循环。
  2. 匹配方法:包括关键字匹配、精确匹配、以及正则匹配。按Ctrl + e可以在 3 中匹配方法中切换。
  3. 是否区分大小写:按Ctrl + t进行切换。

随着对 HSTR 的使用次数越多,我们越感觉 HSTR 确实是很棒的工具。对于想要追求操作效率的各位读者来说,一定不要错过。