zsh:functions: Rewrite resolve()
It was a mess and had to be rewritten. The new version is a bit simpler by dropping unstable features that I never used anyway. It still supports a verbose flag that prints every step of the process.
This commit is contained in:
@@ -154,95 +154,78 @@ _get_config_dir() {
|
|||||||
|
|
||||||
## Function that resolves a command to the end
|
## Function that resolves a command to the end
|
||||||
resolve() {
|
resolve() {
|
||||||
# TODO: comment!!
|
local verbose cmd old_cmd args last_line
|
||||||
# In script mode only the result and its arguments are printed
|
local -a full_cmd
|
||||||
# The result can then be used directly by other scripts without further
|
|
||||||
# manipulation
|
|
||||||
typeset SCRIPT_MODE VERBOSE_MODE 1>&2
|
|
||||||
while getopts "sv" opt 2>/dev/null; do
|
|
||||||
case $opt in
|
|
||||||
s) SCRIPT_MODE=1;;
|
|
||||||
v) VERBOSE_MODE=1;;
|
|
||||||
*) echo "Unknown flag!" >&2
|
|
||||||
return 1;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
shift $(( $OPTIND - 1 ))
|
|
||||||
|
|
||||||
if (( $SCRIPT_MODE )) && (( $VERBOSE_MODE )); then
|
# Since there are multiple occasions were the same line would be printed
|
||||||
echo "Script and verbose mode do no work together." >&2
|
# multiple times, this function makes the output in combination with the
|
||||||
return 1
|
# verbose flag cleaner.
|
||||||
|
local uniq_print() {
|
||||||
|
if [[ "$*" != "$last_line" ]]; then
|
||||||
|
printf "%s\n" "$*"
|
||||||
|
last_line="$*"
|
||||||
fi
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
typeset THIS THIS_COMMAND THIS_ARGUMENTS 1>&2
|
while getopts v flag 2>/dev/null; do
|
||||||
# When receiving a command with arguments, do not differ between
|
[[ "$flag" != "v" ]] || verbose=1
|
||||||
# one and multiple arguments.
|
|
||||||
THIS="$*"
|
|
||||||
THIS_COMMAND="${THIS%% *}"
|
|
||||||
# ${THIS%%* } would result in THIS_COMMAND when no arguements are specified.
|
|
||||||
# We want an empty string in this case.
|
|
||||||
THIS_ARGUMENTS="${THIS#${THIS_COMMAND}}"
|
|
||||||
|
|
||||||
# Resolve all aliases
|
|
||||||
while [[ "$(which $THIS_COMMAND | head -n1)" =~ "^${THIS_COMMAND}: aliased to " ]]; do
|
|
||||||
if (( $VERBOSE_MODE )); then
|
|
||||||
echo $THIS_COMMAND$THIS_ARGUMENTS
|
|
||||||
fi
|
|
||||||
THIS="$(which "$THIS_COMMAND" | cut -d' ' -f4-)"
|
|
||||||
THIS_COMMAND="${THIS%% *}"
|
|
||||||
THIS_ARGUMENTS="${THIS#${THIS_COMMAND}}$THIS_ARGUMENTS"
|
|
||||||
|
|
||||||
done
|
done
|
||||||
|
shift $((OPTIND - 1))
|
||||||
|
|
||||||
command_type="$(type $THIS_COMMAND)"
|
full_cmd=("$@")
|
||||||
if [[ "$command_type" =~ "^$THIS_COMMAND is a shell function from " ]]; then
|
cmd="${full_cmd[1]}"
|
||||||
if (( $SCRIPT_MODE )); then
|
|
||||||
echo -n "$THIS_COMMAND$THIS_ARGUMENTS"
|
(( ! verbose )) || uniq_print "${full_cmd[@]}"
|
||||||
return 0
|
|
||||||
elif (( $VERBOSE_MODE )); then
|
# Resolve aliases
|
||||||
echo "$THIS_COMMAND$THIS_ARGUMENTS"
|
while [[ "$cmd" != "$old_cmd" ]]; do
|
||||||
|
out="$(command -v "$cmd")"
|
||||||
|
# NOTE: cannot be combined for the case that $cmd is not an alias
|
||||||
|
out="${out#alias $cmd=}" # Extract the alias or command
|
||||||
|
out="${${out#\'}%\'}"
|
||||||
|
# Beware of potential empty element leading to print trailing whitespace
|
||||||
|
if (( $#full_cmd > 1)); then
|
||||||
|
full_cmd=($out "${full_cmd[2,-1]}")
|
||||||
else
|
else
|
||||||
echo "$* is resolved to:\n$THIS_COMMAND$THIS_ARGUMENTS"
|
full_cmd=($out)
|
||||||
fi
|
fi
|
||||||
echo -n "${command_type}:"
|
(( ! verbose )) || uniq_print "${full_cmd[@]}"
|
||||||
from_file="$(echo $command_type | cut -d' ' -f7-)"
|
old_cmd="$cmd"
|
||||||
# from_file=${command_type##* }
|
cmd="${full_cmd[1]}"
|
||||||
grep -En -m1 "(function[ \t]+${THIS_COMMAND}[ \t]*(\(\)|)[ \t]*{|${THIS_COMMAND}[ \t]*\(\)[ \t]*{)" "$from_file" \
|
done
|
||||||
| cut -d: -f1
|
|
||||||
|
# Resolve symlinks
|
||||||
|
if [[ -e "$cmd" ]]; then
|
||||||
|
# When we are not verbose a call to realpath is sufficient and way
|
||||||
|
# faster.
|
||||||
|
if (( ! verbose )); then
|
||||||
|
cmd="$(realpath "$cmd")"
|
||||||
|
full_cmd=("$cmd" "${full_cmd[2,-1]}")
|
||||||
else
|
else
|
||||||
if (( $VERBOSE_MODE )); then
|
old_cmd=
|
||||||
echo "$THIS_COMMAND$THIS_ARGUMENTS"
|
while [[ "$cmd" != "$old_cmd" ]]; do
|
||||||
|
# Get filename with potential symlink target
|
||||||
|
out="$(stat -c "%N" "$cmd")"
|
||||||
|
# NOTE: cannot be combined for the case that $cmd is not symlink
|
||||||
|
out="${out#*-> }"
|
||||||
|
out="${${out#\'}%\'}"
|
||||||
|
# Beware of symlinks pointing to a relative path
|
||||||
|
[[ "${out[1]}" = '/' ]] || out="$(dirname "$cmd")/$out"
|
||||||
|
# Beware of potential empty element leading to print trailing
|
||||||
|
# whitespace
|
||||||
|
if (( $#full_cmd > 1)); then
|
||||||
|
full_cmd=("$out" "${full_cmd[2,-1]}")
|
||||||
|
else
|
||||||
|
full_cmd=("$out")
|
||||||
fi
|
fi
|
||||||
THIS_COMMAND="$(which $THIS_COMMAND)"
|
uniq_print "${full_cmd[@]}" # verbose is set
|
||||||
if [[ $? -ne 0 ]]; then
|
old_cmd="$cmd"
|
||||||
echo "${THIS_COMMAND%% *} not found." >&2
|
cmd="${full_cmd[1]}"
|
||||||
return 1
|
done
|
||||||
fi
|
fi
|
||||||
if (( $VERBOSE_MODE )); then
|
|
||||||
echo -n "$THIS_COMMAND"
|
|
||||||
NEXT_STEP="$(file -bh $THIS_COMMAND | cut -d' ' -f4-)"
|
|
||||||
if [[ "${NEXT_STEP:0:1}" != '/' ]]; then
|
|
||||||
NEXT_STEP="${THIS_COMMAND%/*}/$NEXT_STEP"
|
|
||||||
fi
|
|
||||||
while [[ "$(file -bh $THIS_COMMAND)" =~ "^symbolic link to" && "$NEXT_STEP" != "$THIS_COMMAND" ]]; do
|
|
||||||
THIS_COMMAND=$NEXT_STEP
|
|
||||||
NEXT_STEP="$(file -bh $THIS_COMMAND | cut -d' ' -f4-)"
|
|
||||||
if [[ "${NEXT_STEP:0:1}" != '/' ]]; then
|
|
||||||
NEXT_STEP="${THIS_COMMAND%/*}/$NEXT_STEP"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -n "\n$THIS_COMMAND"
|
uniq_print "${full_cmd[@]}"
|
||||||
done
|
|
||||||
echo $THIS_ARGUMENTS
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
THIS_COMMAND="$(realpath $THIS_COMMAND)"
|
|
||||||
if (( $SCRIPT_MODE )); then
|
|
||||||
echo -n "$THIS_COMMAND$THIS_ARGUMENTS"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
echo "$* is resolved to:\n$THIS_COMMAND$THIS_ARGUMENTS"
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
## Grep a keyword at the beginning of a line (ignoring whitespace) in a man page
|
## Grep a keyword at the beginning of a line (ignoring whitespace) in a man page
|
||||||
|
|||||||
Reference in New Issue
Block a user