1
0
Fork 0
mirror of https://github.com/notwa/rc synced 2024-05-18 17:53:23 -07:00

actual submodules?

This commit is contained in:
Connor Olding 2013-06-28 05:43:58 -07:00
parent cc5b057607
commit d5ae7c8eb8
19 changed files with 20 additions and 1001 deletions

15
.gitmodules vendored Normal file
View File

@ -0,0 +1,15 @@
[submodule "sh/z"]
path = sh/z
url = https://github.com/rupa/z.git
[submodule "sh/meow.sh"]
path = sh/meow.sh
url = https://github.com/notwa/meow.sh.git
[submodule "sh/lsf.sh"]
path = sh/lsf.sh
url = https://gist.github.com/5581118.git
[submodule "sh/danny.sh"]
path = sh/danny.sh
url = https://gist.github.com/3393717.git
[submodule "sh/4graze.sh"]
path = sh/4graze.sh
url = https://gist.github.com/2975511.git

1
sh/4graze.sh Submodule

@ -0,0 +1 @@
Subproject commit 8a20da818363a275a2a176fa0569af709e4c1119

View File

@ -1,13 +0,0 @@
#!/bin/bash
url="${1:-}"
[[ "$url" =~ ^https?://boards.4chan.org/([A-Za-z]+)/res/([0-9]+) ]] || exit 1
board="${BASH_REMATCH[1]}"
threadnum="${BASH_REMATCH[2]}"
# TODO: curl version
wgetflags="-erobots=off --no-verbose"
wgetflags+=" --no-clobber --recursive --level=1 --span-hosts"
wgetflags+=" --no-directories --directory-prefix=-$board-$threadnum"
wgetflags+=" --accept=jpg,gif,png --domains=images.4chan.org"
wget $wgetflags $url

1
sh/danny.sh Submodule

@ -0,0 +1 @@
Subproject commit f78ef75f435317df2c22a89f87b3c7ebc413ab04

View File

@ -1,76 +0,0 @@
#!/bin/bash
set -o nounset
# danny wants $20 to search for more than 2 tags
# so we'll search for realtags and grep for faketags
# note that special tags like "score:>10" must be a realtag
realtags="$1"
faketags=${2:-}
ip="67.202.114.134" # danbooru.donmai.us
webpage="post/index?tags=$realtags&limit=100&page="
pages=0
tempfile=`mktemp`
current=
term()
{
rm $current # don't leave it incomplete so it may be redownloaded
exit 1
}
trap 'term' TERM INT
#get='wget -q -erobots=off -O-' # mimic curl
get='curl -s'
page=1
while true; do
$get "http://$ip/${webpage}${page}" > "$tempfile"
posts=$(grep 'Post\.register({' "$tempfile")
IFS=$'\n'
for post in $posts; do
IFS=' '
tags=$(echo $post | grep -oP '(?<=tags":")([^"]+)')
if [ -z "$tags" ]; then continue; fi
badmatch=0
for faketag in $faketags; do
unwanted=0
if [[ $faketag == -* ]]; then
faketag=${faketag:1}
unwanted=1
fi
echo $tags | grep -F -- "$faketag" > /dev/null
result=$?
if [[ $result != $unwanted ]]; then
badmatch=1
break
fi
done
if (($badmatch)); then continue; fi
url=$(echo "$post" | grep -oP '(?<=file_url":")([^"]+)')
if [ -z "$url" ]; then continue; fi
name=$(echo "$url" | cut -d/ -f5)
current="$name"
if [ -n "$name" ]; then
echo $name
$get "$url" > $name
fi
done
IFS=' '
if (("$pages" == "0")); then
# first iteration, discover pagecount
pages=$(grep -oPm1 \
'(?<=>)\d+(?=</a> <a href="/post/index[^"]+" >&gt;&gt;)' \
$tempfile)
pages=${pages:-1}
fi
let page++
if (("$page" > "$pages")); then break; fi
done
rm $tempfile

1
sh/lsf.sh Submodule

@ -0,0 +1 @@
Subproject commit dceb0894b35c55f750ce680f8b5e0d0919308042

View File

@ -1,172 +0,0 @@
#!/bin/bash
# ultra-fancy ultra-pointless `ls -l` alternative
# to be sourced by bash or zsh
# similar project: https://github.com/trapd00r/ls--
# to maintain zsh compatibility:
# $() is surrounded in double quotes
# echo -E is used to avoid \033 expanding
# bare asterisks are escaped to prevent globbing
# arrays are used instead of relying on word expansion
# for loops over "${array[@]}" as it works the same in both
# TODO: set better defaults for quick glances at filesize
# TODO: include sorting somehow
# TODO: handle symlinks nicely
# TODO: append WHI / clr to dir names
_lsf_begin(){
local begin='
me='$UID'
'"$(
awk -F: '{print "unames["$3"]=\""$1"\""}' < /etc/passwd
awk -F: '{print "gnames["$3"]=\""$1"\""}' < /etc/group
for x in $(groups); do echo "us[\"$x\"]=1"; done
i=0;for x in bla red gre yel blu pur cya whi; do
echo -E $x'="\033[3'${i}'m"'
echo -n "$x" | tr a-z A-Z
echo -E '="\033[1;3'${i}'m"'
let i++
done
)"'
clr="\033[0m"
BLD="\033[1m"
s=1
m=60*s
h=60*m
d=24*h
y=365*d
B=1
K=1024*B
M=1024*K
G=1024*M
T=1024*G
ff["time"]="%3d%s " clr
ff["size"]="%4d" clr "%s "
'"$(
for x in s m h d y;do echo "u[\"time,$x\"]=$x";done
for x in B K M G T;do echo "u[\"size,$x\"]=$x";done
ft=(-1 m m\*10 h h\*12 d d\*7 30\*d y y\*2 y\*10)
fut=(s s s m m h h d d d y y)
fct=(RED PUR pur YEL yel GRE gre CYA cya BLU blu BLA)
fs=( 0 K K\*8 M M\*8 G G\*8 T T\*8)
fus=(B B B K K M M G G T)
fcs=(BLA cya CYA CYA yel yel pur pur red red)
pc=(BLA WHI yel YEL blu BLU gre GRE)
i=0;for x in "${ft[@]}"; do echo "f[\"time,$i\"]=$x"; let i++;done
echo "f[\"times\"]=$i"
i=0;for x in "${fs[@]}"; do echo "f[\"size,$i\"]=$x"; let i++;done
echo "f[\"sizes\"]=$i"
i=0;for x in "${fut[@]}";do echo "fu[\"time,$i\"]=\"$x\"";let i++;done
i=0;for x in "${fus[@]}";do echo "fu[\"size,$i\"]=\"$x\"";let i++;done
i=0;for x in "${fct[@]}";do echo "fc[\"time,$i\"]=$x"; let i++;done
i=0;for x in "${fcs[@]}";do echo "fc[\"size,$i\"]=$x"; let i++;done
i=0;for x in "${pc[@]}"; do echo "pc[$i]=$x"; let i++;done
)"
echo -E "$begin"
}
_lsf_cached=
_lsf_program='
function printff(id, n) {
len=f[id "s"]
for(i=0;i<=len;i++) {
idi=id "," i
if(i!=len && n>f[idi]) continue
unit=fu[idi]
printf(fc[idi] ff[id], n/u[id "," unit], unit)
break
}
}
function trunc(str, len) {
e=length(str)>len?"…":""
return substr(str,0,len-(e?1:0)) e
}
function fixlen(str, len) {
return trunc(sprintf("%" len "s", str), len)
}
{
printff("size", $(NF-14))
uid=$(NF-11)
gid=$(NF-10)
is_me=(uid==me)
is_us=(gnames[gid] in us)
bits=("0x" $(NF-12))+0
# note: we ignore the set and sticky bits... for now
type=rshift(and(bits, 0170000), 12)
operm=and(bits, 07)
gperm=rshift(and(bits, 070), 3)
uperm=rshift(and(bits, 0700), 6)
our_perm=or(or((is_me)?uperm:0, (is_us)?gperm:0), operm)
printf(pc[our_perm] "%o " clr, our_perm)
if(OSP) {
printf(pc[uperm] "%o" clr, uperm)
printf(pc[gperm] "%o" clr, gperm)
printf(pc[operm] "%o " clr, operm)
}
if(OSU) {
name=fixlen((uid in unames)?unames[uid]:uid, 6)
if(is_me) name=WHI name clr
printf("%s ", name)
}
if(OSG) {
name=fixlen((gid in gnames)?gnames[gid]:gid, 6)
if(is_us) name=WHI name clr
printf("%s ", name)
}
da=$(NF-4)
dc=$(NF-3)
dm=$(NF-2)
if(OMR) {
max=(da>dm)?da:dm
max=(max>dc)?max:dc
printff("time", now-max)
} else {
printff("time", now-da)
printff("time", now-dm)
printff("time", now-dc)
}
# acquire filename by killing all fields not part of it
NF-=15
fn=$0
if (!OSPA) {
if (NR!=1) fn=substr(fn,firstlen)
else firstlen=length(fn)+2-(fn ~ /\/$/)
}
print fn
}'
lsf(){
local o_showallperm=1 o_showuser=1 o_showgroup=1
local o_mostrecent=0 o_showpath=1 opts=mgupfs opt
while getopts $opts'h' opt; do
case $opt in
f) _lsf_cached=;;
p) o_showallperm=0;;
u) o_showuser=0;;
g) o_showgroup=0;;
m) o_mostrecent=1;;
s) o_showpath=0;;
?) echo "usage: $0 [-$opts] [dir]"
return 1;;
esac
done
[ "$_lsf_cached" ] || _lsf_cached="$(_lsf_begin)"
shift $((OPTIND-1))
find "${1:-.}" -maxdepth 1 -exec stat -t {} + | awk --non-decimal-data \
-v"now=$(date +%s)" -v"OMR=$o_mostrecent" -v"OSU=$o_showuser" \
-v"OSG=$o_showgroup" -v"OSP=$o_showallperm" -v"OSPA=$o_showpath" \
"BEGIN{$_lsf_cached}$_lsf_program"
}

