1
0
mirror of https://github.com/skywind3000/z.lua synced 2026-03-22 15:49:47 +00:00

73 Commits

Author SHA1 Message Date
skywind3000
65bfbf8dfb update lfs detection 2020-06-29 19:40:55 +08:00
skywind3000
1b9630e72d Merge branch 'master' of https://github.com/skywind3000/z.lua 2020-06-29 18:11:32 +08:00
skywind3000
c98d2d783e use lfs module or cffi in luajit if possible 2020-06-29 18:11:23 +08:00
Linwei
057e4f77f3 Merge pull request #108 from exic/patch-1
Update README.md
2020-05-29 17:34:37 +08:00
Jonas
8a90ca6df4 Update README.md
Fix typo
2020-05-29 11:14:38 +02:00
skywind3000
a4c51d8103 update doc 2020-03-28 19:48:20 +08:00
skywind3000
b40df870a6 update doc 2020-03-18 22:47:05 +08:00
skywind3000
a55bb87e1b update docs 2020-03-18 22:38:46 +08:00
skywind3000
c4512b47d2 update doc 2020-03-18 22:36:35 +08:00
skywind3000
6c567b60b3 update doc 2020-03-17 23:12:08 +08:00
skywind3000
8fff9e6471 update doc 2020-03-17 23:11:13 +08:00
skywind3000
f7a9104983 update z.lua 2020-03-17 16:38:30 +08:00
skywind3000
7b43a0afd6 Merge branch 'master' of https://github.com/skywind3000/z.lua 2020-03-17 16:37:48 +08:00
skywind3000
788c0f4b77 new --init option clean to skip hooks 2020-03-17 16:37:21 +08:00
skywind3000
47aa86b0f9 remove files 2020-03-17 11:37:04 +08:00
skywind3000
a1498c8672 update 2020-03-17 02:35:21 +08:00
skywind3000
4c34e29e08 update 2020-03-17 02:26:49 +08:00
skywind3000
3d188ab6d9 update 2020-03-17 02:05:41 +08:00
skywind3000
a5f4cb692c update 2020-03-17 00:50:27 +08:00
skywind3000
77a917d116 update czmod.z 2020-03-17 00:20:06 +08:00
skywind3000
93e9715e7d commit new iposix.c/.h 2020-03-16 23:11:09 +08:00
skywind3000
b7c3fbc4ee update new imembase.c 2020-03-16 22:44:24 +08:00
skywind3000
ebda4aa061 update module 2020-03-16 22:30:50 +08:00
skywind3000
168ec49849 update 2020-03-16 18:48:26 +08:00
skywind3000
ec123de01a update 2020-03-12 18:35:03 +08:00
skywind3000
a0d4750431 commit czmod 2020-03-11 16:23:14 +08:00
skywind3000
d615051a10 improve compinit handling 2020-03-08 00:14:04 +08:00
skywind3000
f448f2ab1f suppress compdef error message if compinit hasn't been invoked. 2020-03-05 18:09:21 +08:00
Linwei
8ed3422670 Merge pull request #93 from Aloxaf/no_compctl
Improve zsh's completion
2020-02-28 17:26:27 +08:00
Aloxaf
3edbda89a0 Improve zsh's completion 2020-02-28 15:32:30 +08:00
Linwei
c9b50b3c50 Merge pull request #92 from kidonng/add-fisher-compatibility
添加 Fisher 支持
2020-02-23 17:28:34 +08:00
Kid
228addbc49 Add Fisher compatibility 2020-02-23 13:48:37 +08:00
skywind3000
bca25eba12 fish shell: set $_ZL_ECHO in global scope 2020-02-10 19:26:22 +08:00
skywind3000
097ca07ecd update fish script 2020-02-10 18:24:20 +08:00
skywind3000
4ee783956d update doc 2020-02-10 10:52:03 +08:00
skywind3000
0effba4021 polish: 1.8.3 2020-02-10 00:14:09 +08:00
skywind3000
cada42e5ea z.lua 1.8.3: polish interactive mode in z -b -i 2020-02-10 00:09:08 +08:00
skywind3000
b8b6d1afd6 z.lua 1.8.2 2020-02-09 23:46:35 +08:00
skywind3000
4abe97f989 jump backwards 2020-02-09 23:39:36 +08:00
skywind3000
756d13d8fa zlua 1.8.1: new -b -i and -b -I for interactive backwards cd 2020-02-09 23:34:37 +08:00
skywind3000
4900651af3 Merge branch 'master' of https://github.com/skywind3000/z.lua 2019-12-29 04:59:20 +08:00
skywind3000
836efd3973 1.7.4: new $_ZL_HYPHEN option 2019-12-29 04:59:08 +08:00
Linwei
3b8b4c1fbb Merge pull request #87 from davidosomething/no-aliases
Introduce _ZL_NO_ALIASES to skip creating aliases
2019-12-26 00:35:12 +08:00
David O'Trakoun
8eaebca04a Introduce _ZL_NO_ALIASES to skip creating aliases 2019-12-25 00:16:44 -05:00
Linwei
fdd037acf8 Merge pull request #85 from rongmu/_zl_fzf_flag-fix
[zsh plugin] allow the user to customize _ZL_FZF_FLAG beforehand
2019-12-10 17:45:04 +08:00
Shaoyun Yu
a817cf6ed2 allow the user to custom _ZL_FZF_FLAG beforehand
increase flexibility: allow the user to custom _ZL_FZF_FLAG before the zsh plugin is loaded
2019-12-10 10:50:55 +09:00
skywind3000
5c36d55698 use lua-filesystem package if possible when $_ZL_USE_LFS is 1 2019-09-07 01:02:48 +08:00
skywind3000
bdab27db1b fixed wrong return value from os.path.exists 2019-09-06 01:21:28 +08:00
skywind3000
e08f5beca4 update doc 2019-08-01 20:06:05 +08:00
skywind3000
a245db0d93 update doc 2019-08-01 19:54:34 +08:00
skywind3000
dd721703c3 1.7.2: improve bash / zsh shell compatibility 2019-08-01 19:46:23 +08:00
Linwei
7920d56c89 Merge pull request #71 from barlik/prompt-command
Do not append semicolon to PROMPT_COMMAND
2019-08-01 17:45:54 +08:00
Linwei
645818ccc8 Merge pull request #72 from barlik/zsh-hooks 2019-08-01 02:41:19 +08:00
Rastislav Barlik
b98911a227 Setting zsh-hooks to be unique is not necessary 2019-07-31 14:46:28 +01:00
Rastislav Barlik
671830059b Do not append semicolon to PROMPT_COMMAND 2019-07-31 13:47:55 +01:00
skywind3000
0fad96124b commit new README.md 2019-06-07 22:17:42 +08:00
skywind3000
465f2b8e62 fixed linux $_ZL_DATA failure 2019-06-07 22:13:29 +08:00
skywind3000
ff9d874ef4 update doc 2019-03-09 17:24:53 +08:00
skywind3000
86120d206e fix: ReplaceFile issue in luajit (windows). 2019-03-09 16:56:46 +08:00
skywind3000
1e0e3523b0 add ranger plugin for z.lua 2019-03-08 16:23:40 +08:00
skywind3000
7eee4e4b13 optimize with ffi (luajit builtin module). 2019-03-04 20:29:43 +08:00
skywind3000
edd71f7a6e update doc 2019-03-02 12:16:50 +08:00
skywind3000
f63a832921 improve errno handling in os.path.exists 2019-03-02 12:06:02 +08:00
skywind3000
f92ad79e2c fixed: os.path.isdir not work for symbol links close #59. 2019-03-02 11:55:39 +08:00
skywind3000
38c1741f4f prevent writing file racing 2019-03-01 14:45:03 +08:00
skywind3000
fdff5c5e1e commit new README.md 2019-02-28 12:24:20 +08:00
skywind3000
b691d537f2 z -b should not match current directory, close #56 2019-02-25 23:20:15 +08:00
skywind3000
472925ac92 improve lua test 2019-02-25 11:01:00 +08:00
Linwei
5ba0e50894 Merge pull request #54 from aaronjensen/patch-1
Use \which in case user has it aliased to type -a
2019-02-24 13:12:20 +08:00
Aaron Jensen
c769dba4dd Use \which in case user has it aliased to type -a 2019-02-23 19:40:26 -08:00
skywind3000
bbca83c9a5 update doc 2019-02-22 22:54:22 +08:00
skywind3000
53c127a4a2 update doc 2019-02-22 22:46:23 +08:00
skywind3000
5f7fa928b6 new $_ZL_FZF_HEIGHT, set to 0 to use fullscreen 2019-02-21 12:12:58 +08:00
6 changed files with 537 additions and 91 deletions

