更懂你的路径切换工具 - z.lua(集 autojump / z / fasd 大成)

2019-02-01 01:00:33 +08:00
 skywind3000

z.lua 是一个快速路径切换工具,它会跟踪你在 shell 下访问过的路径,通过一套称为 Frecent 的机制(源自 FireFox ),经过一段简短的学习之后,z.lua 会帮你跳转到所有匹配正则关键字的路径里 Frecent 值最高的那条路径去。

正则将按顺序进行匹配,"z foo bar" 可以匹配到 /foo/bar,但是不能匹配 /bar/foo。

项目地址:skywind3000/z.lua

有啥特点?

如何安装?

Posix Shells ( Bash、zsh、dash、sh 或 BusyBox 等)中,在你的 .bashrc, .zshrc 或者 .profile 文件中按 shell 类型添加对应语句:

  eval "$(lua /path/to/z.lua  --init bash)"   # BASH 初始化
  eval "$(lua /path/to/z.lua  --init zsh)"    # ZSH 初始化
  eval "$(lua /path/to/z.lua  --init posix)"  # Posix shell 初始化

用下面参数初始化会进入“增强匹配模式”:

  eval "$(lua /path/to/z.lua  --init bash once enhanced)"   # BASH 初始化
  eval "$(lua /path/to/z.lua  --init zsh once enhanced)"    # ZSH 初始化
  eval "$(lua /path/to/z.lua  --init posix once enhanced)"  # Posix shell 初始化

同时 zsh 支持 antigen/oh-my-zsh 等包管理器,可以用下面路径:

  skywind3000/z.lua

进行安装,比如 antigen 的话,在 .zshrc 中加入:

  antigen bundle skywind3000/z.lua

就可以了(主要要放在 antigen apply 语句之前)。Windows 和 Fish Shell 的初始化见文档。

Matching

z.lua 提供两种路径匹配算法:

除了设置环境变量外,还可以通过:

eval "$(lua /path/to/z.lua --init bash enhanced)"

来进入增强模式。

默认匹配

默认情况下 z.lua 使用和 z.sh 类似的匹配算法,成为默认匹配法。给定路径会按顺序匹配各个正则表达式。

增强匹配

你可以通过设置环境变量来启用增强匹配模式:

export _ZL_MATCH_MODE=1

或者使用下面语句:

eval "$(lua /path/to/z.lua --init bash enhanced)"

进行初始化,他们是等效的,记得把上面的 bash 可以根据你的 shell 改为 zsh 或者 posix

对于一个给定的正则关键字序列(即 z 命令后面的参数),某路径有且只有满足下面两个条件才算作 “匹配成功”:

  1. 正则关键字将按顺序进行匹配(这条和默认匹配法相同)。
  2. 最后一个关键字可以和路径名的最后一段相匹配。

如果两条规则同时启用找不到任何结果,那么将会退回到只用规则 1 进行筛选,这两条规则是参考 fasd 引入的。

再我最初实现 z.lua 时,只有一个和 z.sh 类似的默认匹配算法,在网友的建议下,我陆续学习了来自 fasd / autojump 中的优秀理念,并加以完善改进,成为如今集三家之长的 “增强匹配算法” ,给它取个昵称,叫做 “更懂你的匹配算法”。

更新数据库的时机

何时更新数据呢?默认情况下,z.lua 会在每次显示命令提示符时记录当前路径(和 z.sh 一致),但是还提供了一个 $_ZL_ADD_ONCE 的环境变量选项,设置成 1 的话,只有当前路径改变,才会将新路径添加到数据库。

除了设置环境变量外,不同的 shell 下还可以在初始化时增加 "once" 参数来达到相同目的,比如:

eval "$(lua /path/to/z.lua --init bash once enhanced)"
eval "$(lua /path/to/z.lua --init zsh once enhanced)"
lua /path/to/z.lua --init fish once enhanced | source

将会同时启用增强匹配算法和 once 机制,在一些比较慢的硬件下(路由器,cygwin,msys ),使用该机制将有效的提升性能。其实 autojump 在 zsh 下会使用类似 once 的机制,而 bash 下则和 z.sh 类似。

