mirror of
https://github.com/skywind3000/z.lua
synced 2026-03-22 07:39:48 +00:00
Compare commits
46 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3deb8c7b5c | ||
|
|
222b28571f | ||
|
|
48a77adf35 | ||
|
|
72c3676344 | ||
|
|
9dc5875fa3 | ||
|
|
c90279b677 | ||
|
|
9fb8cadda3 | ||
|
|
edd92d935d | ||
|
|
7848a0a2f3 | ||
|
|
515da0a3d1 | ||
|
|
aebd18cec4 | ||
|
|
90223cf10b | ||
|
|
d666c93ed9 | ||
|
|
805e5c24f3 | ||
|
|
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 |
31
README.md
31
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`.
|
||||
|
||||
## 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
|
||||
|
||||
- **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 Fish Shell, Power Shell and Windows cmd.
|
||||
- [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.
|
||||
- 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 ../../..".
|
||||
- Corresponding experience in different shells and operating systems.
|
||||
- Compatible with Lua 5.1, 5.2 and 5.3+
|
||||
@@ -132,6 +142,7 @@ z -b foo # cd to the parent directory starting with foo
|
||||
- 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_HYPHEN` to 1 to treat hyphon (-) as a normal character not a lua regexp keyword.
|
||||
- set `$_ZL_CLINK_PROMPT_PRIORITY` change clink prompt register priority (default 99).
|
||||
|
||||
## Aging
|
||||
|
||||
@@ -448,18 +459,26 @@ sys 0m0.030s
|
||||
|
||||
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
|
||||
|
||||
- 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-).
|
||||
|
||||
@@ -17,7 +17,12 @@ end
|
||||
|
||||
set -x _ZL_DATA "$_ZL_DATA"
|
||||
|
||||
set _zlua_dir (dirname (status --current-filename))
|
||||
set -q XDG_DATA_HOME; or set XDG_DATA_HOME ~/.local/share
|
||||
if functions -q fisher
|
||||
set _zlua_dir $XDG_DATA_HOME/fisher/github.com/skywind3000/z.lua
|
||||
else
|
||||
set _zlua_dir (dirname (status --current-filename))
|
||||
end
|
||||
|
||||
if test -e $_zlua_dir/z.lua
|
||||
if type -q lua
|
||||
|
||||
@@ -69,14 +69,10 @@ class z(ranger.api.commands.Command):
|
||||
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')
|
||||
p = self.fm.execute_command(cmd, universal_newlines=True, stdout=subprocess.PIPE)
|
||||
stdout, stderr = p.communicate()
|
||||
path = stdout.rstrip('\n')
|
||||
self.fm.execute_console('redraw_window')
|
||||
if path and os.path.exists(path):
|
||||
self.fm.cd(path)
|
||||
else:
|
||||
|
||||
6
z.cmd
6
z.cmd
@@ -54,6 +54,12 @@ if /i "%1"=="-x" (
|
||||
goto parse
|
||||
)
|
||||
|
||||
if /i "%1"=="--add" (
|
||||
set "RunMode=--add"
|
||||
shift /1
|
||||
goto parse
|
||||
)
|
||||
|
||||
if "%1"=="-i" (
|
||||
set "InterMode=-i"
|
||||
shift /1
|
||||
|
||||
84
z.lua
84
z.lua
@@ -4,7 +4,7 @@
|
||||
-- z.lua - a cd command that learns, by skywind 2018, 2019, 2020
|
||||
-- Licensed under MIT license.
|
||||
--
|
||||
-- Version 1.8.4, Last Modified: 2020/02/10 19:22
|
||||
-- Version 1.8.9, Last Modified: 2020/12/23 16:37
|
||||
--
|
||||
-- * 10x faster than fasd and autojump, 3x faster than z.sh
|
||||
-- * available for posix shells: bash, zsh, sh, ash, dash, busybox
|
||||
@@ -319,14 +319,16 @@ if os.native.status then
|
||||
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[?]', 300)
|
||||
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, 290, buffer, nil)
|
||||
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)
|
||||
@@ -339,6 +341,21 @@ if os.native.status then
|
||||
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
|
||||
@@ -352,7 +369,7 @@ if os.native.status then
|
||||
return (attr % (2 * isdir)) >= isdir
|
||||
end
|
||||
function os.native.getcwd()
|
||||
local hr = kernel32.GetCurrentDirectoryA(299, buffer)
|
||||
local hr = kernel32.GetCurrentDirectoryA(4096, buffer)
|
||||
if hr <= 0 then return nil end
|
||||
return ffi.string(buffer, hr)
|
||||
end
|
||||
@@ -554,6 +571,9 @@ 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)
|
||||
if not ok then
|
||||
if code == 13 then
|
||||
@@ -1357,6 +1377,14 @@ function z_add(path)
|
||||
end
|
||||
end
|
||||
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)
|
||||
count = count + 1
|
||||
end
|
||||
@@ -1927,6 +1955,8 @@ function main(argv)
|
||||
z_windows_init(opts)
|
||||
elseif opts.fish then
|
||||
z_fish_init(opts)
|
||||
elseif opts.powershell then
|
||||
z_windows_init(opts)
|
||||
else
|
||||
z_shell_init(opts)
|
||||
end
|
||||
@@ -2029,6 +2059,7 @@ end
|
||||
-----------------------------------------------------------------------
|
||||
function z_clink_init()
|
||||
local once = os.environ("_ZL_ADD_ONCE", false)
|
||||
local _zl_clink_prompt_priority = os.environ('_ZL_CLINK_PROMPT_PRIORITY', 99)
|
||||
local previous = ''
|
||||
function z_add_to_database()
|
||||
pwd = clink.get_cwd()
|
||||
@@ -2040,7 +2071,7 @@ function z_clink_init()
|
||||
end
|
||||
z_add(clink.get_cwd())
|
||||
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)
|
||||
local M = z_match({word}, Z_METHOD, Z_SUBDIR)
|
||||
for _, item in pairs(M) do
|
||||
@@ -2201,16 +2232,16 @@ fi
|
||||
local script_complete_zsh = [[
|
||||
_zlua_zsh_tab_completion() {
|
||||
# tab completion
|
||||
local compl
|
||||
read -l compl
|
||||
(( $+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
|
||||
----------------------------------------------------------------------
|
||||
@@ -2231,6 +2262,10 @@ function z_shell_init(opts)
|
||||
local prompt_hook = (not os.environ("_ZL_NO_PROMPT_COMMAND", false))
|
||||
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 prompt_hook then
|
||||
if once then
|
||||
@@ -2400,11 +2435,17 @@ function z_fish_init(opts)
|
||||
print('set -x ZLUA_SCRIPT "' .. os.scriptname() .. '"')
|
||||
print('set -x ZLUA_LUAEXE "' .. os.interpreter() .. '"')
|
||||
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)
|
||||
if once then
|
||||
print(script_init_fish_once)
|
||||
else
|
||||
print(script_init_fish)
|
||||
if prompt_hook then
|
||||
if once then
|
||||
print(script_init_fish_once)
|
||||
else
|
||||
print(script_init_fish)
|
||||
end
|
||||
end
|
||||
print(script_complete_fish)
|
||||
if opts.enhanced ~= nil then
|
||||
@@ -2462,6 +2503,11 @@ if /i "%1"=="-x" (
|
||||
shift /1
|
||||
goto parse
|
||||
)
|
||||
if /i "%1"=="--add" (
|
||||
set "RunMode=--add"
|
||||
shift /1
|
||||
goto parse
|
||||
)
|
||||
if "%1"=="-i" (
|
||||
set "InterMode=-i"
|
||||
shift /1
|
||||
@@ -2594,6 +2640,10 @@ if (!$env:_ZL_NO_PROMPT_COMMAND -and (!$global:_zlua_inited)) {
|
||||
-- initialize cmd/powershell
|
||||
-----------------------------------------------------------------------
|
||||
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
|
||||
print('$script:ZLUA_LUAEXE = "' .. os.interpreter() .. '"')
|
||||
print('$script:ZLUA_SCRIPT = "' .. os.scriptname() .. '"')
|
||||
@@ -2610,7 +2660,9 @@ function z_windows_init(opts)
|
||||
if opts.nc ~= nil then
|
||||
print('$env:_ZL_NO_CHECK = 1')
|
||||
end
|
||||
print(script_init_powershell)
|
||||
if prompt_hook then
|
||||
print(script_init_powershell)
|
||||
end
|
||||
else
|
||||
print('@echo off')
|
||||
print('setlocal EnableDelayedExpansion')
|
||||
@@ -2648,6 +2700,7 @@ end
|
||||
-----------------------------------------------------------------------
|
||||
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
|
||||
@@ -2683,4 +2736,3 @@ if not pcall(debug.getlocal, 4, 1) then
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -6,15 +6,11 @@ ZLUA_SCRIPT="${0:A:h}/z.lua"
|
||||
|
||||
# search lua executable
|
||||
if [[ -z "$ZLUA_EXEC" ]]; then
|
||||
if [[ -x "$(command which lua)" ]]; then
|
||||
ZLUA_EXEC="$(command which lua)"
|
||||
elif [[ -x "$(command which lua5.3)" ]]; then
|
||||
ZLUA_EXEC="$(command which lua5.3)"
|
||||
elif [[ -x "$(command which lua5.2)" ]]; then
|
||||
ZLUA_EXEC="$(command which lua5.2)"
|
||||
elif [[ -x "$(command which lua5.1)" ]]; then
|
||||
ZLUA_EXEC="$(command which lua5.1)"
|
||||
else
|
||||
for lua in lua lua5.3 lua5.2 lua5.1; do
|
||||
ZLUA_EXEC="$(command -v "$lua")"
|
||||
[[ -n "$ZLUA_EXEC" ]] && break
|
||||
done
|
||||
if [[ -z "$ZLUA_EXEC" ]]; then
|
||||
echo "Not find lua in your $PATH, please install it."
|
||||
return
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user