View File

@@ -14,11 +14,11 @@ z.lua 是一个快速路径切换工具,它会跟踪你在 shell 下访问过
- 性能比 **z.sh** 快三倍,比 **fasd** / **autojump** 快十倍以上。 - 性能比 **z.sh** 快三倍,比 **fasd** / **autojump** 快十倍以上。
- 支持 Posix Shellbash, zsh, dash, sh, ash, busybox 等等。 - 支持 Posix Shellbash, zsh, dash, sh, ash, busybox 等等。
- 支持 Fish ShellPower Shell 和 Windows cmd。 - 支持 Fish ShellPower Shell 和 Windows cmd。
- 使用增强匹配算法,更准确的带你去到你想去的地方。 - 使用增强匹配算法,更准确的带你去到你想去的地方。
- 低占用,能够仅在当前路径改变时才更新数据库(将 `$_ZL_ADD_ONCE` 设成 1 - 低占用,能够仅在当前路径改变时才更新数据库(将 `$_ZL_ADD_ONCE` 设成 1
- 交互选择模式,如果有多个匹配结果的话,跳转前允许你进行选择。 - 交互选择模式,如果有多个匹配结果的话,跳转前允许你进行选择。
- 集成 fzf (可选),可以用来做可视化选择或者参数补全。 - 集成 fzf (可选),可以用来做可视化选择或者参数补全。
- 快速跳转到父目录,或者项目根目录,代替反复 “cd ../../.." 。 - 快速跳转到父目录,或者项目根目录,代替反复 “cd ../../.." 。
- 兼容 lua 5.1, 5.2 和 5.3 以上版本。 - 兼容 lua 5.1, 5.2 和 5.3 以上版本。
- 自包含且无额外依赖,单个 `z.lua` 文件完成所有工作。 - 自包含且无额外依赖,单个 `z.lua` 文件完成所有工作。
@@ -42,10 +42,10 @@ z -b foo # 跳转到父目录中名称以 foo 开头的那一级
## Install ## Install
- Posix ShellsBash、zsh、dash、sh 或 BusyBox 等): - Posix ShellsBash、zsh、dash、sh 或 BusyBox 等):
在你的 `.bashrc`, `.zshrc` 或者 `.profile` 文件中按 shell 类型添加对应语句: 在你的 `.bashrc`, `.zshrc` 或者 `.profile` 文件中按 shell 类型添加对应语句:
eval "$(lua /path/to/z.lua --init bash)" # BASH 初始化 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 zsh)" # ZSH 初始化
eval "$(lua /path/to/z.lua --init posix)" # Posix shell 初始化 eval "$(lua /path/to/z.lua --init posix)" # Posix shell 初始化
@@ -79,8 +79,8 @@ z -b foo # 跳转到父目录中名称以 foo 开头的那一级
但是第二种方法需要记得在 z.lua 位置改变或者 lua 版本升级后需要重新生成。 但是第二种方法需要记得在 z.lua 位置改变或者 lua 版本升级后需要重新生成。
- Power Shell: - Power Shell:
在你 Power Shell 的配置文件 `profile.ps1` 中放入下面语句: 在你 Power Shell 的配置文件 `profile.ps1` 中放入下面语句:
iex ($(lua /path/to/z.lua --init powershell) -join "`n") iex ($(lua /path/to/z.lua --init powershell) -join "`n")
@@ -90,7 +90,7 @@ z -b foo # 跳转到父目录中名称以 foo 开头的那一级
- 将 z.lua 和 z.cmd 拷贝到 clink 的安装目录。 - 将 z.lua 和 z.cmd 拷贝到 clink 的安装目录。
- 将 clink 的安装目录添加到 `%PATH%` (z.cmd 可以被任意位置调用到)。 - 将 clink 的安装目录添加到 `%PATH%` (z.cmd 可以被任意位置调用到)。
- 保证 lua 命令在你的 `%PATH%` 环境变量中。 - 保证 lua 命令在你的 `%PATH%` 环境变量中。
- Windows cmder: - Windows cmder:
@@ -111,6 +111,7 @@ z -b foo # 跳转到父目录中名称以 foo 开头的那一级
- 设置 `$_ZL_CD` 用来指定你想用的 cd 命令,比如有人用 cd_func 。 - 设置 `$_ZL_CD` 用来指定你想用的 cd 命令,比如有人用 cd_func 。
- 设置 `$_ZL_ECHO` 为 1 可以在跳转后显示目标路径名称。 - 设置 `$_ZL_ECHO` 为 1 可以在跳转后显示目标路径名称。
- 设置 `$_ZL_MATCH_MODE` 为 1 可以打开 “增强匹配模式”。 - 设置 `$_ZL_MATCH_MODE` 为 1 可以打开 “增强匹配模式”。
- 设置 `$_ZL_HYPHEN` 为 1 可以允许关键字中包含横线 (横线默认是 lua 正则关键字,要转写成 `%-`)。
## Aging ## Aging
@@ -161,7 +162,7 @@ Frecency 是一个由 'recent' 和 'frequency' 组成的合成词,这个术语
对于一个给定的正则关键字序列(即 z 命令后面的参数),只有同时满足两个条件才算匹配成功: 对于一个给定的正则关键字序列(即 z 命令后面的参数),只有同时满足两个条件才算匹配成功:
1. 正则关键字将按顺序进行匹配(这条和默认匹配法相同)。 1. 正则关键字将按顺序进行匹配(这条和默认匹配法相同)。
2. 最后一个关键字可以和路径名的最后一段相匹配。 2. 最后一个关键字可以和路径名的最后一段相匹配。
如果两条规则同时启用找不到任何结果,那么将会退回到只用规则 1 进行筛选,这两条规则是参考 fasd 引入的。 如果两条规则同时启用找不到任何结果,那么将会退回到只用规则 1 进行筛选,这两条规则是参考 fasd 引入的。
@@ -175,14 +176,14 @@ Frecency 是一个由 'recent' 和 'frequency' 组成的合成词,这个术语
30 /home/user/workspace/project2 30 /home/user/workspace/project2
40 /home/user/workspace/project3 40 /home/user/workspace/project3
在增强模式下使用 `"z wo"` 的话,只有 `/home/user/work` 满足匹配,因为按照第二条规则,这是唯一一条最有一段名称匹配 `wo` 的路径。 在增强模式下使用 `"z wo"` 的话,只有 `/home/user/workspace` 满足匹配,因为按照第二条规则,这是唯一一条最有一段名称匹配 `wo` 的路径。
因为最后一级目录名称总是最容易记住的,所以给到它比较高的优先级。在默认匹配算法中,你同样可以用 `"z space$"` 来达到相同的目的,但是 `"z wo"` 可以打更少的字。 因为最后一级目录名称总是最容易记住的,所以给到它比较高的优先级。在默认匹配算法中,你同样可以用 `"z space$"` 来达到相同的目的,但是 `"z wo"` 可以打更少的字。
小技巧: 小技巧:
- 如果你在增强匹配算法下,想让最后一个关键字不当匹配最后一段路径名,还可以像默认匹配算法中一样匹配路径的其他部分的话,你可以在最后加一个独立的 '$' 参数,比如:`"z wo $"` - 如果你在增强匹配算法下,想让最后一个关键字不当匹配最后一段路径名,还可以像默认匹配算法中一样匹配路径的其他部分的话,你可以在最后加一个独立的 '$' 参数,比如:`"z wo $"`
- 如果你在增强匹配算法下,想让最后一个关键字匹配最后一段路径名以前的部分,那么可以增加一个斜杆参数,比如:`"z wo /"`。 - 如果你在增强匹配算法下,想让最后一个关键字匹配最后一段路径名以前的部分,那么可以增加一个斜杆参数,比如:`"z wo /"`。
- 如果没法匹配,同时又存在一条路径名和关键字相同,那么 cd 过去: - 如果没法匹配,同时又存在一条路径名和关键字相同,那么 cd 过去:
@@ -265,11 +266,11 @@ PS你可以使用 `$_ZL_FZF` 环境变量来精确指明 fzf 的可执行路
`"-b"` 选项可以快速回到某一级父目录,避免重复的输入 "cd ../../.."。 `"-b"` 选项可以快速回到某一级父目录,避免重复的输入 "cd ../../.."。
- **(没有参数)**`cd` 到项目根目录,即跳转到最近的包含 (.git/.svn/.hg) 的父目录。 - **(没有参数)**`cd` 到项目根目录,即跳转到最近的包含 (.git/.svn/.hg) 的父目录。
- **(单个参数)**`cd` 到离当前目录最近的以关键字开头的父目录,如果找不到就尝试跳到包含关键字的父目录。 - **(单个参数)**`cd` 到离当前目录最近的以关键字开头的父目录,如果找不到就尝试跳到包含关键字的父目录。
- **(两个参数)**:将当前路径中的第一个关键词替换为第二个关键词。 - **(两个参数)**:将当前路径中的第一个关键词替换为第二个关键词。
为了使用简便,我们继续将 `z -b` 取个别名成 `zb` 将 `z -b` 别名成 `zb`
```bash ```bash
# 一直向上退到项目根目录(就是里面有一个 .git 目录的地方) # 一直向上退到项目根目录(就是里面有一个 .git 目录的地方)
@@ -302,6 +303,8 @@ export _ZL_ROOT_MARKERS=".git,.svn,.hg,.root,package.json"
**Bonus**`zb ..` 相当于 `cd ..``zb ...` 相当于 `cd ../..`,而 `zb ....` 相当于 `cd ../../..` 等等。 最后 `zb ..20` 等同于调用 `cd ..` 二十次。 **Bonus**`zb ..` 相当于 `cd ..``zb ...` 相当于 `cd ../..`,而 `zb ....` 相当于 `cd ../../..` 等等。 最后 `zb ..20` 等同于调用 `cd ..` 二十次。
**Bonus**: 试试 `z -b -i` 以及 `z -b -I`,推荐把他们取个别名成 `zbi` 和 `zbf`。
## 补全功能 ## 补全功能
@@ -350,23 +353,22 @@ $ z -
=> cd - => cd -
``` ```
这个 `dirstack` 是根据 z.lua 的路径历史数据库计算的出来的,所以和具体的 shell 或者操作系统都没有关系。你退出再登陆不会丢失这些路径历史,不同的 shell 之间也可以共享同一份历史数据 这个 `dirstack` 是根据 z.lua 的路径历史数据库计算的出来的,和具体的 shell 或者操作系统无关。你退出再登陆不会丢失这些记录,不同的 shell 之间也可以共享同一份记录
此外,还有另外一种方法,通过使用前面提到的 `-I` 和 `-t` 参数组和,可以使用 fzf 进行交互式选择: 此外,还能通过前面提到的 `-I` 和 `-t` 参数组和,使用 fzf 选择最近去过的目录
```bash ```bash
alias zh='z -I -t .' alias zh='z -I -t .'
``` ```
首先定义个新的别名 `zh`(回到历史路径的意思),我们使用了 `-t` 参数来告诉 `z.lua` 按时间戳为权重进行排序,同时 `-I` 启用 fzf 进行搜索,最后句号代表任意路径。 方便起见,定义个新的别名 `zh`(回到历史路径的意思),我们 `-t` 参数来告诉 `z.lua` 按时间戳为权重排序,同时 `-I` 启用 fzf 搜索,最后句号代表任意路径。
那么当我们在命令行敲入 zh 时,就可以用 fzf 选择最近呆过的路径了: 那么当我们在命令行敲入 zh 时,就可以用 fzf 进行历史路径操作了:
![](images/mru.png) ![](images/mru.png)
第一列数据代表该路径多少秒以前访问过,第二列是路径名称。此时,你可以试着敲几个字母,用 fzf 的字符串模糊匹配进行定位或者用光标键的上和下CTRL+J/K 也可以)来上下移动,最后按回车 cd 过去,或者 ESC 放弃。 第一列上次访问距今多少秒,第二列是目录名。你可以试着敲几个字母,用 fzf 的字符串模糊匹配进行定位或者用光标键的上和下CTRL+J/K 也可以)来上下移动,最后按回车 cd 过去,或者 ESC 放弃。
注意:最好把增强匹配模式打开,这样查看历史路径时可以把当前路径过滤掉。
## Tips ## Tips

