]> src.twobees.de Git - dotfiles.git/blob - stow/oh-my-zsh/.oh-my-zsh/plugins/z/MANUAL.md
dcca3c452878619249adef3daeea5e6fc2e7e269
[dotfiles.git] / stow / oh-my-zsh / .oh-my-zsh / plugins / z / MANUAL.md
1 # Zsh-z
2
3 Zsh-z is a command line tool that allows you to jump quickly to directories that you have visited frequently in the past, or recently -- but most often a combination of the two (a concept known as ["frecency"](https://en.wikipedia.org/wiki/Frecency)). It works by keeping track of when you go to directories and how much time you spend in them. It is then in the position to guess where you want to go when you type a partial string, e.g., `z src` might take you to `~/src/zsh`. `z zsh` might also get you there, and `z c/z` might prove to be even more specific -- it all depends on your habits and how much time you have been using Zsh-z to build up a database. After using Zsh-z for a little while, you will get to where you want to be by typing considerably less than you would need if you were using `cd`.
4
5 Zsh-z is a native Zsh port of [rupa/z](https://github.com/rupa/z), a tool written for `bash` and Zsh that uses embedded `awk` scripts to do the heavy lifting. It was quite possibly my most used command line tool for a couple of years. I decided to translate it, `awk` parts and all, into pure Zsh script, to see if by eliminating calls to external tools (`awk`, `sort`, `date`, `sed`, `mv`, `rm`, and `chown`) and reducing forking through subshells I could make it faster. The performance increase is impressive, particularly on systems where forking is slow, such as Cygwin, MSYS2, and WSL. I have found that, in those environments, switching directories using Zsh-z can be over 100% faster than it is using `rupa/z`.
6
7 There is a noteworthy stability increase as well. Race conditions have always been a problem with `rupa/z`, and users of that utility will occasionally lose their `.z` databases. By having Zsh-z only use Zsh (`rupa/z` uses a hybrid shell code that works on `bash` as well), I have been able to implement a `zsh/system`-based file-locking mechanism similar to [the one @mafredri once proposed for `rupa/z`](https://github.com/rupa/z/pull/199). It is now nearly impossible to crash the database, even through extreme testing.
8
9 There are other, smaller improvements which I try to document in [Improvements and Fixes](#improvements-and-fixes). These include the new default behavior of sorting your tab completions by frecency rather than just letting Zsh sort the raw results alphabetically (a behavior which can be restored if you like it -- [see below](#settings)).
10
11 Zsh-z is a drop-in replacement for `rupa/z` and will, by default, use the same database (`~/.z`), so you can go on using `rupa/z` when you launch `bash`.
12
13 ## Table of Contents
14 - [News](#news)
15 - [Installation](#installation)
16 - [Command Line Options](#command-line-options)
17 - [Settings](#settings)
18 - [Case Sensitivity](#case-sensitivity)
19 - [`ZSHZ_UNCOMMON`](#zshz_uncommon)
20 - [Making `--add` work for you](#making---add-work-for-you)
21 - [Other Improvements and Fixes](#other-improvements-and-fixes)
22 - [Migrating from Other Tools](#migrating-from-other-tools)
23 - [`COMPLETE_ALIASES`](#complete_aliases)
24 - [Known Bugs](#known-bugs)
25
26 ## News
27
28 <details>
29     <summary>Here are the latest features and updates.</summary>
30
31 - June 29, 2022
32     + Zsh-z is less likely to leave temporary files sitting around (props @mafredri).
33 - June 27, 2022
34     + A bug was fixed which was preventing paths with spaces in them from being updated ([#61](https://github.com/agkozak/zsh-z/issues/61)).
35     + If writing to the temporary database file fails, the database will not be clobbered (props @mafredri).
36 - December 19, 2021
37     + ZSH-z will now display tildes for `HOME` during completion when `ZSHZ_TILDE=1` has been set.
38 - November 11, 2021
39     + A bug was fixed which was preventing ranks from being incremented.
40     + `--add` has been made to work with relative paths and has been documented for the user.
41 - October 14, 2021
42     + Completions were being sorted alphabetically, rather than by rank; this error has been fixed.
43 - September 25, 2021
44     + Orthographical change: "Zsh," not "ZSH."
45 - September 23, 2021
46     + `z -xR` will now remove a directory *and its subdirectories* from the database.
47     + `z -x` and `z -xR` can now take an argument; without one, `PWD` is assumed.
48 - September 7, 2021
49     + Fixed the unload function so that it removes the `$ZSHZ_CMD` alias (default: `z`).
50 - August 27, 2021
51     + Using `print -v ... -f` instead of `print -v` to work around longstanding bug in Zsh involving `print -v` and multibyte strings.
52 - August 13, 2021
53     + Fixed the explanation string printed during completion so that it may be formatted with `zstyle`.
54     + Zsh-z now declares `ZSHZ_EXCLUDE_DIRS` as an array with unique elements so that you do not have to.
55 - July 29, 2021
56     + Temporarily disabling use of `print -v`, which seems to be mangling CJK multibyte strings.
57 - July 27, 2021
58     + Internal escaping of path names now works with older versions of ZSH.
59     + Zsh-z now detects and discards any incomplete or incorrectly formattted database entries.
60 - July 10, 2021
61     + Setting `ZSHZ_TRAILING_SLASH=1` makes it so that a search pattern ending in `/` can match the end of a path; e.g. `z foo/` can match `/path/to/foo`.
62 - June 25, 2021
63     + Setting `ZSHZ_TILDE=1` displays the `HOME` directory as `~`.
64 - May 7, 2021
65     + Setting `ZSHZ_ECHO=1` will cause Zsh-z to display the new path when you change directories.
66     + Better escaping of path names to deal paths containing the characters ``\`()[]``.
67 - February 15, 2021
68     + Ranks are displayed the way `rupa/z` now displays them, i.e. as large integers. This should help Zsh-z to integrate with other tools.
69 - January 31, 2021
70     + Zsh-z is now efficient enough that, on MSYS2 and Cygwin, it is faster to run it in the foreground than it is to fork a subshell for it.
71     + `_zshz_precmd` simply returns if `PWD` is `HOME` or in `ZSH_EXCLUDE_DIRS`, rather than waiting for `zshz` to do that.
72 - January 17, 2021
73     + Made sure that the `PUSHD_IGNORE_DUPS` option is respected.
74 - January 14, 2021
75     + The `z -h` help text now breaks at spaces.
76     + `z -l` was not working for Zsh version < 5.
77 - January 11, 2021
78     + Major refactoring of the code.
79     + `z -lr` and `z -lt` work as expected.
80     + `EXTENDED_GLOB` has been disabled within the plugin to accomodate old-fashioned Windows directories with names such as `Progra~1`.
81     + Removed `zshelldoc` documentation.
82 - January 6, 2021
83     + I have corrected the frecency routine so that it matches `rupa/z`'s math, but for the present, Zsh-z will continue to display ranks as 1/10000th of what they are in `rupa/z` -- [they had to multiply theirs by 10000](https://github.com/rupa/z/commit/f1f113d9bae9effaef6b1e15853b5eeb445e0712) to work around `bash`'s inadequacies at dealing with decimal fractions.
84 - January 5, 2021
85     + If you try `z foo`, and `foo` is not in the database but `${PWD}/foo` is a valid directory, Zsh-z will `cd` to it.
86 - December 22, 2020
87     + `ZSHZ_CASE`: when set to `ignore`, pattern matching is case-insensitive; when set to `smart`, patterns are matched case-insensitively when they are all lowercase and case-sensitively when they have uppercase characters in them (a behavior very much like Vim's `smartcase` setting).
88     + `ZSHZ_KEEP_DIRS` is an array of directory names that should not be removed from the database, even if they are not currently available (useful when a drive is not always mounted).
89     + Symlinked datafiles were having their symlinks overwritten; this bug has been fixed.
90
91 </details>
92
93 ## Installation
94
95 ### General observations
96
97 This script can be installed simply by downloading it and sourcing it from your `.zshrc`:
98
99     source /path/to/zsh-z.plugin.zsh
100
101 For tab completion to work, you will want to have loaded `compinit`. The frameworks handle this themselves. If you are not using a framework, put
102
103     autoload -U compinit && compinit
104
105 in your .zshrc somewhere below where you source `zsh-z.plugin.zsh`.
106
107 If you add
108
109     zstyle ':completion:*' menu select
110
111 to your `.zshrc`, your completion menus will look very nice. This `zstyle` invocation should work with any of the frameworks below as well.
112
113 ### For [antigen](https://github.com/zsh-users/antigen) users
114
115 Add the line
116
117     antigen bundle agkozak/zsh-z
118
119 to your `.zshrc`, somewhere above the line that says `antigen apply`.
120
121 ### For [oh-my-zsh](http://ohmyz.sh/) users
122
123 Execute the following command:
124
125     git clone https://github.com/agkozak/zsh-z ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-z
126
127 and add `zsh-z` to the line of your `.zshrc` that specifies `plugins=()`, e.g., `plugins=( git zsh-z )`.
128
129 ### For [prezto](https://github.com/sorin-ionescu/prezto) users
130
131 Execute the following command:
132
133     git clone https://github.com/agkozak/zsh-z.git ~/.zprezto-contrib/zsh-z
134
135 Then edit your `~/.zpreztorc` file. Make sure the line that says
136
137     zstyle ':prezto:load' pmodule-dirs $HOME/.zprezto-contrib
138
139 is uncommented. Then find the section that specifies which modules are to be loaded; it should look something like this:
140
141     zstyle ':prezto:load' pmodule \
142         'environment' \
143         'terminal' \
144         'editor' \
145         'history' \
146         'directory' \
147         'spectrum' \
148         'utility' \
149         'completion' \
150         'prompt'
151
152 Add a backslash to the end of the last line add `'zsh-z'` to the list, e.g.,
153
154     zstyle ':prezto:load' pmodule \
155         'environment' \
156         'terminal' \
157         'editor' \
158         'history' \
159         'directory' \
160         'spectrum' \
161         'utility' \
162         'completion' \
163         'prompt' \
164         'zsh-z'
165
166 Then relaunch `zsh`.
167
168 ### For [zcomet](https://github.com/agkozak/zcomet) users
169         
170 Simply add
171
172     zcomet load agkozak/zsh-z
173
174 to your `.zshrc` (below where you source `zcomet.zsh` and above where you run `zcomet compinit`).
175
176 ### For [zgen](https://github.com/tarjoilija/zgen) users
177
178 Add the line
179
180     zgen load agkozak/zsh-z
181
182 somewhere above the line that says `zgen save`. Then run
183
184     zgen reset
185     zsh
186
187 to refresh your init script.
188
189 ### For [Zim](https://github.com/zimfw/zimfw)
190
191 Add the following line to your `.zimrc`:
192
193     zmodule https://github.com/agkozak/zsh-z
194
195 Then run
196
197     zimfw install
198
199 and restart your shell.
200
201 ### For [Zinit](https://github.com/zdharma-continuum/zinit) users
202
203 Add the line
204
205     zinit load agkozak/zsh-z
206
207 to your `.zshrc`.
208
209 `zsh-z` supports `zinit`'s `unload` feature; just run `zinit unload agkozak/zshz` to restore the shell to its state before `zsh-z` was loaded.
210
211 ### For [Znap](https://github.com/marlonrichert/zsh-snap) users
212
213 Add the line
214
215     znap source agkozak/zsh-z
216
217 somewhere below the line where you `source` Znap itself.
218
219 ### For [zplug](https://github.com/zplug/zplug) users
220
221 Add the line
222
223     zplug "agkozak/zsh-z"
224
225 somewhere above the line that says `zplug load`. Then run
226
227     zplug install
228     zplug load
229
230 to install `zsh-z`.
231
232 ## Command Line Options
233
234 - `--add` Add a directory to the database
235 - `-c`    Only match subdirectories of the current directory
236 - `-e`    Echo the best match without going to it
237 - `-h`    Display help
238 - `-l`    List all matches without going to them
239 - `-r`    Match by rank (i.e. how much time you spend in directories)
240 - `-t`    Time -- match by how recently you have been to directories
241 - `-x`    Remove a directory (by default, the current directory) from the database
242 - `-xR`   Remove a directory (by default, the current directory) and its subdirectories from the database
243
244 # Settings
245
246 Zsh-z has environment variables (they all begin with `ZSHZ_`) that change its behavior if you set them; you can also keep your old ones if you have been using `rupa/z` (they begin with `_Z_`).
247
248 * `ZSHZ_CMD` changes the command name (default: `z`)
249 * `ZSHZ_COMPLETION` can be `'frecent'` (default) or `'legacy'`, depending on whether you want your completion results sorted according to frecency or simply sorted alphabetically
250 * `ZSHZ_DATA` changes the database file (default: `~/.z`)
251 * `ZSHZ_ECHO` displays the new path name when changing directories (default: `0`)
252 * `ZSHZ_EXCLUDE_DIRS` is an array of directories to keep out of the database (default: empty)
253 * `ZSHZ_KEEP_DIRS` is an array of directories that should not be removed from the database, even if they are not currently available (useful when a drive is not always mounted) (default: empty)
254 * `ZSHZ_MAX_SCORE` is the maximum combined score the database entries can have before they begin to age and potentially drop out of the database (default: 9000)
255 * `ZSHZ_NO_RESOLVE_SYMLINKS` prevents symlink resolution (default: `0`)
256 * `ZSHZ_OWNER` allows usage when in `sudo -s` mode (default: empty)
257 * `ZSHZ_TILDE` displays the name of the `HOME` directory as a `~` (default: `0`)
258 * `ZSHZ_TRAILING_SLASH` makes it so that a search pattern ending in `/` can match the final element in a path; e.g., `z foo/` can match `/path/to/foo` (default: `0`)
259 * `ZSHZ_UNCOMMON` changes the logic used to calculate the directory jumped to; [see below](#zshz_uncommon`) (default: `0`)
260
261 ## Case sensitivity
262
263 The default behavior of Zsh-z is to try to find a case-sensitive match. If there is none, then Zsh-z tries to find a case-insensitive match.
264
265 Some users prefer simple case-insensitivity; this behavior can be enabled by setting
266
267     ZSHZ_CASE=ignore
268
269 If you like Vim's `smartcase` setting, where lowercase patterns are case-insensitive while patterns with any uppercase characters are treated case-sensitively, try setting
270
271     ZSHZ_CASE=smart
272
273 ## `ZSHZ_UNCOMMON`
274
275 A common complaint about the default behavior of `rupa/z` and Zsh-z involves "common prefixes." If you type `z code` and the best matches, in increasing order, are
276
277     /home/me/code/foo
278     /home/me/code/bar
279     /home/me/code/bat
280
281 Zsh-z will see that all possible matches share a common prefix and will send you to that directory -- `/home/me/code` -- which is often a desirable result. But if the possible matches are
282
283     /home/me/.vscode/foo
284     /home/me/code/foo
285     /home/me/code/bar
286     /home/me/code/bat
287
288 then there is no common prefix. In this case, `z code` will simply send you to the highest-ranking match, `/home/me/code/bat`.
289
290 You may enable an alternate, experimental behavior by setting `ZSHZ_UNCOMMON=1`. If you do that, Zsh-z will not jump to a common prefix, even if one exists. Instead, it chooses the highest-ranking match -- but it drops any subdirectories that do not include the search term. So if you type `z bat` and `/home/me/code/bat` is the best match, that is exactly where you will end up. If, however, you had typed `z code` and the best match was also `/home/me/code/bat`, you would have ended up in `/home/me/code` (because `code` was what you had searched for). This feature is still in development, and feedback is welcome.
291
292 ## Making `--add` Work for You
293
294 Zsh-z internally uses the `--add` option to add paths to its database. @zachriggle pointed out to me that users might want to use `--add` themselves, so I have altered it a little to make it more user-friendly.
295
296 A good example might involve a directory tree that has Git repositories within it. The working directories could be added to the Zsh-z database as a batch with
297
298     for i in $(find $PWD -maxdepth 3 -name .git -type d); do
299       z --add ${i:h}
300     done
301
302 (As a Zsh user, I tend to use `**` instead of `find`, but it is good to see how deep your directory trees go before doing that.)
303
304
305 ## Other Improvements and Fixes
306
307 * `z -x` works, with the help of `chpwd_functions`.
308 * Zsh-z works on Solaris.
309 * Zsh-z uses the "new" `zshcompsys` completion system instead of the old `compctl` one.
310 * There is no error message when the database file has not yet been created.
311 * There is support for special characters (e.g., `[`) in directory names.
312 * If `z -l` only returns one match, a common root is not printed.
313 * Exit status codes increasingly make sense.
314 * Completions work with options `-c`, `-r`, and `-t`.
315 * If `~/foo` and `~/foob` are matches, `~/foo` is *not* the common root. Only a common parent directory can be a common root.
316 * `z -x` and the new, recursive `z -xR` can take an argument so that you can remove directories other than `PWD` from the database.
317
318 ## Migrating from Other Tools
319
320 Zsh-z's database format is identical to that of `rupa/z`. You may switch freely between the two tools (I still use `rupa/z` for `bash`). `fasd` also uses that database format, but it stores it by default in `~/.fasd`, so you will have to `cp ~/.fasd ~/.z` if you want to use your old directory history.
321
322 If you are coming to Zsh-z (or even to the original `rupa/z`, for that matter) from `autojump`, try using my [`jumpstart-z`](https://github.com/agkozak/jumpstart-z/blob/master/jumpstart-z) tool to convert your old database to the Zsh-z format, or simply run
323
324     awk -F "\t" '{printf("%s|%0.f|%s\n", $2, $1, '"$(date +%s)"')}' < /path/to/autojump.txt > ~/.z
325
326 ## `COMPLETE_ALIASES`
327
328 `z`, or any alternative you set up using `$ZSH_CMD` or `$_Z_CMD`, is an alias. `setopt COMPLETE_ALIASES` divorces the tab completion for aliases from the underlying commands they invoke, so if you enable `COMPLETE_ALIASES`, tab completion for Zsh-z will be broken. You can get it working again, however, by adding under
329
330     setopt COMPLETE_ALIASES
331
332 the line
333
334     compdef _zshz ${ZSHZ_CMD:-${_Z_CMD:-z}}
335
336 That will re-bind `z` or the command of your choice to the underlying Zsh-z function.
337
338 ## Known Bugs
339 It is possible to run a completion on a string with spaces in it, e.g., `z us bi<TAB>` might take you to `/usr/local/bin`. This works, but as things stand, after the completion the command line reads
340
341     z us /usr/local/bin.
342
343 You get where you want to go, but the detritus on the command line is annoying. This is also a problem in `rupa/z`, but I am keen on eventually eliminating this glitch. Advice is welcome.