1
sh/meow.sh Submodule

@ -0,0 +1 @@
Subproject commit 264706a6df14307bf3c791bd639d055c4f14dda3

View File

@ -1,20 +0,0 @@
# meow.sh
Prints out the title, torrent link, and timestamp
for every new release matching your regular expressions
and reminds you that your taste in anime is shit.
## Usage
Just take a peek at `run` and `config.sh` for now.
If you can't figure it out, you're too sane to use this.
## License
These scripts are hardly unique so
I'm not signing my name on them and
I'm not applying any license.
Just pretend they're under the [WTFPL][0]
if you really want to.
[0]: http://www.wtfpl.net/txt/copying/

View File

@ -1,3 +0,0 @@
watch Commie 'Yuyushiki - \d\d' 'Aiura - \d\d'
watch rori 'Hentai Ouji to Warawanai Neko - '
watch FFF 'DATE A LIVE - \d\d(?!v0)'

View File

@ -1,89 +0,0 @@
#!/usr/bin/env bash
SEP=$'\1'
die() {
echo -E "$@" 1>&2
exit 1
}
nullcheck() {
[[ -n "$1" ]] || die "Null group name";
}
sanitize() {
sed -e 's/[^0-9a-zA-Z_]/_/g'
}
splittags() {
awk -v tag="$1" -f "$SRCDIR/splittags.awk"
}
scrape() {
TZ=UTC0 awk -v g="$1" -v timestamp="${2:-0}" -v sep="$SEP" -f "$SRCDIR/scrape.awk"
}
declare -A groupinsane # unsanitized group names
declare -A groupshows # regexes
watch() { # {group name} [regex...]
nullcheck "$1"
local gs="$(sanitize<<<"$1")"
groupinsane[$gs]="$1"
shift
while (( "$#" )); do
groupshows[$gs]+="|($1)"
shift
done
}
declare -A grouptimes # last times timestamp
touchgroup() { # {group name} {unix time}
nullcheck "$1"
local gs="$(sanitize<<<"$1")"
grouptimes[$gs]="$2"
}
groupreleases() { # groupname [timestamp]
nullcheck "$1"
# TODO: escapeurl $1
local URL="http://www.nyaa.eu/?page=search&term=%5B$1%5D&page=rss"
curl -LsS "$URL" > "$1.xml" || die "Failed to retrieve releases for $1"
tr -d '\r\n'"$SEP" < "$1.xml" | splittags item | scrape "$1" "${2:-}"
}
groupfilter() { # groupname regex [timestamp]
groupreleases "$1" "${3:-}" | while IFS=$SEP read -r title etc; do
grep -P "$2" <<< "$title" 1>/dev/null && echo -E "$title$SEP$etc"
done
[ ${PIPESTATUS[0]} = 0 ] || exit 1
}
cleanup() {
for gs in "${!grouptimes[@]}"; do
local v="${grouptimes[$gs]}"
echo -E "touchgroup $gs $v" >> times.sh
[ -e "$gs.xml" ] && rm "$gs.xml"
done
exit ${1:-1}
}
rungroup() {
local insane regex timestamp res recent
insane="${groupinsane[$1]}"
regex="${groupshows[$1]:1}"
timestamp="${grouptimes[$1]}"
res="$(groupfilter "$insane" "$regex" "$timestamp")"
[ $? = 0 ] || return $?
IFS=$SEP read -r _ _ recent <<< "$res"
[ -n "$recent" ] && {
grouptimes[$1]="$recent"
echo -E "$res"
}
return 0
}
runall() {
trap cleanup INT
ret=0
for gs in "${!groupshows[@]}"; do rungroup "$gs" || ret=1; done
cleanup $ret
}