从效果上来讲,z.sh 的模式(关闭 once )强调的是 “在某路径下工作的时间长短”,而 autojump 的模式(启用 once )则强调 “进入某路径的次数多少”。

交互式选择模式

使用 -i 参数进行跳转时, 如果有多个匹配结果,那么 z.lua 会给你显示一个列表:

$ z -i soft
3:  0.25        /home/data/software
2:  3.75        /home/skywind/tmp/comma/software
1:  21          /home/skywind/software
> {光标位置}

然后你按照最前面的序号输入你想要去的地方,比如输入 3 就会进入 /home/data/software。如果你不输入任何东西直接按回车,那么将会直接退出而不进行任何跳转。

Tips

推荐一些常用的命令别名:

alias zc='z -c'      # 严格匹配当前路径的子路径
alias zz='z -i'      # 使用交互式选择模式

同时你可以定义一个名为 zf 的命令,搭配 fzf 进行历史路径模糊匹配:

alias zf='cd "$(z -l -s | fzf --reverse --height 35%)"'

性能评测

最慢的部分当然是添加当前路径到数据库。该操作会在每次你按回车时执行,所以我在我的 Nas 上做了个对比:

$ time autojump --add /tmp
real    0m0.352s
user    0m0.077s
sys     0m0.185s

$ time fasd -A /tmp
real    0m0.618s
user    0m0.076s
sys     0m0.242s

$ time _z --add /tmp
real    0m0.194s
user    0m0.046s
sys     0m0.154s

$ time _zlua --add /tmp
real    0m0.052s
user    0m0.015s
sys     0m0.030s

可以看出,z.lua 是消耗资源最少,并且最快的,可以更流畅的在性能不好的环境中使用。

结论

真的可以卸载 autojump / z / fasd 了。

10424 次点击
所在节点    Linux
41 条回复
skywind3000
2019-02-01 17:49:00 +08:00
@wweir 我已经给出支持我论据的初步测试了,你如果觉得不妥但,欢迎进一步测试来反驳。
wweir
2019-02-01 18:43:13 +08:00
我反驳啥?我只要提出质疑就行了。
谁让你是想推广的那一方的,我们作为用户,就是有这个特权 😄
Yggdroot
2019-02-01 18:54:13 +08:00
@wweir 质疑也要有根有据,而不是无脑喷。
haozhang
2019-02-01 18:56:04 +08:00
@wweir 不要包括我,我没那么厚的脸,被打肿了还要充胖子。
uyhyygyug1234
2019-02-01 20:15:34 +08:00
感觉切换目录这个,fasd z.sh 性能已经挺好了。不过路由器上可能差点。

我见到 https://www.v2ex.com/t/436485 这边有配合 fzf 做交互的的选择,更加直观。




ps 楼主的文章介绍更好的 init.sh 中,提到的“有恒产才会有恒心”想法很好。
skywind3000
2019-02-01 20:58:03 +08:00
@yuikns 该问题已经修复,初始化随机数种子用了一个 os.tmpname() 结果没发现该函数会在 /tmp 建立临时文件。随机数种子已经改写为更好的方式了,不再调用 os.tmpname(),该问题修正。
skywind3000
2019-02-01 21:02:35 +08:00
@uyhyygyug1234 其实下面方法也可以代替:

alias zf='cd "$(z -l -s | fzf --reverse --height 35%)"'

达到你说的这个效果,把 z.sh/z.lua 的历史数据拿出来,放给 fzf 匹配。但是啊,z.lua 的匹配不当会考虑字符串,还会考虑 frecency 权重,不是简单 fzf 那种字符串排序。同时还有很多用于提升效率的匹配规则,也不是 fzf 那种纯字符串匹配。
skywind3000
2019-02-01 21:15:17 +08:00
@dltsgl 能不能自己编译个完整的 lua,有问题再给我反馈。
有些包管理里面的 lua 编译参数都没给全,导致库函数缺胳膊少腿的。
Kobayashi
2019-02-01 21:28:19 +08:00
据我所知,你测试中的 fasd 不准确,应该是 autojump 调用 Python 解释器最为耗时。我是从这里看到的:

