Compare commits
101 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7c1c73af33 | ||
|
|
b63a38b11a | ||
|
|
c524e28851 | ||
|
|
c3a182c6c9 | ||
|
|
771c72de5f | ||
|
|
4bbd0f1e58 | ||
|
|
db1fb1f256 | ||
|
|
19cb43d1ac | ||
|
|
787da9512c | ||
|
|
3875d774cb | ||
|
|
dff590adc1 | ||
|
|
20c0494d44 | ||
|
|
67405d57e8 | ||
|
|
6e67a32520 | ||
|
|
c334bc1ae5 | ||
|
|
0f6318ce4c | ||
|
|
3b55089ad8 | ||
|
|
c58d31ec1d | ||
|
|
7c890c3645 | ||
|
|
7af012cc35 | ||
|
|
019b2af475 | ||
|
|
ef9a49d73d | ||
|
|
7cd399b30d | ||
|
|
9112f0e9cc | ||
|
|
cb4c9d3c8f | ||
|
|
924f61a48b | ||
|
|
30220996ca | ||
|
|
d3ba781d4d | ||
|
|
9a24fef334 | ||
|
|
a9e034cb5c | ||
|
|
992134061a | ||
|
|
b62784b66d | ||
|
|
7f2bfcbfc1 | ||
|
|
86cb43af67 | ||
|
|
71bae7fc0b | ||
|
|
4d89b55363 | ||
|
|
db1a863d40 | ||
|
|
dff016528c | ||
|
|
6fe677aae4 | ||
|
|
ba83bf67b2 | ||
|
|
0992ebf9f1 | ||
|
|
83dfec0843 | ||
|
|
3703c5a0ea | ||
|
|
3894a6b936 | ||
|
|
0905165889 | ||
|
|
3009e33176 | ||
|
|
32786a0592 | ||
|
|
47468a8588 | ||
|
|
f347eaf1c8 | ||
|
|
e11d2e2017 | ||
|
|
3ecc14747f | ||
|
|
632f722ee4 | ||
|
|
9b9c0b82e6 | ||
|
|
08510fe6c6 | ||
|
|
4c05e0d911 | ||
|
|
1ead694395 | ||
|
|
ee6aa2c5ce | ||
|
|
a8e92e0216 | ||
|
|
e2cce39ee4 | ||
|
|
3c88f8d8fa | ||
|
|
786225005c | ||
|
|
481c1774ed | ||
|
|
35e1199eff | ||
|
|
99dbe7b677 | ||
|
|
c88746629b | ||
|
|
336e95b05a | ||
|
|
a3d4f5db68 | ||
|
|
a991162428 | ||
|
|
8210c56414 | ||
|
|
a01b28a8d3 | ||
|
|
695533cee1 | ||
|
|
58425dad65 | ||
|
|
44a2489ba3 | ||
|
|
6e01d4ad52 | ||
|
|
c3c15a3ca9 | ||
|
|
cfad8f54ce | ||
|
|
501f619f94 | ||
|
|
7a8acd469d | ||
|
|
52e066aae7 | ||
|
|
e1a44ee9a5 | ||
|
|
9c0eb6cfbc | ||
|
|
e646d5baa5 | ||
|
|
be90b1a528 | ||
|
|
bda94435fc | ||
|
|
831d617cef | ||
|
|
97fa941ac3 | ||
|
|
c0ff299d67 | ||
|
|
3deb8c7b5c | ||
|
|
222b28571f | ||
|
|
48a77adf35 | ||
|
|
72c3676344 | ||
|
|
9dc5875fa3 | ||
|
|
c90279b677 | ||
|
|
9fb8cadda3 | ||
|
|
edd92d935d | ||
|
|
7848a0a2f3 | ||
|
|
515da0a3d1 | ||
|
|
aebd18cec4 | ||
|
|
90223cf10b | ||
|
|
d666c93ed9 | ||
|
|
805e5c24f3 |
1
.gitignore
vendored
@@ -39,3 +39,4 @@ luac.out
|
|||||||
*.x86_64
|
*.x86_64
|
||||||
*.hex
|
*.hex
|
||||||
|
|
||||||
|
/.vscode/*
|
||||||
|
|||||||
40
README.cn.md
@@ -66,6 +66,11 @@ z -b foo # 跳转到父目录中名称以 foo 开头的那一级
|
|||||||
|
|
||||||
就可以了(主要要放在 antigen apply 语句之前)。
|
就可以了(主要要放在 antigen apply 语句之前)。
|
||||||
|
|
||||||
|
**注意**:使用 WSL-1 的用户,需要安装 `lua-filesystem` 包:
|
||||||
|
|
||||||
|
sudo apt-get install lua-filesystem
|
||||||
|
|
||||||
|
这是由于 wsl-1 的 [bug](https://github.com/microsoft/WSL/issues/5505) 引起的,使用 lua-filesystem 可以避免该问题。
|
||||||
|
|
||||||
- Fish Shell:
|
- Fish Shell:
|
||||||
|
|
||||||
@@ -79,11 +84,22 @@ z -b foo # 跳转到父目录中名称以 foo 开头的那一级
|
|||||||
|
|
||||||
但是第二种方法需要记得在 z.lua 位置改变或者 lua 版本升级后需要重新生成。
|
但是第二种方法需要记得在 z.lua 位置改变或者 lua 版本升级后需要重新生成。
|
||||||
|
|
||||||
|
- Nushell:
|
||||||
|
|
||||||
|
在 `env.nu` 中加入如下代码:
|
||||||
|
|
||||||
|
lua /path/to/z.lua --init nushell | save -f ~/.cache/zlua.nu
|
||||||
|
|
||||||
|
然后在 `config.nu` 中加入如下代码:
|
||||||
|
|
||||||
|
source ~/.cache/zlua.nu
|
||||||
|
alias z = _zlua
|
||||||
|
|
||||||
- Power Shell:
|
- Power Shell:
|
||||||
|
|
||||||
在你 Power Shell 的配置文件 `profile.ps1` 中放入下面语句:
|
在你 Power Shell 的配置文件 `profile.ps1` 中放入下面语句:
|
||||||
|
|
||||||
iex ($(lua /path/to/z.lua --init powershell) -join "`n")
|
Invoke-Expression (& { (lua /path/to/z.lua --init powershell) -join "`n" })
|
||||||
|
|
||||||
|
|
||||||
- Windows cmd (with clink):
|
- Windows cmd (with clink):
|
||||||
@@ -107,7 +123,7 @@ z -b foo # 跳转到父目录中名称以 foo 开头的那一级
|
|||||||
- 设置 `$_ZL_NO_PROMPT_COMMAND` 为 1 来跳过钩子函数初始化(方便自己处理)。
|
- 设置 `$_ZL_NO_PROMPT_COMMAND` 为 1 来跳过钩子函数初始化(方便自己处理)。
|
||||||
- 设置 `$_ZL_EXCLUDE_DIRS` 逗号分隔的路径列表,列表内的路径不会被收集。
|
- 设置 `$_ZL_EXCLUDE_DIRS` 逗号分隔的路径列表,列表内的路径不会被收集。
|
||||||
- 设置 `$_ZL_ADD_ONCE` 为 '1' 时,仅在当前路径 `$PWD` 改变时才更新数据库。
|
- 设置 `$_ZL_ADD_ONCE` 为 '1' 时,仅在当前路径 `$PWD` 改变时才更新数据库。
|
||||||
- 设置 `$_ZL_MAXAGE` 来确定一个数据老化的阀值 (默认为 5000)。
|
- 设置 `$_ZL_MAXAGE` 来确定一个数据老化的阈值 (默认为 5000)。
|
||||||
- 设置 `$_ZL_CD` 用来指定你想用的 cd 命令,比如有人用 cd_func 。
|
- 设置 `$_ZL_CD` 用来指定你想用的 cd 命令,比如有人用 cd_func 。
|
||||||
- 设置 `$_ZL_ECHO` 为 1 可以在跳转后显示目标路径名称。
|
- 设置 `$_ZL_ECHO` 为 1 可以在跳转后显示目标路径名称。
|
||||||
- 设置 `$_ZL_MATCH_MODE` 为 1 可以打开 “增强匹配模式”。
|
- 设置 `$_ZL_MATCH_MODE` 为 1 可以打开 “增强匹配模式”。
|
||||||
@@ -196,7 +212,7 @@ Frecency 是一个由 'recent' 和 'frequency' 组成的合成词,这个术语
|
|||||||
|
|
||||||
cd foo
|
cd foo
|
||||||
|
|
||||||
因此,在增强匹配算法中,你总可以象 cd 命令一样使用 z 命令,而不必当心目标路径是否被记录过。
|
因此,在增强匹配算法中,你总可以像 cd 命令一样使用 z 命令,而不必当心目标路径是否被记录过。
|
||||||
|
|
||||||
- 忽略当前路径:
|
- 忽略当前路径:
|
||||||
|
|
||||||
@@ -209,7 +225,7 @@ Frecency 是一个由 'recent' 和 'frequency' 组成的合成词,这个术语
|
|||||||
|
|
||||||
我当然可以每次使用`z env gems` 来精确指明,但是每当我输入 `z xxx` 我必然是想进行路径跳转的,而不是呆在原地,所以使用增强匹配模式,即便当前目录是最佳匹配,它也能懂得你想跳转的心思。
|
我当然可以每次使用`z env gems` 来精确指明,但是每当我输入 `z xxx` 我必然是想进行路径跳转的,而不是呆在原地,所以使用增强匹配模式,即便当前目录是最佳匹配,它也能懂得你想跳转的心思。
|
||||||
|
|
||||||
再我最初实现 z.lua 时,只有一个和 z.sh 类似的默认匹配算法,在网友的建议下,我陆续学习了来自 fasd / autojump 中的优秀理念,并加以完善改进,成为如今集三家之长的 “增强匹配算法” ,给它取个昵称,叫做 “更懂你的匹配算法”。
|
在我最初实现 z.lua 时,只有一个和 z.sh 类似的默认匹配算法,在网友的建议下,我陆续学习了来自 fasd / autojump 中的优秀理念,并加以完善改进,成为如今集三家之长的 “增强匹配算法” ,给它取个昵称,叫做 “更懂你的匹配算法”。
|
||||||
|
|
||||||
|
|
||||||
## Add once
|
## Add once
|
||||||
@@ -320,7 +336,13 @@ zsh/fish 的补全系统是比较完善的,使用 `z foo<tab>` 就能触发补
|
|||||||
eval "$(lua /path/to/z.lua --init bash enhanced once echo fzf)"
|
eval "$(lua /path/to/z.lua --init bash enhanced once echo fzf)"
|
||||||
```
|
```
|
||||||
|
|
||||||
然后你在 bash 中,输入部分关键字后按 tab,就能把匹配的路径列出来:
|
如果你想在 zsh 中使用 fzf 补全,初始化时在 `--init` 后追加 `fzf` 关键字:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
eval "$(lua /path/to/z.lua --init zsh enhanced once echo fzf)"
|
||||||
|
```
|
||||||
|
|
||||||
|
然后你在 bash/zsh 中,输入部分关键字后按 tab,就能把匹配的路径列出来:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -433,15 +455,13 @@ sys 0m0.030s
|
|||||||
|
|
||||||
描述力强,可以更好的实现核心功能,同时速度更快,纯 shell 开发的话,太多语句是通过子进程 shell 的模式运行,所以性能很差,而 Python 开发的话启动速度又太慢,我在 Cygwin/msys 下用 z.sh 都觉得很卡,autojump/fasd 卡到不能用。
|
描述力强,可以更好的实现核心功能,同时速度更快,纯 shell 开发的话,太多语句是通过子进程 shell 的模式运行,所以性能很差,而 Python 开发的话启动速度又太慢,我在 Cygwin/msys 下用 z.sh 都觉得很卡,autojump/fasd 卡到不能用。
|
||||||
|
|
||||||
最关键的一点,Lua 速度很快 200 KB 的可执行程序,启动速度是 python 的 3倍,perl 的 2 倍,很多命令行工具 go/rust 写成,动不动就 2MB / 3MB,他们都还没有完成加载,lua 脚本可能都运行完了。
|
最关键的一点,Lua 速度很快 200 KB 的可执行程序,启动速度是 python 的 3 倍,perl 的 2 倍,很多命令行工具 go/rust 写成,动不动就 2MB / 3MB,他们都还没有完成加载,lua 脚本可能都运行完了。
|
||||||
|
|
||||||
|
|
||||||
## Credit
|
## Credit
|
||||||
|
|
||||||
Releated projects:
|
我的推特:https://x.com/skywind3000
|
||||||
|
个人博客: https://skywind.me/blog
|
||||||
- [rupa/z](https://github.com/rupa/z): origin z.sh implementation
|
|
||||||
- [JannesMeyer/z.ps](https://github.com/JannesMeyer/z.ps): z for powershell
|
|
||||||
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|||||||
126
README.md
@@ -35,23 +35,24 @@ From people using z.lua:
|
|||||||
- Integrated 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, 5.3+) and luajit.
|
||||||
- Self contained, distributed as a single `z.lua` script, no other dependence.
|
- Self contained, distributed as a single `z.lua` script, no other dependence.
|
||||||
|
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
z foo # cd to most frecent dir matching foo
|
z foo # cd to most frecent dir matching foo
|
||||||
z foo bar # cd to most frecent dir matching foo and bar
|
z foo bar # cd to most frecent dir matching foo and bar
|
||||||
z -r foo # cd to the highest ranked dir matching foo
|
z -r foo # cd to the highest ranked dir matching foo
|
||||||
z -t foo # cd to most recently accessed dir matching foo
|
z -t foo # cd to most recently accessed dir matching foo
|
||||||
z -l foo # list matches instead of cd
|
z -l foo # list matches instead of cd
|
||||||
z -c foo # restrict matches to subdirs of $PWD
|
z -c foo # restrict matches to subdirs of $PWD
|
||||||
z -e foo # echo the best match, don't cd
|
z -e foo # echo the best match, don't cd
|
||||||
z -i foo # cd with interactive selection
|
z -i foo # cd with interactive selection
|
||||||
z -I foo # cd with interactive selection using fzf
|
z -I foo # cd with interactive selection using fzf
|
||||||
z -b foo # cd to the parent directory starting with foo
|
z -b foo # cd to the parent directory starting with foo
|
||||||
|
z -b foo bar # replace foo with bar in cwd and cd there
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@@ -69,21 +70,29 @@ z -b foo # cd to the parent directory starting with foo
|
|||||||
|
|
||||||
and perhaps this:
|
and perhaps this:
|
||||||
|
|
||||||
export _ZL_ECHO=1
|
eval "$(lua /path/to/z.lua --init bash enhanced once echo)"
|
||||||
|
|
||||||
if you want `z.lua` print the new directory after cd.
|
if you want `z.lua` print the new directory after cd.
|
||||||
|
|
||||||
If you want `fzf` tab completion use:
|
For `fzf` tab completion use:
|
||||||
|
|
||||||
eval "$(lua /path/to/z.lua --init bash enhanced once fzf)"
|
eval "$(lua /path/to/z.lua --init bash enhanced once fzf)"
|
||||||
|
|
||||||
|
**NOTE**: For wsl-1 users, `lua-filesystem` must be installed:
|
||||||
|
|
||||||
|
sudo apt-get install lua-filesystem
|
||||||
|
|
||||||
|
To avoid a wsl-1 [defect](https://github.com/microsoft/WSL/issues/5505).
|
||||||
|
|
||||||
- Zsh:
|
- Zsh:
|
||||||
|
|
||||||
put something like this in your `.zshrc`:
|
put something like this in your `.zshrc`:
|
||||||
|
|
||||||
eval "$(lua /path/to/z.lua --init zsh)"
|
eval "$(lua /path/to/z.lua --init zsh)"
|
||||||
|
|
||||||
Options like "enhanced" and "once" can be used after `--init` too. It can also be initialized from "skywind3000/z.lua" with your zsh plugin managers (antigen / oh-my-zsh).
|
Options like "enhanced", "once" and "fzf" can be used after `--init` too. It can also be initialized from "skywind3000/z.lua" with your zsh plugin managers (antigen / oh-my-zsh).
|
||||||
|
|
||||||
|
**NOTE**: for wsl-1 users, `lua-filesystem` must be installed.
|
||||||
|
|
||||||
- Posix Shells:
|
- Posix Shells:
|
||||||
|
|
||||||
@@ -97,37 +106,58 @@ z -b foo # cd to the parent directory starting with foo
|
|||||||
|
|
||||||
To generate old posix compatible script.
|
To generate old posix compatible script.
|
||||||
|
|
||||||
- Fish Shell:
|
- Fish Shell (version `2.4.0` or above):
|
||||||
|
|
||||||
Create `~/.config/fish/conf.d/z.fish` with following code
|
Create `~/.config/fish/conf.d/z.fish` with following code
|
||||||
|
|
||||||
source (lua /path/to/z.lua --init fish | psub)
|
lua /path/to/z.lua --init fish | source
|
||||||
|
|
||||||
Fish version `2.4.0` or above is required.
|
If you'd like `z.lua` to cooperate with fish's own [directory history](https://fishshell.com/docs/3.2/index.html#id34), you can put
|
||||||
|
|
||||||
lua /path/to/z.lua --init fish > ~/.config/fish/conf.d/z.fish
|
set -gx _ZL_CD cd
|
||||||
|
|
||||||
This is another way to initialize z.lua in fish shell, but remember to regenerate z.fish if z.lua has been updated or moved.
|
into the same file.
|
||||||
|
|
||||||
|
- Nushell
|
||||||
|
|
||||||
|
Put something like this in your `env.nu`:
|
||||||
|
|
||||||
|
lua /path/to/z.lua --init nushell | save -f ~/.cache/zlua.nu
|
||||||
|
|
||||||
|
Then put something like this in your `config.nu`:
|
||||||
|
|
||||||
|
source ~/.cache/zlua.nu
|
||||||
|
alias z = _zlua
|
||||||
|
|
||||||
- Power Shell:
|
- Power Shell:
|
||||||
|
|
||||||
|
> ⚠️ **WARNING**: users of [Starship Prompt](https://starship.rs/) should add the following command *after* `starship init`.
|
||||||
|
|
||||||
put something like this in your `profile.ps1`:
|
put something like this in your `profile.ps1`:
|
||||||
|
|
||||||
iex ($(lua /path/to/z.lua --init powershell) -join "`n")
|
Invoke-Expression (& { (lua /path/to/z.lua --init powershell) -join "`n" })
|
||||||
|
|
||||||
|
|
||||||
- Windows cmd (with clink):
|
- Windows cmd (with clink):
|
||||||
|
|
||||||
- copy z.lua and z.cmd to clink's home directory
|
- Copy z.lua and z.cmd to clink's home directory
|
||||||
- Add clink's home to `%PATH%` (z.cmd can be called anywhere)
|
- Add clink's home to `%PATH%` (z.cmd can be called anywhere)
|
||||||
- Ensure that "lua" can be called in `%PATH%`
|
- Ensure that "lua" can be called in `%PATH%`
|
||||||
|
|
||||||
- Windows cmder:
|
- Windows cmder:
|
||||||
|
|
||||||
- copy z.lua and z.cmd to cmder/vendor
|
- Copy z.lua and z.cmd to cmder/vendor
|
||||||
- Add cmder/vendor to `%PATH%`
|
- Add cmder/vendor to `%PATH%`
|
||||||
- Ensure that "lua" can be called in `%PATH%`
|
- Ensure that "lua" can be called in `%PATH%`
|
||||||
|
|
||||||
|
- Windows WSL-1:
|
||||||
|
|
||||||
|
Install `lua-filesystem` module before init z.lua:
|
||||||
|
|
||||||
|
sudo apt-get install lua-filesystem
|
||||||
|
|
||||||
|
This module is required due to a wsl-1 [defect](https://github.com/microsoft/WSL/issues/5505).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Options
|
## Options
|
||||||
|
|
||||||
@@ -137,11 +167,17 @@ z -b foo # cd to the parent directory starting with foo
|
|||||||
- set `$_ZL_EXCLUDE_DIRS` to a comma separated list of dirs to exclude.
|
- set `$_ZL_EXCLUDE_DIRS` to a comma separated list of dirs to exclude.
|
||||||
- set `$_ZL_ADD_ONCE` to '1' to update database only if `$PWD` changed.
|
- set `$_ZL_ADD_ONCE` to '1' to update database only if `$PWD` changed.
|
||||||
- set `$_ZL_MAXAGE` to define a aging threshold (default is 5000).
|
- set `$_ZL_MAXAGE` to define a aging threshold (default is 5000).
|
||||||
- set `$_ZL_CD` to specify your own cd command.
|
- set `$_ZL_CD` to specify your own cd command (default is `builtin cd` in Unix shells).
|
||||||
- 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.
|
- set `$_ZL_HYPHEN` to 0 to treat a hyphen (`-`) as a
|
||||||
|
[lua regexp special character](https://www.lua.org/pil/20.2.html),
|
||||||
|
set `$_ZL_HYPHEN` to 1 to treat a hyphen as a normal character.
|
||||||
|
If `$_ZL_HYPHEN` is not set or if it is set to `auto`, z.lua tries to treat `-`
|
||||||
|
as a lua regexp special character first. If there are no matches, z.lua tries
|
||||||
|
again, this time treating `-` as a normal character.
|
||||||
|
- set `$_ZL_CLINK_PROMPT_PRIORITY` change clink prompt register priority (default 99).
|
||||||
|
|
||||||
## Aging
|
## Aging
|
||||||
|
|
||||||
@@ -157,16 +193,12 @@ To z.lua, a directory that has low ranking but has been accessed recently will q
|
|||||||
|
|
||||||
## Default Matching
|
## Default Matching
|
||||||
|
|
||||||
By default, z.lua uses default matching algorithm similar to the original z.sh. Paths must be match all of the regexes in order.
|
By default, `z.lua` uses default matching algorithm similar to the original `z.sh`. Paths must be match all of the regexes in order.
|
||||||
|
|
||||||
- cd to a directory contains foo:
|
- cd to a directory contains foo:
|
||||||
|
|
||||||
z foo
|
z foo
|
||||||
|
|
||||||
- cd to a directory ends with foo:
|
|
||||||
|
|
||||||
z foo$
|
|
||||||
|
|
||||||
- use multiple arguments:
|
- use multiple arguments:
|
||||||
|
|
||||||
Assuming the following database:
|
Assuming the following database:
|
||||||
@@ -176,6 +208,15 @@ By default, z.lua uses default matching algorithm similar to the original z.sh.
|
|||||||
|
|
||||||
`"z in"` would cd into `/home/user/mail/inbox` as the higher weighted entry. However you can pass multiple arguments to z.lua to prefer a different entry. In the above example, `"z w in"` would then change directory to `/home/user/work/inbox`.
|
`"z in"` would cd into `/home/user/mail/inbox` as the higher weighted entry. However you can pass multiple arguments to z.lua to prefer a different entry. In the above example, `"z w in"` would then change directory to `/home/user/work/inbox`.
|
||||||
|
|
||||||
|
- use regexes:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
z foo$ # cd to a directory ends with foo
|
||||||
|
z %d # cd to a directory that contains a digit
|
||||||
|
```
|
||||||
|
|
||||||
|
Unlike `z.sh`, `z.lua` uses the [Lua regular expression syntax](https://www.lua.org/pil/20.2.html).
|
||||||
|
|
||||||
## Enhanced Matching
|
## Enhanced Matching
|
||||||
|
|
||||||
Enhanced matching can be enabled by exporting the environment:
|
Enhanced matching can be enabled by exporting the environment:
|
||||||
@@ -251,7 +292,7 @@ To enable this, you can set `$_ZL_ADD_ONCE` to `1` before init z.lua. Or you can
|
|||||||
````bash
|
````bash
|
||||||
eval "$(lua /path/to/z.lua --init bash once)"
|
eval "$(lua /path/to/z.lua --init bash once)"
|
||||||
eval "$(lua /path/to/z.lua --init zsh once)"
|
eval "$(lua /path/to/z.lua --init zsh once)"
|
||||||
source (lua /path/to/z.lua --init fish once | psub)
|
lua /path/to/z.lua --init fish once | source
|
||||||
````
|
````
|
||||||
|
|
||||||
With `add once` mode off (default), z.lua will consider the time you spent in the directory (like z.sh). When this mode is on, consider the times you accessed the directory (like autojump), and that could be much faster on slow hardware.
|
With `add once` mode off (default), z.lua will consider the time you spent in the directory (like z.sh). When this mode is on, consider the times you accessed the directory (like autojump), and that could be much faster on slow hardware.
|
||||||
@@ -300,6 +341,7 @@ New option `"-b"` can quickly go back to a specific parent directory in bash ins
|
|||||||
- **(No argument)**: `cd` into the project root, the project root the nearest parent directory with `.git`/`.hg`/`.svn` in it.
|
- **(No argument)**: `cd` into the project root, the project root the nearest parent directory with `.git`/`.hg`/`.svn` in it.
|
||||||
- **(One argument)**: `cd` into the closest parent starting with keyword, if not find, go to the parent containing keyword.
|
- **(One argument)**: `cd` into the closest parent starting with keyword, if not find, go to the parent containing keyword.
|
||||||
- **(Two arguments)**: replace the first value with the second one (in the current path).
|
- **(Two arguments)**: replace the first value with the second one (in the current path).
|
||||||
|
If simple substitution does not work, falls back to fuzzily replacing path components.
|
||||||
|
|
||||||
Let's start by aliasing `z -b` to `zb`:
|
Let's start by aliasing `z -b` to `zb`:
|
||||||
|
|
||||||
@@ -319,6 +361,11 @@ Let's start by aliasing `z -b` to `zb`:
|
|||||||
# substitute jekyll with ghost
|
# substitute jekyll with ghost
|
||||||
~/github/jekyll/test$ zb jekyll ghost
|
~/github/jekyll/test$ zb jekyll ghost
|
||||||
=> cd ~/github/ghost/test
|
=> cd ~/github/ghost/test
|
||||||
|
|
||||||
|
# same as above, but fuzzy
|
||||||
|
~/github/jekyll/test$ zb jek gh
|
||||||
|
=> z ~/github/ gh /test
|
||||||
|
=> cd ~/github/ghost/test # Assuming that's the most frecent match
|
||||||
```
|
```
|
||||||
|
|
||||||
Backward jumping can also be used with `$_ZL_ECHO` option (echo $PWD after cd), which makes it possible to combine them with other tools without actually changing the working directory (eg. ``ls `zb git` ``).
|
Backward jumping can also be used with `$_ZL_ECHO` option (echo $PWD after cd), which makes it possible to combine them with other tools without actually changing the working directory (eg. ``ls `zb git` ``).
|
||||||
@@ -349,6 +396,12 @@ Bash is not as powerful as zsh/fish, so we introduced fzf-completion for bash, i
|
|||||||
eval "$(lua /path/to/z.lua --init bash enhanced once echo fzf)"
|
eval "$(lua /path/to/z.lua --init bash enhanced once echo fzf)"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If you want use fzf completion in zsh, initalize your z.lua and append `fzf` keyword after `--init`:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
eval "$(lua /path/to/z.lua --init zsh enhanced once echo fzf)"
|
||||||
|
```
|
||||||
|
|
||||||
Then press `<tab>` after `z xxx`:
|
Then press `<tab>` after `z xxx`:
|
||||||
|
|
||||||

|

|
||||||
@@ -401,6 +454,14 @@ At last, press `<enter>` to accept or `<ESC>` to give up.
|
|||||||
Remember to enable the [enhanced matching](#enhanced-matching) algorithm, the current working directory can be skipped with it.
|
Remember to enable the [enhanced matching](#enhanced-matching) algorithm, the current working directory can be skipped with it.
|
||||||
|
|
||||||
|
|
||||||
|
## Ranger integration
|
||||||
|
To add a `:z` command to the [`ranger` file manager], copy the `ranger_zlua.py` file to `~/.config/ranger/plugins/`.
|
||||||
|
You can then use `:z foo`, `:z -b foo`, etc. from ranger. Use `:z -h` for help.
|
||||||
|
|
||||||
|
[`ranger` file manager]: https://github.com/ranger/ranger
|
||||||
|
|
||||||
|
To define additional commands (`:zb` for example) in ranger, you can put `alias zb z -b` into `~/.config/ranger/rc.conf`.
|
||||||
|
|
||||||
|
|
||||||
## Tips
|
## Tips
|
||||||
|
|
||||||
@@ -469,7 +530,7 @@ So I still recommend the pure lua script for portability and flexibility, but fo
|
|||||||
Average performance:
|
Average performance:
|
||||||
|
|
||||||
| Name | czmod | z.lua |
|
| Name | czmod | z.lua |
|
||||||
|-|-|-|-|-|
|
|-|-|-|
|
||||||
| **Update Time** | 1.6ms | 13.2ms |
|
| **Update Time** | 1.6ms | 13.2ms |
|
||||||
| **Query Time** | 1.5ms | 9.8ms |
|
| **Query Time** | 1.5ms | 9.8ms |
|
||||||
|
|
||||||
@@ -537,6 +598,7 @@ This project needs help for the tasks below:
|
|||||||
- 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.
|
- Thanks to [@barlik](https://github.com/barlik) for many improvements.
|
||||||
|
- Thanks to [@brglng](https://github.com/brglng) for nushell porting.
|
||||||
|
|
||||||
And many others.
|
And many others.
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 9.0 KiB |
BIN
images/fzf.png
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 8.5 KiB |
BIN
images/mru.png
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 10 KiB |
BIN
images/step1.png
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 7.5 KiB |
BIN
images/step2.png
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 5.7 KiB |
BIN
images/step3.png
|
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 3.6 KiB |
BIN
images/step4.png
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 3.4 KiB |
@@ -17,9 +17,9 @@ end
|
|||||||
|
|
||||||
set -x _ZL_DATA "$_ZL_DATA"
|
set -x _ZL_DATA "$_ZL_DATA"
|
||||||
|
|
||||||
set -q XDG_CONFIG_HOME; or set XDG_CONFIG_HOME ~/.config
|
set -q XDG_DATA_HOME; or set XDG_DATA_HOME ~/.local/share
|
||||||
if functions -q fisher
|
if functions -q fisher
|
||||||
set _zlua_dir $XDG_CONFIG_HOME/fisher/github.com/skywind3000/z.lua
|
set _zlua_dir $XDG_DATA_HOME/fisher/github.com/skywind3000/z.lua
|
||||||
else
|
else
|
||||||
set _zlua_dir (dirname (status --current-filename))
|
set _zlua_dir (dirname (status --current-filename))
|
||||||
end
|
end
|
||||||
@@ -27,6 +27,8 @@ end
|
|||||||
if test -e $_zlua_dir/z.lua
|
if test -e $_zlua_dir/z.lua
|
||||||
if type -q lua
|
if type -q lua
|
||||||
lua $_zlua_dir/z.lua --init fish enhanced once echo | source
|
lua $_zlua_dir/z.lua --init fish enhanced once echo | source
|
||||||
|
else if type -q luajit
|
||||||
|
luajit $_zlua_dir/z.lua --init fish enhanced once echo | source
|
||||||
else if type -q lua5.3
|
else if type -q lua5.3
|
||||||
lua5.3 $_zlua_dir/z.lua --init fish enhanced once echo | source
|
lua5.3 $_zlua_dir/z.lua --init fish enhanced once echo | source
|
||||||
else if type -q lua5.2
|
else if type -q lua5.2
|
||||||
|
|||||||
@@ -2,41 +2,45 @@ import time, sys, os
|
|||||||
import ranger.api
|
import ranger.api
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
old_hook_init = ranger.api.hook_init
|
# $RANGER_LUA and $RANGER_ZLUA variables are deprecated, do not use them.
|
||||||
|
ZLUA_LUAEXE = os.environ.get('RANGER_LUA') or os.environ.get('ZLUA_LUAEXE')
|
||||||
|
ZLUA_SCRIPT = os.environ.get('RANGER_ZLUA') or os.environ.get('ZLUA_SCRIPT')
|
||||||
|
|
||||||
PATH_LUA = os.environ.get('RANGER_LUA')
|
if not ZLUA_LUAEXE:
|
||||||
PATH_ZLUA = os.environ.get('RANGER_ZLUA')
|
|
||||||
|
|
||||||
if not PATH_LUA:
|
|
||||||
for path in os.environ.get('PATH', '').split(os.path.pathsep):
|
for path in os.environ.get('PATH', '').split(os.path.pathsep):
|
||||||
for name in ('lua', 'luajit', 'lua5.3', 'lua5.2', 'lua5.1'):
|
for name in ('lua', 'luajit', 'lua5.3', 'lua5.2', 'lua5.1'):
|
||||||
test = os.path.join(path, name)
|
test = os.path.join(path, name)
|
||||||
test = test + (sys.platform[:3] == 'win' and ".exe" or "")
|
test = test + (sys.platform[:3] == 'win' and ".exe" or "")
|
||||||
if os.path.exists(test):
|
if os.path.exists(test):
|
||||||
PATH_LUA = test
|
ZLUA_LUAEXE = test
|
||||||
break
|
break
|
||||||
|
|
||||||
if not PATH_LUA:
|
def _report_error(msg):
|
||||||
sys.stderr.write('Please install lua or set $RANGER_LUA.\n')
|
sys.stderr.write('ranger_zlua: ' + msg)
|
||||||
sys.exit()
|
raise RuntimeError(msg)
|
||||||
|
|
||||||
if (not PATH_ZLUA) or (not os.path.exists(PATH_ZLUA)):
|
if not ZLUA_LUAEXE:
|
||||||
sys.stderr.write('Not find z.lua, please set $RANGER_ZLUA to absolute path of z.lua.\n')
|
_report_error('Please install lua in $PATH or make sure $ZLUA_LUAEXE points to a lua executable.\n')
|
||||||
sys.exit()
|
if (not ZLUA_SCRIPT) or (not os.path.exists(ZLUA_SCRIPT)):
|
||||||
|
_report_error('Could not find z.lua, please make sure $ZLUA_SCRIPT is set to absolute path of z.lua.\n')
|
||||||
|
|
||||||
|
|
||||||
|
# Inform z.lua about directories the user browses to inside ranger
|
||||||
|
old_hook_init = ranger.api.hook_init
|
||||||
|
|
||||||
def hook_init(fm):
|
def hook_init(fm):
|
||||||
def update_zlua(signal):
|
def update_zlua(signal):
|
||||||
import os, random
|
import os, random
|
||||||
os.environ['_ZL_RANDOM'] = str(random.randint(0, 0x7fffffff))
|
os.environ['_ZL_RANDOM'] = str(random.randint(0, 0x7fffffff))
|
||||||
p = subprocess.Popen([PATH_LUA, PATH_ZLUA, "--add", signal.new.path])
|
p = subprocess.Popen([ZLUA_LUAEXE, ZLUA_SCRIPT, "--add", signal.new.path])
|
||||||
p.wait()
|
p.wait()
|
||||||
if PATH_ZLUA and PATH_LUA and os.path.exists(PATH_ZLUA):
|
if ZLUA_SCRIPT and ZLUA_LUAEXE and os.path.exists(ZLUA_SCRIPT):
|
||||||
fm.signal_bind('cd', update_zlua)
|
fm.signal_bind('cd', update_zlua)
|
||||||
return old_hook_init(fm)
|
return old_hook_init(fm)
|
||||||
|
|
||||||
ranger.api.hook_init = hook_init
|
ranger.api.hook_init = hook_init
|
||||||
|
|
||||||
|
|
||||||
class z(ranger.api.commands.Command):
|
class z(ranger.api.commands.Command):
|
||||||
def execute (self):
|
def execute (self):
|
||||||
import sys, os, time
|
import sys, os, time
|
||||||
@@ -52,13 +56,13 @@ class z(ranger.api.commands.Command):
|
|||||||
elif arg[:1] != '-':
|
elif arg[:1] != '-':
|
||||||
break
|
break
|
||||||
if mode:
|
if mode:
|
||||||
cmd = '"%s" "%s" '%(PATH_LUA, PATH_ZLUA)
|
cmd = '"%s" "%s" '%(ZLUA_LUAEXE, ZLUA_SCRIPT)
|
||||||
if mode in ('-I', '-i', '--'):
|
if mode in ('-I', '-i', '--'):
|
||||||
cmd += ' --cd'
|
cmd += ' --cd'
|
||||||
for arg in args:
|
for arg in args:
|
||||||
cmd += ' "%s"'%arg
|
cmd += ' "%s"'%arg
|
||||||
if mode in ('-e', '-x'):
|
if mode in ('-e', '-x'):
|
||||||
path = subprocess.check_output([PATH_LUA, PATH_ZLUA, '--cd'] + args)
|
path = subprocess.check_output([ZLUA_LUAEXE, ZLUA_SCRIPT, '--cd'] + args)
|
||||||
path = path.decode("utf-8", "ignore")
|
path = path.decode("utf-8", "ignore")
|
||||||
path = path.rstrip('\n')
|
path = path.rstrip('\n')
|
||||||
self.fm.notify(path)
|
self.fm.notify(path)
|
||||||
@@ -69,18 +73,14 @@ class z(ranger.api.commands.Command):
|
|||||||
p = self.fm.execute_command(cmd + ' 2>&1 | less +G', universal_newlines=True)
|
p = self.fm.execute_command(cmd + ' 2>&1 | less +G', universal_newlines=True)
|
||||||
stdout, stderr = p.communicate()
|
stdout, stderr = p.communicate()
|
||||||
else:
|
else:
|
||||||
if mode == '-I':
|
p = self.fm.execute_command(cmd, universal_newlines=True, stdout=subprocess.PIPE)
|
||||||
os.environ['_ZL_FZF_HEIGHT'] = '0'
|
stdout, stderr = p.communicate()
|
||||||
path = subprocess.check_output([PATH_LUA, PATH_ZLUA, '--cd'] + args)
|
path = stdout.rstrip('\n')
|
||||||
self.fm.execute_console('redraw_window')
|
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):
|
if path and os.path.exists(path):
|
||||||
self.fm.cd(path)
|
self.fm.cd(path)
|
||||||
else:
|
else:
|
||||||
path = subprocess.check_output([PATH_LUA, PATH_ZLUA, '--cd'] + args)
|
path = subprocess.check_output([ZLUA_LUAEXE, ZLUA_SCRIPT, '--cd'] + args)
|
||||||
path = path.decode("utf-8", "ignore")
|
path = path.decode("utf-8", "ignore")
|
||||||
path = path.rstrip('\n')
|
path = path.rstrip('\n')
|
||||||
if path and os.path.exists(path):
|
if path and os.path.exists(path):
|
||||||
|
|||||||
30
z.cmd
@@ -1,10 +1,8 @@
|
|||||||
@echo off
|
@echo off
|
||||||
setlocal EnableDelayedExpansion
|
setlocal EnableDelayedExpansion
|
||||||
|
|
||||||
set "HomeDir=%~dp0"
|
|
||||||
set "PathSave=%PATH%"
|
|
||||||
set "LuaExe=lua"
|
set "LuaExe=lua"
|
||||||
set "LuaScript=%HomeDir%z.lua"
|
set "LuaScript=%~dp0z.lua"
|
||||||
set "MatchType=-n"
|
set "MatchType=-n"
|
||||||
set "StrictSub=-n"
|
set "StrictSub=-n"
|
||||||
set "RunMode=-n"
|
set "RunMode=-n"
|
||||||
@@ -54,6 +52,12 @@ if /i "%1"=="-x" (
|
|||||||
goto parse
|
goto parse
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if /i "%1"=="--add" (
|
||||||
|
set "RunMode=--add"
|
||||||
|
shift /1
|
||||||
|
goto parse
|
||||||
|
)
|
||||||
|
|
||||||
if "%1"=="-i" (
|
if "%1"=="-i" (
|
||||||
set "InterMode=-i"
|
set "InterMode=-i"
|
||||||
shift /1
|
shift /1
|
||||||
@@ -85,7 +89,9 @@ if /i "%1"=="--purge" (
|
|||||||
:check
|
:check
|
||||||
|
|
||||||
if /i "%1"=="" (
|
if /i "%1"=="" (
|
||||||
set "RunMode=-l"
|
if /i "%InterMode%"=="" (
|
||||||
|
set "RunMode=-l"
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
for /f "delims=" %%i in ('cd') do set "PWD=%%i"
|
for /f "delims=" %%i in ('cd') do set "PWD=%%i"
|
||||||
@@ -100,13 +106,27 @@ if /i "%RunMode%"=="-n" (
|
|||||||
pushd !NewPath!
|
pushd !NewPath!
|
||||||
pushd !NewPath!
|
pushd !NewPath!
|
||||||
endlocal
|
endlocal
|
||||||
popd
|
goto popdir
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
) else (
|
) else (
|
||||||
call "%LuaExe%" "%LuaScript%" "%RunMode%" %MatchType% %StrictSub% %InterMode% %StripMode% %*
|
call "%LuaExe%" "%LuaScript%" "%RunMode%" %MatchType% %StrictSub% %InterMode% %StripMode% %*
|
||||||
)
|
)
|
||||||
|
|
||||||
|
goto end
|
||||||
|
|
||||||
|
:popdir
|
||||||
|
rem -- Exploits variable expansion and the pushd stack to set the current
|
||||||
|
rem -- directory without leaking a pushd.
|
||||||
|
popd
|
||||||
|
setlocal
|
||||||
|
set "NewPath=%CD%"
|
||||||
|
set "CDCmd=cd /d"
|
||||||
|
if /i not "%_ZL_CD%"=="" (
|
||||||
|
set "CDCmd=%_ZL_CD%"
|
||||||
|
)
|
||||||
|
endlocal & popd & %CDCmd% "%NewPath%"
|
||||||
|
|
||||||
:end
|
:end
|
||||||
echo.
|
echo.
|
||||||
|
|
||||||
|
|||||||
486
z.lua
@@ -1,10 +1,10 @@
|
|||||||
#! /usr/bin/env lua
|
#! /usr/bin/env lua
|
||||||
--=====================================================================
|
--=====================================================================
|
||||||
--
|
--
|
||||||
-- z.lua - a cd command that learns, by skywind 2018, 2019, 2020
|
-- z.lua - a cd command that learns, by skywind 2018-2022
|
||||||
-- Licensed under MIT license.
|
-- Licensed under MIT license.
|
||||||
--
|
--
|
||||||
-- Version 1.8.7, Last Modified: 2020/06/29 18:04
|
-- Version 1.8.22, Last Modified: 2025/05/17 13:54:38
|
||||||
--
|
--
|
||||||
-- * 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
|
||||||
@@ -12,17 +12,18 @@
|
|||||||
-- * compatible with lua 5.1, 5.2 and 5.3+
|
-- * compatible with lua 5.1, 5.2 and 5.3+
|
||||||
--
|
--
|
||||||
-- USE:
|
-- USE:
|
||||||
-- * z foo # cd to most frecent dir matching foo
|
-- * z foo # cd to most frecent dir matching foo
|
||||||
-- * z foo bar # cd to most frecent dir matching foo and bar
|
-- * z foo bar # cd to most frecent dir matching foo and bar
|
||||||
-- * z -r foo # cd to highest ranked dir matching foo
|
-- * z -r foo # cd to highest ranked dir matching foo
|
||||||
-- * z -t foo # cd to most recently accessed dir matching foo
|
-- * z -t foo # cd to most recently accessed dir matching foo
|
||||||
-- * z -l foo # list matches instead of cd
|
-- * z -l foo # list matches instead of cd
|
||||||
-- * z -c foo # restrict matches to subdirs of $PWD
|
-- * z -c foo # restrict matches to subdirs of $PWD
|
||||||
-- * z -e foo # echo the best match, don't cd
|
-- * z -e foo # echo the best match, don't cd
|
||||||
-- * z -x path # remove path from history
|
-- * z -x path # remove path from history
|
||||||
-- * z -i foo # cd with interactive selection
|
-- * z -i foo # cd with interactive selection
|
||||||
-- * z -I foo # cd with interactive selection using fzf
|
-- * z -I foo # cd with interactive selection using fzf
|
||||||
-- * z -b foo # cd to the parent directory starting with foo
|
-- * z -b foo # cd to the parent directory starting with foo
|
||||||
|
-- * z -b foo bar # replace foo with bar in cwd and cd there
|
||||||
--
|
--
|
||||||
-- Bash Install:
|
-- Bash Install:
|
||||||
-- * put something like this in your .bashrc:
|
-- * put something like this in your .bashrc:
|
||||||
@@ -46,12 +47,12 @@
|
|||||||
--
|
--
|
||||||
-- Fish Shell Install:
|
-- Fish Shell Install:
|
||||||
-- * put something like this in your config file:
|
-- * put something like this in your config file:
|
||||||
-- source (lua /path/to/z.lua --init fish | psub)
|
-- lua /path/to/z.lua --init fish | source
|
||||||
--
|
--
|
||||||
-- Power Shell Install:
|
-- Power Shell Install:
|
||||||
--
|
|
||||||
-- * put something like this in your config file:
|
-- * put something like this in your config file:
|
||||||
-- iex ($(lua /path/to/z.lua --init powershell) -join "`n")
|
-- Invoke-Expression (& {
|
||||||
|
-- (lua /path/to/z.lua --init powershell) -join "`n" })
|
||||||
--
|
--
|
||||||
-- Windows Install (with Clink):
|
-- Windows Install (with Clink):
|
||||||
-- * copy z.lua and z.cmd to clink's home directory
|
-- * copy z.lua and z.cmd to clink's home directory
|
||||||
@@ -63,6 +64,10 @@
|
|||||||
-- * Add cmder/vendor to %PATH%
|
-- * Add cmder/vendor to %PATH%
|
||||||
-- * Ensure that "lua" can be called in %PATH%
|
-- * Ensure that "lua" can be called in %PATH%
|
||||||
--
|
--
|
||||||
|
-- Windows WSL-1:
|
||||||
|
-- * Install lua-filesystem module before init z.lua:
|
||||||
|
-- sudo apt-get install lua-filesystem
|
||||||
|
--
|
||||||
-- Configure (optional):
|
-- Configure (optional):
|
||||||
-- set $_ZL_CMD in .bashrc/.zshrc to change the command (default z).
|
-- set $_ZL_CMD in .bashrc/.zshrc to change the command (default z).
|
||||||
-- set $_ZL_DATA in .bashrc/.zshrc to change the datafile (default ~/.zlua).
|
-- set $_ZL_DATA in .bashrc/.zshrc to change the datafile (default ~/.zlua).
|
||||||
@@ -122,7 +127,8 @@ Z_CMD = 'z'
|
|||||||
Z_MATCHMODE = 0
|
Z_MATCHMODE = 0
|
||||||
Z_MATCHNAME = false
|
Z_MATCHNAME = false
|
||||||
Z_SKIPPWD = false
|
Z_SKIPPWD = false
|
||||||
Z_HYPHEN = false
|
Z_HYPHEN = "auto"
|
||||||
|
Z_DATA_SEPARATOR = "|"
|
||||||
|
|
||||||
os.LOG_NAME = os.getenv('_ZL_LOG_NAME')
|
os.LOG_NAME = os.getenv('_ZL_LOG_NAME')
|
||||||
|
|
||||||
@@ -523,13 +529,16 @@ function os.path.abspath(path)
|
|||||||
return test
|
return test
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
for _, python in pairs({'python', 'python2', 'python3'}) do
|
for _, python in pairs({'python3', 'python2', 'python'}) do
|
||||||
local s = 'sys.stdout.write(os.path.abspath(sys.argv[1]))'
|
local s = 'sys.stdout.write(os.path.abspath(sys.argv[1]))'
|
||||||
local s = '-c "import os, sys;' .. s .. '" \'' .. path .. '\''
|
local s = '-c "import os, sys;' .. s .. '" \'' .. path .. '\''
|
||||||
local s = python .. ' ' .. s
|
local s = python .. ' ' .. s
|
||||||
local test = os.path.which(python)
|
local test = os.path.which(python)
|
||||||
if test ~= nil and test ~= '' then
|
if test ~= nil and test ~= '' then
|
||||||
return os.call(s)
|
test = os.call(s)
|
||||||
|
if test ~= nil and test ~= '' then
|
||||||
|
return test
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -576,7 +585,7 @@ function os.path.exists(name)
|
|||||||
end
|
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 or code == 17 then
|
||||||
return true
|
return true
|
||||||
elseif code == 30 then
|
elseif code == 30 then
|
||||||
local f = io.open(name,"r")
|
local f = io.open(name,"r")
|
||||||
@@ -874,6 +883,7 @@ function os.interpreter()
|
|||||||
local lua = os.argv[-1]
|
local lua = os.argv[-1]
|
||||||
if lua == nil then
|
if lua == nil then
|
||||||
io.stderr:write("cannot get executable name, recompiled your lua\n")
|
io.stderr:write("cannot get executable name, recompiled your lua\n")
|
||||||
|
return nil
|
||||||
end
|
end
|
||||||
if os.path.single(lua) then
|
if os.path.single(lua) then
|
||||||
local path = os.path.which(lua)
|
local path = os.path.which(lua)
|
||||||
@@ -1053,6 +1063,26 @@ function path_case_insensitive()
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
-- Read a line of the database and return a list of the 3 fields in it
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
function read_data_line(line)
|
||||||
|
local part = string.split(line, Z_DATA_SEPARATOR)
|
||||||
|
if #part <= 3 then
|
||||||
|
return part
|
||||||
|
end
|
||||||
|
-- If the part is made of more than 3 elements, it's probably because the
|
||||||
|
-- path element contains '|' that have been split. Thus, we want to
|
||||||
|
-- reconstruct it and keep the 2 last elements of part intact as the end
|
||||||
|
-- of the returned part.
|
||||||
|
local path = part[1]
|
||||||
|
for i=2,#part-2 do
|
||||||
|
path = path .. Z_DATA_SEPARATOR .. part[i]
|
||||||
|
end
|
||||||
|
return {path, part[#part-1], part[#part]}
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
-- load and split data
|
-- load and split data
|
||||||
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
@@ -1065,10 +1095,11 @@ function data_load(filename)
|
|||||||
return {}
|
return {}
|
||||||
end
|
end
|
||||||
for line in fp:lines() do
|
for line in fp:lines() do
|
||||||
local part = string.split(line, '|')
|
local part = read_data_line(line)
|
||||||
local item = {}
|
local item = {}
|
||||||
if part and part[1] and part[2] and part[3] then
|
if part and part[1] and part[2] and part[3] then
|
||||||
local key = insensitive and part[1]:lower() or part[1]
|
local key = insensitive and part[1]:lower() or part[1]
|
||||||
|
part[2] = part[2]:gsub(",", ".")
|
||||||
item.name = part[1]
|
item.name = part[1]
|
||||||
item.rank = tonumber(part[2])
|
item.rank = tonumber(part[2])
|
||||||
item.time = tonumber(part[3]) + 0
|
item.time = tonumber(part[3]) + 0
|
||||||
@@ -1126,7 +1157,7 @@ function data_save(filename, M)
|
|||||||
end
|
end
|
||||||
for i = 1, #M do
|
for i = 1, #M do
|
||||||
local item = M[i]
|
local item = M[i]
|
||||||
local text = item.name .. '|' .. item.rank .. '|' .. item.time
|
local text = item.name .. Z_DATA_SEPARATOR .. item.rank .. Z_DATA_SEPARATOR .. item.time
|
||||||
fp:write(text .. '\n')
|
fp:write(text .. '\n')
|
||||||
end
|
end
|
||||||
fp:close()
|
fp:close()
|
||||||
@@ -1283,13 +1314,16 @@ end
|
|||||||
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
-- select matched pathnames
|
-- select matched pathnames
|
||||||
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
function data_select(M, patterns, matchlast)
|
-- z_hyphen must be `true`, `false``, or `"auto"`.
|
||||||
|
function data_select(M, patterns, matchlast, z_hyphen)
|
||||||
local N = {}
|
local N = {}
|
||||||
local i = 1
|
local i = 1
|
||||||
local pats = {}
|
local pats = {}
|
||||||
|
local hyphens = false
|
||||||
for i = 1, #patterns do
|
for i = 1, #patterns do
|
||||||
local p = patterns[i]
|
local p = patterns[i]
|
||||||
if Z_HYPHEN then
|
hyphens = hyphens or string.match(p, "%-")
|
||||||
|
if z_hyphen == true then
|
||||||
p = p:gsub('-', '%%-')
|
p = p:gsub('-', '%%-')
|
||||||
end
|
end
|
||||||
table.insert(pats, case_insensitive_pattern(p))
|
table.insert(pats, case_insensitive_pattern(p))
|
||||||
@@ -1300,6 +1334,9 @@ function data_select(M, patterns, matchlast)
|
|||||||
table.insert(N, item)
|
table.insert(N, item)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if (hyphens and z_hyphen == "auto" and #N == 0) then
|
||||||
|
N = data_select(M, patterns, matchlast, true)
|
||||||
|
end
|
||||||
return N
|
return N
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1449,10 +1486,10 @@ function z_match(patterns, method, subdir)
|
|||||||
method = method ~= nil and method or 'frecent'
|
method = method ~= nil and method or 'frecent'
|
||||||
subdir = subdir ~= nil and subdir or false
|
subdir = subdir ~= nil and subdir or false
|
||||||
local M = data_load(DATA_FILE)
|
local M = data_load(DATA_FILE)
|
||||||
M = data_select(M, patterns, false)
|
M = data_select(M, patterns, false, Z_HYPHEN)
|
||||||
M = data_filter(M)
|
M = data_filter(M)
|
||||||
if Z_MATCHNAME then
|
if Z_MATCHNAME then
|
||||||
local N = data_select(M, patterns, true)
|
local N = data_select(M, patterns, true, Z_HYPHEN)
|
||||||
N = data_filter(N)
|
N = data_filter(N)
|
||||||
if #N > 0 then
|
if #N > 0 then
|
||||||
M = N
|
M = N
|
||||||
@@ -1575,21 +1612,23 @@ function z_cd(patterns)
|
|||||||
if patterns == nil then
|
if patterns == nil then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
if #patterns == 0 then
|
if Z_INTERACTIVE == 0 then
|
||||||
return nil
|
if #patterns == 0 then
|
||||||
end
|
return nil
|
||||||
local last = patterns[#patterns]
|
end
|
||||||
if last == '~' or last == '~/' then
|
local last = patterns[#patterns]
|
||||||
return os.path.expand('~')
|
if last == '~' or last == '~/' then
|
||||||
elseif windows and last == '~\\' then
|
return os.path.expand('~')
|
||||||
return os.path.expand('~')
|
elseif windows and last == '~\\' then
|
||||||
end
|
return os.path.expand('~')
|
||||||
if os.path.isabs(last) and os.path.isdir(last) then
|
end
|
||||||
local size = #patterns
|
if os.path.isabs(last) and os.path.isdir(last) then
|
||||||
if size <= 1 then
|
local size = #patterns
|
||||||
return os.path.norm(last)
|
if size <= 1 then
|
||||||
elseif last ~= '/' and last ~= '\\' then
|
return os.path.norm(last)
|
||||||
return os.path.norm(last)
|
elseif last ~= '/' and last ~= '\\' then
|
||||||
|
return os.path.norm(last)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local M = z_match(patterns, Z_METHOD, Z_SUBDIR)
|
local M = z_match(patterns, Z_METHOD, Z_SUBDIR)
|
||||||
@@ -1627,19 +1666,19 @@ function z_cd(patterns)
|
|||||||
elseif Z_INTERACTIVE == 2 then
|
elseif Z_INTERACTIVE == 2 then
|
||||||
local fzf = os.environ('_ZL_FZF', 'fzf')
|
local fzf = os.environ('_ZL_FZF', 'fzf')
|
||||||
local tmpname = '/tmp/zlua.txt'
|
local tmpname = '/tmp/zlua.txt'
|
||||||
local cmd = '--nth 2.. --reverse --inline-info --tac '
|
local cmd = '--nth 2.. --reverse --info=inline --tac '
|
||||||
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
|
||||||
cmd = ((fzf == '') and 'fzf' or fzf) .. ' ' .. cmd .. ' ' .. flag
|
cmd = ((fzf == '') and 'fzf' or fzf) .. ' ' .. cmd .. ' ' .. flag
|
||||||
|
local height = os.environ('_ZL_FZF_HEIGHT', '35%')
|
||||||
|
if height ~= nil and height ~= '' and height ~= '0' then
|
||||||
|
cmd = cmd .. ' --height ' .. height
|
||||||
|
end
|
||||||
if not windows then
|
if not windows then
|
||||||
tmpname = os.tmpname()
|
tmpname = os.tmpname()
|
||||||
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 .. '"'
|
cmd = cmd .. ' < "' .. tmpname .. '"'
|
||||||
else
|
else
|
||||||
tmpname = os.tmpname():gsub('\\', ''):gsub('%.', '')
|
tmpname = os.tmpname():gsub('[\\:]', ''):gsub('%.', '')
|
||||||
tmpname = os.environ('TMP', '') .. '\\zlua_' .. tmpname .. '.txt'
|
tmpname = os.environ('TMP', '') .. '\\zlua_' .. tmpname .. '.txt'
|
||||||
cmd = 'type "' .. tmpname .. '" | ' .. cmd
|
cmd = 'type "' .. tmpname .. '" | ' .. cmd
|
||||||
end
|
end
|
||||||
@@ -1711,47 +1750,45 @@ function cd_backward(args, options, pwd)
|
|||||||
local pwd = (pwd ~= nil) and pwd or os.pwd()
|
local pwd = (pwd ~= nil) and pwd or os.pwd()
|
||||||
if nargs == 0 then
|
if nargs == 0 then
|
||||||
return find_vcs_root(pwd)
|
return find_vcs_root(pwd)
|
||||||
elseif nargs == 1 then
|
elseif nargs == 1 and args[1]:sub(1, 2) == '..' then
|
||||||
if args[1]:sub(1, 2) == '..' then
|
local size = args[1]:len() - 1
|
||||||
local size = args[1]:len() - 1
|
if args[1]:match('^%.%.+$') then
|
||||||
if args[1]:match('^%.%.+$') then
|
size = args[1]:len() - 1
|
||||||
size = args[1]:len() - 1
|
elseif args[1]:match('^%.%.%d+$') then
|
||||||
elseif args[1]:match('^%.%.%d+$') then
|
size = tonumber(args[1]:sub(3))
|
||||||
size = tonumber(args[1]:sub(3))
|
|
||||||
else
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
local path = pwd
|
|
||||||
for index = 1, size do
|
|
||||||
path = os.path.join(path, '..')
|
|
||||||
end
|
|
||||||
return os.path.normpath(path)
|
|
||||||
else
|
else
|
||||||
pwd = os.path.split(pwd)
|
|
||||||
local test = windows and pwd:gsub('\\', '/') or pwd
|
|
||||||
local key = windows and args[1]:lower() or args[1]
|
|
||||||
if not key:match('%u') then
|
|
||||||
test = test:lower()
|
|
||||||
end
|
|
||||||
local pos, ends = test:rfind('/' .. key)
|
|
||||||
if pos then
|
|
||||||
ends = test:find('/', pos + key:len() + 1, true)
|
|
||||||
ends = ends and ends or test:len()
|
|
||||||
return os.path.normpath(pwd:sub(1, ends))
|
|
||||||
elseif windows and test:startswith(key) then
|
|
||||||
ends = test:find('/', key:len(), true)
|
|
||||||
ends = ends and ends or test:len()
|
|
||||||
return os.path.normpath(pwd:sub(1, ends))
|
|
||||||
end
|
|
||||||
pos = test:rfind(key)
|
|
||||||
if pos then
|
|
||||||
ends = test:find('/', pos + key:len(), true)
|
|
||||||
ends = ends and ends or test:len()
|
|
||||||
return os.path.normpath(pwd:sub(1, ends))
|
|
||||||
end
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
else
|
local path = pwd
|
||||||
|
for index = 1, size do
|
||||||
|
path = os.path.join(path, '..')
|
||||||
|
end
|
||||||
|
return os.path.normpath(path)
|
||||||
|
elseif nargs == 1 then
|
||||||
|
pwd = os.path.split(pwd)
|
||||||
|
local test = windows and pwd:gsub('\\', '/') or pwd
|
||||||
|
local key = windows and args[1]:lower() or args[1]
|
||||||
|
if not key:match('%u') then
|
||||||
|
test = test:lower()
|
||||||
|
end
|
||||||
|
local pos, ends = test:rfind('/' .. key)
|
||||||
|
if pos then
|
||||||
|
ends = test:find('/', pos + key:len() + 1, true)
|
||||||
|
ends = ends and ends or test:len()
|
||||||
|
return os.path.normpath(pwd:sub(1, ends))
|
||||||
|
elseif windows and test:startswith(key) then
|
||||||
|
ends = test:find('/', key:len(), true)
|
||||||
|
ends = ends and ends or test:len()
|
||||||
|
return os.path.normpath(pwd:sub(1, ends))
|
||||||
|
end
|
||||||
|
pos = test:rfind(key)
|
||||||
|
if pos then
|
||||||
|
ends = test:find('/', pos + key:len(), true)
|
||||||
|
ends = ends and ends or test:len()
|
||||||
|
return os.path.normpath(pwd:sub(1, ends))
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
elseif nargs == 2 then
|
||||||
local test = windows and pwd:gsub('\\', '/') or pwd
|
local test = windows and pwd:gsub('\\', '/') or pwd
|
||||||
local src = args[1]
|
local src = args[1]
|
||||||
local dst = args[2]
|
local dst = args[2]
|
||||||
@@ -1762,10 +1799,25 @@ function cd_backward(args, options, pwd)
|
|||||||
if not start then
|
if not start then
|
||||||
return pwd
|
return pwd
|
||||||
end
|
end
|
||||||
|
|
||||||
local lhs = pwd:sub(1, start - 1)
|
local lhs = pwd:sub(1, start - 1)
|
||||||
local rhs = pwd:sub(ends + 1)
|
local rhs = pwd:sub(ends + 1)
|
||||||
return lhs .. dst .. rhs
|
local newpath = lhs .. dst .. rhs
|
||||||
|
if os.path.isdir(newpath) then
|
||||||
|
return newpath
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Get rid of the entire path component that matched `src`.
|
||||||
|
lhs = lhs:gsub("[^/]*$", "")
|
||||||
|
rhs = rhs:gsub("^[^/]*", "")
|
||||||
|
return z_cd({lhs, dst, rhs})
|
||||||
|
-- In the future, it would make sense to have `z -b -c from to to2`
|
||||||
|
-- to z_cd({lhs, dst[1], dst[2]}). Without `-c`, we probably still
|
||||||
|
-- want to support only 2 argumets.
|
||||||
end
|
end
|
||||||
|
|
||||||
|
io.stderr:write("Error: " .. Z_CMD .. " -b takes at most 2 arguments.\n")
|
||||||
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -1823,7 +1875,7 @@ function cd_breadcrumbs(pwd, interactive)
|
|||||||
if not windows then
|
if not windows then
|
||||||
tmpname = os.tmpname()
|
tmpname = os.tmpname()
|
||||||
else
|
else
|
||||||
tmpname = os.tmpname():gsub('\\', ''):gsub('%.', '')
|
tmpname = os.tmpname():gsub('[\\:]', ''):gsub('%.', '')
|
||||||
tmpname = os.environ('TMP', '') .. '\\zlua_' .. tmpname .. '.txt'
|
tmpname = os.environ('TMP', '') .. '\\zlua_' .. tmpname .. '.txt'
|
||||||
end
|
end
|
||||||
fp = io.open(tmpname, 'w')
|
fp = io.open(tmpname, 'w')
|
||||||
@@ -1848,7 +1900,7 @@ function cd_breadcrumbs(pwd, interactive)
|
|||||||
retval = io.read('*l')
|
retval = io.read('*l')
|
||||||
elseif interactive == 2 then
|
elseif interactive == 2 then
|
||||||
local fzf = os.environ('_ZL_FZF', 'fzf')
|
local fzf = os.environ('_ZL_FZF', 'fzf')
|
||||||
local cmd = '--reverse --inline-info --tac '
|
local cmd = '--reverse --info=inline --tac '
|
||||||
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
|
||||||
cmd = ((fzf == '') and 'fzf' or fzf) .. ' ' .. cmd .. ' ' .. flag
|
cmd = ((fzf == '') and 'fzf' or fzf) .. ' ' .. cmd .. ' ' .. flag
|
||||||
@@ -1914,14 +1966,14 @@ 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
|
||||||
if Z_INTERACTIVE == 0 then
|
if #args > 0 or Z_INTERACTIVE == 0 then
|
||||||
path = cd_backward(args, options)
|
path = cd_backward(args, options)
|
||||||
else
|
else
|
||||||
path = cd_breadcrumbs('', Z_INTERACTIVE)
|
path = cd_breadcrumbs('', Z_INTERACTIVE)
|
||||||
end
|
end
|
||||||
elseif options['-'] then
|
elseif options['-'] then
|
||||||
path = cd_minus(args, options)
|
path = cd_minus(args, options)
|
||||||
elseif #args == 0 then
|
elseif #args == 0 and Z_INTERACTIVE == 0 then
|
||||||
path = nil
|
path = nil
|
||||||
else
|
else
|
||||||
path = z_cd(args)
|
path = z_cd(args)
|
||||||
@@ -1951,10 +2003,14 @@ function main(argv)
|
|||||||
for _, key in ipairs(args) do
|
for _, key in ipairs(args) do
|
||||||
opts[key] = 1
|
opts[key] = 1
|
||||||
end
|
end
|
||||||
if windows then
|
if opts.nushell then
|
||||||
|
z_nushell_init(opts)
|
||||||
|
elseif windows then
|
||||||
z_windows_init(opts)
|
z_windows_init(opts)
|
||||||
elseif opts.fish then
|
elseif opts.fish then
|
||||||
z_fish_init(opts)
|
z_fish_init(opts)
|
||||||
|
elseif opts.powershell then
|
||||||
|
z_windows_init(opts)
|
||||||
else
|
else
|
||||||
z_shell_init(opts)
|
z_shell_init(opts)
|
||||||
end
|
end
|
||||||
@@ -1966,9 +2022,14 @@ function main(argv)
|
|||||||
z_print(M, true, false)
|
z_print(M, true, false)
|
||||||
end
|
end
|
||||||
elseif options['--complete'] then
|
elseif options['--complete'] then
|
||||||
local line = args[1] and args[1] or ''
|
local M = {}
|
||||||
local head = line:sub(Z_CMD:len()+1):gsub('^%s+', '')
|
if options['-m1'] then
|
||||||
local M = z_match({head}, Z_METHOD, Z_SUBDIR)
|
M = z_match(args and args or {}, Z_METHOD, Z_SUBDIR)
|
||||||
|
else
|
||||||
|
local line = args[1] and args[1] or ''
|
||||||
|
local head = line:sub(Z_CMD:len()+1):gsub('^%s+', '')
|
||||||
|
M = z_match({head}, Z_METHOD, Z_SUBDIR)
|
||||||
|
end
|
||||||
for _, item in pairs(M) do
|
for _, item in pairs(M) do
|
||||||
print(item.name)
|
print(item.name)
|
||||||
end
|
end
|
||||||
@@ -2043,10 +2104,13 @@ function z_init()
|
|||||||
Z_SKIPPWD = true
|
Z_SKIPPWD = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
assert(Z_HYPHEN == "auto", "Z_HYPHEN initialized to an unexpected value")
|
||||||
if _zl_hyphen ~= nil then
|
if _zl_hyphen ~= nil then
|
||||||
local m = string.lower(_zl_hyphen)
|
local m = string.lower(_zl_hyphen)
|
||||||
if (m == '1' or m == 'yes' or m == 'true' or m == 't') then
|
if (m == '1' or m == 'yes' or m == 'true' or m == 't') then
|
||||||
Z_HYPHEN = true
|
Z_HYPHEN = true
|
||||||
|
elseif (m == '0' or m == 'no' or m == 'false' or m == 'f') then
|
||||||
|
Z_HYPHEN = false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -2057,6 +2121,7 @@ end
|
|||||||
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
function z_clink_init()
|
function z_clink_init()
|
||||||
local once = os.environ("_ZL_ADD_ONCE", false)
|
local once = os.environ("_ZL_ADD_ONCE", false)
|
||||||
|
local _zl_clink_prompt_priority = os.environ('_ZL_CLINK_PROMPT_PRIORITY', 99)
|
||||||
local previous = ''
|
local previous = ''
|
||||||
function z_add_to_database()
|
function z_add_to_database()
|
||||||
pwd = clink.get_cwd()
|
pwd = clink.get_cwd()
|
||||||
@@ -2068,7 +2133,7 @@ function z_clink_init()
|
|||||||
end
|
end
|
||||||
z_add(clink.get_cwd())
|
z_add(clink.get_cwd())
|
||||||
end
|
end
|
||||||
clink.prompt.register_filter(z_add_to_database, 99)
|
clink.prompt.register_filter(z_add_to_database, _zl_clink_prompt_priority)
|
||||||
function z_match_completion(word)
|
function z_match_completion(word)
|
||||||
local M = z_match({word}, Z_METHOD, Z_SUBDIR)
|
local M = z_match({word}, Z_METHOD, Z_SUBDIR)
|
||||||
for _, item in pairs(M) do
|
for _, item in pairs(M) do
|
||||||
@@ -2076,8 +2141,28 @@ function z_clink_init()
|
|||||||
end
|
end
|
||||||
return {}
|
return {}
|
||||||
end
|
end
|
||||||
|
local dirmatchfunc = function (word)
|
||||||
|
clink.matches_are_files(1)
|
||||||
|
return clink.match_files(word..'*', true, clink.find_dirs)
|
||||||
|
end
|
||||||
|
local dirmatchparser = clink.arg.new_parser():set_arguments({ dirmatchfunc })
|
||||||
local z_parser = clink.arg.new_parser()
|
local z_parser = clink.arg.new_parser()
|
||||||
z_parser:set_arguments({ z_match_completion })
|
z_parser:set_arguments({ z_match_completion })
|
||||||
|
z_parser:set_flags("-r", "-i", "-I", "-t", "-l", "-c", "-e", "-b", "-x"..dirmatchparser, "-h")
|
||||||
|
if z_parser.adddescriptions then
|
||||||
|
z_parser:adddescriptions({
|
||||||
|
['-r'] = "cd to highest ranked dir matching",
|
||||||
|
['-i'] = "cd with interactive selection",
|
||||||
|
['-I'] = "cd with interactive selection using fzf",
|
||||||
|
['-t'] = "cd to most recently accessed dir matching",
|
||||||
|
['-l'] = "list matches instead of cd",
|
||||||
|
['-c'] = "restrict matches to subdirs of cwd (or %PWD% if set)",
|
||||||
|
['-e'] = "echo the best match, don't cd",
|
||||||
|
['-b'] = "jump backwards to given dir or to project root",
|
||||||
|
['-x'] = { " dir", "remove path from history" },
|
||||||
|
['-h'] = "show help",
|
||||||
|
})
|
||||||
|
end
|
||||||
clink.arg.register_parser("z", z_parser)
|
clink.arg.register_parser("z", z_parser)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -2112,7 +2197,8 @@ _zlua() {
|
|||||||
-s) local arg_strip="-s" ;;
|
-s) local arg_strip="-s" ;;
|
||||||
-i) local arg_inter="-i" ;;
|
-i) local arg_inter="-i" ;;
|
||||||
-I) local arg_inter="-I" ;;
|
-I) local arg_inter="-I" ;;
|
||||||
-h|--help) local arg_mode="-h" ;;
|
-h) local arg_mode="-h" ;;
|
||||||
|
--help) local arg_mode="-h" ;;
|
||||||
--purge) local arg_mode="--purge" ;;
|
--purge) local arg_mode="--purge" ;;
|
||||||
*) break ;;
|
*) break ;;
|
||||||
esac
|
esac
|
||||||
@@ -2235,6 +2321,31 @@ _zlua_zsh_tab_completion() {
|
|||||||
}
|
}
|
||||||
if [ "${+functions[compdef]}" -ne 0 ]; then
|
if [ "${+functions[compdef]}" -ne 0 ]; then
|
||||||
compdef _zlua_zsh_tab_completion _zlua 2> /dev/null
|
compdef _zlua_zsh_tab_completion _zlua 2> /dev/null
|
||||||
|
compdef ${_ZL_CMD:-z}=_zlua
|
||||||
|
fi
|
||||||
|
]]
|
||||||
|
|
||||||
|
local script_fzf_complete_zsh = [[
|
||||||
|
if command -v fzf >/dev/null 2>&1; then
|
||||||
|
# To redraw line after fzf closes (printf '\e[5n')
|
||||||
|
bindkey '\e[0n' kill-whole-line
|
||||||
|
_zlua_zsh_fzf_complete() {
|
||||||
|
local list=$(_zlua -l ${words[2,-1]})
|
||||||
|
|
||||||
|
if [ -n "$list" ]; then
|
||||||
|
local selected=$(print $list | ${=zlua_fzf} | sed 's/^[0-9,.]* *//')
|
||||||
|
|
||||||
|
if [ -n "$selected" ]; then
|
||||||
|
cd ${selected}
|
||||||
|
printf '\e[5n'
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ "${+functions[compdef]}" -ne 0 ]; then
|
||||||
|
compdef _zlua_zsh_fzf_complete _zlua > /dev/null 2>&1
|
||||||
|
compdef ${_ZL_CMD:-z}=_zlua
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
]]
|
]]
|
||||||
|
|
||||||
@@ -2275,7 +2386,7 @@ function z_shell_init(opts)
|
|||||||
end
|
end
|
||||||
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 "
|
local fzf_cmd = "fzf --nth 2.. --reverse --info=inline --tac "
|
||||||
local height = os.environ('_ZL_FZF_HEIGHT', '35%')
|
local height = os.environ('_ZL_FZF_HEIGHT', '35%')
|
||||||
if height ~= nil and height ~= '' and height ~= '0' then
|
if height ~= nil and height ~= '' and height ~= '0' then
|
||||||
fzf_cmd = fzf_cmd .. ' --height ' .. height .. ' '
|
fzf_cmd = fzf_cmd .. ' --height ' .. height .. ' '
|
||||||
@@ -2291,6 +2402,18 @@ function z_shell_init(opts)
|
|||||||
print(once and script_init_zsh_once or script_init_zsh)
|
print(once and script_init_zsh_once or script_init_zsh)
|
||||||
end
|
end
|
||||||
print(script_complete_zsh)
|
print(script_complete_zsh)
|
||||||
|
if opts.fzf ~= nil then
|
||||||
|
local fzf_cmd = "fzf --nth 2.. --reverse --info=inline --tac "
|
||||||
|
local height = os.environ('_ZL_FZF_HEIGHT', '35%')
|
||||||
|
if height ~= nil and height ~= '' and height ~= '0' then
|
||||||
|
fzf_cmd = fzf_cmd .. ' --height ' .. height .. ' '
|
||||||
|
end
|
||||||
|
local flag = os.environ('_ZL_FZF_FLAG', '')
|
||||||
|
flag = (flag == '' or flag == nil) and '+s -e' or flag
|
||||||
|
fzf_cmd = fzf_cmd .. ' ' .. flag .. ' '
|
||||||
|
print('zlua_fzf="' .. fzf_cmd .. '"')
|
||||||
|
print(script_fzf_complete_zsh)
|
||||||
|
end
|
||||||
elseif opts.posix ~= nil then
|
elseif opts.posix ~= nil then
|
||||||
if prompt_hook then
|
if prompt_hook then
|
||||||
local script = script_init_posix
|
local script = script_init_posix
|
||||||
@@ -2395,7 +2518,9 @@ function _zlua
|
|||||||
end
|
end
|
||||||
|
|
||||||
if test -z "$_ZL_CMD"; set -x _ZL_CMD z; end
|
if test -z "$_ZL_CMD"; set -x _ZL_CMD z; end
|
||||||
alias "$_ZL_CMD"=_zlua
|
function $_ZL_CMD -w _zlua -d "alias $_ZL_CMD=_zlua"
|
||||||
|
_zlua $argv
|
||||||
|
end
|
||||||
]]
|
]]
|
||||||
|
|
||||||
script_init_fish = [[
|
script_init_fish = [[
|
||||||
@@ -2500,6 +2625,11 @@ if /i "%1"=="-x" (
|
|||||||
shift /1
|
shift /1
|
||||||
goto parse
|
goto parse
|
||||||
)
|
)
|
||||||
|
if /i "%1"=="--add" (
|
||||||
|
set "RunMode=--add"
|
||||||
|
shift /1
|
||||||
|
goto parse
|
||||||
|
)
|
||||||
if "%1"=="-i" (
|
if "%1"=="-i" (
|
||||||
set "InterMode=-i"
|
set "InterMode=-i"
|
||||||
shift /1
|
shift /1
|
||||||
@@ -2525,7 +2655,9 @@ if /i "%1"=="--purge" (
|
|||||||
)
|
)
|
||||||
:check
|
:check
|
||||||
if /i "%1"=="" (
|
if /i "%1"=="" (
|
||||||
set "RunMode=-l"
|
if /i "%InterMode%"=="" (
|
||||||
|
set "RunMode=-l"
|
||||||
|
)
|
||||||
)
|
)
|
||||||
for /f "delims=" %%i in ('cd') do set "PWD=%%i"
|
for /f "delims=" %%i in ('cd') do set "PWD=%%i"
|
||||||
if /i "%RunMode%"=="-n" (
|
if /i "%RunMode%"=="-n" (
|
||||||
@@ -2538,12 +2670,22 @@ if /i "%RunMode%"=="-n" (
|
|||||||
pushd !NewPath!
|
pushd !NewPath!
|
||||||
pushd !NewPath!
|
pushd !NewPath!
|
||||||
endlocal
|
endlocal
|
||||||
popd
|
goto popdir
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
) else (
|
) else (
|
||||||
call "%LuaExe%" "%LuaScript%" "%RunMode%" %MatchType% %StrictSub% %InterMode% %StripMode% %*
|
call "%LuaExe%" "%LuaScript%" "%RunMode%" %MatchType% %StrictSub% %InterMode% %StripMode% %*
|
||||||
)
|
)
|
||||||
|
goto end
|
||||||
|
:popdir
|
||||||
|
popd
|
||||||
|
setlocal
|
||||||
|
set "NewPath=%CD%"
|
||||||
|
set "CDCmd=cd /d"
|
||||||
|
if /i not "%_ZL_CD%"=="" (
|
||||||
|
set "CDCmd=%_ZL_CD%"
|
||||||
|
)
|
||||||
|
endlocal & popd & %CDCmd% "%NewPath%"
|
||||||
:end
|
:end
|
||||||
]]
|
]]
|
||||||
|
|
||||||
@@ -2668,22 +2810,143 @@ function z_windows_init(opts)
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
-- nushell
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
local script_zlua_nushell = [[
|
||||||
|
def _zlua --env --wrapped [...args: string] {
|
||||||
|
if ($args | length) != 0 and $args.0 == "--add" {
|
||||||
|
with-env { _ZL_RANDOM: (random int) } { ^$env.ZLUA_LUAEXE $env.ZLUA_SCRIPT --add ...($args | skip 1) }
|
||||||
|
} else if ($args | length) != 0 and $args.0 == "--complete" {
|
||||||
|
^$env.ZLUA_LUAEXE $env.ZLUA_SCRIPT --complete ...($args | skip 1)
|
||||||
|
} else {
|
||||||
|
mut arg_mode = ''
|
||||||
|
mut arg_type = ''
|
||||||
|
mut arg_subdir = ''
|
||||||
|
mut arg_inter = ''
|
||||||
|
mut arg_strip = ''
|
||||||
|
mut count = 0
|
||||||
|
for arg in $args {
|
||||||
|
match $arg {
|
||||||
|
'-l' => { $arg_mode = '-l' },
|
||||||
|
'-e' => { $arg_mode = '-e' },
|
||||||
|
'-x' => { $arg_mode = '-x' },
|
||||||
|
'-t' => { $arg_type = '-t' },
|
||||||
|
'-r' => { $arg_type = '-r' },
|
||||||
|
'-c' => { $arg_subdir = '-c' },
|
||||||
|
'-s' => { $arg_strip = '-s' },
|
||||||
|
'-i' => { $arg_inter = '-i' },
|
||||||
|
'-I' => { $arg_inter = '-I' },
|
||||||
|
'-h' => { $arg_mode = '-h' },
|
||||||
|
'--help' => { $arg_mode = '-h' },
|
||||||
|
'--purge' => { $arg_mode = '--purge' },
|
||||||
|
_ => break
|
||||||
|
}
|
||||||
|
$count += 1
|
||||||
|
}
|
||||||
|
let args = $args | skip $count
|
||||||
|
if $arg_mode == '-h' or $arg_mode == '--purge' {
|
||||||
|
^$env.ZLUA_LUAEXE $env.ZLUA_SCRIPT $arg_mode
|
||||||
|
} else if $arg_mode == '-l' or ($args | length) == 0 {
|
||||||
|
^$env.ZLUA_LUAEXE $env.ZLUA_SCRIPT -l $arg_subdir $arg_type $arg_strip ...$args
|
||||||
|
} else if $arg_mode != '' {
|
||||||
|
^$env.ZLUA_LUAEXE $env.ZLUA_SCRIPT $arg_mode $arg_subdir $arg_type $arg_inter ...$args
|
||||||
|
} else {
|
||||||
|
let zdest = (^$env.ZLUA_LUAEXE $env.ZLUA_SCRIPT --cd $arg_type $arg_subdir $arg_inter ...$args)
|
||||||
|
if $zdest != '' and ($zdest | path exists) {
|
||||||
|
cd $zdest
|
||||||
|
if _ZL_ECHO in $env and $env._ZL_ECHO != '' {
|
||||||
|
pwd
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]]
|
||||||
|
|
||||||
|
local script_init_nushell = [[
|
||||||
|
$env.config = ($env | default {} config).config
|
||||||
|
$env.config = ($env.config | default {} hooks)
|
||||||
|
$env.config = ($env.config | update hooks ($env.config.hooks | default {} env_change))
|
||||||
|
$env.config = ($env.config | update hooks.env_change ($env.config.hooks.env_change | default [] PWD))
|
||||||
|
$env.config = ($env.config | update hooks.env_change.PWD ($env.config.hooks.env_change.PWD | append {|_, dir| _zlua --add $dir }))
|
||||||
|
]]
|
||||||
|
|
||||||
|
local script_complete_nushell = [[
|
||||||
|
let zlua_completer = {|spans| $spans | skip 1 | _zlua --complete -m1 ...$in | lines | where {|x| $x != $env.PWD}}
|
||||||
|
|
||||||
|
$env.config = ($env.config | default {} completions)
|
||||||
|
$env.config = ($env.config | update completions ($env.config.completions | default {} external))
|
||||||
|
$env.config = ($env.config | update completions.external ($env.config.completions.external | default true enable))
|
||||||
|
if completer in $env.config.completions.external {
|
||||||
|
let orig_completer = $env.config.completions.external.completer
|
||||||
|
$env.config = ($env.config | update completions.external.completer {
|
||||||
|
{|spans|
|
||||||
|
match $spans.0 {
|
||||||
|
z => $zlua_completer,
|
||||||
|
_zlua => $zlua_completer,
|
||||||
|
_ => $orig_completer
|
||||||
|
} | do $in $spans
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
$env.config = ($env.config | update completions.external.completer {
|
||||||
|
{|spans|
|
||||||
|
match $spans.0 {
|
||||||
|
z => $zlua_completer,
|
||||||
|
_zlua => $zlua_completer,
|
||||||
|
} | do $in $spans
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
]]
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
-- initialize nushell
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
function z_nushell_init(opts)
|
||||||
|
print('$env.ZLUA_LUAEXE = \'' .. os.interpreter() .. '\'')
|
||||||
|
print('$env.ZLUA_SCRIPT = \'' .. os.scriptname() .. '\'')
|
||||||
|
local prompt_hook = (not os.environ("_ZL_NO_PROMPT_COMMAND", false))
|
||||||
|
if opts.clean ~= nil then
|
||||||
|
prompt_hook = false
|
||||||
|
end
|
||||||
|
print(script_zlua_nushell)
|
||||||
|
if prompt_hook then
|
||||||
|
print(script_init_nushell)
|
||||||
|
end
|
||||||
|
print(script_complete_nushell)
|
||||||
|
if opts.enhanced ~= nil then
|
||||||
|
print('$env._ZL_MATCH_MODE = 1')
|
||||||
|
end
|
||||||
|
if opts.once ~= nil then
|
||||||
|
print('$env._ZL_ADD_ONCE = 1')
|
||||||
|
end
|
||||||
|
if opts.echo ~= nil then
|
||||||
|
print('$env._ZL_ECHO = 1')
|
||||||
|
end
|
||||||
|
if opts.nc ~= nil then
|
||||||
|
print('$env._ZL_NO_CHECK = 1')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
-- help
|
-- help
|
||||||
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
function z_help()
|
function z_help()
|
||||||
local cmd = Z_CMD .. ' '
|
local cmd = Z_CMD .. ' '
|
||||||
print(cmd .. 'foo # cd to most frecent dir matching foo')
|
print(cmd .. 'foo # cd to most frecent dir matching foo')
|
||||||
print(cmd .. 'foo bar # cd to most frecent dir matching foo and bar')
|
print(cmd .. 'foo bar # cd to most frecent dir matching foo and bar')
|
||||||
print(cmd .. '-r foo # cd to highest ranked dir matching foo')
|
print(cmd .. '-r foo # cd to highest ranked dir matching foo')
|
||||||
print(cmd .. '-t foo # cd to most recently accessed dir matching foo')
|
print(cmd .. '-t foo # cd to most recently accessed dir matching foo')
|
||||||
print(cmd .. '-l foo # list matches instead of cd')
|
print(cmd .. '-l foo # list matches instead of cd')
|
||||||
print(cmd .. '-c foo # restrict matches to subdirs of $PWD')
|
print(cmd .. '-c foo # restrict matches to subdirs of $PWD')
|
||||||
print(cmd .. '-e foo # echo the best match, don\'t cd')
|
print(cmd .. '-e foo # echo the best match, don\'t cd')
|
||||||
print(cmd .. '-x path # remove path from history')
|
print(cmd .. '-x path # remove path from history')
|
||||||
print(cmd .. '-i foo # cd with interactive selection')
|
print(cmd .. '-i foo # cd with interactive selection')
|
||||||
print(cmd .. '-I foo # cd with interactive selection using fzf')
|
print(cmd .. '-I foo # cd with interactive selection using fzf')
|
||||||
print(cmd .. '-b foo # cd to the parent directory starting with foo')
|
print(cmd .. '-b foo # cd to the parent directory starting with foo')
|
||||||
|
print(cmd .. '-b foo bar # replace foo with bar in cwd and cd there')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -2727,4 +2990,5 @@ if not pcall(debug.getlocal, 4, 1) then
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- vim: set ts=4 sw=4 tw=0 noet :
|
||||||
|
|
||||||
|
|||||||
@@ -2,19 +2,18 @@
|
|||||||
|
|
||||||
ZLUA_SCRIPT="${0:A:h}/z.lua"
|
ZLUA_SCRIPT="${0:A:h}/z.lua"
|
||||||
|
|
||||||
[[ -n "$ZLUA_EXEC" ]] && [[ ! -x "$ZLUA_EXEC" ]] && ZLUA_EXEC=""
|
if [[ -n "$ZLUA_EXEC" ]] && ! which "$ZLUA_EXEC" &>/dev/null; then
|
||||||
|
echo "$ZLUA_EXEC not found"
|
||||||
|
ZLUA_EXEC=""
|
||||||
|
fi
|
||||||
|
|
||||||
# search lua executable
|
# search lua executable
|
||||||
if [[ -z "$ZLUA_EXEC" ]]; then
|
if [[ -z "$ZLUA_EXEC" ]]; then
|
||||||
if [[ -x "$(command which lua)" ]]; then
|
for lua in lua luajit lua5.4 lua5.3 lua5.2 lua5.1; do
|
||||||
ZLUA_EXEC="$(command which lua)"
|
ZLUA_EXEC="$(command -v "$lua")"
|
||||||
elif [[ -x "$(command which lua5.3)" ]]; then
|
[[ -n "$ZLUA_EXEC" ]] && break
|
||||||
ZLUA_EXEC="$(command which lua5.3)"
|
done
|
||||||
elif [[ -x "$(command which lua5.2)" ]]; then
|
if [[ -z "$ZLUA_EXEC" ]]; then
|
||||||
ZLUA_EXEC="$(command which lua5.2)"
|
|
||||||
elif [[ -x "$(command which lua5.1)" ]]; then
|
|
||||||
ZLUA_EXEC="$(command which lua5.1)"
|
|
||||||
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
|
||||||
@@ -22,7 +21,11 @@ fi
|
|||||||
|
|
||||||
export _ZL_FZF_FLAG=${_ZL_FZF_FLAG:-"-e"}
|
export _ZL_FZF_FLAG=${_ZL_FZF_FLAG:-"-e"}
|
||||||
|
|
||||||
eval "$($ZLUA_EXEC $ZLUA_SCRIPT --init zsh once enhanced)"
|
if [[ -z "$_ZL_ZSH_NO_FZF" ]]; then
|
||||||
|
eval "$($ZLUA_EXEC $ZLUA_SCRIPT --init zsh once enhanced fzf)"
|
||||||
|
else
|
||||||
|
eval "$($ZLUA_EXEC $ZLUA_SCRIPT --init zsh once enhanced)"
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ -z "$_ZL_NO_ALIASES" ]]; then
|
if [[ -z "$_ZL_NO_ALIASES" ]]; then
|
||||||
alias zz='z -i'
|
alias zz='z -i'
|
||||||
|
|||||||