Coder Social home page Coder Social logo

skywind3000 / z.lua Goto Github PK

View Code? Open in Web Editor NEW
2.9K 36.0 136.0 1.03 MB

:zap: A new cd command that helps you navigate faster by learning your habits.

License: MIT License

Lua 90.38% Batchfile 2.33% Shell 2.91% Python 4.37%
autojump bash fasd z cd jump zsh fishshell zsh-plugin shell

z.lua's Introduction

z.lua

A command line tool which helps you navigate faster by learning your habits ⚡

An alternative to z.sh with windows and posix shells support and various improvements.

README in Chinese | 中文文档

Description

z.lua is a faster way to navigate your filesystem. It tracks your most used directories, based on 'frecency'. After a short learning phase, z will take you to the most 'frecent' directory that matches ALL of the regexes given on the command line, in order.

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 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 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.
  • 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, 5.3+) and luajit.
  • Self contained, distributed as a single z.lua script, no other dependence.

Examples

z foo        # cd to most frecent dir matching foo
z foo bar    # cd to most frecent dir matching foo and bar
z -r foo     # cd to the highest ranked dir matching foo
z -t foo     # cd to most recently accessed dir matching foo
z -l foo     # list matches instead of cd
z -c foo     # restrict matches to subdirs of $PWD
z -e foo     # echo the best match, don't cd
z -i foo     # cd with interactive selection
z -I foo     # cd with interactive selection using fzf
z -b foo     # cd to the parent directory starting with foo
z -b foo bar # replace foo with bar in cwd and cd there

Install

  • Fig (works with all shells)

    Fig adds apps, shortcuts, and autocomplete to your existing terminal.

    Install z.lua in just one click.

  • Bash:

    put something like this in your .bashrc:

    eval "$(lua /path/to/z.lua --init bash)"
    

    the default matching algorithm is similar to z.sh to keep compatible, you may like the enhanced matching algorithm for productivity:

    eval "$(lua /path/to/z.lua --init bash enhanced once)"
    

    and perhaps this:

    eval "$(lua /path/to/z.lua --init bash enhanced once echo)"
    

    if you want z.lua print the new directory after cd.

    For fzf tab completion use:

    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.

  • Zsh:

    put something like this in your .zshrc:

    eval "$(lua /path/to/z.lua --init 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:

    put something like this in your .profile:

    eval "$(lua /path/to/z.lua --init posix)"
    

    For old shells like ksh (Korn Shell), some features are missing, you can try:

    eval "$(lua /path/to/z.lua --init posix legacy)"
    

    To generate old posix compatible script.

  • Fish Shell (version 2.4.0 or above):

    Create ~/.config/fish/conf.d/z.fish with following code

    lua /path/to/z.lua --init fish | source
    

    If you'd like z.lua to cooperate with fish's own directory history, you can put

    set -gx _ZL_CD cd
    

    into the same file.

  • Power Shell:

    ⚠️ WARNING: users of Starship Prompt should add the following command after starship init.

    put something like this in your profile.ps1:

    Invoke-Expression (& { (lua /path/to/z.lua --init powershell) -join "`n" })
    
  • Windows cmd (with clink):

    • Copy z.lua and z.cmd to clink's home directory
    • Add clink's home to %PATH% (z.cmd can be called anywhere)
    • Ensure that "lua" can be called in %PATH%
  • Windows cmder:

    • Copy z.lua and z.cmd to cmder/vendor
    • Add cmder/vendor to %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.

Options

  • 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_NO_PROMPT_COMMAND if you're handling PROMPT_COMMAND yourself.
  • 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_MAXAGE to define a aging threshold (default is 5000).
  • 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_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 0 to treat a hyphen (-) as a lua regexp special character, 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

The rank of directories maintained by z.lua undergoes aging based on a simple formula. The rank of each entry is incremented every time it is accessed. When the sum of ranks is over 5000 ($_ZL_MAXAGE), all ranks are multiplied by 0.9. Entries with a rank lower than 1 are forgotten.

Frecency

Frecency is a portmanteau of 'recent' and 'frequency'. It is a weighted rank that depends on how often and how recently something occurred. As far as I know, Mozilla came up with the term.

To z.lua, a directory that has low ranking but has been accessed recently will quickly have higher rank than a directory accessed frequently a long time ago. Frecency is determined at runtime.

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.

  • cd to a directory contains foo:

    z foo
    
  • use multiple arguments:

    Assuming the following database:

    10   /home/user/work/inbox
    30   /home/user/mail/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:

    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.

Enhanced Matching

Enhanced matching can be enabled by exporting the environment:

export _ZL_MATCH_MODE=1

Or, append a enhanced after --init xxx:

eval "$(lua /path/to/z.lua --init bash enhanced)"

For a given set of queries (the set of command-line arguments passed to z.lua), a path is a match if and only if:

  1. Queries match the path in order (same as default method).
  2. The last query matches the last segment of the path.

