90c28b786ae8a8013fc5083e9cf941115152c706
- Author
- Robby Russell <robby@planetargon.com>
- Committer
- Robby Russell <robby@planetargon.com>
- Date
Message
Diff
This diff is truncated to protect this page.
1diff --git a/plugins/z/Makefile b/plugins/z/Makefile
2new file mode 100644
3index 0000000000000000000000000000000000000000..dcf433d40179ea59391a76aa506382d5949b59a3
4--- /dev/null
5+++ b/plugins/z/Makefile
6@@ -0,0 +1,4 @@
7+readme:
8+ @groff -man -Tascii z.1 | col -bx
9+
10+.PHONY: readme
11diff --git a/plugins/z/README b/plugins/z/README
12new file mode 100644
13index 0000000000000000000000000000000000000000..ec5abc6f53d5d02f0cf131137afbfbfb69e504af
14--- /dev/null
15+++ b/plugins/z/README
16@@ -0,0 +1,135 @@
17+Z(1) User Commands Z(1)
18+
19+
20+
21+NAME
22+ z - jump around
23+
24+SYNOPSIS
25+ z [-chlrt] [regex1 regex2 ... regexn]
26+
27+AVAILABILITY
28+ bash, zsh
29+
30+DESCRIPTION
31+ Tracks your most used directories, based on 'frecency'.
32+
33+ After a short learning phase, z will take you to the most 'frecent'
34+ directory that matches ALL of the regexes given on the command line.
35+
36+OPTIONS
37+ -c restrict matches to subdirectories of the current directory.
38+
39+ -h show a brief help message
40+
41+ -l list only
42+
43+ -r match by rank only
44+
45+ -t match by recent access only
46+
47+EXAMPLES
48+ z foo cd to most frecent dir matching foo
49+
50+ z foo bar cd to most frecent dir matching foo and bar
51+
52+ z -r foo cd to highest ranked dir matching foo
53+
54+ z -t foo cd to most recently accessed dir matching foo
55+
56+ z -l foo list all dirs matching foo (by frecency)
57+
58+NOTES
59+ Installation:
60+ Put something like this in your $HOME/.bashrc or $HOME/.zshrc:
61+
62+ . /path/to/z.sh
63+
64+ cd around for a while to build up the db.
65+
66+ PROFIT!!
67+
68+ Optionally:
69+ Set $_Z_CMD to change the command name (default z).
70+ Set $_Z_DATA to change the datafile (default $HOME/.z).
71+ Set $_Z_NO_RESOLVE_SYMLINKS to prevent symlink resolution.
72+ Set $_Z_NO_PROMPT_COMMAND to handle PROMPT_COMMAND/precmd your-
73+ self.
74+ Set $_Z_EXCLUDE_DIRS to an array of directories to exclude.
75+ (These settings should go in .bashrc/.zshrc before the lines
76+ added above.)
77+ Install the provided man page z.1 somewhere like
78+ /usr/local/man/man1.
79+
80+ Aging:
81+ The rank of directories maintained by z undergoes aging based on a sim-
82+ ple formula. The rank of each entry is incremented every time it is
83+ accessed. When the sum of ranks is greater than 6000, all ranks are
84+ multiplied by 0.99. Entries with a rank lower than 1 are forgotten.
85+
86+ Frecency:
87+ Frecency is a portmantaeu of 'recent' and 'frequency'. It is a weighted
88+ rank that depends on how often and how recently something occured. As
89+ far as I know, Mozilla came up with the term.
90+
91+ To z, a directory that has low ranking but has been accessed recently
92+ will quickly have higher rank than a directory accessed frequently a
93+ long time ago.
94+
95+ Frecency is determined at runtime.
96+
97+ Common:
98+ When multiple directories match all queries, and they all have a common
99+ prefix, z will cd to the shortest matching directory, without regard to
100+ priority. This has been in effect, if undocumented, for quite some
101+ time, but should probably be configurable or reconsidered.
102+
103+ Tab Completion:
104+ z supports tab completion. After any number of arguments, press TAB to
105+ complete on directories that match each argument. Due to limitations of
106+ the completion implementations, only the last argument will be com-
107+ pleted in the shell.
108+
109+ Internally, z decides you've requested a completion if the last argu-
110+ ment passed is an absolute path to an existing directory. This may
111+ cause unexpected behavior if the last argument to z begins with /.
112+
113+ENVIRONMENT
114+ A function _z() is defined.
115+
116diff --git a/plugins/z/z.1 b/plugins/z/z.1
117new file mode 100644
118index 0000000000000000000000000000000000000000..022a4b35d3121c32d88209a52bc0db0c4ba93be6
119--- /dev/null
120+++ b/plugins/z/z.1
121@@ -0,0 +1,155 @@
122+.TH "Z" "1" "January 2013" "z" "User Commands"
123+.SH
124+NAME
125+z \- jump around
126+.SH
127+SYNOPSIS
128+z [\-chlrt] [regex1 regex2 ... regexn]
129+.SH
130+AVAILABILITY
131+bash, zsh
132+.SH
133+DESCRIPTION
134+Tracks your most used directories, based on 'frecency'.
135+.P
136+After a short learning phase, \fBz\fR will take you to the most 'frecent'
137+directory that matches ALL of the regexes given on the command line.
138+.SH
139+OPTIONS
140+.TP
141+\fB\-c\fR
142+restrict matches to subdirectories of the current directory.
143+.TP
144+\fB\-h\fR
145+show a brief help message
146+.TP
147+\fB\-l\fR
148+list only
149+.TP
150+\fB\-r\fR
151+match by rank only
152+.TP
153+\fB\-t\fR
154+match by recent access only
155+.SH EXAMPLES
156+.TP 14
157+\fBz foo\fR
158+cd to most frecent dir matching foo
159+.TP 14
160+\fBz foo bar\fR
161+cd to most frecent dir matching foo and bar
162+.TP 14
163+\fBz -r foo\fR
164+cd to highest ranked dir matching foo
165+.TP 14
166+\fBz -t foo\fR
167+cd to most recently accessed dir matching foo
168+.TP 14
169+\fBz -l foo\fR
170+list all dirs matching foo (by frecency)
171+.SH
172+NOTES
173+.SS
174+Installation:
175+.P
176+Put something like this in your \fB$HOME/.bashrc\fR or \fB$HOME/.zshrc\fR:
177+.RS
178+.P
179+\fB. /path/to/z.sh\fR
180+.RE
181+.P
182+\fBcd\fR around for a while to build up the db.
183+.P
184+PROFIT!!
185+.P
186+Optionally:
187+.RS
188+Set \fB$_Z_CMD\fR to change the command name (default \fBz\fR).
189+.RE
190+.RS
191+Set \fB$_Z_DATA\fR to change the datafile (default \fB$HOME/.z\fR).
192+.RE
193+.RS
194+Set \fB$_Z_NO_RESOLVE_SYMLINKS\fR to prevent symlink resolution.
195+.RE
196+.RS
197+Set \fB$_Z_NO_PROMPT_COMMAND\fR to handle \fBPROMPT_COMMAND/precmd\fR yourself.
198+.RE
199+.RS
200+Set \fB$_Z_EXCLUDE_DIRS\fR to an array of directories to exclude.
201+.RE
202+.RS
203+(These settings should go in .bashrc/.zshrc before the lines added above.)
204+.RE
205+.RS
206+Install the provided man page \fBz.1\fR somewhere like \fB/usr/local/man/man1\fR.
207+.RE
208+.SS
209+Aging:
210+The rank of directories maintained by \fBz\fR undergoes aging based on a simple
211+formula. The rank of each entry is incremented every time it is accessed. When
212+the sum of ranks is greater than 6000, all ranks are multiplied by 0.99. Entries
213+with a rank lower than 1 are forgotten.
214+.SS
215+Frecency:
216+Frecency is a portmantaeu of 'recent' and 'frequency'. It is a weighted rank
217+that depends on how often and how recently something occured. As far as I
218+know, Mozilla came up with the term.
219+.P
220+To \fBz\fR, a directory that has low ranking but has been accessed recently
221diff --git a/plugins/z/z.plugin.zsh b/plugins/z/z.plugin.zsh
222new file mode 100644
223index 0000000000000000000000000000000000000000..196b88b12d4204bc523ce18c80c374e216ae49ef
224--- /dev/null
225+++ b/plugins/z/z.plugin.zsh
226@@ -0,0 +1,6 @@
227+_load_z() {
228+ source $1/z.sh
229+}
230+
231+[[ -f $ZSH_CUSTOM/plugins/z/z.plugin.zsh ]] && _load_z $ZSH_CUSTOM/plugins/z
232+[[ -f $ZSH/plugins/z/z.plugin.zsh ]] && _load_z $ZSH/plugins/z
233diff --git a/plugins/z/z.sh b/plugins/z/z.sh
234new file mode 100644
235index 0000000000000000000000000000000000000000..7e444ef4690363187c2c350a9dd63f10c076c63f
236--- /dev/null
237+++ b/plugins/z/z.sh
238@@ -0,0 +1,228 @@
239+# Copyright (c) 2009 rupa deadwyler under the WTFPL license
240+
241+# maintains a jump-list of the directories you actually use
242+#
243+# INSTALL:
244+# * put something like this in your .bashrc/.zshrc:
245+# . /path/to/z.sh
246+# * cd around for a while to build up the db
247+# * PROFIT!!
248+# * optionally:
249+# set $_Z_CMD in .bashrc/.zshrc to change the command (default z).
250+# set $_Z_DATA in .bashrc/.zshrc to change the datafile (default ~/.z).
251+# set $_Z_NO_RESOLVE_SYMLINKS to prevent symlink resolution.
252+# set $_Z_NO_PROMPT_COMMAND if you're handling PROMPT_COMMAND yourself.
253+# set $_Z_EXCLUDE_DIRS to an array of directories to exclude.
254+#
255+# USE:
256+# * z foo # cd to most frecent dir matching foo
257+# * z foo bar # cd to most frecent dir matching foo and bar
258+# * z -r foo # cd to highest ranked dir matching foo
259+# * z -t foo # cd to most recently accessed dir matching foo
260+# * z -l foo # list matches instead of cd
261+# * z -c foo # restrict matches to subdirs of $PWD
262+
263+case $- in
264+ *i*) ;;
265+ *) echo 'ERROR: z.sh is meant to be sourced, not directly executed.'
266+esac
267+
268+[ -d "${_Z_DATA:-$HOME/.z}" ] && {
269+ echo "ERROR: z.sh's datafile (${_Z_DATA:-$HOME/.z}) is a directory."
270+}
271+
272+_z() {
273+
274+ local datafile="${_Z_DATA:-$HOME/.z}"
275+
276+ # bail out if we don't own ~/.z (we're another user but our ENV is still set)
277+ [ -f "$datafile" -a ! -O "$datafile" ] && return
278+
279+ # add entries
280+ if [ "$1" = "--add" ]; then
281+ shift
282+
283+ # $HOME isn't worth matching
284+ [ "$*" = "$HOME" ] && return
285+
286+ # don't track excluded dirs
287+ local exclude
288+ for exclude in "${_Z_EXCLUDE_DIRS[@]}"; do
289+ [ "$*" = "$exclude" ] && return
290+ done
291+
292+ # maintain the file
293+ local tempfile
294+ tempfile="$(mktemp "$datafile.XXXXXX")" || return
295+ while read line; do
296+ [ -d "${line%%\|*}" ] && echo $line
297+ done < "$datafile" | awk -v path="$*" -v now="$(date +%s)" -F"|" '
298+ BEGIN {
299+ rank[path] = 1
300+ time[path] = now
301+ }
302+ $2 >= 1 {
303+ if( $1 == path ) {
304+ rank[$1] = $2 + 1
305+ time[$1] = now
306+ } else {
307+ rank[$1] = $2
308+ time[$1] = $3
309+ }
310+ count += $2
311+ }
312+ END {
313+ if( count > 6000 ) {
314+ for( i in rank ) print i "|" 0.99*rank[i] "|" time[i] # aging
315+ } else for( i in rank ) print i "|" rank[i] "|" time[i]
316+ }
317+ ' 2>/dev/null >| "$tempfile"
318+ if [ $? -ne 0 -a -f "$datafile" ]; then
319+ env rm -f "$tempfile"
320+ else
321+ env mv -f "$tempfile" "$datafile"
322+ fi
323+
324+ # tab completion
325+ elif [ "$1" = "--complete" ]; then
326+ while read line; do
327+ [ -d "${line%%\|*}" ] && echo $line
328+ done < "$datafile" | awk -v q="$2" -F"|" '
329+ BEGIN {
330+ if( q == tolower(q) ) nocase = 1
331+ split(substr(q,3),fnd," ")
332+ }
333+ {
334+ if( nocase ) {
335+ for( i in fnd ) tolower($1) !~ tolower(fnd[i]) && $1 = ""
336+ } else {
337+ for( i in fnd ) $1 !~ fnd[i] && $1 = ""