175 lines
5.7 KiB
Fish
175 lines
5.7 KiB
Fish
|
function __z -d "Jump to a recent directory."
|
||
|
function __print_help -d "Print z help."
|
||
|
printf "Usage: $Z_CMD [-celrth] string1 string2...\n\n"
|
||
|
printf " -c --clean Removes directories that no longer exist from $Z_DATA\n"
|
||
|
printf " -d --dir Opens matching directory using system file manager.\n"
|
||
|
printf " -e --echo Prints best match, no cd\n"
|
||
|
printf " -l --list List matches and scores, no cd\n"
|
||
|
printf " -p --purge Delete all entries from $Z_DATA\n"
|
||
|
printf " -r --rank Search by rank\n"
|
||
|
printf " -t --recent Search by recency\n"
|
||
|
printf " -x --delete Removes the current directory from $Z_DATA\n"
|
||
|
printf " -h --help Print this help\n\n"
|
||
|
end
|
||
|
function __z_legacy_escape_regex
|
||
|
# taken from escape_string_pcre2 in fish
|
||
|
# used to provide compatibility with fish 2
|
||
|
for c in (string split '' $argv)
|
||
|
if contains $c (string split '' '.^$*+()?[{}\\|-]')
|
||
|
printf \\
|
||
|
end
|
||
|
printf '%s' $c
|
||
|
end
|
||
|
end
|
||
|
|
||
|
set -l options h/help c/clean e/echo l/list p/purge r/rank t/recent d/directory x/delete
|
||
|
|
||
|
argparse $options -- $argv
|
||
|
|
||
|
if set -q _flag_help
|
||
|
__print_help
|
||
|
return 0
|
||
|
else if set -q _flag_clean
|
||
|
__z_clean
|
||
|
printf "%s cleaned!\n" $Z_DATA
|
||
|
return 0
|
||
|
else if set -q _flag_purge
|
||
|
echo >$Z_DATA
|
||
|
printf "%s purged!\n" $Z_DATA
|
||
|
return 0
|
||
|
else if set -q _flag_delete
|
||
|
sed -i -e "\:^$PWD|.*:d" $Z_DATA
|
||
|
return 0
|
||
|
end
|
||
|
|
||
|
set -l typ
|
||
|
|
||
|
if set -q _flag_rank
|
||
|
set typ rank
|
||
|
else if set -q _flag_recent
|
||
|
set typ recent
|
||
|
end
|
||
|
|
||
|
set -l z_script '
|
||
|
function frecent(rank, 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(matches, best_match, common) {
|
||
|
# list or return the desired directory
|
||
|
if( list ) {
|
||
|
cmd = "sort -nr"
|
||
|
for( x in matches ) {
|
||
|
if( matches[x] ) {
|
||
|
printf "%-10s %s\n", matches[x], x | cmd
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
if( common ) best_match = common
|
||
|
print best_match
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function common(matches) {
|
||
|
# find the common root of a list of matches, if it exists
|
||
|
for( x in matches ) {
|
||
|
if( matches[x] && (!short || length(x) < length(short)) ) {
|
||
|
short = x
|
||
|
}
|
||
|
}
|
||
|
if( short == "/" ) return
|
||
|
for( x in matches ) if( matches[x] && index(x, short) != 1 ) {
|
||
|
return
|
||
|
}
|
||
|
return short
|
||
|
}
|
||
|
|
||
|
BEGIN {
|
||
|
hi_rank = ihi_rank = -9999999999
|
||
|
}
|
||
|
{
|
||
|
if( typ == "rank" ) {
|
||
|
rank = $2
|
||
|
} else if( typ == "recent" ) {
|
||
|
rank = $3 - t
|
||
|
} else rank = frecent($2, $3)
|
||
|
if( $1 ~ 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]
|
||
|
}
|
||
|
}
|
||
|
|
||
|
END {
|
||
|
# prefer case sensitive
|
||
|
if( best_match ) {
|
||
|
output(matches, best_match, common(matches))
|
||
|
} else if( ibest_match ) {
|
||
|
output(imatches, ibest_match, common(imatches))
|
||
|
}
|
||
|
}
|
||
|
'
|
||
|
|
||
|
set -l qs
|
||
|
for arg in $argv
|
||
|
set -l escaped $arg
|
||
|
if string escape --style=regex '' >/dev/null 2>&1 # use builtin escape if available
|
||
|
set escaped (string escape --style=regex $escaped)
|
||
|
else
|
||
|
set escaped (__z_legacy_escape_regex $escaped)
|
||
|
end
|
||
|
# Need to escape twice, see https://www.math.utah.edu/docs/info/gawk_5.html#SEC32
|
||
|
set escaped (string replace --all \\ \\\\ $escaped)
|
||
|
set qs $qs $escaped
|
||
|
end
|
||
|
set -l q (string join '.*' $qs)
|
||
|
|
||
|
if set -q _flag_list
|
||
|
# Handle list separately as it can print common path information to stderr
|
||
|
# which cannot be captured from a subcommand.
|
||
|
command awk -v t=(date +%s) -v list="list" -v typ="$typ" -v q="$q" -F "|" $z_script "$Z_DATA"
|
||
|
return
|
||
|
end
|
||
|
|
||
|
set target (command awk -v t=(date +%s) -v typ="$typ" -v q="$q" -F "|" $z_script "$Z_DATA")
|
||
|
|
||
|
if test "$status" -gt 0
|
||
|
return
|
||
|
end
|
||
|
|
||
|
if test -z "$target"
|
||
|
printf "'%s' did not match any results\n" "$argv"
|
||
|
return 1
|
||
|
end
|
||
|
|
||
|
if set -q _flag_echo
|
||
|
printf "%s\n" "$target"
|
||
|
else if set -q _flag_directory
|
||
|
if test -n "$ZO_METHOD"
|
||
|
type -q "$ZO_METHOD"; and "$ZO_METHOD" "$target"; and return $status
|
||
|
echo "Cannot open with ZO_METHOD set to $ZO_METHOD"; and return 1
|
||
|
else if test "$OS" = Windows_NT
|
||
|
# Be careful, in msys2, explorer always return 1
|
||
|
type -q explorer; and explorer "$target"
|
||
|
return 0
|
||
|
echo "Cannot open file explorer"
|
||
|
return 1
|
||
|
else
|
||
|
type -q xdg-open; and xdg-open "$target"; and return $status
|
||
|
type -q open; and open "$target"; and return $status
|
||
|
echo "Not sure how to open file manager"; and return 1
|
||
|
end
|
||
|
else
|
||
|
pushd "$target"
|
||
|
end
|
||
|
end
|