From 86b43b4e384eae6d60a4d2081d317c43141f3c90 Mon Sep 17 00:00:00 2001 From: Eric Nielsen Date: Fri, 10 Nov 2017 14:24:43 -0500 Subject: [PATCH] Smart case sensitivity matching by default and add parameters to force case insensitive (`-i`) or case sensitive (`-s`) matching. Also rename `t` variable in main awk script to `now`, as used in the `--add` awk script, use constant regular expression instead of string, and add double quotes to shell script variables. There are minor changes from smart-case to the original "prefer case sensitive" implementation. Considering these directories with their respective 'frecencies': 3 /tmp/foo/bar 5 /tmp/foo/Baz 8 /tmp/Baz 13 /tmp/bar 21 /tmp These would be the results of different queries with the two approaches, considering a filesystem that allows directories with same names and different cases: | query | smart-case | prefer case sensitive | |-------|--------------|-----------------------| | tm | /tmp | /tmp | | Tm | (nothing) | /tmp | | ba | /tmp/bar | /tmp/bar | | Ba | /tmp/Baz | /tmp/Baz | | fo ba | /tmp/foo/Baz | /tmp/foo/bar | | fo Ba | /tmp/foo/Baz | /tmp/foo/Baz | Fixes #209 --- README | 9 +++++++-- z.1 | 10 +++++++++- z.sh | 57 +++++++++++++++++++++++++++++---------------------------- 3 files changed, 45 insertions(+), 31 deletions(-) diff --git a/README b/README index 8f6c834..470305f 100644 --- a/README +++ b/README @@ -6,7 +6,7 @@ NAME z - jump around SYNOPSIS - z [-chlrtx] [regex1 regex2 ... regexn] + z [-cehilrstx] [regex1 regex2 ... regexn] AVAILABILITY bash, zsh @@ -16,7 +16,8 @@ DESCRIPTION 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. + order. By default, smart case sensitivity is used, namely case insensi- + tive match when regexes are lower case, case sensitive match otherwise. For example, z foo bar would match /foo/bar but not /bar/foo. @@ -27,10 +28,14 @@ OPTIONS -h show a brief help message + -i case insensitive match + -l list only -r match by rank only + -s case sensitive match + -t match by recent access only -x remove the current directory from the datafile diff --git a/z.1 b/z.1 index d4cac1a..975e6ec 100644 --- a/z.1 +++ b/z.1 @@ -4,7 +4,7 @@ NAME z \- jump around .SH SYNOPSIS -z [\-chlrtx] [regex1 regex2 ... regexn] +z [\-cehilrstx] [regex1 regex2 ... regexn] .SH AVAILABILITY bash, zsh @@ -14,6 +14,8 @@ 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, in order. +By default, smart case sensitivity is used, namely case insensitive match when +regexes are lower case, case sensitive match otherwise. For example, \fBz foo bar\fR would match \fB/foo/bar\fR but not \fB/bar/foo\fR. .SH @@ -28,12 +30,18 @@ echo the best match, don't cd \fB\-h\fR show a brief help message .TP +\fB\-i\fR +case insensitive match +.TP \fB\-l\fR list only .TP \fB\-r\fR match by rank only .TP +\fB\-s\fR +case sensitive match +.TP \fB\-t\fR match by recent access only .TP diff --git a/z.sh b/z.sh index c2036c6..d74252c 100644 --- a/z.sh +++ b/z.sh @@ -111,18 +111,20 @@ _z() { else # list/go while [ "$1" ]; do case "$1" in - --) while [ "$1" ]; do shift; local fnd="$fnd${fnd:+ }$1";done;; - -*) local opt=${1:1}; while [ "$opt" ]; do case ${opt:0:1} in + --) while [ "$1" ]; do shift; local fnd="$fnd${fnd:+ }$1"; done;; + -*) local opt="${1:1}"; while [ "$opt" ]; do case "${opt:0:1}" in c) local fnd="^$PWD $fnd";; e) local echo=echo;; - h) echo "${_Z_CMD:-z} [-cehlrtx] args" >&2; return;; + h) echo "${_Z_CMD:-z} [-cehilrstx] [regex1 regex2 ... regexn]" >&2; return;; + i) local cas='i';; l) local list=1;; - r) local typ="rank";; - t) local typ="recent";; + r) local typ='r';; + s) local cas='s';; + t) local typ='t';; x) sed -i -e "\:^${PWD}|.*:d" "$datafile";; - esac; opt=${opt:1}; done;; + esac; opt="${opt:1}"; done;; *) local fnd="$fnd${fnd:+ }$1";; - esac; local last=$1; [ "$#" -gt 0 ] && shift; done + esac; local last="$1"; [ "$#" -gt 0 ] && shift; done [ "$fnd" -a "$fnd" != "^$PWD " ] || local list=1 # if we hit enter on a completion just go there @@ -135,10 +137,10 @@ _z() { [ -f "$datafile" ] || return local cd - cd="$( < <( _z_dirs ) awk -v t="$(date +%s)" -v list="$list" -v typ="$typ" -v q="$fnd" -F"|" ' + cd="$( < <( _z_dirs ) awk -v now="$(date +%s)" -v cas="$cas" -v list="$list" -v typ="$typ" -v q="$fnd" -F'|' ' function frecent(rank, time) { # relate frequency and time - dx = t - time + dx = now - time if( dx < 3600 ) return rank * 4 if( dx < 86400 ) return rank * 2 if( dx < 604800 ) return rank / 2 @@ -175,33 +177,32 @@ _z() { return short } BEGIN { - gsub(" ", ".*", q) - hi_rank = ihi_rank = -9999999999 + if( cas == "i" ) { + q = tolower(q) + imatch = 1 + } else if( cas != "s" && q == tolower(q) ) imatch = 1 + gsub(/ /, ".*", q) + hi_rank = -9999999999 } { - if( typ == "rank" ) { + if( typ == "r" ) { rank = $2 - } else if( typ == "recent" ) { - rank = $3 - t + } else if( typ == "t" ) { + rank = $3 - now } else rank = frecent($2, $3) - if( $1 ~ q ) { + if( imatch ) { + x = tolower($1) + } else x = $1 + if( x ~ q ) { matches[$1] = rank - } else if( tolower($1) ~ tolower(q) ) imatches[$1] = rank - if( matches[$1] && matches[$1] > hi_rank ) { - best_match = $1 - hi_rank = matches[$1] - } else if( imatches[$1] && imatches[$1] > ihi_rank ) { - ibest_match = $1 - ihi_rank = imatches[$1] + if( rank > hi_rank ) { + best_match = $1 + hi_rank = rank + } } } END { - # prefer case sensitive - if( best_match ) { - output(matches, best_match, common(matches)) - } else if( ibest_match ) { - output(imatches, ibest_match, common(imatches)) - } + output(matches, best_match, common(matches)) } ')"