View File

@ -1,41 +0,0 @@
#!/usr/bin/env bash
SRCDIR="$(readlink -f "$(dirname "$0")" )"
# TODO: a way to pass opts to transmission-remote
declare -a actions
while getopts 'aph' opt; do
case $opt in
a) actions+=(addtorrent);;
p) actions+=(prettify);;
?) echo -E "usage: $0 [-ap]" 1>&2;;
esac
done
prettify() {
echo -E "$1"$'\n'"dl:"$'\t'"$2"$'\n'"at:"$'\t'"$(date -d @"$3")"
}
declare -a torrents
addtorrent() {
torrents+=("$2")
}
runactions() {
[ ${#actions} = 0 ] && {
cat
return
}
while IFS=$SEP read -r title torrent time; do
for a in "${actions[@]}"; do
"$a" "$title" "$torrent" "$time"
done
done
[ ${#torrents} = 0 ] || transmission-remote -a "${torrents[@]}"
}
. "$SRCDIR/meow.sh"
. config.sh
[ -e times.sh ] && { . times.sh; mv times.sh times.sh.old; }
runall | runactions
exit ${PIPESTATUS[0]}

View File

@ -1,39 +0,0 @@
function opentag(str, tag) {
topen="<"tag">"
tclose="</"tag">"
len=length(tag)
begin=index(str, topen)
end=index(str, tclose)
return (begin && end) ? substr(str, begin+len+2, end-begin-len-2) : ""
}
function unescape(str) {
while (match(str, /&#([0-9]+);/, b))
str=substr(str, 1, RSTART-1) sprintf("%c",b[1]) substr(str, RSTART+RLENGTH)
return str
}
function hotdate(str) {
split(str, d, "[ :]")
return mktime(d[4]" "months[d[3]]" "d[2]" "d[5]" "d[6]" "d[7])
}
BEGIN{
# http://stackoverflow.com/a/2123002
m=split("Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec",d,"|")
for(o=1;o<=m;o++) months[d[o]]=sprintf("%02d",o)
glen=length(g)
}
function run(str) {
title=unescape(opentag(str, "title"))
if (substr(title,1,glen+2) != "["g"]") return
pub=unescape(opentag($0, "pubDate"))
# "date -d \""pub "\" +%s" | getline pubunix
pubunix=hotdate(pub)
if (pubunix <= timestamp) return
torrent=unescape(opentag(str, "link"))
print title sep torrent sep pubunix
}
{run($0)}

View File

@ -1,13 +0,0 @@
{
str=$0
topen="<"tag">"
tclose="</"tag">"
len=length(tag)
for (;;) {
begin=index(str, topen)
end=index(str,tclose)
if (!(begin || end)) break
print substr(str, begin+len+2, end-begin-len-2)
str=substr(str, end+len+3)
}
}

1
sh/z Submodule

@ -0,0 +1 @@
Subproject commit ea574b79df7b0d9b648e73c7d78cf3f05a6d97ea

View File

@ -1,4 +0,0 @@
readme:
@groff -man -Tascii z.1 | col -bx
.PHONY: readme

View File

@ -1,137 +0,0 @@
Z(1) User Commands Z(1)
NAME
z - jump around
SYNOPSIS
z [-chlrtx] [regex1 regex2 ... regexn]
AVAILABILITY
bash, zsh
DESCRIPTION
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.
OPTIONS
-c restrict matches to subdirectories of the current directory
-h show a brief help message
-l list only
-r match by rank only
-t match by recent access only
-x remove the current directory from the datafile
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 highest ranked dir matching foo
z -t foo cd to most recently accessed dir matching foo
z -l foo list all dirs matching foo (by frecency)
NOTES
Installation:
Put something like this in your $HOME/.bashrc or $HOME/.zshrc:
. /path/to/z.sh
cd around for a while to build up the db.
PROFIT!!
Optionally:
Set $_Z_CMD to change the command name (default z).
Set $_Z_DATA to change the datafile (default $HOME/.z).
Set $_Z_NO_RESOLVE_SYMLINKS to prevent symlink resolution.
Set $_Z_NO_PROMPT_COMMAND to handle PROMPT_COMMAND/precmd your-
self.
Set $_Z_EXCLUDE_DIRS to an array of directories to exclude.
(These settings should go in .bashrc/.zshrc before the lines
added above.)
Install the provided man page z.1 somewhere like
/usr/local/man/man1.
Aging:
The rank of directories maintained by z undergoes aging based on a sim-
ple formula. The rank of each entry is incremented every time it is
accessed. When the sum of ranks is greater than 6000, all ranks are
multiplied by 0.99. 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, 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.
Common:
When multiple directories match all queries, and they all have a common
prefix, z will cd to the shortest matching directory, without regard to
priority. This has been in effect, if undocumented, for quite some
time, but should probably be configurable or reconsidered.
Tab Completion:
z supports tab completion. After any number of arguments, press TAB to
complete on directories that match each argument. Due to limitations of
the completion implementations, only the last argument will be com-
pleted in the shell.
Internally, z decides you've requested a completion if the last argu-
ment passed is an absolute path to an existing directory. This may
cause unexpected behavior if the last argument to z begins with /.
ENVIRONMENT
A function _z() is defined.
The contents of the variable $_Z_CMD is aliased to _z 2>&1. If not set,
$_Z_CMD defaults to z.
The environment variable $_Z_DATA can be used to control the datafile
location. If it is not defined, the location defaults to $HOME/.z.
The environment variable $_Z_NO_RESOLVE_SYMLINKS can be set to prevent
resolving of symlinks. If it is not set, symbolic links will be
resolved when added to the datafile.
In bash, z appends a command to the PROMPT_COMMAND environment variable
to maintain its database. In zsh, z appends a function _z_precmd to the
precmd_functions array.
The environment variable $_Z_NO_PROMPT_COMMAND can be set if you want
to handle PROMPT_COMMAND or precmd yourself.
The environment variable $_Z_EXCLUDE_DIRS can be set to an array of
directories to exclude from tracking. $HOME is always excluded. Direc-
tories must be full paths without trailing slashes.
FILES
Data is stored in $HOME/.z. This can be overridden by setting the
$_Z_DATA environment variable. When initialized, z will raise an error
if this path is a directory, and not function correctly.
A man page (z.1) is provided.
SEE ALSO
regex(7), pushd, popd, autojump, cdargs
Please file bugs at https://github.com/rupa/z/
z January 2013 Z(1)

158
sh/z/z.1
View File

@ -1,158 +0,0 @@
.TH "Z" "1" "January 2013" "z" "User Commands"
.SH
NAME
z \- jump around
.SH
SYNOPSIS
z [\-chlrtx] [regex1 regex2 ... regexn]
.SH
AVAILABILITY
bash, zsh
.SH
DESCRIPTION
Tracks your most used directories, based on 'frecency'.
.P
After a short learning phase, \fBz\fR will take you to the most 'frecent'
directory that matches ALL of the regexes given on the command line.
.SH
OPTIONS
.TP
\fB\-c\fR
restrict matches to subdirectories of the current directory
.TP
\fB\-h\fR
show a brief help message
.TP
\fB\-l\fR
list only
.TP
\fB\-r\fR
match by rank only
.TP
\fB\-t\fR
match by recent access only
.TP
\fB\-x\fR
remove the current directory from the datafile
.SH EXAMPLES
.TP 14
\fBz foo\fR
cd to most frecent dir matching foo
.TP 14
\fBz foo bar\fR
cd to most frecent dir matching foo and bar
.TP 14
\fBz -r foo\fR
cd to highest ranked dir matching foo
.TP 14
\fBz -t foo\fR
cd to most recently accessed dir matching foo
.TP 14
\fBz -l foo\fR
list all dirs matching foo (by frecency)
.SH
NOTES
.SS
Installation:
.P
Put something like this in your \fB$HOME/.bashrc\fR or \fB$HOME/.zshrc\fR:
.RS
.P
\fB. /path/to/z.sh\fR
.RE
.P
\fBcd\fR around for a while to build up the db.
.P
PROFIT!!
.P
Optionally:
.RS
Set \fB$_Z_CMD\fR to change the command name (default \fBz\fR).
.RE
.RS
Set \fB$_Z_DATA\fR to change the datafile (default \fB$HOME/.z\fR).
.RE
.RS
Set \fB$_Z_NO_RESOLVE_SYMLINKS\fR to prevent symlink resolution.
.RE
.RS
Set \fB$_Z_NO_PROMPT_COMMAND\fR to handle \fBPROMPT_COMMAND/precmd\fR yourself.
.RE
.RS
Set \fB$_Z_EXCLUDE_DIRS\fR to an array of directories to exclude.
.RE
.RS
(These settings should go in .bashrc/.zshrc before the lines added above.)
.RE
.RS
Install the provided man page \fBz.1\fR somewhere like \fB/usr/local/man/man1\fR.
.RE
.SS
Aging:
The rank of directories maintained by \fBz\fR 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 greater than 6000, all ranks are multiplied by 0.99. Entries
with a rank lower than 1 are forgotten.
.SS
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.
.P
To \fBz\fR, 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.
.P
Frecency is determined at runtime.
.SS
Common:
When multiple directories match all queries, and they all have a common prefix,
\fBz\fR will cd to the shortest matching directory, without regard to priority.
This has been in effect, if undocumented, for quite some time, but should
probably be configurable or reconsidered.
.SS
Tab Completion:
\fBz\fR supports tab completion. After any number of arguments, press TAB to
complete on directories that match each argument. Due to limitations of the
completion implementations, only the last argument will be completed in the
shell.
.P
Internally, \fBz\fR decides you've requested a completion if the last argument
passed is an absolute path to an existing directory. This may cause unexpected
behavior if the last argument to \fBz\fR begins with \fB/\fR.
.SH
ENVIRONMENT
A function \fB_z()\fR is defined.
.P
The contents of the variable \fB$_Z_CMD\fR is aliased to \fB_z 2>&1\fR. If not
set, \fB$_Z_CMD\fR defaults to \fBz\fR.
.P
The environment variable \fB$_Z_DATA\fR can be used to control the datafile
location. If it is not defined, the location defaults to \fB$HOME/.z\fR.
.P
The environment variable \fB$_Z_NO_RESOLVE_SYMLINKS\fR can be set to prevent
resolving of symlinks. If it is not set, symbolic links will be resolved when
added to the datafile.
.P
In bash, \fBz\fR appends a command to the \fBPROMPT_COMMAND\fR environment
variable to maintain its database. In zsh, \fBz\fR appends a function
\fB_z_precmd\fR to the \fBprecmd_functions\fR array.
.P
The environment variable \fB$_Z_NO_PROMPT_COMMAND\fR can be set if you want to
handle \fBPROMPT_COMMAND\fR or \fBprecmd\fR yourself.
.P
The environment variable \fB$_Z_EXCLUDE_DIRS\fR can be set to an array of
directories to exclude from tracking. \fB$HOME\fR is always excluded.
Directories must be full paths without trailing slashes.
.SH
FILES
Data is stored in \fB$HOME/.z\fR. This can be overridden by setting the
\fB$_Z_DATA\fR environment variable. When initialized, \fBz\fR will raise an
error if this path is a directory, and not function correctly.
.P
A man page (\fBz.1\fR) is provided.
.SH
SEE ALSO
regex(7), pushd, popd, autojump, cdargs
.P
Please file bugs at https://github.com/rupa/z/

236
sh/z/z.sh
View File

@ -1,236 +0,0 @@
# Copyright (c) 2009 rupa deadwyler under the WTFPL license
# maintains a jump-list of the directories you actually use
#
# INSTALL:
# * put something like this in your .bashrc/.zshrc:
# . /path/to/z.sh
# * cd around for a while to build up the db
# * PROFIT!!
# * optionally:
# set $_Z_CMD in .bashrc/.zshrc to change the command (default z).
# set $_Z_DATA in .bashrc/.zshrc to change the datafile (default ~/.z).
# set $_Z_NO_RESOLVE_SYMLINKS to prevent symlink resolution.
# set $_Z_NO_PROMPT_COMMAND if you're handling PROMPT_COMMAND yourself.
# set $_Z_EXCLUDE_DIRS to an array of directories to exclude.
#
# USE:
# * 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 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
[ -d "${_Z_DATA:-$HOME/.z}" ] && {
echo "ERROR: z.sh's datafile (${_Z_DATA:-$HOME/.z}) is a directory."
}
_z() {
local datafile="${_Z_DATA:-$HOME/.z}"
# bail if we don't own ~/.z (we're another user but our ENV is still set)
[ -f "$datafile" -a ! -O "$datafile" ] && return
# add entries
if [ "$1" = "--add" ]; then
shift
# $HOME isn't worth matching
[ "$*" = "$HOME" ] && return
# don't track excluded dirs
local exclude
for exclude in "${_Z_EXCLUDE_DIRS[@]}"; do
[ "$*" = "$exclude" ] && return
done
# maintain the file
local tempfile
tempfile="$datafile.$RANDOM"
while read line; do
# only count directories
[ -d "${line%%\|*}" ] && echo $line
done < "$datafile" | awk -v path="$*" -v now="$(date +%s)" -F"|" '
BEGIN {
rank[path] = 1
time[path] = now
}
$2 >= 1 {
if( $1 == path ) {
rank[$1] = $2 + 1
time[$1] = now
} else {
rank[$1] = $2
time[$1] = $3
}
count += $2
}
END {
if( count > 6000 ) {
# aging
for( i in rank ) print i "|" 0.99*rank[i] "|" time[i]
} else for( i in rank ) print i "|" rank[i] "|" time[i]
}
' 2>/dev/null >| "$tempfile"
if [ $? -ne 0 -a -f "$datafile" ]; then
env rm -f "$tempfile"
else
env mv -f "$tempfile" "$datafile" || env rm -f "$tmpfile"
fi
# tab completion
elif [ "$1" = "--complete" ]; then
while read line; do
[ -d "${line%%\|*}" ] && echo $line
done < "$datafile" | awk -v q="$2" -F"|" '
BEGIN {
if( q == tolower(q) ) nocase = 1
split(substr(q,3),fnd," ")
}
{
if( nocase ) {
for( i in fnd ) tolower($1) !~ tolower(fnd[i]) && $1 = ""
} else {
for( i in fnd ) $1 !~ fnd[i] && $1 = ""
}
if( $1 ) print $1
}
' 2>/dev/null
else
# list/go
while [ "$1" ]; do case "$1" in
--) while [ "$1" ]; do shift; local fnd="$fnd $1";done;;
-*) local opt=${1:1}; while [ "$opt" ]; do case ${opt:0:1} in
c) local fnd="^$PWD $fnd";;
h) echo "${_Z_CMD:-z} [-chlrtx] args" >&2; return;;
x) sed -i "\:^${PWD}|.*:d" "$datafile";;
l) local list=1;;
r) local typ="rank";;
t) local typ="recent";;
esac; opt=${opt:1}; done;;
*) local fnd="$fnd $1";;
esac; local last=$1; shift; done
[ "$fnd" -a "$fnd" != "^$PWD " ] || local list=1
# if we hit enter on a completion just go there
case "$last" in
# completions will always start with /
/*) [ -z "$list" -a -d "$last" ] && cd "$last" && return;;
esac
# no file yet
[ -f "$datafile" ] || return
local cd
cd="$(while read line; do
[ -d "${line%%\|*}" ] && echo $line
done < "$datafile" | awk -v t="$(date +%s)" -v list="$list" -v typ="$typ" -v q="$fnd" -F"|" '
function frecent(rank, time) {
# relate frequency and time
dx = t-time
if( dx < 3600 ) return rank*4
if( dx < 86400 ) return rank*2
if( dx < 604800 ) return rank/2
return rank/4
}
function output(files, toopen, common) {
# list or return the desired directory
if( list ) {
cmd = "sort -n >&2"
for( i in files ) {
if( files[i] ) printf "%-10s %s\n", files[i], i | cmd
}
if( common ) {
printf "%-10s %s\n", "common:", common > "/dev/stderr"
}
} else {
if( common ) toopen = common
print toopen
}
}
function common(matches) {
# find the common root of a list of dirs, if it exists
for( i in matches ) {
if( matches[i] && (!short || length(i) < length(short)) ) {
short = i
}
}
if( short == "/" ) return
# use a copy to escape special characters, as we want to return
# the original.
clean_short = short
gsub(/[\(\)\[\]\|]/, "\\\\&", clean_short)
for( i in matches ) if( matches[i] && i !~ clean_short ) return
return short
}
BEGIN { split(q, a, " "); oldf = noldf = -9999999999 }
{
if( typ == "rank" ) {
f = $2
} else if( typ == "recent" ) {
f = $3-t
} else f = frecent($2, $3)
wcase[$1] = nocase[$1] = f
for( i in a ) {
if( $1 !~ a[i] ) delete wcase[$1]
if( tolower($1) !~ tolower(a[i]) ) delete nocase[$1]
}
if( wcase[$1] && wcase[$1] > oldf ) {
cx = $1
oldf = wcase[$1]
} else if( nocase[$1] && nocase[$1] > noldf ) {
ncx = $1
noldf = nocase[$1]
}
}
END {
if( cx ) {
output(wcase, cx, common(wcase))
} else if( ncx ) output(nocase, ncx, common(nocase))
}
')"
[ $? -gt 0 ] && return
[ "$cd" ] && cd "$cd"
fi
}
alias ${_Z_CMD:-z}='_z 2>&1'
[ "$_Z_NO_RESOLVE_SYMLINKS" ] || _Z_RESOLVE_SYMLINKS="-P"
if compctl &> /dev/null; then
# zsh
[ "$_Z_NO_PROMPT_COMMAND" ] || {
# populate directory list, avoid clobbering any other precmds
if [ "$_Z_NO_RESOLVE_SYMLINKS" ]; then
_z_precmd() {
_z --add "${PWD:a}"
}
else
_z_precmd() {
_z --add "${PWD:A}"
}
fi
precmd_functions+=(_z_precmd)
}
_z_zsh_tab_completion() {
# tab completion
local compl
read -l compl
reply=(${(f)"$(_z --complete "$compl")"})
}
compctl -U -K _z_zsh_tab_completion _z
elif complete &> /dev/null; then
# bash
# tab completion
complete -o filenames -C '_z --complete "$COMP_LINE"' ${_Z_CMD:-z}
[ "$_Z_NO_PROMPT_COMMAND" ] || {
# bash populate directory list. avoid clobbering other PROMPT_COMMANDs.
grep -q "_z --add" <<< "$PROMPT_COMMAND" || {
PROMPT_COMMAND="$PROMPT_COMMAND"$'\n''_z --add "$(pwd '$_Z_RESOLVE_SYMLINKS' 2>/dev/null)" 2>/dev/null;'
}
}
fi