mirror of
https://github.com/skywind3000/z.lua
synced 2026-04-20 22:01:29 +00:00
Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
68de23ecef | ||
|
|
5ea08c5dac | ||
|
|
9dd0fec7ed | ||
|
|
fe11dd30c5 | ||
|
|
db92fa0a1c | ||
|
|
b1702839d2 | ||
|
|
1a0428f54e | ||
|
|
31e9d42d08 | ||
|
|
14b942634c | ||
|
|
6cfe2150e9 | ||
|
|
a4c589a724 | ||
|
|
cb8021599c | ||
|
|
91a4d75e62 | ||
|
|
4d4dc8802b | ||
|
|
761b3ebf31 | ||
|
|
4e7ecde314 | ||
|
|
e5c78e3087 | ||
|
|
1fb4f25744 | ||
|
|
6057644adb | ||
|
|
dc02feb424 |
@@ -250,7 +250,9 @@ PS:如果你使用 Fish shell,需要 2.7.0 以上才支持该功能。
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
当你使用 `"z -I vim"` 时,12 条路径被筛选出来,并按照 frecent 排序,他们都包含 "vim" 关键字,在实际 cd 改变路径前,z.lua 会调用 fzf 来让你更方便的选择你想去的地方,每条记录包含左边的 frecent 权重和右边的路径名,权重越高的排在越前面,你可以按回车选择,或者 ESC 退出。
|
当你使用 `"z -I vim"` 时,12 条路径被筛选出来,并按照 frecent 排序,他们都包含 "vim" 关键字,在实际 cd 改变路径前,z.lua 会调用 fzf 来让你更方便的选择你想去的地方,每条记录包含左边的 frecent 权重和右边的路径名,权重越高的排在越前面。
|
||||||
|
|
||||||
|
你可以在 fzf 里输入一些**空格分隔**的关键字(不需要先后顺序),或者按 `CTRL+J` / `CTRL+K` (方向键的上下也可以)进行选择,`ESC` 或者 `CTRL`+`D`/`G` 放弃。
|
||||||
|
|
||||||
你仍然可以用老方法,通过在 `z` 命令后面添加更多关键词来精确的匹配你想去的地方,这个特性给了你一个可视化的方式来做这件事情。为了方便起见,通常把 `z -I` alias 成 `zf` (z + fuzzy finder)。如果搜索结果只有一项,那么 z.lua 会直接跳转过去,不需要启动 fzf 再选择一遍,只有多项结果要选择时,才会启动 fzf。
|
你仍然可以用老方法,通过在 `z` 命令后面添加更多关键词来精确的匹配你想去的地方,这个特性给了你一个可视化的方式来做这件事情。为了方便起见,通常把 `z -I` alias 成 `zf` (z + fuzzy finder)。如果搜索结果只有一项,那么 z.lua 会直接跳转过去,不需要启动 fzf 再选择一遍,只有多项结果要选择时,才会启动 fzf。
|
||||||
|
|
||||||
|
|||||||
27
README.md
27
README.md
@@ -24,7 +24,6 @@ For example, `z foo bar` would match `/foo/bar` but not `/bar/foo`.
|
|||||||
- 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.
|
- Intergrated 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 ../../..".
|
||||||
- Cooperate with [fz](https://github.com/changyuheng/fz) to provide better completion, see [FAQ](https://github.com/skywind3000/z.lua/wiki/FAQ#fzsh-for-better-completion).
|
|
||||||
- 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+
|
||||||
- Self contained, distributed as a single `z.lua` script, no other dependence.
|
- Self contained, distributed as a single `z.lua` script, no other dependence.
|
||||||
@@ -35,7 +34,7 @@ For example, `z foo bar` would match `/foo/bar` but not `/bar/foo`.
|
|||||||
```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 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
|
||||||
@@ -220,14 +219,14 @@ If no match is found, it will fall back to default matching method.
|
|||||||
|
|
||||||
- Skip the current directory:
|
- Skip the current directory:
|
||||||
|
|
||||||
when you are calling `z xxx` but the best match is the current directory, z.lua will choose the 2nd best match result for you. Assuming the database:
|
When you are calling `z xxx` but the best match is the current directory, z.lua will choose the 2nd best match result for you. Assuming the database:
|
||||||
|
|
||||||
10 /Users/Great_Wall/.rbenv/versions/2.4.1/lib/ruby/gems
|
10 /Users/Great_Wall/.rbenv/versions/2.4.1/lib/ruby/gems
|
||||||
20 /Library/Ruby/Gems/2.0.0/gems
|
20 /Library/Ruby/Gems/2.0.0/gems
|
||||||
|
|
||||||
When I use `z gems` by default, it will take me to `/Library/Ruby/Gems/2.0.0/gems`, but it's not what I want, so I press up arrow and execute `z gems` again, it will take me to `/Users/Great_Wall/.rbenv/versions/2.4.1/lib/ruby/gems` and this what I want.
|
When I use `z gems` by default, it will take me to `/Library/Ruby/Gems/2.0.0/gems`, but it's not what I want, so I press up arrow and execute `z gems` again, it will take me to `/Users/Great_Wall/.rbenv/versions/2.4.1/lib/ruby/gems` and this what I want.
|
||||||
|
|
||||||
Of course I can always use `z env gems` to indicate what I want precisely. Skip the current directory means when you use `z xxx` you always want to change directory instead of stay in the same directory and do nothing if current directory is the best match.
|
Of course, I can always use `z env gems` to indicate what I want precisely. Skip the current directory means when you use `z xxx` you always want to change directory instead of stay in the same directory and do nothing if current directory is the best match.
|
||||||
|
|
||||||
The default matching method is designed to be compatible with original z.sh, but the enhanced matching method is much more handy and exclusive to z.lua.
|
The default matching method is designed to be compatible with original z.sh, but the enhanced matching method is much more handy and exclusive to z.lua.
|
||||||
|
|
||||||
@@ -236,7 +235,7 @@ The default matching method is designed to be compatible with original z.sh, but
|
|||||||
|
|
||||||
By default, z.lua will add current directory to database each time before display command prompt (correspond with z.sh). But there is an option to allow z.lua add path only if current working directory changed.
|
By default, z.lua will add current directory to database each time before display command prompt (correspond with z.sh). But there is an option to allow z.lua add path only if current working directory changed.
|
||||||
|
|
||||||
To enable this, you can set `$_ZL_ADD_ONCE` to `1` before init z.lua. Or you can init z.lua on linux like this:
|
To enable this, you can set `$_ZL_ADD_ONCE` to `1` before init z.lua. Or you can initialize z.lua on linux like this:
|
||||||
|
|
||||||
````bash
|
````bash
|
||||||
eval "$(lua /path/to/z.lua --init bash once)"
|
eval "$(lua /path/to/z.lua --init bash once)"
|
||||||
@@ -270,13 +269,15 @@ From version 1.1.0, a new option `"-I"` will allow you to use fzf to select when
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
When we use `"z -I vim"`,12 paths contains keyword "vim" has been matched and ordered by their frecent value, the higher frecent comes with the higher rank. Then without cd to the highest ranked path, z.lua passes all the candidates to fzf. And you can use fzf to select where you want to go, or ESC to quit.
|
When we use `"z -I vim"`,12 paths contains keyword "vim" has been matched and ordered by their frecent value, the higher frecent comes with the higher rank. Then without cd to the highest ranked path, z.lua passes all the candidates to fzf.
|
||||||
|
|
||||||
|
Now you can input some space separated keywords (no order required) or use `CTRL+J`/`CTRL+K` (same as `UP`/`DOWN`) to select where you want to go, or `ESC` / `CTRL`+`D`/`G` to give up.
|
||||||
|
|
||||||
Of course, you can always give more keywords to `z` command to match your destination precisely. `"z -I"` is similar to `"z -i"`, but use fzf. Both `"-i"` and `"-I"` provide you another way for path navigation.
|
Of course, you can always give more keywords to `z` command to match your destination precisely. `"z -I"` is similar to `"z -i"`, but use fzf. Both `"-i"` and `"-I"` provide you another way for path navigation.
|
||||||
|
|
||||||
Usually, `z -I` can be aliased to `zf` (z + fuzzy finder) for convenience. If there are only one path matched, `z -I` will jump to it directly, fzf will only be invoked for multiple matches.
|
Usually, `z -I` can be aliased to `zf` (z + fuzzy finder) for convenience. If there are only one path matched, `z -I` will jump to it directly, fzf will only be invoked for multiple matches. `"z -I ."` or `"zf ."` can be used to use fzf select from entire database.
|
||||||
|
|
||||||
`"z -I ."` or `"zf ."` can be used to use fzf select from entire database. Environment variable `_ZL_FZF_FLAG` is for passing additional arguments to fzf.
|
For more information about this, please visit [wiki - effective with fzf](https://github.com/skywind3000/z.lua/wiki/Effective-with-fzf).
|
||||||
|
|
||||||
NOTE: For fish shell, this feature requires fish 2.7.0 or above. You can specify fzf executable in `$_ZL_FZF` environment variable, `"fzf"` will be called by default.
|
NOTE: For fish shell, this feature requires fish 2.7.0 or above. You can specify fzf executable in `$_ZL_FZF` environment variable, `"fzf"` will be called by default.
|
||||||
|
|
||||||
@@ -285,8 +286,8 @@ NOTE: For fish shell, this feature requires fish 2.7.0 or above. You can specify
|
|||||||
|
|
||||||
New option `"-b"` can quickly go back to a specific parent directory in bash instead of typing "cd ../../.." redundantly.
|
New option `"-b"` can quickly go back to a specific parent directory in bash instead of typing "cd ../../.." redundantly.
|
||||||
|
|
||||||
- **(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, goto 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).
|
||||||
|
|
||||||
Let's start by aliasing `z -b` to `zb`:
|
Let's start by aliasing `z -b` to `zb`:
|
||||||
@@ -419,7 +420,7 @@ Don't forget to read the [Frequently Asked Questions](https://github.com/skywind
|
|||||||
|
|
||||||
## Benchmark
|
## Benchmark
|
||||||
|
|
||||||
The slowest part is adding path to history data file. It will run every time when you press enter (installed in $PROMPT_COMMAND). so I profile it on my nas:
|
The slowest part is adding path to history data file. It will run every time when you press enter (installed in $PROMPT_COMMAND). So I profile it on my NAS:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ time autojump --add /tmp
|
$ time autojump --add /tmp
|
||||||
@@ -457,6 +458,10 @@ As you see, z.lua is the fastest one and requires less resource.
|
|||||||
|
|
||||||
## History
|
## History
|
||||||
|
|
||||||
|
- 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.5 (2019-02-20): `$_ZL_FZF_FLAG` can be used to override fzf flags, default to "+s -e".
|
||||||
|
- 1.5.4 (2019-02-19): fixed: file/path existence detection fails on read-only fs (closed [#49](https://github.com/skywind3000/z.lua/issues/49) by [@contrun](https://github.com/contrun)).
|
||||||
- 1.5.3 (2019-02-17): new `$_ZL_FZF_FLAG` for passing additional flags to fzf, add `-e` argument to fzf.
|
- 1.5.3 (2019-02-17): new `$_ZL_FZF_FLAG` for passing additional flags to fzf, add `-e` argument to fzf.
|
||||||
- 1.5.2 (2019-02-16): be aware of all arguments in fzf completion.
|
- 1.5.2 (2019-02-16): be aware of all arguments in fzf completion.
|
||||||
- 1.5.1 (2019-02-15): new: simulated dir stack by `z -`, `z --` and `z -{num}`.
|
- 1.5.1 (2019-02-15): new: simulated dir stack by `z -`, `z --` and `z -{num}`.
|
||||||
|
|||||||
BIN
images/step1.png
Normal file
BIN
images/step1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
BIN
images/step2.png
Normal file
BIN
images/step2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
BIN
images/step3.png
Normal file
BIN
images/step3.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.6 KiB |
BIN
images/step4.png
Normal file
BIN
images/step4.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.8 KiB |
51
z.lua
51
z.lua
@@ -4,7 +4,7 @@
|
|||||||
-- z.lua - a cd command that learns, by skywind 2018, 2019
|
-- z.lua - a cd command that learns, by skywind 2018, 2019
|
||||||
-- Licensed under MIT license.
|
-- Licensed under MIT license.
|
||||||
--
|
--
|
||||||
-- Version 1.5.3, Last Modified: 2019/02/17 16:22
|
-- Version 1.5.7, Last Modified: 2019/02/21 11:07
|
||||||
--
|
--
|
||||||
-- * 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
|
||||||
@@ -158,6 +158,10 @@ function string:startswith(text)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function string:endswith(text)
|
||||||
|
return text == "" or self:sub(-#text) == text
|
||||||
|
end
|
||||||
|
|
||||||
function string:lstrip()
|
function string:lstrip()
|
||||||
if self == nil then return nil end
|
if self == nil then return nil end
|
||||||
local s = self:gsub('^%s+', '')
|
local s = self:gsub('^%s+', '')
|
||||||
@@ -418,6 +422,8 @@ end
|
|||||||
function os.path.isdir(pathname)
|
function os.path.isdir(pathname)
|
||||||
if pathname == '/' then
|
if pathname == '/' then
|
||||||
return true
|
return true
|
||||||
|
elseif pathname == '' then
|
||||||
|
return false
|
||||||
elseif windows then
|
elseif windows then
|
||||||
if pathname == '\\' then
|
if pathname == '\\' then
|
||||||
return true
|
return true
|
||||||
@@ -425,15 +431,11 @@ function os.path.isdir(pathname)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local name = pathname .. '/'
|
local name = pathname
|
||||||
local ok, err, code = os.rename(name, name)
|
if (not name:endswith('/')) and (not name:endswith('\\')) then
|
||||||
if not ok then
|
name = name .. '/'
|
||||||
if code == 13 then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
end
|
||||||
return true
|
return os.path.exists(name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -445,6 +447,12 @@ function os.path.exists(name)
|
|||||||
if not ok then
|
if not ok then
|
||||||
if code == 13 then
|
if code == 13 then
|
||||||
return true
|
return true
|
||||||
|
elseif code == 30 then
|
||||||
|
local f = io.open(name,"r")
|
||||||
|
if f ~= nil then
|
||||||
|
io.close(f)
|
||||||
|
return true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
@@ -762,6 +770,10 @@ end
|
|||||||
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
function os.environ(name, default)
|
function os.environ(name, default)
|
||||||
local value = os.getenv(name)
|
local value = os.getenv(name)
|
||||||
|
if os.envmap ~= nil and type(os.envmap) == 'table' then
|
||||||
|
local t = os.envmap[name]
|
||||||
|
value = (t ~= nil and type(t) == 'string') and t or value
|
||||||
|
end
|
||||||
if value == nil then
|
if value == nil then
|
||||||
return default
|
return default
|
||||||
elseif type(default) == 'boolean' then
|
elseif type(default) == 'boolean' then
|
||||||
@@ -1266,13 +1278,14 @@ function z_match(patterns, method, subdir)
|
|||||||
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)
|
||||||
|
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)
|
||||||
|
N = data_filter(N)
|
||||||
if #N > 0 then
|
if #N > 0 then
|
||||||
M = N
|
M = N
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
M = data_filter(M)
|
|
||||||
M = data_update_frecent(M)
|
M = data_update_frecent(M)
|
||||||
if method == 'time' then
|
if method == 'time' then
|
||||||
current = os.time()
|
current = os.time()
|
||||||
@@ -1325,7 +1338,7 @@ end
|
|||||||
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
function z_print(M, weight, number)
|
function z_print(M, weight, number)
|
||||||
local N = {}
|
local N = {}
|
||||||
local maxsize = 10
|
local maxsize = 9
|
||||||
local numsize = string.len(tostring(#M))
|
local numsize = string.len(tostring(#M))
|
||||||
for _, item in pairs(M) do
|
for _, item in pairs(M) do
|
||||||
local record = {}
|
local record = {}
|
||||||
@@ -1418,6 +1431,9 @@ function z_cd(patterns)
|
|||||||
elseif Z_INTERACTIVE == 0 then
|
elseif Z_INTERACTIVE == 0 then
|
||||||
return M[1].name
|
return M[1].name
|
||||||
end
|
end
|
||||||
|
if os.environ('_ZL_INT_SORT', false) then
|
||||||
|
table.sort(M, function (a, b) return a.name < b.name end)
|
||||||
|
end
|
||||||
local retval = nil
|
local retval = nil
|
||||||
if Z_INTERACTIVE == 1 then
|
if Z_INTERACTIVE == 1 then
|
||||||
PRINT_MODE = '<stderr>'
|
PRINT_MODE = '<stderr>'
|
||||||
@@ -1439,9 +1455,10 @@ 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 +s --tac -e'
|
local cmd = '--nth 2.. --reverse --inline-info --tac '
|
||||||
cmd = ((fzf == '') and 'fzf' or fzf) .. ' ' .. cmd
|
local flag = os.environ('_ZL_FZF_FLAG', '')
|
||||||
cmd = cmd .. ' ' .. 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
|
if not windows then
|
||||||
tmpname = os.tmpname()
|
tmpname = os.tmpname()
|
||||||
if not os.environ('_ZL_FZF_FULLSCR', false) then
|
if not os.environ('_ZL_FZF_FULLSCR', false) then
|
||||||
@@ -1987,11 +2004,13 @@ 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 +s --tac -e"
|
fzf_cmd = "fzf --nth 2.. --reverse --inline-info --tac "
|
||||||
if not os.environ('_ZL_FZF_FULLSCR', false) then
|
if not os.environ('_ZL_FZF_FULLSCR', false) then
|
||||||
fzf_cmd = fzf_cmd .. ' --height 35%'
|
fzf_cmd = fzf_cmd .. ' --height 35%'
|
||||||
end
|
end
|
||||||
fzf_cmd = fzf_cmd .. ' ' .. os.environ('_ZL_FZF_FLAG', '') .. ' '
|
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('zlua_fzf="' .. fzf_cmd .. '"')
|
||||||
print(script_fzf_complete_bash)
|
print(script_fzf_complete_bash)
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user