mirror of
https://github.com/skywind3000/z.lua
synced 2026-03-22 23:59:48 +00:00
Compare commits
73 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
65bfbf8dfb | ||
|
|
1b9630e72d | ||
|
|
c98d2d783e | ||
|
|
057e4f77f3 | ||
|
|
8a90ca6df4 | ||
|
|
a4c51d8103 | ||
|
|
b40df870a6 | ||
|
|
a55bb87e1b | ||
|
|
c4512b47d2 | ||
|
|
6c567b60b3 | ||
|
|
8fff9e6471 | ||
|
|
f7a9104983 | ||
|
|
7b43a0afd6 | ||
|
|
788c0f4b77 | ||
|
|
47aa86b0f9 | ||
|
|
a1498c8672 | ||
|
|
4c34e29e08 | ||
|
|
3d188ab6d9 | ||
|
|
a5f4cb692c | ||
|
|
77a917d116 | ||
|
|
93e9715e7d | ||
|
|
b7c3fbc4ee | ||
|
|
ebda4aa061 | ||
|
|
168ec49849 | ||
|
|
ec123de01a | ||
|
|
a0d4750431 | ||
|
|
d615051a10 | ||
|
|
f448f2ab1f | ||
|
|
8ed3422670 | ||
|
|
3edbda89a0 | ||
|
|
c9b50b3c50 | ||
|
|
228addbc49 | ||
|
|
bca25eba12 | ||
|
|
097ca07ecd | ||
|
|
4ee783956d | ||
|
|
0effba4021 | ||
|
|
cada42e5ea | ||
|
|
b8b6d1afd6 | ||
|
|
4abe97f989 | ||
|
|
756d13d8fa | ||
|
|
4900651af3 | ||
|
|
836efd3973 | ||
|
|
3b8b4c1fbb | ||
|
|
8eaebca04a | ||
|
|
fdd037acf8 | ||
|
|
a817cf6ed2 | ||
|
|
5c36d55698 | ||
|
|
bdab27db1b | ||
|
|
e08f5beca4 | ||
|
|
a245db0d93 | ||
|
|
dd721703c3 | ||
|
|
7920d56c89 | ||
|
|
645818ccc8 | ||
|
|
b98911a227 | ||
|
|
671830059b | ||
|
|
0fad96124b | ||
|
|
465f2b8e62 | ||
|
|
ff9d874ef4 | ||
|
|
86120d206e | ||
|
|
1e0e3523b0 | ||
|
|
7eee4e4b13 | ||
|
|
edd71f7a6e | ||
|
|
f63a832921 | ||
|
|
f92ad79e2c | ||
|
|
38c1741f4f | ||
|
|
fdff5c5e1e | ||
|
|
b691d537f2 | ||
|
|
472925ac92 | ||
|
|
5ba0e50894 | ||
|
|
c769dba4dd | ||
|
|
bbca83c9a5 | ||
|
|
53c127a4a2 | ||
|
|
5f7fa928b6 |
18
README.cn.md
18
README.cn.md
@@ -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
|
||||||
|
|
||||||
@@ -175,7 +176,7 @@ 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"` 可以打更少的字。
|
||||||
|
|
||||||
@@ -269,7 +270,7 @@ PS:你可以使用 `$_ZL_FZF` 环境变量来精确指明 fzf 的可执行路
|
|||||||
- **(单个参数)**:`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 进行历史路径操作了:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
第一列数据代表该路径多少秒以前访问过,第二列是路径名称。此时,你可以试着敲几个字母,用 fzf 的字符串模糊匹配进行定位,或者用光标键的上和下(CTRL+J/K 也可以)来上下移动,最后按回车 cd 过去,或者 ESC 放弃。
|
第一列上次访问距今多少秒,第二列是目录名。你可以试着敲几个字母,用 fzf 的字符串模糊匹配进行定位,或者用光标键的上和下(CTRL+J/K 也可以)来上下移动,最后按回车 cd 过去,或者 ESC 放弃。
|
||||||
|
|
||||||
注意:最好把增强匹配模式打开,这样查看历史路径时可以把当前路径过滤掉。
|
|
||||||
|
|
||||||
|
|
||||||
## Tips
|
## Tips
|
||||||
|
|||||||
48
README.md
48
README.md
@@ -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. I’m 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. I’m 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.
|
||||||
|
|
||||||
|
|||||||
@@ -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
91
ranger_zlua.py
Normal 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
396
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
|
-- 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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user