View File

@@ -13,16 +13,26 @@ z.lua is a faster way to navigate your filesystem. It tracks your most used dire
For example, `z foo bar` would match `/foo/bar` but not `/bar/foo`. For example, `z foo bar` would match `/foo/bar` but not `/bar/foo`.
## Reputation
From people using z.lua:
- I like this in principal. Im pretty damn predictable at the command line and far too lazy to make shortcuts
- It feels far more intuitive and it's so incredibly convenient to be able to jump between folders I'm working in without having to traverse an entire tree. The shell used to feel so constraining for me, but tools like this are making me enjoy it so much more.
- I can finally have autojump-like functionality on my Raspberry Pi 1 without waiting 30 seconds every time I open a new shell. Thanks z.lua devs.
- Anyway, z.lua is a promising project. If you only need directory jumping, it may be the best choice.
## Features ## Features
- **10x** times faster than **fasd** and **autojump**, **3x** times faster than **z.sh**. - **10x** times faster than **fasd** and **autojump**, **3x** times faster than **z.sh**.
- Gain the ultimate speed with an optional [native module](https://github.com/skywind3000/czmod) written in C.
- Available for **posix shells**: bash, zsh, dash, sh, ash, ksh, busybox and etc. - Available for **posix shells**: bash, zsh, dash, sh, ash, ksh, busybox and etc.
- Available for Fish Shell, Power Shell and Windows cmd. - Available for Fish Shell, Power Shell and Windows cmd.
- [Enhanced matching algorithm](#enhanced-matching) takes you to where ever you want precisely. - [Enhanced matching algorithm](#enhanced-matching) takes you to where ever you want precisely.
- Allow updating database only if `$PWD` changed with "$_ZL_ADD_ONCE" set to 1. - Allow updating database only if `$PWD` changed with "$_ZL_ADD_ONCE" set to 1.
- Interactive selection enables you to choose where to go before cd. - Interactive selection enables you to choose where to go before cd.
- Intergrated with FZF (optional) for interactive selection and completion. - Integrated with FZF (optional) for interactive selection and completion.
- Quickly go back to a parent directory instead of typing "cd ../../..". - Quickly go back to a parent directory instead of typing "cd ../../..".
- Corresponding experience in different shells and operating systems. - Corresponding experience in different shells and operating systems.
- Compatible with Lua 5.1, 5.2 and 5.3+ - Compatible with Lua 5.1, 5.2 and 5.3+
@@ -131,6 +141,7 @@ z -b foo # cd to the parent directory starting with foo
- set `$_ZL_ECHO` to 1 to display new directory name after cd. - set `$_ZL_ECHO` to 1 to display new directory name after cd.
- set `$_ZL_MATCH_MODE` to 1 to enable enhanced matching. - set `$_ZL_MATCH_MODE` to 1 to enable enhanced matching.
- set `$_ZL_NO_CHECK` to 1 to disable path validation, use `z --purge` to clean - set `$_ZL_NO_CHECK` to 1 to disable path validation, use `z --purge` to clean
- set `$_ZL_HYPHEN` to 1 to treat hyphon (-) as a normal character not a lua regexp keyword.
## Aging ## Aging
@@ -195,7 +206,7 @@ If no match is found, it will fall back to default matching method.
30 /home/user/workspace/project2 30 /home/user/workspace/project2
40 /home/user/workspace/project3 40 /home/user/workspace/project3
If you use `"z wo"` in enhanced matching mode, only the `/home/user/work` will be matched, because according to rule No.2 it is the only path whose last segment matches `"wo"`. If you use `"z wo"` in enhanced matching mode, only the `/home/user/workspace` will be matched, because according to rule No.2 it is the only path whose last segment matches `"wo"`.
Since the last segment of a path is always easier to be recalled, it is sane to give it higher priority. You can also achieve this by typing `"z space$"` in both methods, but `"z wo"` is easier to type. Since the last segment of a path is always easier to be recalled, it is sane to give it higher priority. You can also achieve this by typing `"z space$"` in both methods, but `"z wo"` is easier to type.
@@ -322,6 +333,7 @@ If you want `zb` jump back to a parent directory contains a `.root` or `package.
**Bonus**: `zb ..` equals to `cd ..`, `zb ...` equals to `cd ../..` and `zb ....` equals to `cd ../../..`, and so on. Finally, `zb ..20` equals to `cd (..)x20`. **Bonus**: `zb ..` equals to `cd ..`, `zb ...` equals to `cd ../..` and `zb ....` equals to `cd ../../..`, and so on. Finally, `zb ..20` equals to `cd (..)x20`.
**Bonus**: try `z -b -i` and `z -b -I` and you can alias them to `zbi` and `zbf`.
## Completion ## Completion
@@ -446,18 +458,38 @@ sys 0m0.030s
As you see, z.lua is the fastest one and requires less resource. As you see, z.lua is the fastest one and requires less resource.
## Native Module
z.lua is fast enough for most case, the path tracking action will be triggered each time when you change your current directory.
## Reputation So I still recommend the pure lua script for portability and flexibility, but for someone who really care about `10ms` or `1ms` things, this module can help them to gain the ultimate speed.
- [czmod](https://github.com/skywind3000/czmod): native module to boost `z.lua`.
Average performance:
| Name | czmod | z.lua |
|-|-|-|-|-|
| **Update Time** | 1.6ms | 13.2ms |
| **Query Time** | 1.5ms | 9.8ms |
- "I like this in principal. Im pretty damn predictable at the command line and far too lazy to make shortcuts"
- "It feels far more intuitive and it's so incredibly convenient to be able to jump between folders I'm working in without having to traverse an entire tree. The shell used to feel so constraining for me, but tools like this are making me enjoy it so much more. "
- "I can finally have autojump-like functionality on my Raspberry Pi 1 without waiting 30 seconds every time I open a new shell. Thanks z.lua devs."
- "Anyway, z.lua is a promising project. If you only need directory jumping, it may be the best choice."
## History ## History
- 1.8.7 (2020-06-29): use lfs or luajit's cffi if possible.
- 1.8.4 (2020-02-10): fish shell: set `$_ZL_ECHO` to global scope.
- 1.8.3 (2020-02-09): new: `z -b -i` and `z -b -I` to jump backwards in interactive mode.
- 1.7.4 (2019-12-29): new: `$_ZL_HYPHEN` to treat hyphen as a normal character, see [here](https://github.com/skywind3000/z.lua/wiki/FAQ#how-to-input-a-hyphen---in-the-keyword-).
- 1.7.3 (2019-09-07): use [lua-filesystem](http://keplerproject.github.io/luafilesystem/) package if possible when `$_ZL_USE_LFS` is `1`.
- 1.7.2 (2019-08-01): Improve bash/zsh shell compatibility by [@barlik](https://github.com/barlik).
- 1.7.1 (2019-06-07): Fixed: `$_ZL_DATA` failure on Linux sometimes.
- 1.7.0 (2019-03-09): Support [ranger](https://github.com/skywind3000/z.lua/wiki/FAQ#how-to-integrate-zlua-to-ranger-), fix ReplaceFile issue in luajit (windows).
- 1.6.0 (2019-03-04): optimize with ffi module (luajit builtin module).
- 1.5.11 (2019-03-02): fixed: os.path.isdir doesn't work for symbol link folders.
- 1.5.10 (2019-03-01): Prevent writing file racing.
- 1.5.9 (2019-02-25): `z -b` should not match current directory (close #56).
- 1.5.8 (2019-02-21): new `$_ZL_FZF_HEIGHT` to control `--height` parameter in fzf.
- 1.5.7 (2019-02-21): rename `$_ZL_FZF_SORT` to `$_ZL_INT_SORT` it will affect both `-i` and `-I`. - 1.5.7 (2019-02-21): rename `$_ZL_FZF_SORT` to `$_ZL_INT_SORT` it will affect both `-i` and `-I`.
- 1.5.6 (2019-02-20): set `$_ZL_FZF_SORT` to 1 to sort directories by alphabet in fzf. - 1.5.6 (2019-02-20): set `$_ZL_FZF_SORT` to 1 to sort directories by alphabet in fzf.
- 1.5.5 (2019-02-20): `$_ZL_FZF_FLAG` can be used to override fzf flags, default to "+s -e". - 1.5.5 (2019-02-20): `$_ZL_FZF_FLAG` can be used to override fzf flags, default to "+s -e".
@@ -490,6 +522,7 @@ As you see, z.lua is the fastest one and requires less resource.
This project needs help for the tasks below: This project needs help for the tasks below:
- [ ] Support csh/tcsh.
- [ ] Completion: Actually I got little knowledge in completion, and need help to improve it. - [ ] Completion: Actually I got little knowledge in completion, and need help to improve it.
- [ ] Completion: Implement completion for Power Shell. - [ ] Completion: Implement completion for Power Shell.
- [ ] Completion: Implement completion for different arguments. - [ ] Completion: Implement completion for different arguments.
@@ -503,6 +536,7 @@ This project needs help for the tasks below:
- Thanks to [@TeddyDD](https://github.com/TeddyDD) for Fish Shell porting. - Thanks to [@TeddyDD](https://github.com/TeddyDD) for Fish Shell porting.
- Thanks to [@manhong2112](https://github.com/manhong2112) for Power Shell porting. - Thanks to [@manhong2112](https://github.com/manhong2112) for Power Shell porting.
- Thanks to [@BarbUk](https://github.com/BarbUk) for fzf completion in Bash. - Thanks to [@BarbUk](https://github.com/BarbUk) for fzf completion in Bash.
- Thanks to [@barlik](https://github.com/barlik) for many improvements.
And many others. And many others.

View File

@@ -17,7 +17,12 @@ end
set -x _ZL_DATA "$_ZL_DATA" set -x _ZL_DATA "$_ZL_DATA"
set _zlua_dir (dirname (status --current-filename)) set -q XDG_CONFIG_HOME; or set XDG_CONFIG_HOME ~/.config
if functions -q fisher
set _zlua_dir $XDG_CONFIG_HOME/fisher/github.com/skywind3000/z.lua
else
set _zlua_dir (dirname (status --current-filename))
end
if test -e $_zlua_dir/z.lua if test -e $_zlua_dir/z.lua
if type -q lua if type -q lua
@@ -35,6 +40,8 @@ if test -e $_zlua_dir/z.lua
alias zz='z -i' # cd with interactive selection alias zz='z -i' # cd with interactive selection
alias zf='z -I' # use fzf to select in multiple matches alias zf='z -I' # use fzf to select in multiple matches
alias zb='z -b' # quickly cd to the parent directory alias zb='z -b' # quickly cd to the parent directory
alias zbi='z -b -i' # interactive jump backward
alias zbf='z -b -I' # interactive jump backward with fzf
set -U ZLUA_SCRIPT "$ZLUA_SCRIPT" 2> /dev/null set -U ZLUA_SCRIPT "$ZLUA_SCRIPT" 2> /dev/null
set -U ZLUA_LUAEXE "$ZLUA_LUAEXE" 2> /dev/null set -U ZLUA_LUAEXE "$ZLUA_LUAEXE" 2> /dev/null
end end

91
ranger_zlua.py Normal file
View File

@@ -0,0 +1,91 @@
import time, sys, os
import ranger.api
import subprocess
old_hook_init = ranger.api.hook_init
PATH_LUA = os.environ.get('RANGER_LUA')
PATH_ZLUA = os.environ.get('RANGER_ZLUA')
if not PATH_LUA:
for path in os.environ.get('PATH', '').split(os.path.pathsep):
for name in ('lua', 'luajit', 'lua5.3', 'lua5.2', 'lua5.1'):
test = os.path.join(path, name)
test = test + (sys.platform[:3] == 'win' and ".exe" or "")
if os.path.exists(test):
PATH_LUA = test
break
if not PATH_LUA:
sys.stderr.write('Please install lua or set $RANGER_LUA.\n')
sys.exit()
if (not PATH_ZLUA) or (not os.path.exists(PATH_ZLUA)):
sys.stderr.write('Not find z.lua, please set $RANGER_ZLUA to absolute path of z.lua.\n')
sys.exit()
def hook_init(fm):
def update_zlua(signal):
import os, random
os.environ['_ZL_RANDOM'] = str(random.randint(0, 0x7fffffff))
p = subprocess.Popen([PATH_LUA, PATH_ZLUA, "--add", signal.new.path])
p.wait()
if PATH_ZLUA and PATH_LUA and os.path.exists(PATH_ZLUA):
fm.signal_bind('cd', update_zlua)
return old_hook_init(fm)
ranger.api.hook_init = hook_init
class z(ranger.api.commands.Command):
def execute (self):
import sys, os, time
args = self.args[1:]
if args:
mode = ''
for arg in args:
if arg in ('-l', '-e', '-x', '-h', '--help', '--'):
mode = arg
break
elif arg in ('-I', '-i'):
mode = arg
elif arg[:1] != '-':
break
if mode:
cmd = '"%s" "%s" '%(PATH_LUA, PATH_ZLUA)
if mode in ('-I', '-i', '--'):
cmd += ' --cd'
for arg in args:
cmd += ' "%s"'%arg
if mode in ('-e', '-x'):
path = subprocess.check_output([PATH_LUA, PATH_ZLUA, '--cd'] + args)
path = path.decode("utf-8", "ignore")
path = path.rstrip('\n')
self.fm.notify(path)
elif mode in ('-h', '-l', '--help'):
p = self.fm.execute_command(cmd + '| less +G', universal_newlines=True)
stdout, stderr = p.communicate()
elif mode == '--':
p = self.fm.execute_command(cmd + ' 2>&1 | less +G', universal_newlines=True)
stdout, stderr = p.communicate()
else:
if mode == '-I':
os.environ['_ZL_FZF_HEIGHT'] = '0'
path = subprocess.check_output([PATH_LUA, PATH_ZLUA, '--cd'] + args)
self.fm.execute_console('redraw_window')
else:
p = self.fm.execute_command(cmd, universal_newlines=True, stdout=subprocess.PIPE)
stdout, stderr = p.communicate()
path = stdout.rstrip('\n')
if path and os.path.exists(path):
self.fm.cd(path)
else:
path = subprocess.check_output([PATH_LUA, PATH_ZLUA, '--cd'] + args)
path = path.decode("utf-8", "ignore")
path = path.rstrip('\n')
if path and os.path.exists(path):
self.fm.cd(path)
else:
self.fm.notify('No matching found', bad = True)
return True

396
z.lua
View File

@@ -1,10 +1,10 @@
#! /usr/bin/env lua #! /usr/bin/env lua
--===================================================================== --=====================================================================
-- --
-- z.lua - a cd command that learns, by skywind 2018, 2019 -- z.lua - a cd command that learns, by skywind 2018, 2019, 2020
-- Licensed under MIT license. -- Licensed under MIT license.
-- --
-- Version 1.5.7, Last Modified: 2019/02/21 11:07 -- Version 1.8.7, Last Modified: 2020/06/29 18:04
-- --
-- * 10x faster than fasd and autojump, 3x faster than z.sh -- * 10x faster than fasd and autojump, 3x faster than z.sh
-- * available for posix shells: bash, zsh, sh, ash, dash, busybox -- * available for posix shells: bash, zsh, sh, ash, dash, busybox
@@ -74,6 +74,8 @@
-- set $_ZL_MAXAGE to define a aging threshold (default is 5000). -- set $_ZL_MAXAGE to define a aging threshold (default is 5000).
-- set $_ZL_MATCH_MODE to 1 to enable enhanced matching mode. -- set $_ZL_MATCH_MODE to 1 to enable enhanced matching mode.
-- set $_ZL_NO_CHECK to 1 to disable path validation. z --purge to clear. -- set $_ZL_NO_CHECK to 1 to disable path validation. z --purge to clear.
-- set $_ZL_USE_LFS to 1 to use lua-filesystem package
-- set $_ZL_HYPHEN to 1 to stop treating hyphen as a regexp keyword
-- --
--===================================================================== --=====================================================================
@@ -120,6 +122,7 @@ Z_CMD = 'z'
Z_MATCHMODE = 0 Z_MATCHMODE = 0
Z_MATCHNAME = false Z_MATCHNAME = false
Z_SKIPPWD = false Z_SKIPPWD = false
Z_HYPHEN = false
os.LOG_NAME = os.getenv('_ZL_LOG_NAME') os.LOG_NAME = os.getenv('_ZL_LOG_NAME')
@@ -302,10 +305,124 @@ function os.log(text)
end end
-----------------------------------------------------------------------
-- ffi optimize (luajit has builtin ffi module)
-----------------------------------------------------------------------
os.native = {}
os.native.status, os.native.ffi = pcall(require, "ffi")
if os.native.status then
local ffi = os.native.ffi
if windows then
ffi.cdef[[
int GetFullPathNameA(const char *name, uint32_t size, char *out, char **name);
int ReplaceFileA(const char *dstname, const char *srcname, void *, uint32_t, void *, void *);
uint32_t GetTickCount(void);
uint32_t GetFileAttributesA(const char *name);
uint32_t GetCurrentDirectoryA(uint32_t size, char *ptr);
uint32_t GetShortPathNameA(const char *longname, char *shortname, uint32_t size);
uint32_t GetLongPathNameA(const char *shortname, char *longname, uint32_t size);
]]
local kernel32 = ffi.load('kernel32.dll')
local buffer = ffi.new('char[?]', 4100)
local INVALID_FILE_ATTRIBUTES = 0xffffffff
local FILE_ATTRIBUTE_DIRECTORY = 0x10
os.native.kernel32 = kernel32
function os.native.GetFullPathName(name)
local hr = kernel32.GetFullPathNameA(name, 4096, buffer, nil)
return (hr > 0) and ffi.string(buffer, hr) or nil
end
function os.native.ReplaceFile(replaced, replacement)
local hr = kernel32.ReplaceFileA(replaced, replacement, nil, 2, nil, nil)
return (hr ~= 0) and true or false
end
function os.native.GetTickCount()
return kernel32.GetTickCount()
end
function os.native.GetFileAttributes(name)
return kernel32.GetFileAttributesA(name)
end
function os.native.GetLongPathName(name)
local hr = kernel32.GetLongPathNameA(name, buffer, 4096)
return (hr ~= 0) and ffi.string(buffer, hr) or nil
end
function os.native.GetShortPathName(name)
local hr = kernel32.GetShortPathNameA(name, buffer, 4096)
return (hr ~= 0) and ffi.string(buffer, hr) or nil
end
function os.native.GetRealPathName(name)
local short = os.native.GetShortPathName(name)
if short then
return os.native.GetLongPathName(short)
end
return nil
end
function os.native.exists(name)
local attr = os.native.GetFileAttributes(name)
return attr ~= INVALID_FILE_ATTRIBUTES
end
function os.native.isdir(name)
local attr = os.native.GetFileAttributes(name)
local isdir = FILE_ATTRIBUTE_DIRECTORY
if attr == INVALID_FILE_ATTRIBUTES then
return false
end
return (attr % (2 * isdir)) >= isdir
end
function os.native.getcwd()
local hr = kernel32.GetCurrentDirectoryA(4096, buffer)
if hr <= 0 then return nil end
return ffi.string(buffer, hr)
end
else
ffi.cdef[[
typedef struct { long tv_sec; long tv_usec; } timeval;
int gettimeofday(timeval *tv, void *tz);
int access(const char *name, int mode);
char *realpath(const char *path, char *resolve);
char *getcwd(char *buf, size_t size);
]]
local timeval = ffi.new('timeval[?]', 1)
local buffer = ffi.new('char[?]', 4100)
function os.native.gettimeofday()
local hr = ffi.C.gettimeofday(timeval, nil)
local sec = tonumber(timeval[0].tv_sec)
local usec = tonumber(timeval[0].tv_usec)
return sec + (usec * 0.000001)
end
function os.native.access(name, mode)
return ffi.C.access(name, mode)
end
function os.native.realpath(name)
local path = ffi.C.realpath(name, buffer)
return (path ~= nil) and ffi.string(buffer) or nil
end
function os.native.getcwd()
local hr = ffi.C.getcwd(buffer, 4099)
return hr ~= nil and ffi.string(buffer) or nil
end
end
function os.native.tickcount()
if windows then
return os.native.GetTickCount()
else
return math.floor(os.native.gettimeofday() * 1000)
end
end
os.native.init = true
end
----------------------------------------------------------------------- -----------------------------------------------------------------------
-- get current path -- get current path
----------------------------------------------------------------------- -----------------------------------------------------------------------
function os.pwd() function os.pwd()
if os.native and os.native.getcwd then
local hr = os.native.getcwd()
if hr then return hr end
end
if os.getcwd then
return os.getcwd()
end
if windows then if windows then
local fp = io.popen('cd') local fp = io.popen('cd')
if fp == nil then if fp == nil then
@@ -372,6 +489,10 @@ end
----------------------------------------------------------------------- -----------------------------------------------------------------------
function os.path.abspath(path) function os.path.abspath(path)
if path == '' then path = '.' end if path == '' then path = '.' end
if os.native and os.native.GetFullPathName then
local test = os.native.GetFullPathName(path)
if test then return test end
end
if windows then if windows then
local script = 'FOR /f "delims=" %%i IN ("%s") DO @echo %%~fi' local script = 'FOR /f "delims=" %%i IN ("%s") DO @echo %%~fi'
local script = string.format(script, path) local script = string.format(script, path)
@@ -427,13 +548,17 @@ function os.path.isdir(pathname)
elseif windows then elseif windows then
if pathname == '\\' then if pathname == '\\' then
return true return true
elseif pathname:match('^%a:[/\\]$') then
return true
end end
end end
if os.native and os.native.isdir then
return os.native.isdir(pathname)
end
if clink and os.isdir then
return os.isdir(pathname)
end
local name = pathname local name = pathname
if (not name:endswith('/')) and (not name:endswith('\\')) then if (not name:endswith('/')) and (not name:endswith('\\')) then
name = name .. '/' name = name .. os.path.sep
end end
return os.path.exists(name) return os.path.exists(name)
end end
@@ -443,6 +568,12 @@ end
-- file or path exists -- file or path exists
----------------------------------------------------------------------- -----------------------------------------------------------------------
function os.path.exists(name) function os.path.exists(name)
if name == '/' then
return true
end
if os.native and os.native.exists then
return os.native.exists(name)
end
local ok, err, code = os.rename(name, name) local ok, err, code = os.rename(name, name)
if not ok then if not ok then
if code == 13 then if code == 13 then
@@ -453,6 +584,12 @@ function os.path.exists(name)
io.close(f) io.close(f)
return true return true
end end
elseif name:sub(-1) == '/' and code == 20 and (not windows) then
local test = name .. '.'
ok, err, code = os.rename(test, test)
if code == 16 or code == 13 or code == 22 then
return true
end
end end
return false return false
end end
@@ -867,6 +1004,9 @@ function math.random_init()
seed = seed .. rnd seed = seed .. rnd
end end
seed = seed .. tostring(os.clock() * 10000000) seed = seed .. tostring(os.clock() * 10000000)
if os.native and os.native.tickcount then
seed = seed .. tostring(os.native.tickcount())
end
local number = 0 local number = 0
for i = 1, seed:len() do for i = 1, seed:len() do
local k = string.byte(seed:sub(i, i)) local k = string.byte(seed:sub(i, i))
@@ -956,15 +1096,29 @@ function data_save(filename, M)
local tmpname = nil local tmpname = nil
local i local i
filename = os.path.expand(filename) filename = os.path.expand(filename)
if windows then math.random_init()
fp = io.open(filename, 'w') while true do
else
math.random_init()
tmpname = filename .. '.' .. tostring(os.time()) tmpname = filename .. '.' .. tostring(os.time())
tmpname = tmpname .. math.random_string(8) if os.native and os.native.tickcount then
local rnd = os.getenv('_ZL_RANDOM') local key = os.native.tickcount() % 1000
tmpname = tmpname .. '' .. (rnd and rnd or '') tmpname = tmpname .. string.format('%03d', key)
-- print('tmpname: '..tmpname) tmpname = tmpname .. math.random_string(5)
else
tmpname = tmpname .. math.random_string(8)
end
if not os.path.exists(tmpname) then
-- print('tmpname: '..tmpname)
break
end
end
if windows then
if os.native and os.native.ReplaceFile then
fp = io.open(tmpname, 'w')
else
fp = io.open(filename, 'w')
tmpname = nil
end
else
fp = io.open(tmpname, 'w') fp = io.open(tmpname, 'w')
end end
if fp == nil then if fp == nil then
@@ -977,7 +1131,14 @@ function data_save(filename, M)
end end
fp:close() fp:close()
if tmpname ~= nil then if tmpname ~= nil then
os.rename(tmpname, filename) if windows then
local ok, err, code = os.rename(tmpname, filename)
if not ok then
os.native.ReplaceFile(filename, tmpname)
end
else
os.rename(tmpname, filename)
end
os.remove(tmpname) os.remove(tmpname)
end end
return true return true
@@ -1128,6 +1289,9 @@ function data_select(M, patterns, matchlast)
local pats = {} local pats = {}
for i = 1, #patterns do for i = 1, #patterns do
local p = patterns[i] local p = patterns[i]
if Z_HYPHEN then
p = p:gsub('-', '%%-')
end
table.insert(pats, case_insensitive_pattern(p)) table.insert(pats, case_insensitive_pattern(p))
end end
for i = 1, #M do for i = 1, #M do
@@ -1213,6 +1377,14 @@ function z_add(path)
end end
end end
if not skip then if not skip then
if windows then
if os.native and os.native.GetRealPathName then
local ts = os.native.GetRealPathName(path)
if ts then
path = ts
end
end
end
M = data_insert(M, path) M = data_insert(M, path)
count = count + 1 count = count + 1
end end
@@ -1441,7 +1613,7 @@ function z_cd(patterns)
io.stderr:write('> ') io.stderr:write('> ')
io.stderr:flush() io.stderr:flush()
local input = io.read('*l') local input = io.read('*l')
if input == nil then if input == nil or input == '' then
return nil return nil
end end
local index = tonumber(input) local index = tonumber(input)
@@ -1461,8 +1633,9 @@ function z_cd(patterns)
cmd = ((fzf == '') and 'fzf' or fzf) .. ' ' .. cmd .. ' ' .. flag cmd = ((fzf == '') and 'fzf' or fzf) .. ' ' .. cmd .. ' ' .. flag
if not windows then if not windows then
tmpname = os.tmpname() tmpname = os.tmpname()
if not os.environ('_ZL_FZF_FULLSCR', false) then local height = os.environ('_ZL_FZF_HEIGHT', '35%')
cmd = cmd .. ' --height 35%' if height ~= nil and height ~= '' and height ~= '0' then
cmd = cmd .. ' --height ' .. height
end end
cmd = cmd .. ' < "' .. tmpname .. '"' cmd = cmd .. ' < "' .. tmpname .. '"'
else else
@@ -1554,6 +1727,7 @@ function cd_backward(args, options, pwd)
end end
return os.path.normpath(path) return os.path.normpath(path)
else else
pwd = os.path.split(pwd)
local test = windows and pwd:gsub('\\', '/') or pwd local test = windows and pwd:gsub('\\', '/') or pwd
local key = windows and args[1]:lower() or args[1] local key = windows and args[1]:lower() or args[1]
if not key:match('%u') then if not key:match('%u') then
@@ -1621,6 +1795,91 @@ function cd_minus(args, options)
end end
-----------------------------------------------------------------------
-- cd breadcrumbs: z -b -i, z -b -I
-----------------------------------------------------------------------
function cd_breadcrumbs(pwd, interactive)
local pwd = (pwd == nil or pwd == '') and os.pwd() or pwd
local pwd = os.path.normpath(pwd)
local path, _ = os.path.split(pwd)
local elements = {}
local interactive = interactive and interactive or 1
local fullname = os.environ('_ZL_FULL_PATH', false)
while true do
local head, name = os.path.split(path)
if head == path then -- reached root
table.insert(elements, {head, head})
break
elseif name ~= '' then
table.insert(elements, {name, path})
else
break
end
path = head
end
local tmpname = '/tmp/zlua.txt'
local fp = io.stderr
if interactive == 2 then
if not windows then
tmpname = os.tmpname()
else
tmpname = os.tmpname():gsub('\\', ''):gsub('%.', '')
tmpname = os.environ('TMP', '') .. '\\zlua_' .. tmpname .. '.txt'
end
fp = io.open(tmpname, 'w')
end
-- print table
local maxsize = string.len(tostring(#elements))
for i = #elements, 1, -1 do
local item = elements[i]
local name = item[1]
local text = string.rep(' ', maxsize - string.len(i)) .. tostring(i)
text = text .. ': ' .. (fullname and item[2] or item[1])
fp:write(text .. '\n')
end
if fp ~= io.stderr then
fp:close()
end
local retval = ''
-- select from stdin or fzf
if interactive == 1 then
io.stderr:write('> ')
io.stderr:flush()
retval = io.read('*l')
elseif interactive == 2 then
local fzf = os.environ('_ZL_FZF', 'fzf')
local cmd = '--reverse --inline-info --tac '
local flag = os.environ('_ZL_FZF_FLAG', '')
flag = (flag == '' or flag == nil) and '+s -e' or flag
cmd = ((fzf == '') and 'fzf' or fzf) .. ' ' .. cmd .. ' ' .. flag
if not windows then
local height = os.environ('_ZL_FZF_HEIGHT', '35%')
if height ~= nil and height ~= '' and height ~= '0' then
cmd = cmd .. ' --height ' .. height
end
cmd = cmd .. '< "' .. tmpname .. '"'
else
cmd = 'type "' .. tmpname .. '" | ' .. cmd
end
retval = os.call(cmd)
os.remove(tmpname)
if retval == '' or retval == nil then
return nil
end
local pos = retval:find(':')
if not pos then
return nil
end
retval = retval:sub(1, pos - 1):gsub('^%s*', '')
end
local index = tonumber(retval)
if index == nil or index < 1 or index > #elements then
return nil
end
return elements[index][2]
end
----------------------------------------------------------------------- -----------------------------------------------------------------------
-- main entry -- main entry
----------------------------------------------------------------------- -----------------------------------------------------------------------
@@ -1655,7 +1914,11 @@ function main(argv)
if options['--cd'] or options['-e'] then if options['--cd'] or options['-e'] then
local path = '' local path = ''
if options['-b'] then if options['-b'] then
path = cd_backward(args, options) if Z_INTERACTIVE == 0 then
path = cd_backward(args, options)
else
path = cd_breadcrumbs('', Z_INTERACTIVE)
end
elseif options['-'] then elseif options['-'] then
path = cd_minus(args, options) path = cd_minus(args, options)
elseif #args == 0 then elseif #args == 0 then
@@ -1727,16 +1990,14 @@ function z_init()
local _zl_matchname = os.getenv('_ZL_MATCH_NAME') local _zl_matchname = os.getenv('_ZL_MATCH_NAME')
local _zl_skippwd = os.getenv('_ZL_SKIP_PWD') local _zl_skippwd = os.getenv('_ZL_SKIP_PWD')
local _zl_matchmode = os.getenv('_ZL_MATCH_MODE') local _zl_matchmode = os.getenv('_ZL_MATCH_MODE')
local _zl_hyphen = os.getenv('_ZL_HYPHEN')
if _zl_data ~= nil and _zl_data ~= "" then if _zl_data ~= nil and _zl_data ~= "" then
if windows then if windows then
DATA_FILE = _zl_data DATA_FILE = _zl_data
else else
-- avoid windows environments affect cygwin & msys -- avoid windows environments affect cygwin & msys
if _zl_data:sub(2, 2) ~= ':' then if not string.match(_zl_data, '^%a:[/\\]') then
local t = _zl_data:sub(3, 3) DATA_FILE = _zl_data
if t ~= '/' and t ~= "\\" then
DATA_FILE = _zl_data
end
end end
end end
end end
@@ -1782,6 +2043,12 @@ function z_init()
Z_SKIPPWD = true Z_SKIPPWD = true
end end
end end
if _zl_hyphen ~= nil then
local m = string.lower(_zl_hyphen)
if (m == '1' or m == 'yes' or m == 'true' or m == 't') then
Z_HYPHEN = true
end
end
end end
@@ -1876,14 +2143,14 @@ alias ${_ZL_CMD:-z}='_zlua'
local script_init_bash = [[ local script_init_bash = [[
case "$PROMPT_COMMAND" in case "$PROMPT_COMMAND" in
*_zlua?--add*) ;; *_zlua?--add*) ;;
*) PROMPT_COMMAND="(_zlua --add \"\$(command pwd 2>/dev/null)\" &);$PROMPT_COMMAND" ;; *) PROMPT_COMMAND="(_zlua --add \"\$(command pwd 2>/dev/null)\" &)${PROMPT_COMMAND:+;$PROMPT_COMMAND}" ;;
esac esac
]] ]]
local script_init_bash_fast = [[ local script_init_bash_fast = [[
case "$PROMPT_COMMAND" in case "$PROMPT_COMMAND" in
*_zlua?--add*) ;; *_zlua?--add*) ;;
*) PROMPT_COMMAND="(_zlua --add \"\$PWD\" &);$PROMPT_COMMAND" ;; *) PROMPT_COMMAND="(_zlua --add \"\$PWD\" &)${PROMPT_COMMAND:+;$PROMPT_COMMAND}" ;;
esac esac
]] ]]
@@ -1895,7 +2162,7 @@ _zlua_precmd() {
} }
case "$PROMPT_COMMAND" in case "$PROMPT_COMMAND" in
*_zlua_precmd*) ;; *_zlua_precmd*) ;;
*) PROMPT_COMMAND="_zlua_precmd;$PROMPT_COMMAND" ;; *) PROMPT_COMMAND="_zlua_precmd${PROMPT_COMMAND:+;$PROMPT_COMMAND}" ;;
esac esac
]] ]]
@@ -1922,7 +2189,7 @@ local script_init_zsh = [[
_zlua_precmd() { _zlua_precmd() {
(_zlua --add "${PWD:a}" &) (_zlua --add "${PWD:a}" &)
} }
typeset -gaU precmd_functions typeset -ga precmd_functions
[ -n "${precmd_functions[(r)_zlua_precmd]}" ] || { [ -n "${precmd_functions[(r)_zlua_precmd]}" ] || {
precmd_functions[$(($#precmd_functions+1))]=_zlua_precmd precmd_functions[$(($#precmd_functions+1))]=_zlua_precmd
} }
@@ -1932,7 +2199,7 @@ local script_init_zsh_once = [[
_zlua_precmd() { _zlua_precmd() {
(_zlua --add "${PWD:a}" &) (_zlua --add "${PWD:a}" &)
} }
typeset -gaU chpwd_functions typeset -ga chpwd_functions
[ -n "${chpwd_functions[(r)_zlua_precmd]}" ] || { [ -n "${chpwd_functions[(r)_zlua_precmd]}" ] || {
chpwd_functions[$(($#chpwd_functions+1))]=_zlua_precmd chpwd_functions[$(($#chpwd_functions+1))]=_zlua_precmd
} }
@@ -1962,16 +2229,16 @@ fi
local script_complete_zsh = [[ local script_complete_zsh = [[
_zlua_zsh_tab_completion() { _zlua_zsh_tab_completion() {
# tab completion # tab completion
local compl
read -l compl
(( $+compstate )) && compstate[insert]=menu # no expand (( $+compstate )) && compstate[insert]=menu # no expand
reply=(${(f)"$(_zlua --complete "$compl")"}) local -a tmp=(${(f)"$(_zlua --complete "${words/_zlua/z}")"})
_describe "directory" tmp -U
} }
compctl -U -K _zlua_zsh_tab_completion _zlua if [ "${+functions[compdef]}" -ne 0 ]; then
compdef _zlua_zsh_tab_completion _zlua 2> /dev/null
fi
]] ]]
----------------------------------------------------------------------- -----------------------------------------------------------------------
-- initialize bash/zsh -- initialize bash/zsh
---------------------------------------------------------------------- ----------------------------------------------------------------------
@@ -1992,6 +2259,10 @@ function z_shell_init(opts)
local prompt_hook = (not os.environ("_ZL_NO_PROMPT_COMMAND", false)) local prompt_hook = (not os.environ("_ZL_NO_PROMPT_COMMAND", false))
local once = os.environ("_ZL_ADD_ONCE", false) or opts.once ~= nil local once = os.environ("_ZL_ADD_ONCE", false) or opts.once ~= nil
if opts.clean ~= nil then
prompt_hook = false
end
if opts.bash ~= nil then if opts.bash ~= nil then
if prompt_hook then if prompt_hook then
if once then if once then
@@ -2005,8 +2276,9 @@ function z_shell_init(opts)
print(script_complete_bash) print(script_complete_bash)
if opts.fzf ~= nil then if opts.fzf ~= nil then
fzf_cmd = "fzf --nth 2.. --reverse --inline-info --tac " fzf_cmd = "fzf --nth 2.. --reverse --inline-info --tac "
if not os.environ('_ZL_FZF_FULLSCR', false) then local height = os.environ('_ZL_FZF_HEIGHT', '35%')
fzf_cmd = fzf_cmd .. ' --height 35%' if height ~= nil and height ~= '' and height ~= '0' then
fzf_cmd = fzf_cmd .. ' --height ' .. height .. ' '
end end
local flag = os.environ('_ZL_FZF_FLAG', '') local flag = os.environ('_ZL_FZF_FLAG', '')
flag = (flag == '' or flag == nil) and '+s -e' or flag flag = (flag == '' or flag == nil) and '+s -e' or flag
@@ -2160,18 +2432,24 @@ function z_fish_init(opts)
print('set -x ZLUA_SCRIPT "' .. os.scriptname() .. '"') print('set -x ZLUA_SCRIPT "' .. os.scriptname() .. '"')
print('set -x ZLUA_LUAEXE "' .. os.interpreter() .. '"') print('set -x ZLUA_LUAEXE "' .. os.interpreter() .. '"')
local once = (os.getenv("_ZL_ADD_ONCE") ~= nil) or opts.once ~= nil local once = (os.getenv("_ZL_ADD_ONCE") ~= nil) or opts.once ~= nil
local prompt_hook = (not os.environ("_ZL_NO_PROMPT_COMMAND", false))
if opts.clean ~= nil then
prompt_hook = false
end
print(script_zlua_fish) print(script_zlua_fish)
if once then if prompt_hook then
print(script_init_fish_once) if once then
else print(script_init_fish_once)
print(script_init_fish) else
print(script_init_fish)
end
end end
print(script_complete_fish) print(script_complete_fish)
if opts.enhanced ~= nil then if opts.enhanced ~= nil then
print('set -x _ZL_MATCH_MODE 1') print('set -x _ZL_MATCH_MODE 1')
end end
if opts.echo then if opts.echo then
print('set _ZL_ECHO 1') print('set -g _ZL_ECHO 1')
end end
if opts.nc then if opts.nc then
print('set -x _ZL_NO_CHECK 1') print('set -x _ZL_NO_CHECK 1')
@@ -2354,6 +2632,10 @@ if (!$env:_ZL_NO_PROMPT_COMMAND -and (!$global:_zlua_inited)) {
-- initialize cmd/powershell -- initialize cmd/powershell
----------------------------------------------------------------------- -----------------------------------------------------------------------
function z_windows_init(opts) function z_windows_init(opts)
local prompt_hook = (not os.environ("_ZL_NO_PROMPT_COMMAND", false))
if opts.clean ~= nil then
prompt_hook = false
end
if opts.powershell ~= nil then if opts.powershell ~= nil then
print('$script:ZLUA_LUAEXE = "' .. os.interpreter() .. '"') print('$script:ZLUA_LUAEXE = "' .. os.interpreter() .. '"')
print('$script:ZLUA_SCRIPT = "' .. os.scriptname() .. '"') print('$script:ZLUA_SCRIPT = "' .. os.scriptname() .. '"')
@@ -2370,7 +2652,9 @@ function z_windows_init(opts)
if opts.nc ~= nil then if opts.nc ~= nil then
print('$env:_ZL_NO_CHECK = 1') print('$env:_ZL_NO_CHECK = 1')
end end
print(script_init_powershell) if prompt_hook then
print(script_init_powershell)
end
else else
print('@echo off') print('@echo off')
print('setlocal EnableDelayedExpansion') print('setlocal EnableDelayedExpansion')
@@ -2404,7 +2688,34 @@ end
----------------------------------------------------------------------- -----------------------------------------------------------------------
-- testing case -- LFS optimize
-----------------------------------------------------------------------
os.lfs = {}
os.lfs.enable = os.getenv('_ZL_USE_LFS')
os.lfs.enable = '1'
if os.lfs.enable ~= nil then
local m = string.lower(os.lfs.enable)
if (m == '1' or m == 'yes' or m == 'true' or m == 't') then
os.lfs.status, os.lfs.pkg = pcall(require, 'lfs')
if os.lfs.status then
local lfs = os.lfs.pkg
os.path.exists = function (name)
return lfs.attributes(name) and true or false
end
os.path.isdir = function (name)
local mode = lfs.attributes(name)
if not mode then
return false
end
return (mode.mode == 'directory') and true or false
end
end
end
end
-----------------------------------------------------------------------
-- program entry
----------------------------------------------------------------------- -----------------------------------------------------------------------
if not pcall(debug.getlocal, 4, 1) then if not pcall(debug.getlocal, 4, 1) then
-- main script -- main script
@@ -2417,4 +2728,3 @@ if not pcall(debug.getlocal, 4, 1) then
end end

View File

@@ -6,29 +6,31 @@ ZLUA_SCRIPT="${0:A:h}/z.lua"
# search lua executable # search lua executable
if [[ -z "$ZLUA_EXEC" ]]; then if [[ -z "$ZLUA_EXEC" ]]; then
if [[ -x "$(which lua)" ]]; then if [[ -x "$(command which lua)" ]]; then
ZLUA_EXEC="$(which lua)" ZLUA_EXEC="$(command which lua)"
elif [[ -x "$(which lua5.3)" ]]; then elif [[ -x "$(command which lua5.3)" ]]; then
ZLUA_EXEC="$(which lua5.3)" ZLUA_EXEC="$(command which lua5.3)"
elif [[ -x "$(which lua5.2)" ]]; then elif [[ -x "$(command which lua5.2)" ]]; then
ZLUA_EXEC="$(which lua5.2)" ZLUA_EXEC="$(command which lua5.2)"
elif [[ -x "$(which lua5.1)" ]]; then elif [[ -x "$(command which lua5.1)" ]]; then
ZLUA_EXEC="$(which lua5.1)" ZLUA_EXEC="$(command which lua5.1)"
else else
echo "Not find lua in your $PATH, please install it." echo "Not find lua in your $PATH, please install it."
return return
fi fi
fi fi
export _ZL_FZF_FLAG="-e" export _ZL_FZF_FLAG=${_ZL_FZF_FLAG:-"-e"}
eval "$($ZLUA_EXEC $ZLUA_SCRIPT --init zsh once enhanced)" eval "$($ZLUA_EXEC $ZLUA_SCRIPT --init zsh once enhanced)"
if [[ -z "$_ZL_NO_ALIASES" ]]; then
alias zz='z -i' alias zz='z -i'
alias zc='z -c' alias zc='z -c'
alias zf='z -I' alias zf='z -I'
alias zb='z -b' alias zb='z -b'
alias zh='z -I -t .' alias zbi='z -b -i'
alias zzc='zz -c' alias zbf='z -b -I'
alias zh='z -I -t .'
alias zzc='zz -c'
fi