Skip to content

Instantly share code, notes, and snippets.

@hypersoft
Last active June 4, 2022 00:53
Show Gist options
  • Save hypersoft/5003746 to your computer and use it in GitHub Desktop.
Save hypersoft/5003746 to your computer and use it in GitHub Desktop.
libcore.sh Generated from auto chained library using lib.cache.
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