Use dynamic dispatch for scripting libs
parent
bbe64105e4
commit
d1b095f98c
@ -0,0 +1,36 @@
|
||||
LOADED_LIBS=
|
||||
|
||||
include() {
|
||||
local file
|
||||
for file in "${@}"; do
|
||||
if [ -f "${XDG_DATA_HOME}/buddy/lib/${file}.sh" ]; then
|
||||
# shellcheck disable=SC1090
|
||||
. "${XDG_DATA_HOME}/buddy/lib/${file}.sh"
|
||||
else
|
||||
>&2 echo "include unknown: ${file}"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
require() {
|
||||
local file
|
||||
local previous
|
||||
for file in "${@}"; do
|
||||
echo "$LOADED_LIBS" | while read -r previous; do
|
||||
if [ -z "${previous}" ]; then
|
||||
continue
|
||||
elif [ "${previous}" = "${file}" ]; then
|
||||
continue 2
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -z "${LOADED_LIBS}" ]; then
|
||||
LOADED_LIBS=${file}
|
||||
else
|
||||
LOADED_LIBS="${LOADED_LIBS}\n${file}"
|
||||
fi
|
||||
|
||||
include "${file}"
|
||||
done
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
require bail
|
||||
|
||||
add_date_prefix () (
|
||||
if [ ! -f "$1" ]; then
|
||||
bail "unknown file: $1"
|
||||
fi
|
||||
mv "$1" "$(dirname "$1")/$(date -r "$1" +"%F")_$(basename "$1")"
|
||||
)
|
@ -0,0 +1,9 @@
|
||||
require bail
|
||||
|
||||
assert_command() (
|
||||
for cmd in "${@}"; do
|
||||
if ! command -v "${cmd}" 1>&2 >/dev/null; then
|
||||
bail "command not installed: ${cmd}"
|
||||
fi
|
||||
done
|
||||
)
|
@ -0,0 +1,7 @@
|
||||
require bail
|
||||
|
||||
must_be_root() (
|
||||
if [ "$(id --user)" != 0 ]; then
|
||||
bail "must run as root"
|
||||
fi
|
||||
)
|
@ -0,0 +1,4 @@
|
||||
bail() (
|
||||
echo >&2 "$@"
|
||||
exit 1
|
||||
)
|
@ -0,0 +1,3 @@
|
||||
file_age_in_seconds() (
|
||||
echo $(($(date +"%s") - $(stat -c "%Y" "${1}")))
|
||||
)
|
@ -0,0 +1,17 @@
|
||||
require assert/command
|
||||
|
||||
assert_command dasel gem jq
|
||||
|
||||
gem_env() (
|
||||
NAME=${1:-}
|
||||
if [ "${NAME}" ]; then
|
||||
gem environment |
|
||||
dasel --read yaml --write json |
|
||||
jq '.["RubyGems Environment"] | to_entries | map((.value | keys)[0] as $key | {key: $key, value: .value[$key] }) | from_entries' |
|
||||
jq --raw-output '.["'"${NAME}"'"]'
|
||||
else
|
||||
gem environment |
|
||||
dasel --read yaml --write json |
|
||||
jq '.["RubyGems Environment"] | to_entries | map((.value | keys)[0] as $key | {key: $key, value: .value[$key] }) | from_entries'
|
||||
fi
|
||||
)
|
@ -0,0 +1,11 @@
|
||||
require assert/command
|
||||
require bail
|
||||
|
||||
assert_command exiftool
|
||||
|
||||
get_bitrate() (
|
||||
if [ ! -f "$1" ]; then
|
||||
bail "unknown file: $1"
|
||||
fi
|
||||
exiftool -AudioBitrate "$1" | awk '{print $4}'
|
||||
)
|
@ -0,0 +1,7 @@
|
||||
github_download_url() (
|
||||
USER=$1
|
||||
REPO=$2
|
||||
TAG=$3
|
||||
FILE=$4
|
||||
echo "https://github.com/$USER/$REPO/releases/download/v${TAG}/${FILE}"
|
||||
)
|
@ -0,0 +1,16 @@
|
||||
require assert/command
|
||||
|
||||
assert_command rg
|
||||
|
||||
github_install_scripts() (
|
||||
rg github.com "${HOME}/.local/bin" |
|
||||
sed 's/:/ /' |
|
||||
sed 's/=/ /g' |
|
||||
awk '{print $3}' |
|
||||
sed 's|https://github.com/||g' |
|
||||
sed 's|/| |g' |
|
||||
awk '{print $1 " " $2}' |
|
||||
sed 's| |/|g' |
|
||||
sort |
|
||||
uniq
|
||||
)
|
@ -0,0 +1,8 @@
|
||||
require github/install_scripts
|
||||
require github/latest_release
|
||||
|
||||
github_install_scripts_latest_releases() (
|
||||
for REPO in $(github_install_scripts); do
|
||||
echo "${REPO} $(github_latest_release "${REPO}")"
|
||||
done
|
||||
)
|
@ -0,0 +1,5 @@
|
||||
require github/tags
|
||||
|
||||
github_latest_release() (
|
||||
github_tags "$@" | head -n 1
|
||||
)
|
@ -0,0 +1,14 @@
|
||||
require file_age_in_seconds
|
||||
require mkdir_if_missing
|
||||
|
||||
github_release_json() (
|
||||
PROJECT=$1
|
||||
DAY_IN_SECONDS=$((60 * 60 * 24))
|
||||
JSON=${XDG_CACHE_HOME}/apps/meta/${PROJECT}/releases.json
|
||||
mkdir_if_missing "$(dirname "${JSON}")"
|
||||
FILE_AGE=$(file_age_in_seconds "${JSON}")
|
||||
if [[ ! -f ${JSON} || ${FILE_AGE} -gt ${DAY_IN_SECONDS} ]]; then
|
||||
curl --silent --output "${JSON}" "https://api.github.com/repos/${PROJECT}/releases"
|
||||
fi
|
||||
echo "${JSON}"
|
||||
)
|
@ -0,0 +1,14 @@
|
||||
require assert/command
|
||||
|
||||
assert_command curl
|
||||
|
||||
github_releases() (
|
||||
USER=${1}
|
||||
REPO=${2-}
|
||||
if [ -z "${REPO}" ]; then
|
||||
USER=$(echo "${1}" | sed 's|/| |g' | awk '{print $1}')
|
||||
REPO=$(echo "${1}" | sed 's|/| |g' | awk '{print $2}')
|
||||
fi
|
||||
curl --silent --header "Accept: application/vnd.github.v3+json" \
|
||||
"https://api.github.com/repos/${USER}/${REPO}/releases"
|
||||
)
|
@ -0,0 +1,15 @@
|
||||
require assert/command
|
||||
|
||||
assert_command curl jq
|
||||
|
||||
github_tags() (
|
||||
USER=${1}
|
||||
REPO=${2-}
|
||||
if [ -z "${REPO}" ]; then
|
||||
USER=$(echo "${1}" | sed 's|/| |g' | awk '{print $1}')
|
||||
REPO=$(echo "${1}" | sed 's|/| |g' | awk '{print $2}')
|
||||
fi
|
||||
curl --silent --header "Accept: application/vnd.github.v3+json" \
|
||||
"https://api.github.com/repos/${USER}/${REPO}/tags" |
|
||||
jq -r '.[].name'
|
||||
)
|
@ -0,0 +1,6 @@
|
||||
go_deps() (
|
||||
GO_MOD=${1:-go.mod}
|
||||
START_AT=$(grep -n '^require ($' "${GO_MOD}" | awk -F : '{print $1}' | head -n 1)
|
||||
END_AT=$(grep -n '^)$' "${GO_MOD}" | awk -F : '{print $1}' | head -n 1)
|
||||
awk 'NR>'"${START_AT}"' && NR<'"${END_AT}"' {print $1}' "${GO_MOD}"
|
||||
)
|
@ -0,0 +1,14 @@
|
||||
require assert/command
|
||||
|
||||
assert_command bat dasel
|
||||
|
||||
json_to_yaml() (
|
||||
ARG=${1-}
|
||||
if [ -z "${ARG}" ]; then
|
||||
dasel --read json --write yaml | bat --language yaml
|
||||
elif [ -f "${ARG}" ]; then
|
||||
dasel --read json --write yaml --file "${ARG}" | bat --language yaml
|
||||
else
|
||||
echo "${ARG}" | dasel --read json --write yaml | bat --language yaml
|
||||
fi
|
||||
)
|
@ -0,0 +1,17 @@
|
||||
make_script() (
|
||||
for FILE in "$@"; do
|
||||
cat <<EOF >"${FILE}"
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
main() (
|
||||
echo "todo"
|
||||
exit 1
|
||||
)
|
||||
|
||||
main "\$@"
|
||||
EOF
|
||||
chmod +x "${FILE}"
|
||||
done
|
||||
)
|
@ -0,0 +1,13 @@
|
||||
require assert/command
|
||||
|
||||
assert_command jpegtran
|
||||
|
||||
min_jpg() (
|
||||
for FILE in "$@"; do
|
||||
PERMISSIONS=$(stat --format '%a' "${FILE}")
|
||||
OUT_FILE=$(mktemp)
|
||||
jpegtran -optimize -perfect -outfile "${OUT_FILE}" "${FILE}"
|
||||
mv "${OUT_FILE}" "${FILE}"
|
||||
chmod "${PERMISSIONS}" "${FILE}"
|
||||
done
|
||||
)
|
@ -0,0 +1,13 @@
|
||||
require assert/command
|
||||
|
||||
assert_command pngcrush
|
||||
|
||||
min_png() (
|
||||
for FILE in "$@"; do
|
||||
PERMISSIONS=$(stat --format '%a' "${FILE}")
|
||||
OUT_FILE=$(mktemp)
|
||||
pngcrush -rem alla -reduce -brute "${FILE}" "${OUT_FILE}"
|
||||
mv "${OUT_FILE}" "${FILE}"
|
||||
chmod "${PERMISSIONS}" "${FILE}"
|
||||
done
|
||||
)
|
@ -0,0 +1,8 @@
|
||||
mkdir_if_missing() (
|
||||
dir=${1}
|
||||
sudo=${2-}
|
||||
if [ ! -d "${dir}" ]; then
|
||||
# shellcheck disable=SC2086
|
||||
$sudo mkdir -p "${dir}"
|
||||
fi
|
||||
)
|
@ -0,0 +1,4 @@
|
||||
node_current() (
|
||||
curl --silent https://nodejs.org/dist/index.tab |
|
||||
cut -f 1,10 | grep '-' | head -n 1 | cut -f 1
|
||||
)
|
@ -0,0 +1,4 @@
|
||||
node_lts() (
|
||||
curl --silent https://nodejs.org/dist/index.tab |
|
||||
cut -f 1,10 | grep -v '-' | head -n 2 | tail -n 1 | cut -f 1
|
||||
)
|
@ -0,0 +1,43 @@
|
||||
relative_path() (
|
||||
# both $1 and $2 are absolute paths beginning with /
|
||||
# $1 must be a canonical path; that is none of its directory
|
||||
# components may be ".", ".." or a symbolic link
|
||||
#
|
||||
# returns relative path to $2/$target from $1/$src
|
||||
src=$1
|
||||
target=$2
|
||||
|
||||
common_part=$src
|
||||
result=
|
||||
|
||||
while [ "${target#"$common_part"}" = "$target" ]; do
|
||||
# no match, means that candidate common part is not correct
|
||||
# go up one level (reduce common part)
|
||||
common_part=$(dirname "$common_part")
|
||||
# and record that we went back, with correct / handling
|
||||
if [ -z "$result" ]; then
|
||||
result=..
|
||||
else
|
||||
result=../$result
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$common_part" = / ]; then
|
||||
# special case for root (no common path)
|
||||
result=$result/
|
||||
fi
|
||||
|
||||
# since we now have identified the common part,
|
||||
# compute the non-common part
|
||||
forward_part=${target#"$common_part"}
|
||||
|
||||
# and now stick all parts together
|
||||
if [ -n "$result" ] && [ -n "$forward_part" ]; then
|
||||
result=$result$forward_part
|
||||
elif [ -n "$forward_part" ]; then
|
||||
# extra slash removal
|
||||
result=${forward_part#?}
|
||||
fi
|
||||
|
||||
printf '%s' "$result"
|
||||
)
|
@ -0,0 +1,12 @@
|
||||
#shellcheck disable=SC2120
|
||||
slugify() (
|
||||
if [ "$#" -ne 0 ]; then
|
||||
#shellcheck disable=SC2119
|
||||
echo "$@" | slugify
|
||||
else
|
||||
iconv --to-code ascii//TRANSLIT |
|
||||
sed -E 's/[^a-zA-Z0-9]+/-/g' |
|
||||
sed -E 's/^-+\|-+$//g' |
|
||||
tr '[:upper:]' '[:lower:]'
|
||||
fi
|
||||
)
|
@ -0,0 +1,8 @@
|
||||
unlink_if_set() (
|
||||
dir=$1
|
||||
sudo=${2-}
|
||||
if [ -L "${dir}" ]; then
|
||||
# shellcheck disable=SC2086
|
||||
${sudo} unlink "${dir}"
|
||||
fi
|
||||
)
|
@ -0,0 +1,15 @@
|
||||
require assert/command
|
||||
|
||||
assert_command bat dasel
|
||||
|
||||
yaml_to_json() (
|
||||
ARG=${1-}
|
||||
command_installed bat dasel
|
||||
if [ -z "${ARG}" ]; then
|
||||
dasel --read yaml --write json | bat --language json
|
||||
elif [ -f "${ARG}" ]; then
|
||||
dasel --read yaml --write json --file "${ARG}" | bat --language json
|
||||
else
|
||||
echo "${ARG}" | dasel --read yaml --write json | bat --language json
|
||||
fi
|
||||
)
|
Loading…
Reference in New Issue