https://reddit.com/r/linux/comments/agkx07/zlua_a_better_method_to_change_directory/eecu8op?context=3

作者有考虑像 fasd 一样从输入的命令中提取路径信息、文件信息吗?

@uyhyygyug1234 autojump, z, fasd, z.lua, zsh-z 对比可以看看上边的链接。从结论上讲,fasd 因为抓取了输入的命令中的路径,考虑的要比其他几位多。
但从速度上来看,z.lua 和 zsh-z 最快,前者支持 POSIX sh,但后者也说明其实慢的不是 shell 脚本,而是因为 z 中调用外部命令耗时。
uyhyygyug1234
2019-02-01 21:34:19 +08:00
uyhyygyug1234
2019-02-01 21:35:29 +08:00
貌似 z[dot]sh 这个触发了外链 spam 规则。只能贴图了。
GPU
2019-02-02 00:58:36 +08:00
我用 oh my zsh 的话怎么安装这个插件

我在 .zshrc 里面 加入 plugins=( skywind3000/z.lua ) 这样不生效 .

还是这种方式只支持 antigen
skywind3000
2019-02-02 01:05:37 +08:00
@GPU 我不用 oh-my-zsh 啊,试试这个:

git clone https://github.com/skywind3000/z.lua $ZSH_CUSTOM/plugins/zlua

然后配置里:
plugins=( ... zlua )
Kobayashi
2019-02-02 10:05:56 +08:00
@uyhyygyug1234 关于 fasd 速度啥不是对你说的,是想问作者有没有支持 fasd 做法的计划。z.lua 替换 z 和 autojump 是可能,替换 fasd 就算了。z.lua 既没有 v 的功能,也没有从命令行提取路径的特性,比不上 fasd。

fzf 我自己也在用,fzf 的 wiki 有列出你给出的脚本,不过还是谢谢了。好像我记得 fzf 加入--height 参数可以把 fzf 菜单移动到光标下,而不是全屏,我个人喜欢这么干。
Kobayashi
2019-02-02 10:12:26 +08:00
@skywind3000 我猜作者以前没写过 ZSH 插件,也不用 ZSH 框架、插件管理器?插件脚本名应该与插件所在文件夹名、项目名一致。即把插件脚本改名为 z.lua.plugin.zsh ,这基本上已经成为 ZSH 插件的规范要求。现在的命名根本没办法被 oh-my-zsh 加载,大部分插件管理器也加不了。

只要想问一下作者,有没有考虑给 z.lua 加入类似 fasd 的命令内容提取?
skywind3000
2019-02-02 11:47:42 +08:00
@Kobayashi 我一直用 antigen,只要后缀有 .plugin.zsh 它就识别了,没用 oh-my-zsh,已经改成 z.lua.plugin.zsh 了。关于 fasd,我感觉它这种疯狂收集所有路径的开销太大,我几台 nas / 路由 和 cygwin/wsl 根本吃不消,用不起。暂时不是 z.lua 的目标,未来我会花时间增加更多便利的跳转机制,以及 fzf 的集成。
Kobayashi
2019-02-02 14:35:42 +08:00
@skywind3000 恩,我确实没有考虑到在路由上的消耗问题,谢谢解答。
a132811
2019-02-05 09:27:38 +08:00
lua ${HOME}/conf/z.lua --init zsh
ZLUA_SCRIPT="usage: which [-as] program ..."

报错了呢?
skywind3000
2019-02-05 13:06:13 +08:00
@a132811 你的 lua 有问题,是不是 brew 安装的啊? z.lua 需要取得 zlua 可执行的路径,结果取不出来。重新按默认参数编译一个 lua 解决。
stdout
2019-11-08 12:21:13 +08:00
果断换成 z.lua 了,fasd 太慢了。按这 enter 不动明显能感觉出来。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/532304

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX