#!/usr/bin/env bash #SHML:START #************************************************# # SHML - Shell Markup Language Framework # v1.1.0 # (MIT) # by Justin Dorfman - @jdorfman # && Joshua Mervine - @mervinej # # http://shml.xyz #************************************************# SHML_VERSION="1.1.0" # Progress Bar ## # options: # SHML_PROGRESS_CHAR - width of progress bar, default '#' # SHML_PROGRESS_WIDTH - width of progress bar, default 60 # SHML_PROGRESS_MAX - maximum progress value, default 100 # SHML_PROGRESS_BREAK - put a new line at the end of the output, default 'true' # SHML_PROGRESS_CLEAR - clear line at the end of the output, default 'false' # SHML_PGOGRESS_NOCURSOR - hide the cursor, default 'true' progress() { [[ -z $SHML_PROGRESS_WIDTH ]] && SHML_PROGRESS_WIDTH=60 [[ -z $SHML_PROGRESS_BREAK ]] && SHML_PROGRESS_BREAK=true [[ -z $SHML_PROGRESS_CLEAR ]] && SHML_PROGRESS_CLEAR=false [[ -z $SHML_PROGRESS_NOCURSOR ]] && SHML_PROGRESS_NOCURSOR=true # defaults local __title="Progress" local __steps=10 local __char="#" # arg parser [[ ! -z $1 ]] && __title=$1 [[ ! -z $2 ]] && __steps=$2 [[ ! -z $3 ]] && __char="$3" local __width=${SHML_PROGRESS_WIDTH} local __break=${SHML_PROGRESS_BREAK} local __clear=${SHML_PROGRESS_CLEAR} local __ncursor=${SHML_PROGRESS_NOCURSOR} local __pct=0 local __num=0 local __len=0 local __bar='' local __line='' # ensure terminal [[ -t 1 ]] || return 1 # ensure tput if test "$(which tput)"; then if $__ncursor; then # hide cursor tput civis trap 'tput cnorm; exit 1' SIGINT fi fi while read __value; do # compute pct __pct=$(( __value * 100 / __steps )) # compute number of blocks to display __num=$(( __value * __width / __steps )) # create bar string if [ $__num -gt 0 ]; then __bar=$(printf "%0.s${__char}" $(seq 1 $__num)) fi __line=$(printf "%s [%-${__witdth}s] (%d%%)" "$__title" "$__bar" "$__pct") # print bar echo -en "${__line}\r" done # clear line if requested if $__clear; then __len=$(echo -en "$__line" | wc -c) printf "%$((__len + 1))s\r" " " fi # new line if requested $__break && echo # show cursor again test "$(which tput)" && $__ncursor && tput cnorm } # Confirm / Dialog ## __default_confirm_success_input="y Y yes Yes YES ok OK Ok okay Okay OKAY k K continue Continue CONTINUE proceed Proceed PROCEED success Success SUCCESS successful Successful SUCCESSFUL good Good GOOD" confirm() { [[ -z $1 ]] && return 127 [[ -z $SHML_CONFIRM_SUCCESS ]] && SHML_CONFIRM_SUCCESS=$__default_confirm_success_input echo -ne "$1 " local found=false while read __input; do for str in $(echo $SHML_CONFIRM_SUCCESS); do [[ "$str" == "$__input" ]] && found=true done break done if $found; then [[ ! -z $2 ]] && eval $2 return 0 else [[ ! -z $3 ]] && eval $3 return 1 fi } dialog() { [[ -z $1 ]] && return 127 [[ -z $2 ]] && return 127 echo -en "$1 " while read __input; do eval "$2 $__input" break done } # Foreground (Text) ## fgcolor() { local __end='\033[39m' local __color=$__end # end by default case "$1" in end|off|reset) __color=$__end;; black|000000|000) __color='\033[30m';; red|F00BAF) __color='\033[31m';; green|00CD00) __color='\033[32m';; yellow|CDCD00) __color='\033[33m';; blue|0286fe) __color='\033[34m';; magenta|e100cc) __color='\033[35m';; cyan|00d3cf) __color='\033[36m';; gray|e4e4e4) __color='\033[90m';; darkgray|4c4c4c) __color='\033[91m';; lightgreen|00fe00) __color='\033[92m';; lightyellow|f8fe00) __color='\033[93m';; lightblue|3a80b5) __color='\033[94m';; lightmagenta|fe00fe) __color='\033[95m';; lightcyan|00fefe) __color='\033[96m';; white|ffffff|fff) __color='\033[97m';; esac if test "$2"; then echo -en "$__color$2$__end" else echo -en "$__color" fi } # Backwards Compatibility color() { fgcolor "$@" } # Aliases fgc() { fgcolor "$@" } c() { fgcolor "$@" } # Background ## bgcolor() { local __end='\033[49m' local __color=$__end # end by default case "$1" in end|off|reset) __color=$__end;; black|000000|000) __color='\033[40m';; red|F00BAF) __color='\033[41m';; green|00CD00) __color='\033[42m';; yellow|CDCD00) __color='\033[43m';; blue|0286fe) __color='\033[44m';; magenta|e100cc) __color='\033[45m';; cyan|00d3cf) __color='\033[46m';; gray|e4e4e4) __color='\033[47m';; darkgray|4c4c4c) __color='\033[100m';; lightred) __color='\033[101m';; lightgreen|00fe00) __color='\033[102m';; lightyellow|f8fe00) __color='\033[103m';; lightblue|3a80b5) __color='\033[104m';; lightmagenta|fe00fe) __color='\033[105m';; lightcyan|00fefe) __color='\033[106m';; white|fffff|fff) __color='\033[107m';; esac if test "$2"; then echo -en "$__color$2$__end" else echo -en "$__color" fi } #Backwards Compatibility background() { bgcolor "$@" } #Aliases bgc() { bgcolor "$@" } bg() { bgcolor "$@" } ## Color Bar color-bar() { if test "$2"; then for i in "$@"; do echo -en "$(background "$i" " ")" done; echo else for i in {16..21}{21..16}; do echo -en "\033[48;5;${i}m \033[0m" done; echo fi } #Alises cb() { color-bar "$@" } bar() { color-bar "$@" } ## Attributes ## attribute() { local __end='\033[0m' local __attr=$__end # end by default case "$1" in end|off|reset) __attr=$__end;; bold) __attr='\033[1m';; dim) __attr='\033[2m';; underline) __attr='\033[4m';; blink) __attr='\033[5m';; invert) __attr='\033[7m';; hidden) __attr='\033[8m';; esac if test "$2"; then echo -en "$__attr$2$__end" else echo -en "$__attr" fi } a() { attribute "$@" } ## Elements br() { echo -e "\n\r" } tab() { echo -e "\t" } indent() { local __len=4 local __int='^[0-9]+$' if test "$1"; then if [[ $1 =~ $__int ]] ; then __len=$1 fi fi while [ $__len -gt 0 ]; do echo -n " " __len=$(( $__len - 1 )) done } i() { indent "$@" } hr() { local __len=60 local __char='-' local __int='^[0-9]+$' if ! test "$2"; then if [[ $1 =~ $__int ]] ; then __len=$1 elif test "$1"; then __char=$1 fi else __len=$2 __char=$1 fi while [ $__len -gt 0 ]; do echo -n "$__char" __len=$(( $__len - 1 )) done } # Icons ## icon() { local i=''; case "$1" in check|checkmark) i='\xE2\x9C\x93';; X|x|xmark) i='\xE2\x9C\x98';; '<3'|heart) i='\xE2\x9D\xA4';; sun) i='\xE2\x98\x80';; '*'|star) i='\xE2\x98\x85';; darkstar) i='\xE2\x98\x86';; umbrella) i='\xE2\x98\x82';; flag) i='\xE2\x9A\x91';; snow|snowflake) i='\xE2\x9D\x84';; music) i='\xE2\x99\xAB';; scissors) i='\xE2\x9C\x82';; tm|trademark) i='\xE2\x84\xA2';; copyright) i='\xC2\xA9';; apple) i='\xEF\xA3\xBF';; skull|bones) i='\xE2\x98\xA0';; ':-)'|':)'|smile|face) i='\xE2\x98\xBA';; esac echo -ne "$i"; } # Emojis ## emoji() { local i="" case "$1" in 1F603|smiley|'=)'|':-)'|':)') i='😃';; 1F607|innocent|halo) i='😇';; 1F602|joy|lol|laughing) i='😂';; 1F61B|tongue|'=p'|'=P') i='😛';; 1F60A|blush|'^^'|blushing) i='😊';; 1F61F|worried|sadface|sad) i='😟';; 1F622|cry|crying|tear) i='😢';; 1F621|rage|redface) i='😡';; 1F44B|wave|hello|goodbye) i='👋';; 1F44C|ok_hand|perfect|okay|nice|ok) i='👌';; 1F44D|thumbsup|+1|like) i='👍';; 1F44E|thumbsdown|-1|no|dislike) i='👎';; 1F63A|smiley_cat|happycat) i='😺';; 1F431|cat|kitten|:3|kitty) i='🐱';; 1F436|dog|puppy) i='🐶';; 1F41D|bee|honeybee|bumblebee) i='🐝';; 1F437|pig|pighead) i='🐷';; 1F435|monkey_face|monkey) i='🐵';; 1F42E|cow|happycow) i='🐮';; 1F43C|panda_face|panda|shpanda) i='🐼';; 1F363|sushi|raw|sashimi) i='🍣';; 1F3E0|home|house) i='🏠';; 1F453|eyeglasses|bifocals) i='👓';; 1F6AC|smoking|smoke|cigarette) i='🚬';; 1F525|fire|flame|hot|snapstreak) i='🔥';; 1F4A9|hankey|poop|poo|shit) i='💩';; 1F37A|beer|homebrew|brew) i='🍺';; 1F36A|cookie|biscuit|chocolate) i='🍪';; 1F512|lock|padlock|secure) i='🔒';; 1F513|unlock|openpadlock) i='🔓';; 2B50|star|yellowstar) i='⭐';; 1F0CF|black_joker|joker|wild) i='🃏';; 2705|white_check_mark|check) i='✅';; 274C|x|cross|xmark) i='❌';; 1F6BD|toilet|restroom|loo) i='🚽';; 1F514|bell|ringer|ring) i='🔔';; 1F50E|mag_right|search|magnify) i='🔎';; 1F3AF|dart|bullseye|darts) i='🎯';; 1F4B5|dollar|cash|cream) i='💵';; 1F4AD|thought_balloon|thinking) i='💭';; 1F340|four_leaf_clover|luck) i='🍀';; esac echo -ne "$i" } function e { emoji "$@" } #SHML:END # Usage / Examples ## if [ "$0" = "$BASH_SOURCE" ]; then if [[ $@ =~ .*-v.* ]]; then echo "shml version ${SHML_VERSION}" exit 0 fi I=2 echo -e " $(color "lightblue") #$(hr "*" 48)# # SHML - Shell Markup Language Framework # v${SHML_VERSION} # (MIT) # by Justin Dorfman - @jdorfman # && Joshua Mervine - @mervinej # # https://maxcdn.github.io/shml/ #$(hr "*" 48)# $(color "end") $(a bold 'SHML Usage / Help') $(hr '=') $(a bold 'Section 0: Sourcing') $(hr '-') $(i $I)When installed in path: $(i $I) source \$(which shml.sh) $(i $I)When installed locally: $(i $I) source ./shml.sh $(a bold 'Section 1: Foreground') $(hr '-') $(i $I)\$(color red \"foo bar\") $(i $I)$(color red "foo bar") $(i $I)\$(color blue \"foo bar\") $(i $I)$(color blue "foo bar") $(i $I)\$(fgcolor green) $(i $I) >>foo bar<< $(i $I) >>bah boo<< $(i $I)\$(fgcolor end) $(i $I)$(fgcolor green) $(i $I)>>foo bar<< $(i $I)>>bah boo<< $(i $I)$(fgcolor end) $(i $I)Short Hand: $(a underline 'c') $(i $I)\$(c red 'foo') $(i $I)Argument list: $(i $I)black, red, green, yellow, blue, magenta, cyan, gray, $(i $I)white, darkgray, lightgreen, lightyellow, lightblue, $(i $I)lightmagenta, lightcyan $(i $I)Termination: end, off, reset $(i $I)Default (no arg): end $(a bold 'Section 2: Background') $(hr '-') $(i $I)\$(bgcolor red \"foo bar\") $(i $I)$(background red "foo bar") $(i $I)\$(background blue \"foo bar\") $(i $I)$(background blue "foo bar") $(i $I)\$(background green) $(i $I)$(i $I)>>foo bar<< $(i $I)$(i $I)>>bah boo<< $(i $I)\$(background end) $(background green) $(i $I)>>foo bar<< $(i $I)>>bah boo<< $(background end) $(i $I)Short Hand: $(a underline 'bg') $(i $I)\$(bg red 'foo') $(i $I)Argument list: $(i $I)black, red, green, yellow, blue, magenta, cyan, gray, $(i $I)white, darkgray, lightred, lightgreen, lightyellow, $(i $I)lightblue, lightmagenta, lightcyan $(i $I)Termination: end, off, reset $(i $I)Default (no arg): end $(a bold 'Section 3: Attributes') $(hr '-') $(i $I)$(a bold "Attributes only work on vt100 compatible terminals.") $(i $I)> Note: $(i $I)> $(a underline 'attribute end') turns off everything, $(i $I)> including foreground and background color. $(i $I)\$(attribute bold \"foo bar\") $(i $I)$(attribute bold "foo bar") $(i $I)\$(attribute underline \"foo bar\") $(i $I)$(attribute underline "foo bar") $(i $I)\$(attribute blink \"foo bar\") $(i $I)$(attribute blink "foo bar") $(i $I)\$(attribute invert \"foo bar\") $(i $I)$(attribute invert "foo bar") $(i $I)\$(attribute dim) $(i $I)$(i $I)>>foo bar<< $(i $I)$(i $I)>>bah boo<< $(i $I)\$(attribute end) $(i $I)$(attribute dim) $(i $I)$(i $I)>>foo bar<< $(i $I)$(i $I)>>bah boo<< $(i $I)$(attribute end) $(i $I)Short Hand: $(a underline 'a') $(i $I)\$(a bold 'foo') $(i $I)Argument list: $(i $I)bold, dim, underline, blink, invert, hidden $(i $I)Termination: end, off, reset $(i $I)Default (no arg): end $(a bold 'Section 4: Elements') $(hr '-') $(i $I)foo\$(br)\$(tab)bar $(i $I)foo$(br)$(tab)bar $(i $I) $(i $I)foo\$(br)\$(indent)bar\$(br)\$(indent 6)boo $(i $I)foo$(br)$(indent)bar$(br)$(indent 6)boo $(i $I) $(i $I)> Note: short hand for $(a underline 'indent') is $(a underline 'i') $(i $I) $(i $I)\$(hr) $(i $I)$(hr) $(i $I) $(i $I)\$(hr 50) $(i $I)$(hr 50) $(i $I) $(i $I)\$(hr '~' 40) $(i $I)$(hr '~' 40) $(i $I) $(i $I)\$(hr '#' 30) $(i $I)$(hr '#' 30) $(a bold 'Section 5: Icons') $(hr '-') $(i $I)Icons $(i $I)$(hr '-' 10) $(i $I)\$(icon check) \$(icon '<3') \$(icon '*') \$(icon ':)') $(i $I)$(icon check) $(icon '<3') $(icon '*') $(icon 'smile') $(i $I)Argument list: $(i $I)check|checkmark, X|x|xmark, <3|heart, sun, *|star, $(i $I)darkstar, umbrella, flag, snow|snowflake, music, $(i $I)scissors, tm|trademark, copyright, apple, $(i $I):-)|:)|smile|face $(a bold 'Section 6: Emojis') $(hr '-') $(i $I)Couldn't peep it with a pair of \$(emoji bifocals) $(i $I)Couldn't peep it with a pair of $(emoji bifocals) $(i $I) $(i $I)I'm no \$(emoji joker) play me as a \$(emoji joker) $(i $I)I'm no $(emoji joker) play me as a $(emoji joker) $(i $I) $(i $I)\$(emoji bee) on you like a \$(emoji house) on \$(emoji fire), \$(emoji smoke) ya $(i $I)$(emoji bee) on you like a $(emoji house) on $(emoji fire), $(emoji smoke) ya $(i $I) $(i $I)$(a bold 'Each Emoji has 1 or more alias') $(i $I) $(i $I)\$(emoji smiley) \$(emoji 1F603) \$(emoji '=)') \$(emoji ':-)') \$(emoji ':)') $(i $I)$(emoji smiley) $(emoji 1F603) $(emoji '=)') $(emoji ':-)') $(emoji ':)') $(a bold 'Section 7: Color Bar') $(hr '-') $(i $I)\$(color-bar) $(i $I)$(color-bar) $(i $I) $(i $I)\$(color-bar red green yellow blue magenta \\ $(i $I)$(i 15)cyan lightgray darkgray lightred \\ $(i $I)$(i 15)lightgreen lightyellow lightblue \\ $(i $I)$(i 15)lightmagenta lightcyan) $(i $I)$(color-bar red green yellow blue magenta \ cyan lightgray darkgray lightred \ lightgreen lightyellow lightblue \ lightmagenta lightcyan) $(i $I)Short Hand: $(a underline 'bar') $(i $I) $(i $I)\$(bar black yellow black yellow black yellow) $(i $I)$(bar black yellow black yellow black yellow) $(a bold "Section 8: $(color red "[EXPERIMENTAL]") Progress Bar") $(hr '-') $(i $I)Usage: progress [TITLE] [STEPS] [CHAR] $(i $I) - 'title' defines the progress bar title $(i $I) - 'steps' defines the number of steps for the progress bar to act upon $(i $I) - 'char' defines the character to be displayed in the progress bar $(i $I)Example: $(i $I)echo "\$\(color green\)" $(i $I)for i in \$(seq 0 10); do echo \$i; sleep .25; done | progress $(i $I)echo "\$\(color end\)" $(color green "$(i $I)Example [#################### ] (50%)") $(i $I)'progress' supports overriding default values by setting the following variables: $(i $I) - SHML_PROGRESS_WIDTH - width of progress bar, default 60 $(i $I) - SHML_PROGRESS_BREAK - put a new line at the end of the output, default 'true' $(i $I) - SHML_PROGRESS_CLEAR - clear line at the end of the output, default 'false' $(i $I) - SHML_PGOGRESS_NOCURSOR - hide the cursor, default 'true' $(i $I)NOTE: These variables $(a bold 'must') be defined before sourcing 'shml'! $(a bold "Section 9: $(color red "[EXPERIMENTAL]") Confirm") $(hr '-') $(i $I)Ask a yes or no question and handle results. $(i $I)Usage: confirm QUESTION [SUCCESS_FUNCTION] [FAILURE_FUNCTION] $(i $I)Supports the following as affirmitive responses by default: $(for r in `echo "$__default_confirm_success_input"`; do echo "$(i $I) - '$r'"; done) $(i $I)Default affirmtive responses can be overwritten by setting 'SHML_CONFIRM_SUCCESS'. $(i $I)Example: $(i $I)function on_success() { $(i $I) echo \"yay\" $(i $I)} $(i $I)function on_failure() { $(i $I) echo \"boo\" $(i $I)} $(i $I)confirm \"CREAM?\" \"on_success\" \"on_failure\" $(a bold "Section 9: $(color red "[EXPERIMENTAL]") Dialog") $(hr '-') $(i $I)Asks a question and passes the answer to a response handler function. $(i $I)Usage: dialog QUESTION [RESPONSE_FUNCTION] $(i $I)Example: $(i $I)function on_response() { $(i $I) echo \"hello $1\" $(i $I)} $(i $I)dialog \"What is your name?\" \"on_response\" " | less -r fi # vim: ft=sh: