diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2024-04-10 14:16:20 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2024-04-10 14:16:20 -0700 |
commit | 5977af54dc0806445445a8732905c8d7ba572e41 (patch) | |
tree | 2ff5b934ba98592e82fcb184576485417a94bfb8 | |
parent | 285220820eb842b4dfe52c19852bf71fca517c74 (diff) | |
download | cdlog-5977af54dc0806445445a8732905c8d7ba572e41.tar.gz cdlog-5977af54dc0806445445a8732905c8d7ba572e41.tar.bz2 cdlog-5977af54dc0806445445a8732905c8d7ba572e41.zip |
New: search feature.
* cdlog.sh (cdlog.at2index, cdlog.at2path): New functions.
(cdlog.chdir, cdlog.rot, cdlog.mcd): Support searches
as way of specifying the target path or entry.
* README.md: Document searches.
-rw-r--r-- | README.md | 22 | ||||
-rw-r--r-- | cdlog.sh | 114 |
2 files changed, 109 insertions, 27 deletions
@@ -82,6 +82,28 @@ array. The `cdlog.chdir` function recognizes an alias only if it is invoked as `cdlog.chdir -p <alias>`, which is the way `cd` invokes it. +## Searches + +Search are arguments which begin with `@`. The rest +of such an argument argument is interpreted as a pattern which is applied +against the history to find the most recent path containing a match. + +In commands which accept a numeric argument denoting a reference +to the `cdlog` history by position, the `@` prefix may be omitted +from the search pattern. For instance `cs foo` will +swap the current directory with the most recent history entry +whose path contains a match for `foo`, and `cs @foo` will do +exactly the same thing. + +When a pattern can is used in situations in which a path +or alias is expected, namely as an argument to `cd`, the `@` +is not optional, because without it, the argument would be +interpreted as a path or alias. + +To include a leading `@` as part of the search pattern, write `@@`: +the first `@` is recognized as the prefix, and removed; the +second `@` remains as part of the pattern. + ## Persistence Whenever the history changes, the current directory and the @@ -152,6 +152,37 @@ cdlog.recover() fi } +# Resolve @ search item to number +cdlog.at2index() +{ + local i + local pat=${1#@} + + for i in "${!cdlog_hist[@]}"; do + if [[ ${cdlog_hist[$i]} =~ $pat ]] ; then + echo $i + return 0 + fi + done + return 1 +} + +# Resolve @ search item to path +cdlog.at2path() +{ + local i + local pat=${1#@} + + for i in "${!cdlog_hist[@]}"; do + local path=${cdlog_hist[$i]} + if [[ $path =~ $pat ]] ; then + echo $path + return 0 + fi + done + return 1 +} + # Change to directory: this is aliased to cd command. cdlog.chdir() { @@ -162,6 +193,15 @@ cdlog.chdir() if [ $# -eq 2 -a "$1" = -P ] ; then case $2 in + ( @* ) + if def=$(cdlog.at2path "$2"); then + set -- -P "$def" + print=y + else + printf "cdlog.chdir: no match for %s\n" "$2" + return 1 + fi + ;; ( */* ) ;; ( [1-9] ) @@ -218,6 +258,7 @@ cdlog.rot() local cur=$PWD local p=$cur local n=$cur + local i declare -n d=cdlog_hist local first=y @@ -225,22 +266,30 @@ cdlog.rot() while [ $# -gt 0 ] ; do n=$1; shift - case $n in - ( [1-9] ) - if [ $first ] ; then - command cd "${d[$n]}" || return - printf "%s\n" "$PWD" - else - d[$p]=${d[$n]} - fi - first= - p=$n - ;; - ( * ) - printf "cdlog.rot: bad argument: %s\n" "$n" - return 1 - ;; - esac + while true; do + case $n in + ( [1-9] ) + if [ $first ] ; then + command cd "${d[$n]}" || return + printf "%s\n" "$PWD" + else + d[$p]=${d[$n]} + fi + first= + p=$n + ;; + ( * ) + if i=$(cdlog.at2index "$n"); then + n=$i + continue + else + printf "cdlog.rot: no match for %s\n" "$n" + return 1 + fi + ;; + esac + break + done done d[$p]=$cur @@ -324,18 +373,29 @@ cdlog.mcd() printf "\e[A\e[K" done - case "$sel" in - ( [1-9] ) - if [ $swap ] ; then - cdlog.rot $sel - else - if cdlog.chdir -P "${d[$sel]}" ; then - printf "%s\n" "$PWD" + while true; do + case "$sel" in + ( [1-9] ) + if [ $swap ] ; then + cdlog.rot $sel + else + if cdlog.chdir -P "${d[$sel]}" ; then + printf "%s\n" "$PWD" + fi fi - fi - res=$? - ;; - esac + res=$? + ;; + ( * ) + if i=$(cdlog.at2index "$sel"); then + sel=$i + continue + else + printf "cdlog.mcd: no match for %s\n" "$sel" + return 1 + fi + esac + break + done return $res } |