From 19a28440aca21dfc76b0490d443d5f62e917337c Mon Sep 17 00:00:00 2001 From: Connor Olding Date: Sat, 13 Jul 2024 02:17:38 -0700 Subject: [PATCH] rewrite `witch` to be compatible with more shells --- sh/witch | 99 ++++++++++++++++++++++++-------------------------------- 1 file changed, 43 insertions(+), 56 deletions(-) diff --git a/sh/witch b/sh/witch index f7b7d5a..15086a5 100755 --- a/sh/witch +++ b/sh/witch @@ -1,67 +1,54 @@ #!/usr/bin/env sh -# NO_ZSH NO_BASH YES_DASH YES_ASH -# this is `which` from Debian. the only changes are superficial (formatting). -# this does not work as-is with zsh. +# YES_ZSH YES_BASH YES_DASH YES_ASH +### @ witch +### this is a personal rewrite of `which` from Debian. +### the original version didn't run on certain shells, +### and inherited inconsistent behaviors from getopts. set -ef -if test -n "$KSH_VERSION"; then - puts() { - print -r -- "$*" - } -else - puts() { - printf '%s\n' "$*" - } -fi - -ALLMATCHES=0 - -while getopts a whichopts -do - case "$whichopts" in - a) ALLMATCHES=1 ;; - ?) puts "Usage: $0 [-a] args"; exit 2 ;; +all=0 +for flag; do + case "$flag" in + (--) shift; break;; + (-?*) + shift + while flag="${flag#?}"; [ -n "$flag" ]; do + case "$flag" in + (a*) all=1;; + (*) + printf >&2 'Illegal option: -%.1s\n' "$flag" + printf 'Usage: %s\n' "$0 [-a] args" + exit 2;; + esac + done;; + (*) break esac done -shift $(($OPTIND - 1)) -if [ "$#" -eq 0 ]; then - ALLRET=1 -else - ALLRET=0 -fi -case $PATH in - (*[!:]:) PATH="$PATH:" ;; -esac -for PROGRAM in "$@"; do - RET=1 - IFS_SAVE="$IFS" - IFS=: - case $PROGRAM in - */*) - if [ -f "$PROGRAM" ] && [ -x "$PROGRAM" ]; then - puts "$PROGRAM" - RET=0 +[ "$#" != 0 ] && res=1 || res=0 + +IFS=: +for prog; do + err=1 + case "$prog" in + (*/*) + if [ -f "$prog" ] && [ -x "$prog" ]; then + printf %s\\n "$prog" + err=0 + fi;; + (*) + set -- $(printf %s: "$PATH") + for sub; do + [ -n "$sub" ] || sub=. + if [ -f "$sub/$prog" ] && [ -x "$sub/$prog" ]; then + printf %s\\n "$sub/$prog" + err=0 + [ "$all" = 1 ] || break fi - ;; - *) - for ELEMENT in $PATH; do - if [ -z "$ELEMENT" ]; then - ELEMENT=. - fi - if [ -f "$ELEMENT/$PROGRAM" ] && [ -x "$ELEMENT/$PROGRAM" ]; then - puts "$ELEMENT/$PROGRAM" - RET=0 - [ "$ALLMATCHES" -eq 1 ] || break - fi - done - ;; + done;; esac - IFS="$IFS_SAVE" - if [ "$RET" -ne 0 ]; then - ALLRET=1 - fi + [ "$err" = 0 ] || res=1 done -exit "$ALLRET" +exit "$res"