From 5d39ad2255447a15acbbb6073651cf0832dc062d Mon Sep 17 00:00:00 2001 From: a-sansara Date: Fri, 7 Jul 2017 03:38:04 +0200 Subject: [PATCH] initial commit --- README | 4 + bes.ini | 15 ++ dist/bes-config | 572 ++++++++++++++++++++++++++++++++++++++++++++++ src/config.sh | 37 +++ src/main.sh | 36 +++ src/test/test.ini | 13 ++ src/usage.sh | 17 ++ 7 files changed, 694 insertions(+) create mode 100644 README create mode 100644 bes.ini create mode 100755 dist/bes-config create mode 100644 src/config.sh create mode 100644 src/main.sh create mode 100644 src/test/test.ini create mode 100644 src/usage.sh diff --git a/README b/README new file mode 100644 index 0000000..4315985 --- /dev/null +++ b/README @@ -0,0 +1,4 @@ +bes-config +========== + +bes-config is a small bash bes config display aaplication diff --git a/bes.ini b/bes.ini new file mode 100644 index 0000000..db9e20e --- /dev/null +++ b/bes.ini @@ -0,0 +1,15 @@ +[project] +vendor = bes +name = config +version = 1.0 +license = "GNU GPL v3" +author = a-Sansara +type = application +homepage = "https://git.pluie.org/meta-tech/bes-config" +description = "bes-config is a small bash bes config display application" +keywords = "bash, bes, config" + +[require] +bes.ini = 1.1 +bes.echo = 1.1 +bes.install = 1.0 diff --git a/dist/bes-config b/dist/bes-config new file mode 100755 index 0000000..96dd9bc --- /dev/null +++ b/dist/bes-config @@ -0,0 +1,572 @@ +#!/bin/bash +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# @author a-Sansara - https://git.pluie.org/meta-tech/bes-echo +# @app bes-echo +# @license GNU GPL v3 +# @date 2017-05-13 23:50:54 CET +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +function bes.echo.boot () +{ + BES_TERM_WIDTH=${BES_TERM_WIDTH:-105} + BES_NOCOLOR=${BES_NOCOLOR:-0} + + if [ "$BES_NOCOLOR" -eq 0 ]; then + Cok="\033[0;38;5;43m"; Cko="\033[0;38;5;217m" + Coff="\033[m"; Ctitle="\033[1;48;5;24;1;38;5;15m" + Cdone="\033[1;48;5;36;1;38;5;15m"; Cfail="\033[1;48;5;196;1;38;5;15m" + Cspe="\033[1;38;5;223m"; Citem="\033[1;38;5;214m" + Cval="\033[1;38;5;215m"; Cusa="\033[1;38;5;214m" + Cbra="\033[1;38;5;203m"; Crepo="\033[1;38;5;223m" + Cmeta="\033[1;38;5;30m"; Ctext="\033[1;38;5;30m" + Copt="\033[1;38;5;81m"; Csep="\033[1;38;5;241m" + Cerr="\033[1;38;5;196m"; Ccom="\033[0;38;5;139m" + Csection="\033[1;38;5;97m"; Caction="\033[0;38;5;37m" + fi +} +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +function bes.echo () +{ + local msg=${1:-''} + local isAction=${2:-'0'} + local symbol=${3:-' *'} + if [ ! "$BES_NOCOLOR" = 1 ]; then + local c=" " + if [ -z "$isAction" ] || [ "$isAction" = 1 ]; then + c=$Caction + fi + if [ ! "$isAction" = 0 ]; then + c=" $Citem$symbol $c" + fi + echo -e " $c$msg$Coff" + else + if [ ! "$isAction" = 0 ]; then + msg=" $symbol $msg" + fi + echo -e "$msg" + fi +} +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +function bes.echo.action () +{ + bes.echo "$1" 1 +} +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +function bes.echo.title () +{ + echo + bes.echo " ${Citem}☪ ${Csection}$1 ${Cspe}$2${Coff}" + echo +} +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +function bes.echo.keyval () +{ + local c=': ' + if [ ! "$BES_NOCOLOR" = 1 ]; then + c="$Citem: ${Cval}" + fi + local len="%-15s " +# printf "%s %s [UP]\n" $PROC_NAME "${line:${#PROC_NAME}}" + bes.echo "$(printf $len $1) $c$2 " 1 " " +} +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +function bes.echo.state () +{ + local len=8 + printf "%0.s " $(seq 1 $(($BES_TERM_WIDTH-${len}))) + if [ "$1" = 0 ]; then + echo -e "${Cdone} OK ${Coff}" + else + echo -e "${Cfail} KO ${Coff}" + fi +} +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +function bes.echo.rs () +{ + local rs=${1:-0} + if [ "$rs" -eq 0 ]; then + echo -e " ${Cdone} done ${Coff}" + else + echo -e " ${Cfail} failed ${Coff}" + fi +} +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +function bes.echo.error () +{ + echo -e "\n${Cerr} error : ${Coff}\n\t$1 ${Coff}\n" +} +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +function bes.echo.sepline () +{ + local char=${1:-'_'} + local width=${2:-$BES_TERM_WIDTH} + echo -ne "${Csep} " + printf "%0.s$char" $(seq 1 $width) + echo -e "${Coff}" +} +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +function bes.echo.app () +{ + local msg=${1:-''} + local version=${2:-''} + local author=${3:-'a-Sansara'} + if [ ! -z "$2" ]; then + msg="$msg ${Cval}v$version" + fi + local len="$1${version}license : GNU GPL v3 author:$author" + bes.echo.sepline + echo -ne "\n $Ctitle $msg $Coff" + printf "%0.s " $(seq 1 $(($BES_TERM_WIDTH-${#len}-15))) + echo -e " ${Cmeta}license : ${Coff}GNU GPL v3 ${Cmeta}author : ${Cval}$author" + bes.echo.sepline +} +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +function bes.echo.colormap () +{ + for fgbg in 38 48 ; do + for color in {0..256} ; do + echo -en "\e[${fgbg};5;${color}m ${color}\t\e[0m" + if [ $((($color + 1) % 7)) == 0 ] ; then + echo + fi + done + echo + done +} +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +bes.echo.boot +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# @author a-Sansara - https://git.pluie.org/meta-tech/bes-echo +# @app bes-ini +# @license GNU GPL v3 +# @date 2017-05-19 22:52:59 CET +# +# bes alter '__' to '_' , rename bes.ini to bes.ini +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# > https://github.com/rudimeier/bash_ini_parser +# +# Copyright (c) 2009 Kevin Porter / Advanced Web Construction Ltd +# (http://coding.tinternet.info, http://webutils.co.uk) +# Copyright (c) 2010-2014 Ruediger Meier +# (https://github.com/rudimeier/) +# +# License: BSD-3-Clause, see LICENSE file +# +# Simple INI file parser. +# +# See README for usage. +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +function bes.ini () +{ + # Be strict with the prefix, since it's going to be run through eval + function check_prefix() + { + if ! [[ "${VARNAME_PREFIX}" =~ ^[a-zA-Z_][a-zA-Z0-9_]*$ ]] ;then + echo "bes.ini: invalid prefix '${VARNAME_PREFIX}'" >&2 + return 1 + fi + } + + function check_ini_file() + { + if [ ! -r "$INI_FILE" ] ;then + echo "bes.ini: '${INI_FILE}' doesn't exist or not" \ + "readable" >&2 + return 1 + fi + } + + # enable some optional shell behavior (shopt) + function pollute_bash() + { + if ! shopt -q extglob ;then + SWITCH_SHOPT="${SWITCH_SHOPT} extglob" + fi + if ! shopt -q nocasematch ;then + SWITCH_SHOPT="${SWITCH_SHOPT} nocasematch" + fi + shopt -q -s ${SWITCH_SHOPT} + } + + # unset all local functions and restore shopt settings before returning + # from bes.ini() + function cleanup_bash() + { + shopt -q -u ${SWITCH_SHOPT} + unset -f check_prefix check_ini_file pollute_bash cleanup_bash + } + + local INI_FILE="" + local INI_SECTION="" + + # {{{ START Deal with command line args + + # Set defaults + local BOOLEANS=1 + local VARNAME_PREFIX=INI + local CLEAN_ENV=0 + + # {{{ START Options + + # Available options: + # --boolean Whether to recognise special boolean values: ie for 'yes', 'true' + # and 'on' return 1; for 'no', 'false' and 'off' return 0. Quoted + # values will be left as strings + # Default: on + # + # --prefix=STRING String to begin all returned variables with (followed by '_'). + # Default: INI + # + # First non-option arg is filename, second is section name + + while [ $# -gt 0 ] + do + + case $1 in + + --clean | -c ) + CLEAN_ENV=1 + ;; + + --booleans | -b ) + shift + BOOLEANS=$1 + ;; + + --prefix | -p ) + shift + VARNAME_PREFIX=$1 + ;; + + * ) + if [ -z "$INI_FILE" ] + then + INI_FILE=$1 + else + if [ -z "$INI_SECTION" ] + then + INI_SECTION=$1 + fi + fi + ;; + + esac + + shift + done + + if [ -z "$INI_FILE" ] && [ "${CLEAN_ENV}" = 0 ] ;then + echo -e "Usage: bes.ini [-c] [-b 0| -b 1]] [-p PREFIX] FILE"\ + "[SECTION]\n or bes.ini -c [-p PREFIX]" >&2 + cleanup_bash + return 1 + fi + + if ! check_prefix ;then + cleanup_bash + return 1 + fi + + local INI_ALL_VARNAME="${VARNAME_PREFIX}_ALL_VARS" + local INI_ALL_SECTION="${VARNAME_PREFIX}_ALL_SECTIONS" + local INI_NUMSECTIONS_VARNAME="${VARNAME_PREFIX}_NUMSECTIONS" + if [ "${CLEAN_ENV}" = 1 ] ;then + eval unset "\$${INI_ALL_VARNAME}" + fi + unset ${INI_ALL_VARNAME} + unset ${INI_ALL_SECTION} + unset ${INI_NUMSECTIONS_VARNAME} + + if [ -z "$INI_FILE" ] ;then + cleanup_bash + return 0 + fi + + if ! check_ini_file ;then + cleanup_bash + return 1 + fi + + # Sanitise BOOLEANS - interpret "0" as 0, anything else as 1 + if [ "$BOOLEANS" != "0" ] + then + BOOLEANS=1 + fi + + + # }}} END Options + + # }}} END Deal with command line args + + local LINE_NUM=0 + local SECTIONS_NUM=0 + local SECTION="" + + # IFS is used in "read" and we want to switch it within the loop + local IFS=$' \t\n' + local IFS_OLD="${IFS}" + + # we need some optional shell behavior (shopt) but want to restore + # current settings before returning + local SWITCH_SHOPT="" + pollute_bash + + while read -r line || [ -n "$line" ] + do +#echo line = "$line" + + ((LINE_NUM++)) + + # Skip blank lines and comments + if [ -z "$line" -o "${line:0:1}" = ";" -o "${line:0:1}" = "#" ] + then + continue + fi + + # Section marker? + if [[ "${line}" =~ ^\[[a-zA-Z0-9_]{1,}\]$ ]] + then + + # Set SECTION var to name of section (strip [ and ] from section marker) + SECTION="${line#[}" + SECTION="${SECTION%]}" + eval "${INI_ALL_SECTION}=\"\${${INI_ALL_SECTION}# } $SECTION\"" + ((SECTIONS_NUM++)) + + continue + fi + + # Are we getting only a specific section? And are we currently in it? + if [ ! -z "$INI_SECTION" ] + then + if [ "$SECTION" != "$INI_SECTION" ] + then + continue + fi + fi + + # Valid var/value line? (check for variable name and then '=') + if ! [[ "${line}" =~ ^[a-zA-Z0-9._]{1,}[[:space:]]*= ]] + then + echo "Error: Invalid line:" >&2 + echo " ${LINE_NUM}: $line" >&2 + cleanup_bash + return 1 + fi + + + # split line at "=" sign + IFS="=" + read -r VAR VAL <<< "${line}" + IFS="${IFS_OLD}" + + # delete spaces around the equal sign (using extglob) + VAR="${VAR%%+([[:space:]])}" + VAL="${VAL##+([[:space:]])}" + VAR=$(echo $VAR) + + + # Construct variable name: + # ${VARNAME_PREFIX}_$SECTION_$VAR + # Or if not in a section: + # ${VARNAME_PREFIX}_$VAR + # In both cases, full stops ('.') are replaced with underscores ('_') + if [ -z "$SECTION" ] + then + VARNAME=${VARNAME_PREFIX}_${VAR//./_} + else + VARNAME=${VARNAME_PREFIX}_${SECTION}_${VAR//./_} + fi + eval "${INI_ALL_VARNAME}=\"\${${INI_ALL_VARNAME}# } ${VARNAME}\"" + + if [[ "${VAL}" =~ ^\".*\"$ ]] + then + # remove existing double quotes + VAL="${VAL##\"}" + VAL="${VAL%%\"}" + elif [[ "${VAL}" =~ ^\'.*\'$ ]] + then + # remove existing single quotes + VAL="${VAL##\'}" + VAL="${VAL%%\'}" + elif [ "$BOOLEANS" = 1 ] + then + # Value is not enclosed in quotes + # Booleans processing is switched on, check for special boolean + # values and convert + + # here we compare case insensitive because + # "shopt nocasematch" + case "$VAL" in + yes | true | on ) + VAL=1 + ;; + no | false | off ) + VAL=0 + ;; + esac + fi + + + # enclose the value in single quotes and escape any + # single quotes and backslashes that may be in the value + VAL="${VAL//\\/\\\\}" + VAL="\$'${VAL//\'/\'}'" + + eval "$VARNAME=$VAL" + done <"${INI_FILE}" + + # return also the number of parsed sections + eval "$INI_NUMSECTIONS_VARNAME=$SECTIONS_NUM" + + cleanup_bash +} + +# < https://github.com/rudimeier/bash_ini_parser +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# @author a-Sansara - https://git.pluie.org/meta-tech/bes-install +# @app bes-install +# @license GNU GPL v3 +# @date 2017-07-07 02:21:51 CET +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +function bes.install () +{ + local app=${1} + local url=${2} + local path=${3:-/usr/local/bin} + local done=1 + bes.echo.title "Installing $app ${Coff}in" "$path" + + if [ -f "./$app" ]; then + rm ./$app + fi + wget -q $url + if [ $? -eq 0 ]; then + chmod +x ./$app + if [ -d $path ]; then + sudo mv ./$app $path/$app + local done=$? + bes.echo.state $done + else + bes.echo.error "install directory do not exists : ${Cspe}$path" + fi + else + bes.echo.error "can not download latest version of app $app. please check url : $url" + fi + bes.echo.rs $done +} + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +function bes.config () +{ + bes.echo.title "Reading Configuration Project" $APP_NAME + if [ -f ./bes.ini ]; then + bes.ini ./bes.ini -p bes -b 1 + + local keys="vendor name version license author type homepage description keywords" + local value="" + local hasconf=0 + for key in $keys; do + value="bes_project_$key" + if [ ! -z "${!value}" ]; then + hasconf=1 + bes.echo.keyval $key "${!value}" + fi + done + if [ "$hasconf" = "0" ]; then + bes.echo " -" + fi + + bes.echo.title "Dependencies" + bes.ini ./bes.ini require -p bes -b 1 + local prefix="bes_require" + local key="" + for name in ${bes_ALL_VARS}; do + key=${name:${#prefix}+1} + local tmp=${key//_/.} + bes.echo.keyval "$tmp" "${!name}" + done + else + bes.echo " $project does not have bes.ini file" + fi + echo +} + + BES_BIN_DIR="$(cd "$( dirname "${BASH_SOURCE[0]}")" && pwd)" + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +function bes.fn.list () +{ + while IFS= read -r line; do + if [ ! "${line:11}" = "bes.fn.list" ] && [ ! "${line:11}" = "read_ini" ]; then + echo "${line:11}" + fi + done < <(declare -F) +} +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +function bes.export () +{ + # $1 : fromFnName + # $2 : toFnName + local code=$(declare -f "$1") + local len=${#1} + source /dev/stdin < <(echo "$2${code:len}") +} + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +function bes.usage () +{ + echo -e " ${Cusa}Usage :${Coff}\n + ${Ccom}\tRead current project bes.ini configuration file + ${Cspe}\t$APP_NAME + ${Ccom}\tInstall or update $APP_NAME on specified BINDIR directory or in /etc/local/bin directory + ${Cspe}\t$APP_NAME ${Copt}-i${Ctext}, ${Copt}install ${Copt}[ ${Ctext}BINDIR${Copt} ] + ${Ccom}\tDisplay program version + ${Cspe}\t$APP_NAME ${Copt}-v${Ctext}, ${Copt}version + ${Ccom}\tDisplay this help + ${Cspe}\t$APP_NAME ${Copt}-h${Ctext}, ${Copt}help" + + echo -e "${Coff}" +} +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# @author a-Sansara - https://git.pluie.org/meta-tech/bes-config +# @app bes-config +# @license GNU GPL v3 +# @date 2017-06-16 04:38:52 CET +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + BES_VERSION=0.2 + BES_NAME="bes-config" + BES_URL="https://git.pluie.org/meta-tech/$BES_NAME/raw/latest/dist/$BES_NAME" + APP_DIR=$(pwd) + APP_NAME=$(basename $(pwd)) + APP_BIN=$APP_DIR/dist/$APP_NAME + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +function bes.main () +{ + if [ "$1" = "version" ] || [ "$1" = "-v" ]; then + echo $BES_VERSION + else + bes.echo.app $BES_NAME $BES_VERSION + echo + if [ "$1" = "install" ] || [ "$1" = "-i" ]; then + bes.install "$BES_NAME" "$BES_URL" "$2" + elif [ "$1" = "help" ] || [ "$1" = "-h" ]; then + bes.usage + else + bes.config + fi + echo + fi +} + +bes.main $* diff --git a/src/config.sh b/src/config.sh new file mode 100644 index 0000000..1896dcd --- /dev/null +++ b/src/config.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +function bes.config () +{ + bes.echo.title "Reading Configuration Project" $APP_NAME + if [ -f ./bes.ini ]; then + bes.ini ./bes.ini -p bes -b 1 + + local keys="vendor name version license author type homepage description keywords" + local value="" + local hasconf=0 + for key in $keys; do + value="bes_project_$key" + if [ ! -z "${!value}" ]; then + hasconf=1 + bes.echo.keyval $key "${!value}" + fi + done + if [ "$hasconf" = "0" ]; then + bes.echo " -" + fi + + bes.echo.title "Dependencies" + bes.ini ./bes.ini require -p bes -b 1 + local prefix="bes_require" + local key="" + for name in ${bes_ALL_VARS}; do + key=${name:${#prefix}+1} + local tmp=${key//_/.} + bes.echo.keyval "$tmp" "${!name}" + done + else + bes.echo " $project does not have bes.ini file" + fi + echo +} diff --git a/src/main.sh b/src/main.sh new file mode 100644 index 0000000..bd33f90 --- /dev/null +++ b/src/main.sh @@ -0,0 +1,36 @@ +#!/bin/bash +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# @author a-Sansara - https://git.pluie.org/meta-tech/bes-config +# @app bes-config +# @license GNU GPL v3 +# @date 2017-06-16 04:38:52 CET +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + BES_VERSION=0.2 + BES_NAME="bes-config" + BES_URL="https://git.pluie.org/meta-tech/$BES_NAME/raw/latest/dist/$BES_NAME" + APP_DIR=$(pwd) + APP_NAME=$(basename $(pwd)) + APP_BIN=$APP_DIR/dist/$APP_NAME + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +function bes.main () +{ + if [ "$1" = "version" ] || [ "$1" = "-v" ]; then + echo $BES_VERSION + else + bes.echo.app $BES_NAME $BES_VERSION + echo + if [ "$1" = "install" ] || [ "$1" = "-i" ]; then + bes.install "$BES_NAME" "$BES_URL" "$2" + elif [ "$1" = "help" ] || [ "$1" = "-h" ]; then + bes.usage + else + bes.config + fi + echo + fi +} + +bes.main $* diff --git a/src/test/test.ini b/src/test/test.ini new file mode 100644 index 0000000..47b2102 --- /dev/null +++ b/src/test/test.ini @@ -0,0 +1,13 @@ +var1 = true +var2 = off + +[section] +;var1=mavar1 +var2="mavar2" + + +[project] +var1 = mavar1 +var2 = "mavar2" +var3=on +var4="mavar4" diff --git a/src/usage.sh b/src/usage.sh new file mode 100644 index 0000000..042e058 --- /dev/null +++ b/src/usage.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +function bes.usage () +{ + echo -e " ${Cusa}Usage :${Coff}\n + ${Ccom}\tRead current project bes.ini configuration file + ${Cspe}\t$APP_NAME + ${Ccom}\tInstall or update $APP_NAME on specified BINDIR directory or in /etc/local/bin directory + ${Cspe}\t$APP_NAME ${Copt}-i${Ctext}, ${Copt}install ${Copt}[ ${Ctext}BINDIR${Copt} ] + ${Ccom}\tDisplay program version + ${Cspe}\t$APP_NAME ${Copt}-v${Ctext}, ${Copt}version + ${Ccom}\tDisplay this help + ${Cspe}\t$APP_NAME ${Copt}-h${Ctext}, ${Copt}help" + + echo -e "${Coff}" +}