If no match is found, it will fall back to default matching method.

  • match the last segment of the path:

    Assuming the following database:

    10   /home/user/workspace
    20   /home/user/workspace/project1
    30   /home/user/workspace/project2
    40   /home/user/workspace/project3
    

    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.

    Tips for rule No.2:

    • If you want your last query not only to match the last segment of the path, append '$' as the last query. eg. "z wo $".
    • If you want your last query not to match the last segment of the path, append '/' as the last query. eg. "z wo /".
  • cd to the existent path if there is no match:

    Sometimes if you use:

    z foo
    

    And there is no matching result in the database, but there is an existent directory which can be accessed with the name "foo" from current directory, "z foo" will just work as:

    cd foo
    

    So, in the enhanced matching method, you can always use z like cd to change directory even if the new directory is untracked (hasn't been accessed).

  • 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:

    10   /Users/Great_Wall/.rbenv/versions/2.4.1/lib/ruby/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.

    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.

Add Once

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 initialize z.lua on linux like this:

eval "$(lua /path/to/z.lua --init bash once)"
eval "$(lua /path/to/z.lua --init zsh once)"
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.

Interactive Selection

When there are multiple matches found, using z -i will display a list:

$ z -i soft
3:  0.25        /home/data/software
2:  3.75        /home/skywind/tmp/comma/software
1:  21          /home/skywind/software
> {CURSOR}

And then you can input the number and choose where to go before actual cd. eg. input 3 to cd to /home/data/software. And if you just press ENTER and input nothing, it will just quit and stay where you were.

NOTE: for fish shell, this feature requires fish 2.7.0 or above.

FZF Supports

From version 1.1.0, a new option "-I" will allow you to use fzf to select when there are multiple matches.

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.

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.

For more information about this, please visit 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.

Jump Backwards

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.
  • (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). If simple substitution does not work, falls back to fuzzily replacing path components.

Let's start by aliasing z -b to zb:

# go all the way up to the project root (in this case, the one that has .git in it)
~/github/lorem/src/public$ zb
  => cd ~/github/lorem

# cd into to the first parent directory named g*
~/github/vimium/src/public$ zb g
  => cd ~/github

# goto the site directory quickly
~/github/demo/src/org/main/site/utils/file/reader/whatever$ zb si
  => cd ~/github/demo/src/org/main/site

# substitute jekyll with ghost
~/github/jekyll/test$ zb jekyll ghost
  => 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` ).

Environment variable $_ZL_ROOT_MARKERS is a comma separated list for project root locating, and can be redefined as:

export _ZL_ROOT_MARKERS=".git,.svn,.hg,.root,package.json"

If you want zb jump back to a parent directory contains a .root or package.json in it.

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

For zsh/fish, completion can be triggered by z foo<tab>. and a list of candidates will display in zsh / fish:

Press <tab> again, you can select your destination in a visualized way.

Bash is not as powerful as zsh/fish, so we introduced fzf-completion for bash, initialize your z.lua and append fzf keyword after --init:

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:

eval "$(lua /path/to/z.lua --init zsh enhanced once echo fzf)"

Then press <tab> after z xxx:

With the help of fzf, completion in bash is much easier now.

z.lua can cooperate with fz for better completion result in both bash and zsh, for more information see FAQ.

NOTE: To enable this, command fzf must be found in $PATH before initialization.

Most Recently Accessed Path

z.lua provides a fast way to visit MRU directories without typing any keyword. That is dirstack, which records recently visited paths and can be manipulated by z -, z -- and z -{num}:

# display current dir stack
$ z --    
 0  /home/skywind/work/match/memory-match
 1  /home/skywind/.local/etc
 2  /home/skywind/software/vifm-0.9.1
 3  /home/skywind/work
 4  /home/skywind/work/match

# cd to the 2nd directory in the stack
$ z -2
  => cd /home/skywind/software/vifm-0.9.1

# popup stacktop (cd to previous directory), same as "z -0"
$ z -
  => cd -

The dirstack is calculated from z.lua's database, and has no dependency on shells or systems. You will not lost records after re-login, and history can be shared across shells and sessions.

There is another way to access MRU directories interactively by utilizing parameter -I (fzf) and -t (sort by time):

alias zh='z -I -t .'

The new alias zh (jump to history) is very easy to input:

The first column indicates how many seconds ago you have visited, and the second column is the path name. With zh, you can type some character to use string matching in fzf, or use <Up>/<Down> (as well as CTRL+j/k) to move the selector (red >) up and down.

At last, press <enter> to accept or <ESC> to give up.

Remember to enable the 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.

To define additional commands (:zb for example) in ranger, you can put alias zb z -b into ~/.config/ranger/rc.conf.

Tips

Recommended aliases you may find useful:

alias zz='z -c'      # restrict matches to subdirs of $PWD
alias zi='z -i'      # cd with interactive selection
alias zf='z -I'      # use fzf to select in multiple matches
alias zb='z -b'      # quickly cd to the parent directory

Import data from z.sh:

cat ~/.z >> ~/.zlua

Import data from autojump:

FN="$HOME/.local/share/autojump/autojump.txt"
awk -F '\t' '{print $2 "|" $1 "|" 0}' $FN >> ~/.zlua

Don't forget to read the Frequently Asked Questions.

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:

$ time autojump --add /tmp
real    0m0.352s
user    0m0.077s
sys     0m0.185s

$ time fasd -A /tmp
real    0m0.618s
user    0m0.076s
sys     0m0.242s

$ time _z --add /tmp
real    0m0.194s
user    0m0.046s
sys     0m0.154s

$ time _zlua --add /tmp
real    0m0.052s
user    0m0.015s
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.

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: native module to boost z.lua.

Average performance:

Name czmod z.lua
Update Time 1.6ms 13.2ms
Query Time 1.5ms 9.8ms

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.
  • 1.7.3 (2019-09-07): use lua-filesystem package if possible when $_ZL_USE_LFS is 1.
  • 1.7.2 (2019-08-01): Improve bash/zsh shell compatibility by @barlik.
  • 1.7.1 (2019-06-07): Fixed: $_ZL_DATA failure on Linux sometimes.
  • 1.7.0 (2019-03-09): Support 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.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 by @contrun).
  • 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.1 (2019-02-15): new: simulated dir stack by z -, z -- and z -{num}.
  • 1.5.0 (2019-02-14): fixed minor issues in backward jumping.
  • 1.4.7 (2019-02-13): Don't use regex in backward jumping (use plain text instead).
  • 1.4.6 (2019-02-12): change: _ZL_EXCLUDE_DIRS to a comma separated list of dirs to exclude.
  • 1.4.5 (2019-02-10): improve bash fzf completion and posix compatibility.
  • 1.4.4 (2019-02-10): supports legacy posix shells like ksh, init with z.lua --init posix legacy.
  • 1.4.3 (2019-02-08): fixed minor issues.
  • 1.4.2 (2019-02-06): you can disabled path validation by $_ZL_NO_CHECK, and use z --purge to clear bad paths manually.
  • 1.4.1 (2019-02-06): fzf tab-completion in bash (@BarbUk), fixed hang in fish shell (close #29).
  • 1.4.0 (2019-02-04): Ported to Power Shell (@manhong2112)
  • 1.3.0 (2019-02-04): Backward jumping, prevent "cd ../../.." repeatly.
  • 1.2.0 (2019-02-03): Upgrade string lib and path lib.
  • 1.1.0 (2019-02-02): New option '-I' to use fzf to select from multiple matches.
  • 1.0.0 (2019-02-01): Fixed minor issues and make it stable.
  • 0.5.0 (2019-01-21): Ported to Fish Shell (@TeddyDD).
  • 0.4.1 (2019-01-20): Don't return failed exit code when $_ZL_ECHO is unbind (Mario Rodas).
  • 0.4.0 (2019-01-17): new enhanced matching algorithm,can be enabled by appending enhanced keyword after --init.
  • 0.3.0 (2018-12-26): new option -i to enable interactive selection.
  • 0.2.0 (2018-11-25): new option $_ZL_ADD_ONCE to enable updating datafile only if $PWD changed.
  • 0.1.0 (2018-04-30): supports windows cmd, cmder and conemu.
  • 0.0.0 (2018-03-21): initial commit, compatible with original z.sh.

Help

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: Implement completion for Power Shell.
  • Completion: Implement completion for different arguments.
  • Packaging: make it possible to be installed easily in different systems or popular plugin managers.

Thanks

  • Thanks to @rupa for inspiring me to start this project.
  • Thanks to @vigneshwaranr and @shyiko for inspiring me the backward jumping.
  • Thanks to @TeddyDD for Fish Shell porting.
  • Thanks to @manhong2112 for Power Shell porting.
  • Thanks to @BarbUk for fzf completion in Bash.
  • Thanks to @barlik for many improvements.

And many others.

License

Licensed under MIT license.

z.lua's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

z.lua's Issues

Using regex with $_ZL_EXCLUDE_DIRS

Currently I am excluding dirs with an array but I wonder if regex can be used instead. If possible, could you give me an example? Thank you for your helpful tool.

Fails on my Mac using ohmyzsh

I tried installing z.lua on my MacOS 10.14.3. I am running version 5.3.5 of lua.

Installation steps:

(cmd)>git clone [email protected]:skywind3000/z.lua.git .zlua
(cmd)>vim ~/.zshrc

Added the following lines at the end of .zshrc:

# Configure z.lua
eval "$(lua /Users/anasharm/.zlua/z.lua --init zsh)"

When I closed and restarted my iTerm, I get the following error:

/usr/local/bin/lua: /Users/anasharm/.zlua/z.lua:883: Is a directory
stack traceback:
	[C]: in for iterator 'for iterator'
	/Users/anasharm/.zlua/z.lua:883: in function 'data_load'
	/Users/anasharm/.zlua/z.lua:1137: in function 'z_add'
	/Users/anasharm/.zlua/z.lua:1605: in function 'main'
	/Users/anasharm/.zlua/z.lua:2336: in main chunk
	[C]: in ?

Any ideas?

'z -b' should not match current directory

Version

Version 1.5.8, Last Modified: 2019/02/21 12:08

Environment

  • macOS 10.14.3
  • fish 2.6.0
  • zsh 5.7.1

Step

$ mkdir -p a/b/c/d/a
=> ~
$ cd a/b/c/d/a
=> ~/a/b/c/d/a
$ z -b a
=> ~/a/b/c/d/a
$ z -b b
=> ~/a/b

Problem

z -b a should jump to ~/a, but it stays at ~/a/b/c/d/a.

z --help has mentioned that cd to the parent directory.

z -b foo    # cd to the parent directory starting with foo

I think 'z -b' should not match current directory.

'popen' not supported

The readme says compatible with lua 5.1, 5.2 and 5.3+, but I got the following error when using.

lua: /home/.z.lua/z.lua:212: 'popen' not supported
stack traceback:
	[C]: in function 'popen'
	/home/.z.lua/z.lua:212: in function </home/.z.lua/z.lua:211>
	(...tail calls...)
	/home/.z.lua/z.lua:1400: in function 'z_shell_init'
	/home/.z.lua/z.lua:1135: in function 'main'
	/home/.z.lua/z.lua:1574: in main chunk
	[C]: in ?

lua -v

Lua 5.2.3  Copyright (C) 1994-2013 Lua.org, PUC-Rio

uname -a

Linux xxx 2.6.32-504.8.1.el6.x86_64 #1 SMP  x86_64 x86_64 GNU/Linux

failed to detect scriptname on read only file system

The function os.scriptname uses rename to detect if a file exists. Rename will always fail on my nixos machine as the executable lies in a read only file system. Here is the log after adding print(name, ok, err, code) to the function os.path.exists. Actually file /nix/store/99p0nyqgayic2ipqx2x4lr4njl8f5nrz-python3-3.6.8/bin/realpath do exist.

 lua ~/.z.lua/z.lua --init zsh                                                                                              ~
/nix/store/99p0nyqgayic2ipqx2x4lr4njl8f5nrz-python3-3.6.8/bin/realpath  nil     Read-only file system   30
/home/e/bin/realpath    nil     No such file or directory       2
/run/wrappers/bin/realpath      nil     No such file or directory       2
/home/e/.bin/realpath   nil     No such file or directory       2
/home/e/.bin/realpath   nil     No such file or directory       2
/home/e/.local/bin/realpath     nil     No such file or directory       2
/home/e/.cabal/bin/realpath     nil     No such file or directory       2
/home/e/.cargo/bin/realpath     nil     No such file or directory       2
/home/e/Local/go/bin/realpath   nil     No such file or directory       2
/home/e/.node/node_modules/.bin/realpath        nil     No such file or directory       2
/usr/local/bin/realpath nil     No such file or directory       2
/usr/bin/realpath       nil     No such file or directory       2
/bin/realpath   nil     No such file or directory       2
/home/e/.nix-profile/bin/realpath       nil     Read-only file system   30
/nix/var/nix/profiles/default/bin/realpath      nil     No such file or directory       2
/run/current-system/sw/bin/realpath     nil     Read-only file system   30
/etc/profiles/per-user/e/bin/realpath   nil     No such file or directory       2
/nix/store/99p0nyqgayic2ipqx2x4lr4njl8f5nrz-python3-3.6.8/bin/perl      nil     Read-only file system   30
/home/e/bin/perl        nil     No such file or directory       2
/run/wrappers/bin/perl  nil     No such file or directory       2
/home/e/.bin/perl       nil     No such file or directory       2
/home/e/.bin/perl       nil     No such file or directory       2
/home/e/.local/bin/perl nil     No such file or directory       2
/home/e/.cabal/bin/perl nil     No such file or directory       2
/home/e/.cargo/bin/perl nil     No such file or directory       2
/home/e/Local/go/bin/perl       nil     No such file or directory       2
/home/e/.node/node_modules/.bin/perl    nil     No such file or directory       2
/usr/local/bin/perl     nil     No such file or directory       2
/usr/bin/perl   nil     No such file or directory       2
/bin/perl       nil     No such file or directory       2
/home/e/.nix-profile/bin/perl   nil     Read-only file system   30
/nix/var/nix/profiles/default/bin/perl  nil     No such file or directory       2
/run/current-system/sw/bin/perl nil     Read-only file system   30
/etc/profiles/per-user/e/bin/perl       nil     No such file or directory       2
/nix/store/99p0nyqgayic2ipqx2x4lr4njl8f5nrz-python3-3.6.8/bin/python    nil     Read-only file system   30
/home/e/bin/python      nil     No such file or directory       2
/run/wrappers/bin/python        nil     No such file or directory       2
/home/e/.bin/python     nil     No such file or directory       2
/home/e/.bin/python     nil     No such file or directory       2
/home/e/.local/bin/python       nil     No such file or directory       2
/home/e/.cabal/bin/python       nil     No such file or directory       2
/home/e/.cargo/bin/python       nil     No such file or directory       2
/home/e/Local/go/bin/python     nil     No such file or directory       2
/home/e/.node/node_modules/.bin/python  nil     No such file or directory       2
/usr/local/bin/python   nil     No such file or directory       2
/usr/bin/python nil     No such file or directory       2
/bin/python     nil     No such file or directory       2
/home/e/.nix-profile/bin/python nil     Read-only file system   30
/nix/var/nix/profiles/default/bin/python        nil     No such file or directory       2
/run/current-system/sw/bin/python       nil     Read-only file system   30
/etc/profiles/per-user/e/bin/python     nil     No such file or directory       2
/nix/store/99p0nyqgayic2ipqx2x4lr4njl8f5nrz-python3-3.6.8/bin/python2   nil     Read-only file system   30
/home/e/bin/python2     nil     No such file or directory       2
/run/wrappers/bin/python2       nil     No such file or directory       2
/home/e/.bin/python2    nil     No such file or directory       2
/home/e/.bin/python2    nil     No such file or directory       2
/home/e/.local/bin/python2      nil     No such file or directory       2
/home/e/.cabal/bin/python2      nil     No such file or directory       2
/home/e/.cargo/bin/python2      nil     No such file or directory       2
/home/e/Local/go/bin/python2    nil     No such file or directory       2
/home/e/.node/node_modules/.bin/python2 nil     No such file or directory       2
/usr/local/bin/python2  nil     No such file or directory       2
/usr/bin/python2        nil     No such file or directory       2
/bin/python2    nil     No such file or directory       2
/home/e/.nix-profile/bin/python2        nil     Read-only file system   30
/nix/var/nix/profiles/default/bin/python2       nil     No such file or directory       2
/run/current-system/sw/bin/python2      nil     Read-only file system   30
/etc/profiles/per-user/e/bin/python2    nil     No such file or directory       2
/nix/store/99p0nyqgayic2ipqx2x4lr4njl8f5nrz-python3-3.6.8/bin/python3   nil     Read-only file system   30
/home/e/bin/python3     nil     No such file or directory       2
/run/wrappers/bin/python3       nil     No such file or directory       2
/home/e/.bin/python3    nil     No such file or directory       2
/home/e/.bin/python3    nil     No such file or directory       2
/home/e/.local/bin/python3      nil     No such file or directory       2
/home/e/.cabal/bin/python3      nil     No such file or directory       2
/home/e/.cargo/bin/python3      nil     No such file or directory       2
/home/e/Local/go/bin/python3    nil     No such file or directory       2
/home/e/.node/node_modules/.bin/python3 nil     No such file or directory       2
/usr/local/bin/python3  nil     No such file or directory       2
/usr/bin/python3        nil     No such file or directory       2
/bin/python3    nil     No such file or directory       2
/home/e/.nix-profile/bin/python3        nil     Read-only file system   30
/nix/var/nix/profiles/default/bin/python3       nil     No such file or directory       2
/run/current-system/sw/bin/python3      nil     Read-only file system   30
/etc/profiles/per-user/e/bin/python3    nil     No such file or directory       2
lua: /home/e/.z.lua/z.lua:1415: attempt to concatenate a nil value
stack traceback:
        /home/e/.z.lua/z.lua:1415: in function 'z_shell_init'
        /home/e/.z.lua/z.lua:1150: in function 'main'
        /home/e/.z.lua/z.lua:1696: in main chunk
        [C]: in ?

The number of entries in the list of `z -I .` shouldn't be fixed

I just noticed something in the following image, that the list of z -I . doesn't list all the entries in database like z -i . does, there is plenty extra place in my terminal, maybe you shouldn't hard-code the number of entries in the database, but list the entries as many as possible according to the size of terminal screen, or you can give us an variable so we can choose the number we want. (I personally prefer the first solution.)

qq

Compatibility with fzf z integration

I'm using this fzf+z integration https://github.com/junegunn/fzf/wiki/examples#z:

unalias z 2> /dev/null
z() {
  [ $# -gt 0 ] && _z "$*" && return
  cd "$(_z -l 2>&1 | fzf --height 40% --nth 2.. --reverse --inline-info +s --tac --query "${*##-* }" | sed 's/^[0-9,.]* *//')"
}

How do I adjust it for z-lua? The problem is that I want to have "z" alias to always call fzf, and I should save it with a different name somehow (it's "_z" in the above example). Thanks!

Performance compared to z.sh

I've been evaluating z.lua and so far I couldn't replicate 3x performance improvement claim compared to z.sh.

3x times faster than z.sh

~ ➤ time bash -ic 'for i in {1..1000}; do _zlua --add /tmp; done' &>/dev/null
bash -ic 'for i in {1..1000}; do _zlua --add /tmp; done' &> /dev/null  2.73s user 1.38s system 99% cpu 4.129 total
~ ➤ time bash -ic 'for i in {1..1000}; do _z --add /tmp; done' &>/dev/null   
bash -ic 'for i in {1..1000}; do _z --add /tmp; done' &> /dev/null  4.64s user 2.74s system 100% cpu 7.311 total

Based on my calculations on two different systems, the performance improvement is "only" 1.7x.

Not work in cmder of Powershell startup tasks

Works well in Windows 10 system Powershell terminal.
But with cmder, powershell start task, z comamnd only list paths which typed in system Powershell termianl, not beside any paths typed in cmder.

add Fish shell support

I'll try to add support for Fish soon, opening issuse as reminder. (unless somebody else already working on it?)

I skimmed thorough the code and It shouldn't be hard to port (just tedious af).

Command doesn't work correctly for segments with hyphens

On 1.7.0

[dnugent@local ~/tmp]$ pwd
/home/dnugent/tmp
[dnugent@local ~/tmp]$ mkdir my-dir
[dnugent@local ~/tmp]$ cd my-dir
[dnugent@local ~/tmp/my-dir]$ cd ..
[dnugent@local ~/tmp]$ z my-dir
/home/dnugent/tmp/my-dir
[dnugent@local ~/tmp/my-dir]$ cd ..
[dnugent@local ~/tmp]$ mkdir mydir
[dnugent@local ~/tmp]$ cd mydir
[dnugent@local ~/tmp/mydir]$ cd ..
[dnugent@local ~/tmp]$ z my-dir
/home/dnugent/tmp/mydir
[dnugent@local ~/tmp/mydir]$ cd ..
[dnugent@local ~/tmp]$ z -l my-dir
8          /home/dnugent/tmp/mydir
[dnugent@local ~/tmp]$ kak
[dnugent@local ~/tmp]$ cd my-dir
[dnugent@local ~/tmp/my-dir]$ cd ..
[dnugent@local ~/tmp]$ z -l my
8          /home/dnugent/tmp/mydir
12         /home/dnugent/tmp/my-dir
[dnugent@local ~/tmp]$ z my
/home/dnugent/tmp/my-dir
[dnugent@local ~/tmp/my-dir]$ cd ..
[dnugent@local ~/tmp]$ z my-dir
/home/dnugent/tmp/mydir
[dnugent@local ~/tmp/mydir]$

匹配对带横杆的路径失败

环境:macosx 10.12.6; 命令行:zsh

usage: 添加eval "$(lua $HOME/.oh-my-zsh/custom/plugins/z.lua/z.lua --init zsh)"到.zshrc,普通模式


比如说我有一个目录是 ~/Documents/github/vue-my-ui,路径是带横杆的,我想跳到这路径:

case1:使用z vue能跳转,使用z vue-my-ui不能跳转到对应目录。

case2:使用z -l vue能list出来,使用z -l vue-my-ui不能出来。

case3:使用z -l github/vue能list出来,使用z -l github/vue-my-ui不能list出来。

其他的z指令都是这样,不知道是不是我用法有问题,只要搜路径带横杆的,都搜不出来。

Edit weights / ranks for directory?

For example, in autojump there is a file called autojump.txt in the root wting/autojump#90

where you can edit the values for the directories you want to increase their rank to match first.
Is something like this possible for z.lua?

sort the path in the list

Currently z.lua couldn't sort the path in the list, so when some subdir entries in the list, they will be in different places, it's hard to find what I want from the messed-up list.

So please add a option for z.lua to sort the path. It is very useful when using z -I or z -i(fzf itself sorts the path by default, but it doesn't work with z.lua).

[Feature Request] support hyphen (-) shortcut to go back last directory

It will be a nice feature to support the hyphen - as a shortcut.

The behavior of z - should be similar to cd -.

An argument of - is converted to $OLDPWD before the directory change is attempted

The behavior of z -i - and z -I - should be similar to enhancd. It will take a hyphen (-) string as an argument, it searchs from the last 10 directory items in the log. With it, you can search easily the directory you used last.

$ z -I -
  /home/lisa/Dropbox/etc/dotfiles
  /home/lisa/Dropbox
  /home/lisa/src/github.com
  /home/lisa/src/github.com/b4b4r07/cli
  /home
  /home/lisa/src
  /home/lisa/src/github.com/b4b4r07/enhancd
  /home/lisa/src/github.com/b4b4r07/gotcha
  /home/lisa/src/github.com/b4b4r07
> /home/lisa/src/github.com/b4b4r07/portfolio
  10/10
> _	

刚使用,发现个小问题

我有路径~/home/workspace/testFuzzyMatch~/home/workspace,当在~执行命令: z wo 时,路径切到~/home/workspace/testFuzzyMatch,而我想切到~/home/workspace,而且我认为后者更匹配。

z.sh 可以做到。

Not work on git bash windows 下的git bash中不生效

I had try normal bash --init and normal z.cmd way
but both not work
when use normal bash init, it print out no setlocal
when use z.cmd no printout and don't change dir
我尝试了--init bash的方法,也尝试了添加clink到path变量的z.cmd方法,但是不生效
前者依然识别为windows下,我查看了z.lua中的windows判断,似乎不受eval "$(lua /path/to/z.lua --init bash enhanced)"而单独设置local windows的true和false,但git bash在windows是否可以按照常规bash来处理的,因为如果用z.sh,git bash是可行的
而z.cmd为啥在git bash中直接没有输出,也没有目录切换,我暂时没有看出问题

[suggestion] cold start issue

After a fresh install of z.lua, in order to use it, the user have to use cd first to build the history, which is not very smart. Maybe you can directly read the user's command history to find those cd command and add the corresponding directories automatically.

In this way, z.lua becomes smarter.

Let z -c match only the relative part of directory

Currently, z -c (and other options) match patterns against the whole directory to filter. However, this can be confusing (especially for z -c). As an example, assume z outputs:
2 /home/user/h
4 /home/user/a
Now at /home/user, z -c h goes to a, because '/home' contains 'h' and matches the pattern. This looks confusing for me, I suppose that z -c, as all its possible targets share the same prefix, should not match patterns against that prefix (pwd).

Several unintended global variables

Hello !
if you run luac -p -l -l z.lua | grep GETTABUP you'll find several unintended global variables (mostly forgot to add local) and in one case you didn't declare a variable at all :

function os.path.split(path)
	if path == '' then
		return '', ''
	end
	local pos = path:rfind('/')
	if os.path.sep == '\\' then
		local p2 = path:rfind('\\')
		if pos == nil and p2 ~= nil then
			pos = p2
		elseif p1 ~= nil and p2 ~= nil then --?????? p1 never declared
			pos = (pos < p2) and pos or p2
		end

Cheers !

Some paths can only be added as administrator

I tried to add C:\Program Files (x86)\World of Warcraft\_classic_ to the z index by doing cd C:\Program Files (x86)\World of Warcraft\_classic_ without admin rights.
But the directory doesn't show up in z -l and i can't jump into it with z classic.
When i do the same as administrator it works.
Interestingly C:\Program Files (x86)\World of Warcraft works without admin privileges.

I don't understand why z would need admin privileges for this?
Is there any way around it?

Edit weights / ranks for directory?

For example, in autojump there is a file called autojump.txt in the root where you can edit the values for the directories you want to increase their rank to match first.
Is something like this possible for z.lua?

Directories changes won't affect the cd history of the fish shell

fish v2.7.1
z.lua version: 5c2e0c6

When using z.lua to change directories, it seems it won't affect the cd history of the fish shell, when I want to go back to the previous directory using command cd -, it says "Hit end of history…" and it is unable to go back. I know I can use z -b to go back to the history, but most of time cd - is much simpler.

But I tried it in bash shell, it works as expected.

Fails on mac with zsh

I tried to initiate z.lua on my mac but I can't get it to work. I keep getting:
_zlua:32: = not found

In my .zshrc:
eval "$(lua <home>/lib/z.lua/z.lua --init zsh)"

lua version 5.3.5
Zsh version 5.3

sometime `z sth<tab>` can't get correct result

$z<CR>
0.5         /root/seafile/seafile-data/seafile/conf
0.5         /etc/systemd
0.5         /etc
0.5         /root/.fzf
0.5         /root/.dotfile
0.5         /root/seafile/seafile-data/seafile/ccnet
0.5         /root/tool
0.5         /root/.tmux/tmux-resurrect
0.5         /root/.dotfile/vps/leanote
0.5         /root/seafile/seafile-data
1           /root/seafile/seafile-data/seafile
1           /root/.vim
1           /etc/ssl
1           /root/.vim/etc
1           /root/.dotfile/vps/v2ray
1.5         /root/seafile
4.5         /root/.dotfile/vps/caddy
10          /root/.dotfile/vps
32          /root/.dotfile/vps/seafile
36          /root/tool/caddy

z seafile<TAB> get corrent result

$z seafile<TAB>
/root/.dotfile/vps/seafile                /root/seafile/seafile-data                /root/seafile/seafile-data/seafile/ccnet                                          
/root/seafile                             /root/seafile/seafile-data/seafile        /root/seafile/seafile-data/seafile/conf 

z caddy <TAB> failed

$z caddy<TAB>
$z /root/ 

z caddy <CR> can work

$z caddy<CR>
~/tool/caddy $

"cd to the existent path if there is no match:" doesn't work in fish shell

fish v2.7.1
z.lua version: 5c2e0c6

There is one part in README.md
“”“
cd to the existent path if there is no match:

Sometimes if you use:

z foo

And there is no matching result in the database, but there is an existent directory which can be accessed with the name "foo" from current directory, "z foo" will just work as:

cd foo
“””

But it doesn't work as expected either with or without enabling "enhanced" mode, it will not cd into the a directory (not in the z.lua database) in the current path.

z -i doesn't work in fish shell

z -i word or z -i don't work with my fish shell(2.7.1)

z -i word shows nothing
z -i shows the full list like z

BTW:
I successfully make it work with bash shell, and z -i word works as expected. But IMHO, z -i without extra word should display the full list for interactive selection, currently z -i works like z.

hangs fish

Thanks for adding fish support, but when I use this, after cding once and then pressing enter, the prompt just hangs for a few seconds.

lua z.lua --init fish > ~/.config/fish/conf.d/z.fish
# open new terminal
cd dl
# press enter, hang

fish, version 3.0.0

fzf not autoinstalled with z.lua.plugin.zsh

i have fzf installed, i'd love it if z.lua.plugin.sh would automatically detect that and add it as part of loading it in my plugin manager, i.e.

zplugin load junegunn/fzf-bin
zplugin light skywind3000/z.lua

error in fish shell

After doing the instructions in README.md, the following error message shows up:

`- (line 1): The file “” is not executable by this user
begin; '' '' --add /home/echecod/Public
^
from sourcing file -
called on line 60 of file /usr/share/fish/functions/eval.fish

in function “eval”
called on standard input

in function “_zlua_call”
called on line 13 of file -
with parameter list “ --add /home/echecod/Public”

in function “_zlua”
called on line 59 of file -
with parameter list “--add /home/echecod/Public”

in function “_zlua_precmd”
called on standard input

in event handler: handler for generic event “fish_prompt”

`

z word$ does notwork with fishshell

fish, version 2.7.1

Since syntax like word$ is not right in fishshell, it will print

$ z word$
fish: Expected a variable name after this $.
z word$

So in fishshell, the feature that z word$ to cd to a directory ends with foo is unusable.

Not work in bash

# .bashrc
if [[ ! -f $DOTFILE_DIR/pkgs/z.lua/z.lua ]]; then
  return 0
fi

_ZL_CMD=z
_ZL_DATA=$HOME/.z_lua
_ZL_NO_PROMPT_COMMAND=true
# _ZL_EXCLUDE_DIRS=(.git)
# _ZL_CD=cd
_ZL_MATCH_MODE=1

eval "$(lua "$DOTFILE_DIR"/pkgs/z.lua/z.lua --init bash)"

alias zc='z -c'      # restrict matches to subdirs of $PWD
alias zz='z -i'      # cd with interactive selection
alias zf='cd "$(z -l -s | fzf --reverse --height 35%)"'

image

And I find the directory which _ZL_DATA points to is empty.


bash version: GNU bash,version 4.4.12(1)-release (x86_64-apple-darwin15.6.0)
lua version: 5.3.4

[Feature Request] Fuzzy matching as a fallback

One feature I really liked in fasd is, that fuzzy matching is performed, when the other matching algorithms to not yield a result.

Comparison of matching algorithms in fasd and z.lua:

fasd

  1. Queries match the path in order (same as default method).
  2. The last query matches the last segment of the path.
  3. If no match is found, fasd will try the same process ignoring case. If still no match is found, fasd will allow extra characters to be placed between query characters for fuzzy matching.

z.lua

  1. Queries match the path in order (same as default method).
  2. The last query matches the last segment of the path.

Did you consider to make the 3rd matching algorithm available in z.lua?

Imporve auto-complete feature with same name directories (in fish shell).

In fish, for instance, if I have two directories named same but in different path, like ~/scripts and ~/projects/scripts, and when the current directory in the shell is ~, I input scripts and then press tab, z.lua will only display the one which is just in the current directory, behaves like that:

╭─ ~ 
╰─$ (*゚∇゚)  z scripts/
scripts/__init__.py       scripts/cfapi.py ...

and plugin-z(another z implementation) will behave like this:

╭─ ~ 
╰─$ (*゚∇゚)  z scripts
/home/kiri/projects/scripts  /home/kiri/scripts

By the way, the flag -i is not working, (which has been referred in #15 ,) and it's also not an elegant way compared with auto-complete using tab.

Thank you for your wonderful work! Just willing to see it becoming more perfect!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.