Skip to content

Instantly share code, notes, and snippets.

@mattyclarkson
Created November 29, 2019 18:09
Show Gist options
  • Save mattyclarkson/d2de388aa246bc5a1046ce2f90aa4916 to your computer and use it in GitHub Desktop.
Save mattyclarkson/d2de388aa246bc5a1046ce2f90aa4916 to your computer and use it in GitHub Desktop.
POSIX sh boilerplate
#!/bin/sh
# # The MIT License (MIT)
#
# Copyright © 2019 **Tub Technology** _<licence@tub.technology>_
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
# files (the “Software”), to deal in the Software without
# restriction, including without limitation the rights to use,
# copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following
# conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
set -eu
IFS="
"
fprint() (
FD="${1}"
FMT="${2}"
shift 2
if [ -t "${FD}" ]; then
readonly RED="\\\\033[31m"
readonly GREEN="\\\\033[32m"
readonly YELLOW="\\\\033[33m"
readonly BLUE="\\\\033[34m"
readonly CYAN="\\\\033[35m"
readonly MAGENTA="\\\\033[36m"
readonly RESET="\\\\033[0m"
else
readonly RED=""
readonly GREEN=""
readonly YELLOW=""
readonly BLUE=""
readonly CYAN=""
readonly MAGENTA=""
readonly RESET=""
fi
readonly CLR="$(echo "${FMT}" | sed "
s|<r>|${RED}|g;
s|<y>|${YELLOW}|g;
s|<g>|${GREEN}|g;
s|<b>|${BLUE}|g;
s|<c>|${CYAN}|g;
s|<m>|${MAGENTA}|g;
s|<>|${RESET}|g
")"
# shellcheck disable=SC2059
printf "${CLR}" "$@" 1>&"${FD}"
)
stdout() (
FMT="${1}"
shift 1
fprint 1 "${FMT}\n" "$@"
)
stderr() (
FMT="${1}"
shift 1
fprint 2 "${FMT}\n" "$@"
)
trace() (
if [ "${VERBOSITY:-1}" -ge 4 ]; then
stdout "$@"
fi
)
debug() (
if [ "${VERBOSITY:-1}" -ge 3 ]; then
stdout "$@"
fi
)
info() (
if [ "${VERBOSITY:-1}" -ge 2 ]; then
stdout "$@"
fi
)
warn() (
if [ "${VERBOSITY:-1}" -ge 1 ]; then
stderr "$@"
fi
)
note() (
FMT="${1}"
shift 1
stderr "<y> Note:<> ${FMT}" "$@"
)
error() (
FMT="${1}"
shift 1
stderr "<r>Error:<> ${FMT}" "$@"
)
available() (
MISSING=""
for EXECUTABLE in "$@"; do
if ! command -v "${EXECUTABLE}" >/dev/null 2>&1; then
MISSING="${MISSING} ${EXECUTABLE}"
fi
done
if test -n "${MISSING}"; then
error "Missing dependencies:<y>${MISSING}<>"
note "Use your package manager to install"
exit 1
fi
)
LOCATION="${LOCATION:-tool/dependencies}"
VERBOSITY="${VERBOSITY:-2}"
usage() (
CODE="${1:-0}"
MSG="${2:-}"
shift 2 2>/dev/null || true
if [ -n "${MSG}" ]; then
"$([ "${CODE}" -gt 0 ] && echo error || echo stdout)" "${MSG}" "$@"
fi
PRINT="$([ "${CODE}" = 0 ] && echo stdout || echo stderr)"
"${PRINT}" "Usage: <b>$0<> [<c>OPTIONS<>]… [<m>LOCATION<>]"
"${PRINT}" ""
"${PRINT}" "Options:"
"${PRINT}" " <c>-q<> quiet output, can use multiple times"
"${PRINT}" " <c>-v<> verbose output, can use multiple times"
"${PRINT}" ""
"${PRINT}" "Positional:"
"${PRINT}" " <m>LOCATION<> location to install dependencies (<b>${LOCATION}<>)"
"${PRINT}" ""
"${PRINT}" "Environment:"
"${PRINT}" " <g>LOCATION<> location to install dependencies"
"${PRINT}" " <g>VERBOSITY<> the output level (<b>${VERBOSITY}<>)"
"${PRINT}" ""
"${PRINT}" "Examples:"
"${PRINT}" " - Install dependencies in default location"
"${PRINT}" " <b>$0<>"
"${PRINT}" " - Install dependencies in specific location"
"${PRINT}" " <b>$0<> <c>my/custom/install/path<>"
[ -n "${CODE:-}" ] && exit "${CODE}"
)
readonly DEPENDENCIES="bash curl git mkdir rm unzip which xz"
# shellcheck disable=SC2086
available ${DEPENDENCIES}
while getopts "hqv" OPT; do
case "${OPT}" in
q) VERBOSITY=$((VERBOSITY - 1)) ;;
v) VERBOSITY=$((VERBOSITY + 1)) ;;
h) usage 0 ;;
*) usage 1 "Invalid argument: <y>${OPT}<>" ;;
esac
done
if [ $# -gt 1 ]; then
usage 1 "Invalid number of positional arguments: <y>$#<>"
elif [ $# -eq 1 ]; then
LOCATION="$*"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment