diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..2504eda --- /dev/null +++ b/.gitmodules @@ -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 diff --git a/sh/4graze.sh b/sh/4graze.sh new file mode 160000 index 0000000..8a20da8 --- /dev/null +++ b/sh/4graze.sh @@ -0,0 +1 @@ +Subproject commit 8a20da818363a275a2a176fa0569af709e4c1119 diff --git a/sh/4graze.sh/4graze.sh b/sh/4graze.sh/4graze.sh deleted file mode 100755 index 79eb809..0000000 --- a/sh/4graze.sh/4graze.sh +++ /dev/null @@ -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 diff --git a/sh/danny.sh b/sh/danny.sh new file mode 160000 index 0000000..f78ef75 --- /dev/null +++ b/sh/danny.sh @@ -0,0 +1 @@ +Subproject commit f78ef75f435317df2c22a89f87b3c7ebc413ab04 diff --git a/sh/danny.sh/danny.sh b/sh/danny.sh/danny.sh deleted file mode 100755 index 62f3140..0000000 --- a/sh/danny.sh/danny.sh +++ /dev/null @@ -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+(?= >>)' \ - $tempfile) - pages=${pages:-1} - fi - - let page++ - if (("$page" > "$pages")); then break; fi -done - -rm $tempfile diff --git a/sh/lsf.sh b/sh/lsf.sh new file mode 160000 index 0000000..dceb089 --- /dev/null +++ b/sh/lsf.sh @@ -0,0 +1 @@ +Subproject commit dceb0894b35c55f750ce680f8b5e0d0919308042 diff --git a/sh/lsf.sh/lsf.sh b/sh/lsf.sh/lsf.sh deleted file mode 100755 index 21d4804..0000000 --- a/sh/lsf.sh/lsf.sh +++ /dev/null @@ -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" -} diff --git a/sh/meow.sh b/sh/meow.sh new file mode 160000 index 0000000..264706a --- /dev/null +++ b/sh/meow.sh @@ -0,0 +1 @@ +Subproject commit 264706a6df14307bf3c791bd639d055c4f14dda3 diff --git a/sh/meow.sh/README.md b/sh/meow.sh/README.md deleted file mode 100644 index 10d1005..0000000 --- a/sh/meow.sh/README.md +++ /dev/null @@ -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/ diff --git a/sh/meow.sh/config.sh b/sh/meow.sh/config.sh deleted file mode 100644 index 59dcb88..0000000 --- a/sh/meow.sh/config.sh +++ /dev/null @@ -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)' diff --git a/sh/meow.sh/meow.sh b/sh/meow.sh/meow.sh deleted file mode 100644 index 6c6c4e4..0000000 --- a/sh/meow.sh/meow.sh +++ /dev/null @@ -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 -} diff --git a/sh/meow.sh/run b/sh/meow.sh/run deleted file mode 100755 index 0cb8a20..0000000 --- a/sh/meow.sh/run +++ /dev/null @@ -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]} diff --git a/sh/meow.sh/scrape.awk b/sh/meow.sh/scrape.awk deleted file mode 100644 index bc4c0f1..0000000 --- a/sh/meow.sh/scrape.awk +++ /dev/null @@ -1,39 +0,0 @@ -function opentag(str, tag) { - topen="<"tag">" - tclose="" - 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)} diff --git a/sh/meow.sh/splittags.awk b/sh/meow.sh/splittags.awk deleted file mode 100644 index 689f54a..0000000 --- a/sh/meow.sh/splittags.awk +++ /dev/null @@ -1,13 +0,0 @@ -{ - str=$0 - topen="<"tag">" - tclose="" - 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) - } -} diff --git a/sh/z b/sh/z new file mode 160000 index 0000000..ea574b7 --- /dev/null +++ b/sh/z @@ -0,0 +1 @@ +Subproject commit ea574b79df7b0d9b648e73c7d78cf3f05a6d97ea diff --git a/sh/z/Makefile b/sh/z/Makefile deleted file mode 100644 index dcf433d..0000000 --- a/sh/z/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -readme: - @groff -man -Tascii z.1 | col -bx - -.PHONY: readme diff --git a/sh/z/README b/sh/z/README deleted file mode 100644 index 4257001..0000000 --- a/sh/z/README +++ /dev/null @@ -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) diff --git a/sh/z/z.1 b/sh/z/z.1 deleted file mode 100644 index 4d2a607..0000000 --- a/sh/z/z.1 +++ /dev/null @@ -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/ diff --git a/sh/z/z.sh b/sh/z/z.sh deleted file mode 100644 index 6dc70f9..0000000 --- a/sh/z/z.sh +++ /dev/null @@ -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