introduce --verbosity flag rather than mixed logging settings; correct color misnaming to ANSI convention; added sanity-check; simplified hello-world; created FZF_USER_INPUT to replace the confusing FZF_HEAD and FZF_TAIL
This commit is contained in:
		@@ -1,4 +1,6 @@
 | 
			
		||||
#!/bin/zsh
 | 
			
		||||
#####################################################################
 | 
			
		||||
 | 
			
		||||
MAIN() {
 | 
			
		||||
	SUCCESS 'hello world!'
 | 
			
		||||
	SUCCESS 'Hello, World!'
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -119,12 +119,51 @@ SCWRYPTS__GET_RUNSTRING__zsh() {
 | 
			
		||||
		|| SCWRYPT_FILENAME="$GROUP_PATH/$SCWRYPT_TYPE/$SCWRYPT_NAME" \
 | 
			
		||||
		;
 | 
			
		||||
 | 
			
		||||
	echo "source '$SCWRYPT_FILENAME'; CHECK_ENVIRONMENT; MAIN"
 | 
			
		||||
	printf "
 | 
			
		||||
		source '$SCWRYPT_FILENAME'
 | 
			
		||||
		CHECK_ENVIRONMENT
 | 
			
		||||
		ERRORS=0
 | 
			
		||||
 | 
			
		||||
		export USAGE=\"
 | 
			
		||||
			usage: -
 | 
			
		||||
 | 
			
		||||
			args: -
 | 
			
		||||
 | 
			
		||||
			options: -
 | 
			
		||||
			  -h, --help      display this message and exit
 | 
			
		||||
			  -v, --verbose   output debugging information
 | 
			
		||||
 | 
			
		||||
			description: -
 | 
			
		||||
		\"
 | 
			
		||||
 | 
			
		||||
		[ ! \$USAGE__usage ] && export USAGE__usage='[...options...]'
 | 
			
		||||
 | 
			
		||||
		() {
 | 
			
		||||
			local MAIN_ARGS=()
 | 
			
		||||
			local VARSPLIT
 | 
			
		||||
			while [[ \$# -gt 0 ]]
 | 
			
		||||
			do
 | 
			
		||||
				case \$1 in
 | 
			
		||||
					-[a-z][a-z]* )
 | 
			
		||||
						VARSPLIT=\$(echo \"\$1 \" | sed 's/^\\\\(-.\\\\)\\\\(.*\\\\) /\\\\1 -\\\\2/')
 | 
			
		||||
						set -- throw-away \$(echo \" \$VARSPLIT \") \${@:2}
 | 
			
		||||
						;;
 | 
			
		||||
					-h | --help    ) USAGE; exit 0 ;;
 | 
			
		||||
					-v | --verbose ) INFO \"setting SCWRYPTS_LOG_LEVEL to 'debug'\"; export SCWRYPTS_LOG_LEVEL=debug ;;
 | 
			
		||||
					* ) MAIN_ARGS+=(\$1) ;;
 | 
			
		||||
				esac
 | 
			
		||||
				shift 1
 | 
			
		||||
			done
 | 
			
		||||
			MAIN \${MAIN_ARGS[@]}
 | 
			
		||||
		} "
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SCWRYPTS__GET_RUNSTRING__zsh_v3_compatibility() {
 | 
			
		||||
SCWRYPTS__GET_RUNSTRING__zsh_v3() {
 | 
			
		||||
	WARNING "scwrypts zsh/v3 runstrings are now deprecated; please update to scwrypts v4 format"
 | 
			
		||||
 | 
			
		||||
	__CHECK_DEPENDENCY zsh || return 1
 | 
			
		||||
 | 
			
		||||
	[ $(eval echo '$SCWRYPTS_TYPE__'$SCWRYPT_GROUP) ] \
 | 
			
		||||
@@ -132,8 +171,6 @@ SCWRYPTS__GET_RUNSTRING__zsh_v3_compatibility() {
 | 
			
		||||
		|| echo "source $GROUP_PATH/$SCWRYPT_TYPE/$SCWRYPT_NAME" \
 | 
			
		||||
		;
 | 
			
		||||
 | 
			
		||||
	WARNING "scwrypts zsh/v3 runstrings are now deprecated; please update to scwrypts v4 format"
 | 
			
		||||
 | 
			
		||||
	return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,22 +2,22 @@ __BLACK='\033[0;30m'
 | 
			
		||||
__DARK_GRAY='\033[1;30m'
 | 
			
		||||
 | 
			
		||||
__RED='\033[0;31m'
 | 
			
		||||
__LIGHT_RED='\033[1;31m'
 | 
			
		||||
__BRIGHT_RED='\033[1;31m'
 | 
			
		||||
 | 
			
		||||
__GREEN='\033[0;32m'
 | 
			
		||||
__LIGHT_GREEN='\033[1;32m'
 | 
			
		||||
__BRIGHT_GREEN='\033[1;32m'
 | 
			
		||||
 | 
			
		||||
__ORANGE='\033[0;33m'
 | 
			
		||||
__YELLOW='\033[1;33m'
 | 
			
		||||
__YELLOW='\033[0;33m'
 | 
			
		||||
__BRIGHT_YELLOW='\033[1;33m'
 | 
			
		||||
 | 
			
		||||
__BLUE='\033[1;34m'
 | 
			
		||||
__DARK_BLUE='\033[0;34m'
 | 
			
		||||
__BLUE='\033[0;34m'
 | 
			
		||||
__BRIGHT_BLUE='\033[1;34m'
 | 
			
		||||
 | 
			
		||||
__PURPLE='\033[1;35m'
 | 
			
		||||
__DARK_PURPLE='\033[0;35m'
 | 
			
		||||
__MAGENTA='\033[0;35m'
 | 
			
		||||
__BRIGHT_MAGENTA='\033[1;35m'
 | 
			
		||||
 | 
			
		||||
__CYAN='\033[1;36m'
 | 
			
		||||
__DARK_CYAN='\033[0;36m'
 | 
			
		||||
__CYAN='\033[0;36m'
 | 
			
		||||
__BRIGHT_CYAN='\033[1;36m'
 | 
			
		||||
 | 
			
		||||
__WHITE='\033[1;37m'
 | 
			
		||||
__LIGHT_GRAY='\033[0;37m'
 | 
			
		||||
@@ -27,17 +27,17 @@ __COLOR_RESET='\033[0m'
 | 
			
		||||
__GET_RANDOM_COLOR() {
 | 
			
		||||
	local COLORS=(
 | 
			
		||||
		$__RED
 | 
			
		||||
		$__LIGHT_RED
 | 
			
		||||
		$__BRIGHT_RED
 | 
			
		||||
		$__GREEN
 | 
			
		||||
		$__LIGHT_GREEN
 | 
			
		||||
		$__ORANGE
 | 
			
		||||
		$__BRIGHT_GREEN
 | 
			
		||||
		$__YELLOW
 | 
			
		||||
		$__BRIGHT_YELLOW
 | 
			
		||||
		$__BLUE
 | 
			
		||||
		$__DARK_BLUE
 | 
			
		||||
		$__PURPLE
 | 
			
		||||
		$__DARK_PURPLE
 | 
			
		||||
		$__BRIGHT_BLUE
 | 
			
		||||
		$__MAGENTA
 | 
			
		||||
		$__BRIGHT_MAGENTA
 | 
			
		||||
		$__CYAN
 | 
			
		||||
		$__DARK_CYAN
 | 
			
		||||
		$__BRIGHT_CYAN
 | 
			
		||||
		$__WHITE
 | 
			
		||||
	)
 | 
			
		||||
	print "$__COLOR_RESET${COLORS[$(shuf -i 1-${#COLORS[@]} -n 1)]}"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +1,14 @@
 | 
			
		||||
__CHECK_DEPENDENCIES() {
 | 
			
		||||
	local DEP ERROR=0
 | 
			
		||||
	local DEP ERRORS=0
 | 
			
		||||
	local SCWRYPTS_LOG_LEVEL=1
 | 
			
		||||
	[ ! $E ] && E=ERROR
 | 
			
		||||
 | 
			
		||||
	DEPENDENCIES=($(echo $DEPENDENCIES | sed 's/ \+/\n/g' | sort -u))
 | 
			
		||||
 | 
			
		||||
	for DEP in ${DEPENDENCIES[@]}; do __CHECK_DEPENDENCY $DEP || ((ERROR+=1)); done
 | 
			
		||||
	__CHECK_COREUTILS || ((ERROR+=$?))
 | 
			
		||||
	for DEP in ${DEPENDENCIES[@]}; do __CHECK_DEPENDENCY $DEP || ((ERRORS+=1)); done
 | 
			
		||||
	__CHECK_COREUTILS || ((ERRORS+=$?))
 | 
			
		||||
 | 
			
		||||
	return $ERROR
 | 
			
		||||
	return $ERRORS
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__CHECK_DEPENDENCY() {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
__CHECK_REQUIRED_ENV() {
 | 
			
		||||
	local SCWRYPTS_LOG_LEVEL=1
 | 
			
		||||
	local VAR ERROR=0
 | 
			
		||||
	REQUIRED_ENV=($(echo $REQUIRED_ENV | sed 's/\s\+/\n/g' | sort -u))
 | 
			
		||||
	for VAR in ${REQUIRED_ENV[@]}; do __CHECK_ENV_VAR $VAR || ((ERROR+=1)); done
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										57
									
								
								zsh/lib/utils/io.fzf.zsh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								zsh/lib/utils/io.fzf.zsh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,57 @@
 | 
			
		||||
FZF() {
 | 
			
		||||
	[ $CI ] && FAIL 1 'currently in CI, but FZF requires user input'
 | 
			
		||||
 | 
			
		||||
	local FZF_ARGS=()
 | 
			
		||||
 | 
			
		||||
	FZF_ARGS+=(-i)
 | 
			
		||||
	FZF_ARGS+=(--ansi)
 | 
			
		||||
	FZF_ARGS+=(--bind=ctrl-c:cancel)
 | 
			
		||||
	FZF_ARGS+=(--height=50%)
 | 
			
		||||
	FZF_ARGS+=(--layout=reverse)
 | 
			
		||||
 | 
			
		||||
	local SELECTION=$(fzf ${FZF_ARGS[@]} --prompt "$1 : " ${@:2})
 | 
			
		||||
	PROMPT "$1"
 | 
			
		||||
 | 
			
		||||
	[ $BE_QUIET ] || {
 | 
			
		||||
		[[ $SCWRYPTS_LOG_LEVEL -ge 1 ]] && echo $SELECTION >&2
 | 
			
		||||
	}
 | 
			
		||||
	echo $SELECTION
 | 
			
		||||
	[ $SELECTION ]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FZF_USER_INPUT() { # allow user to type custom answers; reconfirm if ambiguous with select
 | 
			
		||||
	local FZF_OUTPUT=$(BE_QUIET=1 FZF $@ --print-query | sed '/^$/d' | sort -u)
 | 
			
		||||
	[[ $SCWRYPTS_LOG_LEVEL -ge 1 ]] && echo $FZF_OUTPUT | head -n1 >&2
 | 
			
		||||
	[ ! $FZF_OUTPUT ] && return 1
 | 
			
		||||
 | 
			
		||||
	[[ $(echo "$FZF_OUTPUT" | wc -l) -eq 1 ]] \
 | 
			
		||||
		&& { echo "$FZF_OUTPUT"; return 0; }
 | 
			
		||||
 | 
			
		||||
	local FZF_OUTPUT=$(
 | 
			
		||||
		echo "$FZF_OUTPUT" \
 | 
			
		||||
			| sed "1s/\$/^$(printf "$__LIGHT_GRAY\\033[3m")<- what you typed$(printf $__COLOR_RESET)/" \
 | 
			
		||||
			| sed "2s/\$/^$(printf "$__LIGHT_GRAY\\033[3m")<- what you selected$(printf $__COLOR_RESET)/" \
 | 
			
		||||
			| column -ts '^' \
 | 
			
		||||
			| BE_QUIET=1 FZF "$@ (clarify)" \
 | 
			
		||||
		)
 | 
			
		||||
 | 
			
		||||
	[[ $SCWRYPTS_LOG_LEVEL -ge 1 ]] && echo $FZF_OUTPUT >&2
 | 
			
		||||
	FZF_OUTPUT=$(echo $FZF_OUTPUT | sed 's/\s\+<- what you .*$//')
 | 
			
		||||
	echo $FZF_OUTPUT
 | 
			
		||||
	[ $FZF_OUTPUT ]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#####################################################################
 | 
			
		||||
### vvv DEPRECATED vvv ##############################################
 | 
			
		||||
#####################################################################
 | 
			
		||||
 | 
			
		||||
FZF_HEAD() {  # prefer user input over selected
 | 
			
		||||
	WARNING 'FZF_HEAD is deprecated; please switch to FZF_USER_INPUT (drop-in fix!)'
 | 
			
		||||
	FZF $@ --print-query | sed '/^$/d' | head -n1;
 | 
			
		||||
}
 | 
			
		||||
FZF_TAIL() {  # prefer selected over user input
 | 
			
		||||
	WARNING 'FZF_TAIL is deprecated; please switch to FZF_USER_INPUT (drop-in fix!)'
 | 
			
		||||
	FZF $@ --print-query | sed '/^$/d' | tail -n1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#####################################################################
 | 
			
		||||
							
								
								
									
										38
									
								
								zsh/lib/utils/io.print.zsh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								zsh/lib/utils/io.print.zsh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
PRINT() {
 | 
			
		||||
	local MESSAGE
 | 
			
		||||
	local LAST_LINE_END='\n'
 | 
			
		||||
	local STDERR=1
 | 
			
		||||
	local STDOUT=0
 | 
			
		||||
 | 
			
		||||
	local LTRIM=1
 | 
			
		||||
	while [[ $# -gt 0 ]]
 | 
			
		||||
	do
 | 
			
		||||
		case $1 in
 | 
			
		||||
			-n | --no-trim-tabs ) LTRIM=0 ;;
 | 
			
		||||
			-x | --no-line-end  ) LAST_LINE_END='' ;;
 | 
			
		||||
			-o | --use-stdout   ) STDOUT=1; STDERR=0 ;;
 | 
			
		||||
			* ) MESSAGE+="$(echo $1) " ;;
 | 
			
		||||
		esac
 | 
			
		||||
		shift 1
 | 
			
		||||
	done
 | 
			
		||||
 | 
			
		||||
	MESSAGE="$(echo "$MESSAGE" | sed 's/%/%%/g')"
 | 
			
		||||
 | 
			
		||||
	local STYLED_MESSAGE="$({
 | 
			
		||||
		printf "${COLOR}"
 | 
			
		||||
		while IFS='' read line
 | 
			
		||||
		do
 | 
			
		||||
			[[ $PREFIX =~ ^[[:space:]]\+$ ]] && printf '\n'
 | 
			
		||||
 | 
			
		||||
			printf "${PREFIX} : $(echo "$line" | sed 's/^	\+//; s/ \+$//')"
 | 
			
		||||
 | 
			
		||||
			PREFIX=$(echo $PREFIX | sed 's/./ /g')
 | 
			
		||||
		done <<< $MESSAGE
 | 
			
		||||
	})"
 | 
			
		||||
	STYLED_MESSAGE="${COLOR}$(echo "$STYLED_MESSAGE" | sed 's/%/%%/g')${__COLOR_RESET}${LAST_LINE_END}"
 | 
			
		||||
 | 
			
		||||
	[[ $STDERR -eq 1 ]] && printf $STYLED_MESSAGE >&2
 | 
			
		||||
	[[ $STDOUT -eq 1 ]] && printf $STYLED_MESSAGE
 | 
			
		||||
 | 
			
		||||
	return 0
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										65
									
								
								zsh/lib/utils/io.usage.zsh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								zsh/lib/utils/io.usage.zsh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,65 @@
 | 
			
		||||
USAGE() { # formatter for USAGE variable
 | 
			
		||||
	[ ! $USAGE ] && return 0
 | 
			
		||||
	local USAGE_LINE=$(echo $USAGE | grep -i '^[	]*usage *:' | sed 's/^[		]*//')
 | 
			
		||||
 | 
			
		||||
	[ $USAGE__usage ] && echo $USAGE_LINE | grep -q 'usage: -' \
 | 
			
		||||
		&& USAGE_LINE=$(echo $USAGE_LINE | sed "s/usage: -/usage: $USAGE__usage/")
 | 
			
		||||
 | 
			
		||||
	[ $__SCWRYPT ] \
 | 
			
		||||
		&& USAGE_LINE=$(
 | 
			
		||||
			echo $USAGE_LINE \
 | 
			
		||||
				| sed "s;^[^:]*:;& scwrypts $SCWRYPT_NAME --;" \
 | 
			
		||||
				| sed 's/ \{2,\}/ /g; s/scwrypts -- scwrypts/scwrypts/' \
 | 
			
		||||
			)
 | 
			
		||||
 | 
			
		||||
	local THE_REST=$(echo $USAGE | grep -vi '^[		]*usage *:' )
 | 
			
		||||
 | 
			
		||||
	local DYNAMIC_USAGE_ELEMENT
 | 
			
		||||
	#
 | 
			
		||||
	# create dynamic usage elements (like 'args') by defining USAGE__<element>
 | 
			
		||||
	# then using the syntax "<element>: -" in your USAGE variable
 | 
			
		||||
	#
 | 
			
		||||
	# e.g.
 | 
			
		||||
	#
 | 
			
		||||
	# USAGE__args="
 | 
			
		||||
	#	subcommand arg 1   arg 1 description
 | 
			
		||||
	#   subcommand arg 2   some other description
 | 
			
		||||
	# "
 | 
			
		||||
	#
 | 
			
		||||
	# USAGE="
 | 
			
		||||
	# usage: some-command [...args...]
 | 
			
		||||
	#
 | 
			
		||||
	# args: -
 | 
			
		||||
	#   -h, --help   some arguments are applicable everywhere
 | 
			
		||||
	# "
 | 
			
		||||
	#
 | 
			
		||||
	for DYNAMIC_USAGE_ELEMENT in $(echo $THE_REST | sed -n 's/^\([^:]*\): -$/\1/p')
 | 
			
		||||
	do
 | 
			
		||||
		DYNAMIC_USAGE_ELEMENT_TEXT=$(eval echo '$USAGE__'$DYNAMIC_USAGE_ELEMENT)
 | 
			
		||||
		#[ $DYNAMIC_USAGE_ELEMENT_TEXT ] || continue
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		case $DYNAMIC_USAGE_ELEMENT in
 | 
			
		||||
			description )
 | 
			
		||||
				DYNAMIC_USAGE_ELEMENT_TEXT=$(echo "$DYNAMIC_USAGE_ELEMENT_TEXT" | perl -p0e 's/^[\n\s]+//')
 | 
			
		||||
			DYNAMIC_USAGE_ELEMENT_TEXT="$__YELLOW\\033[03m$DYNAMIC_USAGE_ELEMENT_TEXT\\033[0m"
 | 
			
		||||
				;;
 | 
			
		||||
			* )
 | 
			
		||||
			DYNAMIC_USAGE_ELEMENT_TEXT=$(echo $DYNAMIC_USAGE_ELEMENT_TEXT | sed 's/[^	]/  &/')
 | 
			
		||||
				;;
 | 
			
		||||
		esac
 | 
			
		||||
 | 
			
		||||
		THE_REST=$(echo $THE_REST | perl -pe "s$DYNAMIC_USAGE_ELEMENT: -$DYNAMIC_USAGE_ELEMENT:\n$DYNAMIC_USAGE_ELEMENT_TEXT\n\n")
 | 
			
		||||
	done
 | 
			
		||||
 | 
			
		||||
	# allow for dynamic 'description: -' but delete the 'description:' header line
 | 
			
		||||
	THE_REST=$(echo $THE_REST | sed '/^[		]*description:$/d')
 | 
			
		||||
 | 
			
		||||
	echo "$__BLUE$USAGE_LINE$__COLOR_RESET\n\n$THE_REST" \
 | 
			
		||||
		| sed "s/^\t\+//; s/\s\+$//; s/^\\s*$//;" \
 | 
			
		||||
		| sed '/./,$!d; :a; /^\n*$/{$d;N;ba;};' \
 | 
			
		||||
		| perl -p0e 's/\n{2,}/\n\n/g' \
 | 
			
		||||
		| perl -p0e 's/:\n{2,}/:\n/g' \
 | 
			
		||||
		| perl -p0e 's/([a-z]+:)\n([a-z]+:)/\2/g' \
 | 
			
		||||
		>&2
 | 
			
		||||
}
 | 
			
		||||
@@ -1,216 +1,115 @@
 | 
			
		||||
PRINT() {
 | 
			
		||||
	local MESSAGE
 | 
			
		||||
	local LAST_LINE_END='\n'
 | 
			
		||||
	local STDERR=1
 | 
			
		||||
	local STDOUT=0
 | 
			
		||||
 | 
			
		||||
	local LTRIM=1
 | 
			
		||||
	while [[ $# -gt 0 ]]
 | 
			
		||||
	do
 | 
			
		||||
		case $1 in
 | 
			
		||||
			-n | --no-trim-tabs ) LTRIM=0 ;;
 | 
			
		||||
			-x | --no-line-end  ) LAST_LINE_END='' ;;
 | 
			
		||||
			-o | --use-stdout   ) STDOUT=1; STDERR=0 ;;
 | 
			
		||||
			* ) MESSAGE+="$(echo $1) " ;;
 | 
			
		||||
		esac
 | 
			
		||||
		shift 1
 | 
			
		||||
	done
 | 
			
		||||
 | 
			
		||||
	MESSAGE="$(echo "$MESSAGE" | sed 's/%/%%/g')"
 | 
			
		||||
 | 
			
		||||
	local STYLED_MESSAGE="$({
 | 
			
		||||
		printf "${COLOR}"
 | 
			
		||||
		while IFS='' read line
 | 
			
		||||
		do
 | 
			
		||||
			[[ $PREFIX =~ ^[[:space:]]\+$ ]] && printf '\n'
 | 
			
		||||
 | 
			
		||||
			printf "${PREFIX} : $(echo "$line" | sed 's/^	\+//; s/ \+$//')"
 | 
			
		||||
 | 
			
		||||
			PREFIX=$(echo $PREFIX | sed 's/./ /g')
 | 
			
		||||
		done <<< $MESSAGE
 | 
			
		||||
	})"
 | 
			
		||||
	STYLED_MESSAGE="${COLOR}$(echo "$STYLED_MESSAGE" | sed 's/%/%%/g')${__COLOR_RESET}${LAST_LINE_END}"
 | 
			
		||||
 | 
			
		||||
	[[ $STDERR -eq 1 ]] && printf $STYLED_MESSAGE >&2
 | 
			
		||||
	[[ $STDOUT -eq 1 ]] && printf $STYLED_MESSAGE
 | 
			
		||||
 | 
			
		||||
	return 0
 | 
			
		||||
}
 | 
			
		||||
#####################################################################
 | 
			
		||||
### basic colorized print messages ##################################
 | 
			
		||||
#####################################################################
 | 
			
		||||
 | 
			
		||||
source "${0:a:h}/io.print.zsh"
 | 
			
		||||
[ ! $ERRORS ] && ERRORS=0
 | 
			
		||||
ERROR()    { PREFIX="ERROR    ✖" COLOR=$__RED    PRINT "$@"; ((ERRORS+=1)); }
 | 
			
		||||
SUCCESS()  { PREFIX="SUCCESS  ✔" COLOR=$__GREEN  PRINT "$@"; }
 | 
			
		||||
WARNING()  { PREFIX="WARNING  " COLOR=$__ORANGE PRINT "$@"; }
 | 
			
		||||
STATUS()   { PREFIX="STATUS    " COLOR=$__BLUE   PRINT "$@"; }
 | 
			
		||||
REMINDER() { PREFIX="REMINDER " COLOR=$__PURPLE PRINT "$@"; }
 | 
			
		||||
INFO()     { PREFIX="INFO     ℹ" COLOR=$__WHITE  PRINT "$@"; }
 | 
			
		||||
 | 
			
		||||
PROMPT() {
 | 
			
		||||
	PREFIX="PROMPT   " COLOR=$__CYAN PRINT "$@"
 | 
			
		||||
	PREFIX="USER     ⌨" COLOR=$__CYAN PRINT '' --no-line-end
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FAIL()  { ERROR "${@:2}"; exit $1; }
 | 
			
		||||
ABORT() { FAIL 69 'user abort'; }
 | 
			
		||||
 | 
			
		||||
CHECK_ERRORS() {
 | 
			
		||||
	local FAIL_OUT=1
 | 
			
		||||
	local DISPLAY_USAGE=1
 | 
			
		||||
 | 
			
		||||
	while [[ $# -gt 0 ]]
 | 
			
		||||
	do
 | 
			
		||||
		case $1 in
 | 
			
		||||
			--no-fail  ) FAIL_OUT=0 ;;
 | 
			
		||||
			--no-usage ) DISPLAY_USAGE=0 ;;
 | 
			
		||||
		esac
 | 
			
		||||
		shift 1
 | 
			
		||||
	done
 | 
			
		||||
 | 
			
		||||
	[ ! $ERRORS ] && ERRORS=0
 | 
			
		||||
	[[ $ERRORS -eq 0 ]] && return 0
 | 
			
		||||
 | 
			
		||||
	[[ $DISPLAY_USAGE -eq 1 ]] && USAGE
 | 
			
		||||
 | 
			
		||||
	[[ $FAIL_OUT -eq 1 ]] && exit $ERRORS
 | 
			
		||||
 | 
			
		||||
ERROR() {  # command encountered an error
 | 
			
		||||
	[[ $SCWRYPTS_LOG_LEVEL -ge 1 ]] \
 | 
			
		||||
		&& PREFIX="ERROR    ✖" COLOR=$__RED            PRINT "$@"
 | 
			
		||||
	((ERRORS+=1))
 | 
			
		||||
	return $ERRORS
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
USAGE() { # formatter for USAGE variable
 | 
			
		||||
	[ ! $USAGE ] && return 0
 | 
			
		||||
	local USAGE_LINE=$(echo $USAGE | grep -i '^[	]*usage *:' | sed 's/^[		]*//')
 | 
			
		||||
SUCCESS() {  # command completed successfully
 | 
			
		||||
	[[ $SCWRYPTS_LOG_LEVEL -ge 1 ]] \
 | 
			
		||||
		&& PREFIX="SUCCESS  ✔" COLOR=$__GREEN          PRINT "$@"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	[ $USAGE__usage ] && echo $USAGE_LINE | grep -q 'usage: -' \
 | 
			
		||||
		&& USAGE_LINE=$(echo $USAGE_LINE | sed "s/usage: -/usage: $USAGE__usage/")
 | 
			
		||||
REMINDER() {  # include sysadmin reminder or other important notice to users
 | 
			
		||||
	[[ $SCWRYPTS_LOG_LEVEL -ge 1 ]] \
 | 
			
		||||
		&& PREFIX="REMINDER " COLOR=$__BRIGHT_MAGENTA PRINT "$@"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	[ $__SCWRYPT ] \
 | 
			
		||||
		&& USAGE_LINE=$(
 | 
			
		||||
			echo $USAGE_LINE \
 | 
			
		||||
				| sed "s;^[^:]*:;& scwrypts $SCWRYPT_NAME --;" \
 | 
			
		||||
				| sed 's/ \{2,\}/ /g; s/scwrypts -- scwrypts/scwrypts/' \
 | 
			
		||||
			)
 | 
			
		||||
STATUS() {  # general status updates (prefer this to generic 'echo')
 | 
			
		||||
	[[ $SCWRYPTS_LOG_LEVEL -ge 2 ]] \
 | 
			
		||||
		&& PREFIX="STATUS    " COLOR=$__BLUE           PRINT "$@"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	local THE_REST=$(echo $USAGE | grep -vi '^[		]*usage *:' )
 | 
			
		||||
WARNING() {  # warning-level messages; not errors
 | 
			
		||||
	[[ $SCWRYPTS_LOG_LEVEL -ge 3 ]] \
 | 
			
		||||
		&& PREFIX="WARNING  " COLOR=$__YELLOW         PRINT "$@"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	local DYNAMIC_USAGE_ELEMENT
 | 
			
		||||
	#
 | 
			
		||||
	# create dynamic usage elements (like 'args') by defining USAGE__<element>
 | 
			
		||||
	# then using the syntax "<element>: -" in your USAGE variable
 | 
			
		||||
	#
 | 
			
		||||
	# e.g.
 | 
			
		||||
	#
 | 
			
		||||
	# USAGE__args="
 | 
			
		||||
	#	subcommand arg 1   arg 1 description
 | 
			
		||||
	#   subcommand arg 2   some other description
 | 
			
		||||
	# "
 | 
			
		||||
	#
 | 
			
		||||
	# USAGE="
 | 
			
		||||
	# usage: some-command [...args...]
 | 
			
		||||
	#
 | 
			
		||||
	# args: -
 | 
			
		||||
	#   -h, --help   some arguments are applicable everywhere
 | 
			
		||||
	# "
 | 
			
		||||
	#
 | 
			
		||||
	for DYNAMIC_USAGE_ELEMENT in $(echo $THE_REST | sed -n 's/^\([^:]*\): -$/\1/p')
 | 
			
		||||
DEBUG() {  # helpful during development or (sparingly) to help others' development
 | 
			
		||||
	[[ $SCWRYPTS_LOG_LEVEL -gt 4 ]] \
 | 
			
		||||
		&& PREFIX="DEBUG    ℹ" COLOR=$__WHITE          PRINT "$@"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PROMPT() {  # you probably want to use yN or INPUT from below
 | 
			
		||||
	[[ $SCWRYPTS_LOG_LEVEL -ge 1 ]] \
 | 
			
		||||
		&& PREFIX="PROMPT   " COLOR=$__CYAN PRINT "$@" \
 | 
			
		||||
		&& PREFIX="USER     ⌨" COLOR=$__BRIGHT_CYAN PRINT '' --no-line-end \
 | 
			
		||||
		;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FAIL()  { SCWRYPTS_LOG_LEVEL=1 ERROR "${@:2}"; exit $1; }
 | 
			
		||||
ABORT() { FAIL 69 'user abort'; }
 | 
			
		||||
 | 
			
		||||
#####################################################################
 | 
			
		||||
### check for reported errors and format USAGE contents #############
 | 
			
		||||
#####################################################################
 | 
			
		||||
 | 
			
		||||
CHECK_ERRORS() {
 | 
			
		||||
	local FAIL_OUT=true
 | 
			
		||||
	local DISPLAY_USAGE=true
 | 
			
		||||
 | 
			
		||||
	[ ! $ERRORS ] && ERRORS=0
 | 
			
		||||
 | 
			
		||||
	while [[ $# -gt 0 ]]
 | 
			
		||||
	do
 | 
			
		||||
		DYNAMIC_USAGE_ELEMENT_TEXT=$(eval echo '$USAGE__'$DYNAMIC_USAGE_ELEMENT)
 | 
			
		||||
		case $1 in
 | 
			
		||||
			--fail    ) FAIL_OUT=true  ;;
 | 
			
		||||
			--no-fail ) FAIL_OUT=false ;;
 | 
			
		||||
 | 
			
		||||
		[[ ! $DYNAMIC_USAGE_ELEMENT =~ ^description$ ]] \
 | 
			
		||||
			&& DYNAMIC_USAGE_ELEMENT_TEXT=$(echo $DYNAMIC_USAGE_ELEMENT_TEXT | sed 's/[^	]/  &/')
 | 
			
		||||
 | 
			
		||||
		THE_REST=$(echo $THE_REST | perl -pe "s/$DYNAMIC_USAGE_ELEMENT: -/$DYNAMIC_USAGE_ELEMENT:\n$DYNAMIC_USAGE_ELEMENT_TEXT\n\n/")
 | 
			
		||||
			--usage    ) DISPLAY_USAGE=true  ;;
 | 
			
		||||
			--no-usage ) DISPLAY_USAGE=false ;;
 | 
			
		||||
		esac
 | 
			
		||||
		shift 1
 | 
			
		||||
	done
 | 
			
		||||
 | 
			
		||||
	# allow for dynamic 'description: -' but delete the 'description:' header line
 | 
			
		||||
	THE_REST=$(echo $THE_REST | sed '/^[		]*description:$/d')
 | 
			
		||||
	[[ $ERRORS -eq 0 ]] && return 0
 | 
			
		||||
 | 
			
		||||
	echo "$__DARK_BLUE$USAGE_LINE$__COLOR_RESET\n\n$THE_REST" \
 | 
			
		||||
		| sed "s/^\t\+//; s/\s\+$//; s/^\\s*$//;" \
 | 
			
		||||
		| sed '/./,$!d; :a; /^\n*$/{$d;N;ba;};' \
 | 
			
		||||
		| perl -p0e 's/\n{2,}/\n\n/g' \
 | 
			
		||||
		| perl -p0e 's/:\n{2,}/:\n/g' \
 | 
			
		||||
		>&2
 | 
			
		||||
	[[ $DISPLAY_USAGE =~ true ]] && USAGE
 | 
			
		||||
 | 
			
		||||
	[[ $FAIL_OUT =~ true ]] && exit $ERRORS || return $ERRORS
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
INPUT() {
 | 
			
		||||
	PROMPT "${@:2}"
 | 
			
		||||
	READ $1
 | 
			
		||||
	local VALUE=$(eval echo '$'$1)
 | 
			
		||||
	[ $VALUE ]
 | 
			
		||||
}
 | 
			
		||||
source "${0:a:h}/io.usage.zsh"
 | 
			
		||||
 | 
			
		||||
Yn() {
 | 
			
		||||
#####################################################################
 | 
			
		||||
### facilitate user prompt and input ################################
 | 
			
		||||
#####################################################################
 | 
			
		||||
 | 
			
		||||
Yn() {  # ask a yes-or-no question (default yes)
 | 
			
		||||
	PROMPT "$@ [Yn]"
 | 
			
		||||
	[ $CI ] && { echo y; return 0; }
 | 
			
		||||
	[ $CI ] && { echo y >&2; return 0; }
 | 
			
		||||
	[ $__SCWRYPTS_YES ] && [[ $__SCWRYPTS_YES -eq 1 ]] && { echo y; return 0; }
 | 
			
		||||
 | 
			
		||||
	local Yn; READ -k Yn; echo >&2
 | 
			
		||||
	[[ $Yn =~ [nN] ]] && return 1 || return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
yN() {
 | 
			
		||||
yN() {  # ask a yes-or-no question (default no)
 | 
			
		||||
	PROMPT "$@ [yN]"
 | 
			
		||||
	[ $CI ] && { echo y; return 0; }
 | 
			
		||||
	[ $CI ] && { echo y >&2; return 0; }
 | 
			
		||||
	[ $__SCWRYPTS_YES ] && [[ $__SCWRYPTS_YES -eq 1 ]] && { echo y; return 0; }
 | 
			
		||||
 | 
			
		||||
	local yN; READ -k yN; echo >&2
 | 
			
		||||
	[[ $yN =~ [yY] ]] && return 0 || return 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CAPTURE() {
 | 
			
		||||
	[ ! $USAGE ] && USAGE="
 | 
			
		||||
	usage: stdout-varname stderr-varname [...cmd and args...]
 | 
			
		||||
 | 
			
		||||
	captures stdout and stderr on separate variables for a command
 | 
			
		||||
	"
 | 
			
		||||
	{
 | 
			
		||||
		IFS=$'\n' read -r -d '' $2;
 | 
			
		||||
		IFS=$'\n' read -r -d '' $1;
 | 
			
		||||
	} < <((printf '\0%s\0' "$(${@:3})" 1>&2) 2>&1)
 | 
			
		||||
INPUT() {  # read a single line of user input
 | 
			
		||||
	PROMPT "${@:2}"
 | 
			
		||||
	READ $1
 | 
			
		||||
	local VALUE=$(eval echo '$'$1)
 | 
			
		||||
	[ $VALUE ]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#####################################################################
 | 
			
		||||
source "${0:a:h}/io.fzf.zsh"  # allow user to select from a list of inputs
 | 
			
		||||
 | 
			
		||||
GETSUDO() {
 | 
			
		||||
	echo "\\033[1;36mPROMPT    : checking sudo password...\\033[0m" >&2
 | 
			
		||||
	sudo echo hi >/dev/null 2>&1 </dev/tty \
 | 
			
		||||
		&& SUCCESS '...authenticated!' \
 | 
			
		||||
		|| { ERROR 'failed :c'; return 1; }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
LESS() { less -R $@ </dev/tty >/dev/tty; }
 | 
			
		||||
 | 
			
		||||
FZF()      {
 | 
			
		||||
	[ $CI ] && {
 | 
			
		||||
		ERROR 'currently in CI, but FZF requires user input'
 | 
			
		||||
		exit 1
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	local FZF_ARGS=()
 | 
			
		||||
 | 
			
		||||
	FZF_ARGS+=(-i)
 | 
			
		||||
	FZF_ARGS+=(--ansi)
 | 
			
		||||
	FZF_ARGS+=(--bind=ctrl-c:cancel)
 | 
			
		||||
	FZF_ARGS+=(--height=50%)
 | 
			
		||||
	FZF_ARGS+=(--layout=reverse)
 | 
			
		||||
 | 
			
		||||
	local SELECTION=$(fzf ${FZF_ARGS[@]} --layout=reverse --prompt "$1 : " ${@:2})
 | 
			
		||||
	PROMPT "$1"
 | 
			
		||||
	echo $SELECTION >&2
 | 
			
		||||
	echo $SELECTION
 | 
			
		||||
}
 | 
			
		||||
FZF_HEAD() { FZF $@ --print-query | sed '/^$/d' | head -n1; } # prefer user input over selected
 | 
			
		||||
FZF_TAIL() { FZF $@ --print-query | sed '/^$/d' | tail -n1; } # prefer selected over user input
 | 
			
		||||
 | 
			
		||||
READ()  {
 | 
			
		||||
	[ $CI ] && {
 | 
			
		||||
		INFO 'currently in CI, skipping READ'
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
	read $@ </dev/tty
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
EDIT() {
 | 
			
		||||
EDIT() {  # edit a file in user's preferred editor
 | 
			
		||||
	[ $CI ] && {
 | 
			
		||||
		INFO 'currently in CI, skipping EDIT'
 | 
			
		||||
		return 0
 | 
			
		||||
@@ -221,6 +120,12 @@ EDIT() {
 | 
			
		||||
	SUCCESS "finished editing '$1'!"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#####################################################################
 | 
			
		||||
### basic commands with tricky states or default requirements #######
 | 
			
		||||
#####################################################################
 | 
			
		||||
 | 
			
		||||
LESS() { less -R $@ </dev/tty >/dev/tty; }
 | 
			
		||||
 | 
			
		||||
YQ() {
 | 
			
		||||
	yq --version | grep -q mikefarah || {
 | 
			
		||||
		yq $@
 | 
			
		||||
@@ -229,3 +134,37 @@ YQ() {
 | 
			
		||||
 | 
			
		||||
	yq eval '... comments=""' | yq $@
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#####################################################################
 | 
			
		||||
### other i/o utilities #############################################
 | 
			
		||||
#####################################################################
 | 
			
		||||
 | 
			
		||||
CAPTURE() {
 | 
			
		||||
	[ ! $USAGE ] && USAGE="
 | 
			
		||||
		usage: stdout-varname stderr-varname [...cmd and args...]
 | 
			
		||||
 | 
			
		||||
		captures stdout and stderr on separate variables for a command
 | 
			
		||||
	"
 | 
			
		||||
	{
 | 
			
		||||
		IFS=$'\n' read -r -d '' $2;
 | 
			
		||||
		IFS=$'\n' read -r -d '' $1;
 | 
			
		||||
	} < <((printf '\0%s\0' "$(${@:3})" 1>&2) 2>&1)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
GETSUDO() {
 | 
			
		||||
	echo "\\033[1;36mPROMPT    : checking sudo password...\\033[0m" >&2
 | 
			
		||||
	sudo echo hi >/dev/null 2>&1 </dev/tty \
 | 
			
		||||
		&& SUCCESS '...authenticated!' \
 | 
			
		||||
		|| { ERROR 'failed :c'; return 1; }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
READ()  {
 | 
			
		||||
	[ $CI ] && {
 | 
			
		||||
		INFO 'currently in CI, skipping READ'
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
	read $@ </dev/tty
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										52
									
								
								zsh/sanity-check
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										52
									
								
								zsh/sanity-check
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,52 @@
 | 
			
		||||
#!/bin/zsh
 | 
			
		||||
#####################################################################
 | 
			
		||||
 | 
			
		||||
USAGE__options='
 | 
			
		||||
	-e, --exit-code         desired exit code of the function (default "0")
 | 
			
		||||
	-f, --output-function   one of the zsh/utils output functions (default "SUCCESS")
 | 
			
		||||
	-m, --message           a message to display (default "Hello, World!")
 | 
			
		||||
'
 | 
			
		||||
 | 
			
		||||
USAGE__description='
 | 
			
		||||
	a simple hello-world-style script which allows specific scwrypts
 | 
			
		||||
	conditions to be quickly emulated
 | 
			
		||||
'
 | 
			
		||||
 | 
			
		||||
#####################################################################
 | 
			
		||||
 | 
			
		||||
MAIN() {
 | 
			
		||||
	local OUTPUT_FUNCTION=SUCCESS
 | 
			
		||||
	local EXIT_CODE=0
 | 
			
		||||
	local MESSAGE='Hello, world!'
 | 
			
		||||
 | 
			
		||||
	ARGUMENT_REQUIRED() { ERROR "'$1' requires an argument"; }
 | 
			
		||||
 | 
			
		||||
	while [[ $# -gt 0 ]]
 | 
			
		||||
	do
 | 
			
		||||
		case $1 in
 | 
			
		||||
			-e | --exit-code )
 | 
			
		||||
				EXIT_CODE="$2"
 | 
			
		||||
				[ $2 ] && shift 1 || ARGUMENT_REQUIRED
 | 
			
		||||
				;;
 | 
			
		||||
			-f | --output-function )
 | 
			
		||||
				OUTPUT_FUNCTION="$2"
 | 
			
		||||
				[ $2 ] && shift 1 || ARGUMENT_REQUIRED
 | 
			
		||||
				;;
 | 
			
		||||
			-m | --message )
 | 
			
		||||
				MESSAGE="$2"
 | 
			
		||||
				[ $2 ] && shift 1 || ARGUMENT_REQUIRED
 | 
			
		||||
				;;
 | 
			
		||||
			* ) ERROR "unknown argument '$1'" ;;
 | 
			
		||||
		esac
 | 
			
		||||
		shift 1
 | 
			
		||||
	done
 | 
			
		||||
 | 
			
		||||
	CHECK_ERRORS
 | 
			
		||||
 | 
			
		||||
	##########################################
 | 
			
		||||
 | 
			
		||||
	[[ $OUTPUT_FUNCTION =~ ^FAIL$ ]] && FAIL $EXIT_CODE "$MESSAGE"
 | 
			
		||||
 | 
			
		||||
	$OUTPUT_FUNCTION "$MESSAGE"
 | 
			
		||||
	return $EXIT_CODE
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user