Last active
June 4, 2022 00:53
-
-
Save hypersoft/5003746 to your computer and use it in GitHub Desktop.
libcore.sh Generated from auto chained library using lib.cache.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
lib.array.count () | |
{ | |
eval echo \${#$1[@]}; | |
} | |
lib.array.dump () | |
{ | |
declare ref2="$1[@]"; | |
IFS='' printf %s$'\1' "${!ref2}"; | |
} | |
lib.array.keys () | |
{ | |
eval echo \${!$1[@]}; | |
} | |
lib.array.ids () | |
{ | |
echo $(printf "$1[%i] " $(lib.array.keys $1)); | |
} | |
lib.array.pop () | |
{ | |
[[ $1 == -d ]] && { declare d="${2//%/%%}"; shift 2; } | |
declare d="${d:-$'\n'}" var=$1; declare -i count=`lib.array.count $1`; | |
(( count )) || return; count=$(( count - $2)); | |
eval "set -- \${$var[@]:$count}"; printf %s "$1"; shift; | |
declare arg=''; for arg; do printf -- "$d%s" "$arg"; done; | |
eval declare -ga $var="'(\${$var[@]:0:$count})'" | |
} | |
lib.array.push () | |
{ | |
declare target=$1; shift; | |
declare -i index=$(lib.array.count $target); | |
declare IFS=''; | |
for item; do | |
printf -v $target[index++] %s "$item"; | |
done; | |
} | |
lib.array.read () | |
{ | |
echo unset $( lib.array.gen.range $1 0-$((`lib.array.count $1` - 1)) ); | |
declare -i i=0; | |
while read -d$'\1' $1[i++]; do true; done; | |
unset $1[$((i-1))]; | |
} | |
lib.array.shift () | |
{ | |
[[ $1 == -d ]] && { declare d="${2//%/%%}"; shift 2; } | |
declare d="${d:-'\n'}" var=$1; declare -i count=`lib.array.count $1`; | |
(( count )) || return; (( $2 <= count )) || return; | |
count=$2; eval "set -- \${$var[@]:0:$count}"; printf -- %s "$1"; shift; | |
declare arg=''; for arg; do printf -- ''"$d%s" "$arg"; done; | |
eval declare -ga $var="'(\${$var[@]:$count})'"; | |
} | |
lib.lang.bash.function () | |
{ | |
(($#)) || return; | |
(printf '%s\n{\n' "$1 ()"; shift; (($#)) || set -- /dev/stdin; | |
for file; do IFS='' read -rN0 source < "$file"; printf '%s' "$source"; done; | |
printf '\n}\n\n'; | |
) | |
} | |
lib.shell.error () | |
{ | |
declare -A trace; | |
read trace[line] trace[sub] trace[file] < <(caller 0); | |
[[ -z "${trace[line]}" ]] && trace[line]=$BASH_LINENO; | |
[[ -z "${trace[file]}" ]] && { | |
trace[file]=`readlink -e /dev/stdin`; | |
trace[file]=${trace[file]/`pwd`\/}; | |
} | |
[[ -z "${trace[sub]}" ]] && trace[sub]="${FUNCNAME[1]}"; | |
[[ -z "${trace[sub]}" ]] && trace[sub]="main"; | |
[[ "${trace[sub]}" =~ ^"$FUNCNAME"$ ]] && { | |
trace[file]=$0; | |
trace[sub]="fatal: main"; | |
}; | |
[[ "${trace[sub]}" =~ ^source$ ]] && { | |
trace[sub]="main"; | |
}; | |
printf %s\\n "($SHLVL) ${trace[file]}: ${trace[sub]}: line ${trace[line]}`printf ': %s' "${@}"`" >&2; | |
unset e; ${e:?"`printf %b '\E[2K\E[1A'`"}; | |
} | |
lib.var.id () | |
{ | |
[[ "$1" =~ ^([a-zA-Z\_][a-zA-Z0-9_]+)\.(.*)$ ]] && { | |
echo ${BASH_REMATCH[1]}[${BASH_REMATCH[2]//:/.}]; | |
return; | |
} | |
[[ "$1" =~ ^([a-zA-Z\_][a-zA-Z0-9_]+)\[? ]] && { | |
echo "$1"; | |
return; | |
} | |
lib.shell.error "\`$1'" "is not a valid variant label"; | |
} | |
lib.param.source () | |
{ | |
if [[ "$1 $2" == 'shift loop' ]]; then | |
shift 2; | |
declare expr="${1}"; | |
declare body="${2#$(printf '\n')*}"; | |
declare fallback=${3:-'lib.shell.error "$1" "unhandled invocation operator"}'}; | |
printf 'while [[ "${1}" =~ %s ]]; do\n\n%s\n\n%s;\n\ndone;\n' "$expr" "${body}" "${fallback%*;}"; | |
return; | |
else | |
if [[ "$1 $2" == 'parse option' ]]; then | |
shift 2; | |
declare postop=${4}; | |
[[ -z "$postop" ]] || postop="${postop%*;};"; | |
printf '%s\n' '[[ "$1" =~ ^('$1')$ ]] && { '`lib.var.id $2`'="'$3'"; shift 1; '"$postop"' };'; | |
return; | |
else | |
if [[ "$1 $2" == 'parse argument' ]]; then | |
shift 2; | |
declare postop=${3}; | |
[[ -z "$postop" ]] || postop="${postop%*;};"; | |
printf '[[ "$1" =~ ^(%s)=?(.*)$ ]] && { ' "$1"; | |
printf '[[ -z "${BASH_REMATCH[2]}" ]] && { %s="$2"; shift 2; } || ' "`lib.var.id $2`"; | |
printf '{ %s="${BASH_REMATCH[2]}"; shift 1; }; %s };\n' "`lib.var.id $2`" "$postop"; | |
return; | |
fi; | |
fi; | |
fi | |
} | |
lib.param.unique () | |
{ | |
local arg; local -A RECORDS; | |
for arg; do | |
if [[ ${RECORDS[$arg]} == defined ]]; then continue; fi; | |
RECORDS[$arg]=defined; echo "$arg"; | |
done; | |
} | |
lib.path.list () | |
{ | |
declare -i __recursive=0; | |
eval "$(lib.param.source parse option -r __recursive 1)"; | |
(shopt -s dotglob; path="${1+${1%/}/}"; shift; | |
[[ -d "$path" || -z "$path" ]] || { | |
echo $FUNCNAME: error: \`$path\' is not a directory >&2; return 1; | |
} | |
IFS=$'\1'; | |
for f in `printf '%s\1' "$path"*`; do IFS=$' \t\n'; | |
[[ "$f" != '*' ]] && printf '%s\n' "$f"; | |
[[ "$__recursive" == 1 && -d "$f" ]] && $FUNCNAME -r "$f"; | |
done; | |
); | |
} | |
lib.param.filter () | |
{ | |
declare -i inverted=0; eval "$(lib.param.source parse option '-i|--inverted' inverted 1)"; | |
declare arg rx="$1"; shift; | |
(( $# )) || return 2; | |
(( inverted )) && { | |
for arg; do [[ "$arg" =~ $rx ]] || printf '%s\n' "$arg"; done; | |
} || { | |
for arg; do [[ "$arg" =~ $rx ]] && printf '%s\n' "$arg"; done; | |
}; | |
} | |
lib.read.for () | |
{ | |
# Usage: lib.read.for [line|char|record delimiter "char"] [do command] [in file ...] | |
declare -A env[line]=0 env[delimited]=0 env[binary]=0; declare -i EOF; | |
if [[ "$1" == char ]]; then env[binary]=1; shift; | |
elif [[ "$1" == line ]]; then env[line]=1; shift; | |
elif [[ "$1$2" == recorddelimiter ]]; then env[delimited]=1 env[delimiter]="$3"; | |
shift 2; shift; fi; # remove that shift and ur dead on the next comparison. | |
[[ "$_" == shift ]] && { | |
[[ "$1" == do ]] && { env[command]="$2"; shift 2; }; | |
[[ $? && "$1" == in ]] && shift; | |
}; (($#)) || set -- /dev/stdin; | |
env[files]=$#; | |
(( env[binary] )) && { | |
declare file char; [[ -n "${env[command]}" ]] && { | |
for file; do EOF=0; while (( ! EOF )); do | |
read -rN1 char; EOF=$?; true; | |
${env[command]} "$char" || return; | |
done <"$file"; done; return; | |
} || { | |
for file; do while read -rN1 char; do | |
printf "%c" "$char"; done <"$file"; | |
done; return; | |
} | |
} || (( env[line] )) && { | |
declare file line; [[ -n "${env[command]}" ]] && { | |
for file; do while IFS='' read -r line; do | |
EOF=0 ${env[command]} "$line" || return; done <"$file"; | |
EOF=1 ${env[command]} "$line"; | |
done; return; | |
} || { "$BASH_SOURCE: $FUNCNAME: $LINENO: error: set line: callback"; | |
return; | |
} | |
} || (( env[delimited] )) && { | |
declare file record; [[ -n "${env[command]}" ]] && { | |
for file; do while IFS='' read -rd "${env[delimiter]}" record; do | |
EOF=0 ${env[command]} "$record" || return; done <"$file"; | |
EOF=1 ${env[command]} "$record"; | |
done; return; | |
} || { "$BASH_SOURCE: $FUNCNAME: $LINENO: error: set delimited: callback"; | |
return; | |
} | |
} || { | |
declare file content; [[ -n "${env[command]}" ]] && { | |
for file; do IFS='' read -rN0 content <"$file"; | |
${env[command]} '%s' "$content" || return; | |
done; return; | |
} || \ | |
for file; do IFS='' read -rN0 content <"$file"; printf '%s' "$content"; done; | |
}; | |
} | |
lib.var.engine () | |
{ | |
[[ "$1" == --initialize ]] && { | |
(( VARENGINE )) && return; | |
declare script="/tmp/$$.$RANDOM.`date +%s`.var.eng"; | |
cat <<-"EOF" > "$script"; | |
exec 4>&- 5>&-; rm $0; | |
shopt -s expand_aliases; | |
declare -i LINE; | |
alias io.send="printf %s$'\1'" io.receive="read -rd $'\1'"; | |
property.var.name () | |
{ | |
[[ "$1" =~ ^([a-zA-Z_][a-zA-Z0-9_]+)\.(.*)$ ]] && { | |
echo "${BASH_REMATCH[1]}[${BASH_REMATCH[2]}]"; | |
return; | |
} | |
[[ "$1" =~ ^([a-zA-Z_][a-zA-Z0-9_]+)\[? ]] && { | |
echo "$1"; | |
return; | |
} | |
echo "$0: error: \`$1'" "is not a valid variant label" >&2; | |
} | |
property.var.declared () | |
{ | |
eval [[ "\${$1+declared}" == 'declared' ]] && \ | |
io.send true || io.send false; | |
} | |
property.var.filter () | |
{ | |
declare arg rx="$1" rxm='&&'; shift; | |
[[ ${rx:0:1} == - ]] && { | |
rx="${rx:1}"; rxm='||' | |
} | |
(( $# )) || return 2; | |
declare action='for arg; do [[ "$arg" =~ $rx ]] '"$rxm"' printf "%s\\n" "$arg"; done;'; | |
eval "$action"; | |
} | |
lib.var.engine.parse () | |
{ | |
let LINE++; [[ -z "$line" ]] && return; declare -a cmd; read -a cmd <<<"$line"; | |
if [[ "${cmd}" == exit ]]; then $line; fi; | |
if [[ "${cmd}" == erase ]]; then | |
unset "`property.var.name ${cmd[1]}`"; return; fi; | |
if [[ "${cmd}" == defined ]]; then | |
property.var.declared "`property.var.name ${cmd[1]}`"; return; fi; | |
if [[ "${cmd}" == set ]]; then | |
declare "___varname___"="`property.var.name "${cmd[1]}"`"; | |
declare -gA "${___varname___}"; | |
[[ "$___varname___" =~ ^IFS$ ]] && ___varname___ = _; | |
IFS='' io.receive "${___varname___}"; return; | |
fi; | |
if [[ "${cmd}" == get ]]; then | |
declare _vn="`property.var.name "${cmd[1]}"`"; | |
printf '%s' "${!_vn}"; | |
io.send ''; return; | |
fi; | |
if [[ "${cmd}" == names ]]; then | |
property.var.filter "${cmd[1]}" `printf '${!%s@} ' {a..z} {A..Z} | eval echo "$(read -rN0; echo $REPLY)"`; | |
io.send ''; return; | |
fi; | |
if [[ "${cmd}" == keys ]]; then | |
declare _vn; | |
printf -v _vn 'printf '\'${cmd[1]}'.%%s\n'\'' ${!%s[@]}' "`property.var.name "${cmd[1]}"`"; | |
property.var.filter "${cmd[2]:-.*}" $(eval $_vn); | |
io.send ''; return; | |
fi; | |
printf %s\\n "$0: line $LINE: unrecognized command: $cmd" >&2; | |
} | |
while IFS='' read -r line; do let LINE++; lib.var.engine.parse "$line"; done; | |
[[ -n "$line" ]] && lib.var.engine.parse "$line"; | |
EOF | |
declare stderr=/dev/`ps "$$" | { read; read _ termio _; echo "$termio"; }`; | |
exec 4<> <(:) 5<> <(:); | |
{ exec 6> "$stderr"; exec -a "$FUNCNAME" bash "$script" <&4 >&5 2>&6 & } 2>&-; | |
declare -gA VARENGINE=$! VARENGINE[stdin]="/dev/fd/4" \ | |
VARENGINE[stdout]="/dev/fd/5" VARENGINE[pid]=$!; | |
return; | |
}; | |
var () | |
{ | |
(( ! VARENGINE[pid] )) && { | |
echo $FUNCNAME: fatal: no property engine alive >&2; return 127; | |
}; | |
# logic check that does not really do anything apparently useful | |
(( VARENGINE[ppid] != $$ )) && { | |
echo $FUNCNAME: error: incorrect process rights: $* >&2; return 2; | |
} | |
# logic check that does not really do anything apparently useful | |
(( VARENGINE[pshlvl] != SHLVL )) && { | |
echo $FUNCNAME: error: incorrect shell level: $* >&2; return 2; | |
} | |
[[ "$1" == set ]] && { | |
# echo set >&2; | |
# logic check that does not really do anything apparently useful | |
while (( VARENGINE[transfer] )); do sleep 0.001; done; | |
VARENGINE[transfer]=1; | |
echo "$1 $2"; shift 2; | |
(( $# )) && ( IFS=''; printf %s "$@"; ) || "lib.read.for"; | |
echo -n $'\1'; | |
VARENGINE[transfer]=0; | |
return; | |
} > "${VARENGINE[stdin]}"; | |
[[ "$1" =~ ^defined$ ]] && { | |
# logic check that does not really do anything apparently useful | |
while (( VARENGINE[transfer] )); do sleep 0.001; done; | |
VARENGINE[transfer]=1; | |
echo "$1 $2" > "${VARENGINE[stdin]}"; | |
IFS='' read -rd $'\1' < "${VARENGINE[stdout]}"; | |
VARENGINE[transfer]=0; | |
[[ "$REPLY" == true ]]; | |
return; | |
}; | |
[[ "$1" =~ ^erase$ ]] && { | |
# logic check that does not really do anything apparently useful | |
while (( VARENGINE[transfer] )); do sleep 0.001; done; | |
VARENGINE[transfer]=1; | |
echo "$1 $2" > "${VARENGINE[stdin]}"; | |
VARENGINE[transfer]=0; | |
return; | |
}; | |
[[ "$1" =~ ^keys$ ]] && { | |
# echo get >&2; | |
# logic check that does not really do anything apparently useful | |
while (( VARENGINE[transfer] )); do sleep 0.001; done; | |
VARENGINE[transfer]=1; | |
echo "$1 $2 $3" > "${VARENGINE[stdin]}"; | |
IFS='' read -rd $'\1' $4 < "${VARENGINE[stdout]}"; | |
VARENGINE[transfer]=0; | |
[[ -z "$4" ]] && IFS='' printf %s "$REPLY"; | |
return; | |
}; | |
[[ "$1" =~ ^get|names$ ]] && { | |
# echo get >&2; | |
# logic check that does not really do anything apparently useful | |
while (( VARENGINE[transfer] )); do sleep 0.001; done; | |
VARENGINE[transfer]=1; | |
echo "$1 $2" > "${VARENGINE[stdin]}"; | |
IFS='' read -rd $'\1' $3 < "${VARENGINE[stdout]}"; | |
VARENGINE[transfer]=0; | |
[[ -z "$3" ]] && IFS='' printf %s "$REPLY"; | |
return; | |
}; | |
}; | |
lib.var.engine --initialize && \ | |
declare -gA VARENGINE[ppid]=$$ VARENGINE[pshlvl]=$SHLVL VARENGINE[transfer]=0; | |
true; | |
} | |
lib.cache () | |
{ | |
lib.var.engine; var defined lib || var set lib ""; | |
lib.cache.name () | |
{ | |
declare -A _opt[function]=0; | |
eval "$(lib.param.source parse option -f _opt[function] 1)"; | |
printf -v "$1" %s "${!1//\//.}"; | |
(( _opt[function] )) && printf -v "$1" %s "${!1%.sh}"; | |
} | |
lib.cache.get () | |
{ | |
declare alias="$1"; lib.cache.name -f alias; | |
var defined lib.cache.$alias && var get "lib.cache.$alias" $2; | |
} | |
lib.cache.set () | |
{ | |
declare alias="$1"; lib.cache.name -f alias; | |
var set "lib.cache.$alias" "${@:2}"; | |
} | |
lib.cache.list () | |
{ | |
declare data alias="$1"; lib.cache.name -f alias; shift; | |
lib.cache.get $alias data; (($#)) && { | |
lib.param.unique ${data} ${@} | lib.cache.set $alias; | |
} || { printf %s\\n "$FUNCNAME: error: missing parameters" >&2; return 1; }; | |
} | |
lib.cache () | |
{ | |
[[ -z "$1" ]] && return; declare file="$1"; | |
((job && tot)) || lib.cache.term.status "caching $file"; | |
[[ -d "$file" ]] && { lib.cache.term.status "caching directory $file"; | |
lib.cache.list dirs "${file}"; return; | |
}; | |
[[ "$file" =~ \.sh$ ]] && { lib.cache.list funcs "${file}"; | |
lib.cache.set "${file%.sh}.file" "$file"; | |
lib.cache.set "${file}" < "$file"; | |
return; | |
}; | |
[[ "$file" =~ \.dep$ ]] && { lib.cache.list deps "${file}"; | |
lib.cache.set "${file}.file" "$file"; | |
lib.cache.set "${file}" < "$file"; | |
return; | |
}; | |
lib.cache.list other "${file}"; | |
} | |
lib.cache.update () | |
{ | |
declare arg; for arg; do lib.cache "$arg"; done; | |
} | |
lib.cache.import () | |
{ | |
eval "$(lib.cache.make "$@")"; | |
} | |
lib.cache.stale () | |
{ | |
declare file; for file in `lib.cache.get funcs`; do | |
[[ -N "$file" || ! -e "${file%.sh}.dep" ]] && { echo "$file"; continue; }; | |
done; | |
} | |
lib.cache.make () | |
{ | |
var set lib.cache.build ""; | |
declare function body deps list; (($#)) || set -- `lib.cache.get funcs`; | |
for function; do lib.cache.name -f function; | |
lib.cache.get $function.dep deps; | |
printf -v list '%s\n' "${list}${deps}${function}"; | |
done; | |
lib.cache.list build `lib.param.unique $list`; | |
for function in `lib.cache.get build`; do | |
lib.cache.get $function | lib.lang.bash.function $function; | |
done; | |
} | |
lib.cache.term.status () | |
{ | |
{ | |
printf "%b" '\E[A\E[2K'; printf "%s\n" "$*"; | |
} >&2; | |
} | |
lib.cache.chain () | |
{ | |
lib.cache.scan.dep () | |
{ | |
declare functions dep dat depfile datfile; lib.cache.get funcs functions; | |
lib.param.unique $(for function; do lib.cache.name -f function; | |
datfile="${function//.//}.sh" depfile="${function//.//}.dep"; | |
[[ -e "$depfile" && ! -N "$datfile" && ! -N $depfile ]] && { | |
lib.cache.get "$function.dep"; echo "$function"; continue; | |
} || { | |
lib.cache.term.status "($job/$tot) scanning $function ..."; | |
[[ -N "$datfile" ]] && lib.cache.set "$function" < "$datfile"; | |
lib.cache.get "$function" body; | |
for name in $functions; do | |
lib.cache.name -f name; | |
datfile="${name//.//}.sh" depfile="${name//.//}.dep"; | |
[[ "$name" =~ "$function" ]] && continue; | |
[[ "$body" =~ [^\.]?"$name"[^\.]? ]] && { | |
printf -v dat %s "`lib.cache.scan.dep "$name"`"; | |
[[ ! -e $depfile || $datfile -nt $depfile ]] && { | |
lib.cache.term.status "($job/$tot) caching ${name//\//.}.dep ..."; | |
echo "$dat" > "${depfile}"; | |
} | |
lib.cache "${depfile}"; | |
echo "$dat"; echo "$name"; continue; | |
} | |
done; | |
} | |
done ); | |
} | |
lib.cache.make.deps () | |
{ | |
(($#)) || set -- `lib.cache.get funcs`; | |
declare file dep; for file; do | |
dep="${file%.sh}.dep"; | |
[[ "$dep" -nt "$file" ]] || { | |
lib.cache.term.status "($job/$tot) writing ${dep//\//.} ..."; | |
lib.cache.scan.dep $file > "$dep"; | |
lib.cache "$dep"; | |
} | |
done; | |
} | |
(($#)) || { set -- `lib.cache.stale`; } | |
(($#)) && { echo ''; ls "$@"; echo ''$'\n'; } >&2; | |
declare file f; declare -a deps; declare -i job tot=$#; | |
for file; do let job++; f="$file"; lib.cache.name -f f; | |
lib.cache.term.status "($job/$tot) scanning ${f} ..."; | |
lib.cache.make.deps "$file"; | |
lib.cache "$file"; | |
lib.array.push deps `lib.cache.get ${file%.sh}.dep` | |
done; | |
(($#)) && lib.cache.term.status "`lib.array.count deps` dependency links chained"; | |
unset -f lib.cache.make.deps lib.cache.scan.dep; | |
} | |
lib.cache.path () | |
{ | |
echo '' >&2; | |
set -- `lib.path.list -r $1`; | |
lib.cache.term.status "caching $# resource$((($# > 1)) && printf s) ... "; | |
for path do lib.cache $path; done; | |
set -- `lib.cache.get dirs`; declare dirs=$#; | |
set -- `lib.cache.get funcs`; declare funcs=$#; | |
(( funcs )) && { | |
lib.cache.term.status "$funcs functions in $dirs directories"; | |
lib.cache.chain; | |
} || { | |
lib.cache.term.status "Warning: no functions present"; | |
} | |
} | |
} | |
lib.date.serial () | |
{ | |
date +%s; | |
} | |
lib.file.close () | |
{ | |
# specify /dev/fd/N or N ... | |
(($#)) && eval $(printf 'exec '; | |
for __arg; do printf ' %i>&-' "${__arg##*/}"; done; echo \;; | |
); | |
} | |
lib.file.open () | |
{ | |
: lib.param.source required | |
declare _Target=REPLY; eval "$(lib.param.source parse argument -v _Target)"; | |
declare _Mode="$1" _File="$2"; _Mode="${_Mode/-rw/<>}"; _Mode="${_Mode/-r/<}"; | |
_Mode="${_Mode/-w/>}"; _Mode="${_Mode/-a/>>}"; declare -i _Start=9; | |
while [[ -e /dev/fd/$_Start ]]; do let _Start++; done; | |
eval exec "$_Start${_Mode}${_File:-/dev/null}"; | |
[[ "$_Target" != REPLY ]] && { printf -v "$_Target" %s "/dev/fd/$_Start"; | |
} || { echo "/dev/fd/$_Start"; } | |
} | |
lib.func.declared () | |
{ | |
declare -F "$1" >/dev/null; | |
} | |
lib.func.dump () | |
{ | |
declare -f $@; | |
} | |
lib.func.list () | |
{ | |
declare -pF | (while read backing flags func; do printf '%s\n' "$func"; done;) | |
} | |
lib.gen.temp () | |
{ | |
declare NOW=''; lib.date.serial -v NOW; | |
printf %08X%s\\n $(( SECONDS * RANDOM )) "$(printf -- .%08X \ | |
$(( ( RANDOM * 314 ) + NOW )) $(( SECONDS * RANDOM )) $(( ( RANDOM * $$ ) + NOW )))"; | |
} | |
lib.lang.bash.comment () | |
{ | |
lib.read.for line do "echo # "; | |
} | |
lib.lang.bash.doc () | |
{ | |
declare data="$(lib.read.for)"; | |
lib.bash.doc.fmt() { printf 'echo -E "%s";\n' "$1"; }; | |
data="${data//\"/\\\"}"; data="${data//\$/\\\$}"; data="${data//\`/\\\`}"; | |
printf %s "$data" | lib.read.for line do lib.bash.doc.fmt; | |
unset -f lib.bash.doc.fmt; | |
} | |
lib.param.count () | |
{ | |
printf %i "$#"; | |
} | |
lib.var.declared () | |
{ | |
eval [[ "\${$1+declared}" == 'declared' ]]; | |
} | |
lib.param.parse () | |
{ | |
[[ $1 == --cache ]] && { | |
lib.var.declared ARGC && lib.var.declared ARGV || \ | |
echo 'declare -i ARGC; declare -a ARGV;'; return; | |
}; | |
[[ $1 == --init ]] && { | |
lib.var.declared opts && lib.var.declared optargs && \ | |
lib.var.declared optl && lib.var.declared optargl || \ | |
echo "declare opts optargs optl optargl;"; return; | |
}; | |
[[ $1 == --master ]] && { | |
$FUNCNAME --cache; $FUNCNAME --init; return; | |
}; | |
eval `$FUNCNAME --master`; | |
while [[ ${1:0:1} == - ]]; do | |
[[ $1 == -- ]] && { shift; break; }; | |
[[ $1 =~ ^(-la|-al|--arg-long|--long-arg)$ ]] && { optargl=${2}; shift 2; continue; }; | |
[[ $1 =~ ^(-lo|-ol|--opt-long|--long-opt)$ ]] && { optl=$2; shift 2; continue; }; | |
[[ $1 =~ ^(-vla|-val|--var-arg-long|--long-arg-var)$ ]] && { optargl="${!2}"; shift 2; continue; }; | |
[[ $1 =~ ^(-vlo|-vol|--var-opt-long|--long-opt-var)$ ]] && { optl="${!2}"; shift 2; continue; }; | |
[[ $1 =~ ^(-sa|-as|--arg-short|--short-arg)$ ]] && { optargs=$2; shift 2; continue; }; | |
[[ $1 =~ ^(-so|-os|--opt-short|--short-opt)$ ]] && { opts=$2; shift 2; continue; }; | |
[[ $1 =~ ^(-vsa|-vas|--var-arg-short|--short-arg-var)$ ]] && { optargs="${!2}"; shift 2; continue; }; | |
[[ $1 =~ ^(-vso|-vos|--var-opt-short|--short-opt-var)$ ]] && { opts="${!2}"; shift 2; continue; }; | |
break; | |
done | |
declare arg; for arg; do | |
[[ $arg == -- ]] && { lib.array.push ARGV --; continue; }; | |
[[ $arg =~ ^-- ]] && { | |
lib.param.parse.long -- "$arg" | |
continue; | |
} | |
[[ $arg =~ ^- ]] && { | |
lib.param.parse.short -- "$arg"; | |
continue; | |
} | |
lib.array.push ARGV "$arg"; | |
done; | |
for arg in "${ARGV[@]}"; do | |
printf ' "%s"' "${arg//\"/\\\"}"; | |
done; | |
} | |
lib.param.long () | |
{ | |
eval `lib.param.parse --init`; declare dest=ARGV; | |
while [[ ${1:0:1} == - ]]; do | |
[[ $1 == -- ]] && { shift; break; }; | |
[[ $1 == -a ]] && { dest=$2; shift 2; continue; }; | |
[[ $1 =~ ^(-la|-al|--arg-long|--long-arg)$ ]] && { optargl=${2}; shift 2; continue; }; | |
[[ $1 =~ ^(-lo|-ol|--opt-long|--long-opt)$ ]] && { optl=$2; shift 2; continue; }; | |
[[ $1 =~ ^(-vla|-val|--var-arg-long|--long-arg-var)$ ]] && { optargl="${!2}"; shift 2; continue; }; | |
[[ $1 =~ ^(-vlo|-vol|--var-opt-long|--long-opt-var)$ ]] && { optl="${!2}"; shift 2; continue; }; | |
break; | |
done | |
optargl=${optargl//,/\|}; optl=${optl//,/\|}; | |
[[ $1 =~ ^--(${optl})$ ]] && { | |
lib.array.push $dest "--${BASH_REMATCH[1]}" | |
return; | |
} | |
[[ $1 =~ ^--(${optargl})=?(.*)$ ]] && { | |
lib.array.push $dest "--${BASH_REMATCH[1]}" | |
[[ -n "${BASH_REMATCH[2]}" ]] && lib.array.push $dest "${BASH_REMATCH[2]}"; | |
return; | |
} | |
} | |
lib.param.short () | |
{ | |
eval `lib.param.parse --init`; declare dest=ARGV; | |
while [[ ${1:0:1} == - ]]; do | |
[[ $1 == -- ]] && { shift; break; }; | |
[[ $1 == -a ]] && { dest=$2; shift 2; continue; }; | |
[[ $1 =~ ^(-sa|-as|--arg-short|--short-arg)$ ]] && { optargs=$2; shift 2; continue; }; | |
[[ $1 =~ ^(-so|-os|--opt-short|--short-opt)$ ]] && { opts=$2; shift 2; continue; }; | |
[[ $1 =~ ^(-vsa|-vas|--var-arg-short|--short-arg-var)$ ]] && { optargs="${!2}"; shift 2; continue; }; | |
[[ $1 =~ ^(-vso|-vos|--var-opt-short|--short-opt-var)$ ]] && { opts="${!2}"; shift 2; continue; }; | |
break; | |
done | |
{ | |
while read -rN1 char; do | |
[[ $char =~ ^[$opts]$ ]] && { lib.array.push $dest "-$char"; continue; }; | |
[[ $char =~ ^[$optargs]$ ]] && { lib.array.push $dest "-$char"; break; } | |
return 3; | |
done; | |
[[ $char =~ [$optargs] ]] && { | |
declare arg; read -rN0 arg; | |
[[ "$arg" =~ ^[=\:"`echo -E \n\t' '`"](.*)$ ]] && arg="${arg:1}"; | |
[[ -n "$arg" ]] && { lib.array.push $dest "$arg"; }; | |
return; | |
} | |
} < <(echo -En "${1:1}"); | |
} | |
lib.path.relative () | |
{ | |
declare -a path basedir; declare -i index=0; | |
IFS=/ read -a path <<<"${1%%/}"; IFS=/ read -a basedir <<<"`pwd`"; | |
while ((index < ${#basedir[@]})); do | |
[[ "${path[index]}" == "${basedir[index]}" ]] && { let index++; continue; }; | |
break; | |
done; | |
((index == 1)) && { echo "$1"; return; }; | |
for path in "${basedir[@]:${#basedir[@]}-index+1}"; do echo -n ../; done; | |
printf -v path %s "${path[@]:index:1}`printf /%s "${path[@]:index+1}"`"; | |
echo "${path%%/}"; | |
} | |
lib.session.owner () | |
{ | |
read owner _ < <(who -m); | |
printf '%s\n' "$owner"; | |
} | |
lib.session.tty () | |
{ | |
declare link; read _ link < <(who -m); | |
printf '%s\n' "/dev/$link"; | |
} | |
lib.shell.path () | |
{ | |
type -p "$1"; | |
} | |
lib.shell.run () | |
{ | |
declare -A param=$FUNCNAME \ | |
param[shortopt]='\?hcbv' param[longopt]='help,usage,check-syntax,barebones,verbose' \ | |
param[shortarg]='af' param[longarg]='file,alias' \ | |
param[file]='/dev/stdin' param[alias]="$param" \ | |
param[barebones]='0' param[verbose]='0' param[check-syntax]='0' \ | |
param[execopt]='' param[bashopt]=''; | |
[[ $1 =~ ^(-\?|-h|--help|--usage)$ ]] && { | |
echo "USAGE: $param [-cbv] [-a alias] [-f script] [--] ARG ..."; | |
echo ''; | |
[[ ${BASH_REMATCH[1]} == -? ]] && { | |
echo 'See --help for further information'; | |
echo ''; return 1; | |
} | |
[[ ${BASH_REMATCH[1]} == --usage ]] && { | |
echo 'See --help for further information'; | |
echo ''; return; | |
} | |
echo ' Execute or check the syntax of the given source in a subshell as a'; | |
echo ' named command.'; | |
echo ''; [[ ${BASH_REMATCH[1]} == -h ]] && return; | |
echo 'OPTIONS'; | |
echo ' -c or --check-syntax'" Parse only, bash syntax check"; | |
echo ' -b or --barebones'" Do not copy shell environment to"; | |
echo ' '" subprocess"; | |
echo ' -v or --verbose'" List source lines as they are parsed"; | |
echo ' -f or --file'" Direct source from file if not provided,"; | |
echo ' '" read stdin"; | |
echo ' -a or --alias'" Set script argument \$0, if not provided"; | |
echo ' '" default is: $param"; | |
echo ''; | |
echo ' Exit Status:'; | |
echo ' Whatever the source reports as an exit status, or true if the syntax'; | |
echo ' check succeeded.'; | |
echo ''; | |
return; | |
} | |
eval set -- "$(lib.param.parse \ | |
-vsa param[shortarg] -vso param[shortopt] \ | |
-vla param[longarg] -vlo param[longopt] -- "$@" | |
)"; | |
eval "$(lib.param.source shift loop - " | |
$(lib.param.source parse option -- _ this break;) | |
$(lib.param.source parse option '-b|--barebones' param[barebones] 1 continue;) | |
$(lib.param.source parse option '-?|-h|--help|--usage' param[barebones] 1 "$param \${BASH_REMATCH[1]}; return;") | |
$(lib.param.source parse option '-c|--check-syntax' param[check-syntax] 1 continue;) | |
$(lib.param.source parse option '-v|--verbose' param[verbose] 1 continue;) | |
$(lib.param.source parse argument '-a|--alias' param[alias] continue;) | |
$(lib.param.source parse argument '-f|--file' param[file] continue;) | |
" break; | |
)"; | |
# setup user config.. | |
(( param[barebones] )) && param[execopt]=-c; | |
(( param[verbose] )) && param[bashopt]=-v; | |
(( param[check-syntax] )) && param[bashopt]=${param[bashopt]:--}n; | |
# Create a new aliased shell. | |
(exec ${param[execopt]} -a "${param[alias]}" -- bash ${param[bashopt]} -s -- "$@";) \ | |
< "${param[file]}"; | |
} | |
lib.string.repeat () | |
{ | |
declare __ovar__; printf -v __ovar__ %*s $2; | |
printf %s ${__ovar__// /${1}}; | |
} | |
lib.val.calc () | |
{ | |
math() | |
{ | |
: | |
} | |
} | |
lib.var.printf () | |
{ | |
[[ "$1" =~ ^('-v')=?(.*)$ ]] && { | |
declare _commit='' ; | |
[[ -z "${BASH_REMATCH[2]}" ]] && { | |
_commit="$(lib.var.id "$2")" || return; shift 2; | |
} || { | |
_commit="$(lib.var.id "${BASH_REMATCH[2]}")" || return; shift 1; | |
}; | |
(($#)) && { | |
IFS='' read -rN0 "$_commit" < <(${FUNCNAME:-$0} -- "$@"); return; | |
} || { | |
IFS='' echo -E "$_commit"; return; | |
}; | |
} | |
[[ "$1" == '--' ]] && shift; | |
declare _vformat="$1" _pformat="$1" _fmt _tail; shift; | |
while [[ -n "$_vformat" ]]; do | |
if [[ "$_vformat" =~ ^([^\%]*)('%s['[\*[sv0-9]+']'|'%c['[\*[iv0-9]+']'|'%vt['[\*\ a-z0-9,]+\]|'%v'|%%?[^\%]*)?(.*) ]]; then | |
builtin printf %b "${BASH_REMATCH[1]}"; | |
_fmt="${BASH_REMATCH[2]}" _tail="${BASH_REMATCH[3]}"; | |
[[ "${_fmt}" =~ ^'%vt['([\*\ a-z0-9,]+)']' ]] && { | |
declare _match="${BASH_REMATCH[1]}"; | |
[[ "$_match" == *s ]] && { _match="$1"; shift; }; | |
[[ "$_match" == *v ]] && { _fmt="$(lib.var.id "$1")" || return; | |
_match="${!_fmt}"; shift; }; | |
_match="${_match/,/;}"; | |
_match="${_match/default/0}"; _match="${_match//bright/1}"; | |
_match="${_match//dim/2}"; _match="${_match//underline/4}"; | |
_match="${_match//blink/5}"; _match="${_match//reverse/7}"; | |
_match="${_match//hidden/8}"; _match="${_match// /}"; | |
_match="${_match//fc/3}"; _match="${_match//bg/4}"; | |
_match="${_match//black/0}"; _match="${_match//red/1}"; | |
_match="${_match//green/2}"; _match="${_match//yellow/3}"; | |
_match="${_match//blue/4}"; _match="${_match//magenta/5}"; | |
_match="${_match//cyan/6}"; _match="${_match//white/7}"; | |
builtin printf -- %b '\E['${_match}'m' || return; | |
builtin printf -v _vformat %s "${_tail}"; continue; | |
} | |
[[ "${_fmt}" =~ ^'%c['([\*iv0-9]+)']' ]] && { | |
declare _match="${BASH_REMATCH[1]}"; | |
[[ "$_match" == '*i' ]] && { _match="$1"; shift; }; | |
[[ "$_match" == '*v' ]] && { _fmt="$(lib.var.id "$1")" || return; | |
_match="${!_fmt}"; shift; }; | |
builtin printf -v _fmt '%*s' $_match; | |
_fmt="${_fmt// /${1:0:1}}"; shift; | |
builtin printf -- "%s" "${_fmt}" || return; shift; | |
builtin printf -v _vformat %s "${_tail}"; continue; | |
} | |
[[ "${_fmt}" =~ ^'%s['([\*sv0-9]+)']' ]] && { | |
declare _match="${BASH_REMATCH[1]}"; | |
[[ "$_match" == '*s' ]] && { _match="$1"; shift; }; | |
[[ "$_match" == '*v' ]] && { _fmt="$(lib.var.id "$1")" || return; | |
_match="${!_fmt}"; shift; }; | |
builtin printf -v _fmt '%*s' $_match; | |
_fmt="${_fmt// /${1}}"; shift; | |
builtin printf -- "%s" "${_fmt}" || return; shift; | |
builtin printf -v _vformat %s "${_tail}"; continue; | |
} | |
[[ "${_fmt}" =~ ^'%v' ]] && { | |
declare _v="$(lib.var.id "$1")" || return; | |
builtin printf -- "%s" "${!_v}" || return; shift; | |
builtin printf -v _vformat %s "${_tail}"; continue; | |
} | |
[[ "${_fmt}" =~ [^\\]\* ]] && { # the format requesting a parameter ... | |
builtin printf -- "${_fmt}" "$1" "$2" || return; shift 2; | |
} || { builtin printf -- "${_fmt}" "$1" || return; shift; } | |
builtin printf -v _vformat %s "${_tail}"; | |
fi; | |
done ; | |
(($#)) && $FUNCNAME "$_pformat" "$@"; | |
} | |
lib.var.root () | |
{ | |
[[ "$1" =~ ^([a-zA-Z_][a-zA-Z0-9_]+)\.?(.*)$ ]] && { | |
declare -gA ${BASH_REMATCH[1]}="${!BASH_REMATCH[1]}"; | |
return; | |
} | |
} | |
lib.var.type () | |
{ | |
{ | |
if declare -pA ${1:-invalid.property} >/dev/null; then echo "hash"; | |
elif declare -pa ${1:-invalid.property} >/dev/null; then echo "array"; | |
elif declare -pi ${1:-invalid.property} >/dev/null; then echo "integer"; | |
elif [[ $1 =~ ^(.+)\[.+\]$ ]]; then | |
[[ `lib.var.type ${BASH_REMATCH[1]}` =~ ^(hash|array)$ ]] && { | |
[[ ${BASH_REMATCH[1]} == hash ]] && { echo key; } || { | |
[[ ${BASH_REMATCH[1]} == array ]] && echo index; | |
} | |
} | |
elif lib.var.declared $1; then echo "string"; fi; | |
} 2>/dev/null; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment