messaging.sh (5683B)
1 #!/usr/bin/env zsh 2 3 init_commandline() { 4 ### Options configuration 5 # 6 # Hi, dear developer! Are you trying to add a new subcommand, or 7 # to add some options? Well, keep in mind that option names are 8 # global: they cannot bear a different meaning or behaviour across 9 # subcommands. 10 # 11 # For example, "-s" means "size" and accepts one argument. If you 12 # are tempted to add an alternate option "-s" (e.g., to mean 13 # "silent", and that doesn't accept any argument) DON'T DO IT! 14 # 15 # There are two reasons for that: 16 # I. Usability; users expect that "-s" is "size" 17 # II. Option parsing WILL EXPLODE if you do this kind of bad 18 # things (it will complain: "option defined more than once") 19 # 20 # If you want to use the same option in multiple commands then you 21 # can only use the non-abbreviated long-option version like: 22 # -force and NOT -f 23 # 24 25 26 ### Detect subcommand 27 local -aU every_opts #every_opts behave like a set; that is, an array with unique elements 28 for optspec in $subcommands_opts$main_opts; do 29 for opt in ${=optspec}; do 30 every_opts+=${opt} 31 done 32 done 33 local -a oldstar 34 oldstar=($argv) 35 #### detect early: useful for --optiion-parsing 36 zparseopts -M -D -Adiscardme ${every_opts} 37 if [[ -n ${(k)discardme[--option-parsing]} ]]; then 38 echo $1 39 if [[ -n "$1" ]]; then 40 return 1 41 fi 42 return 0 43 fi 44 unset discardme 45 if ! zparseopts -M -E -D -Adiscardme ${every_opts}; then 46 _failure "Error parsing." 47 return 127 48 fi 49 unset discardme 50 subcommand=$1 51 if [[ -z $subcommand ]]; then 52 subcommand="__default" 53 fi 54 55 if [[ -z ${(k)subcommands_opts[$subcommand]} ]]; then 56 _warning "There's no such command \"::1 subcommand::\"." $subcommand 57 exitv=127 _failure "Please try -h for help." 58 fi 59 argv=(${oldstar}) 60 unset oldstar 61 62 ### Parsing global + command-specific options 63 # zsh magic: ${=string} will split to multiple arguments when spaces occur 64 set -A cmd_opts ${main_opts} ${=subcommands_opts[$subcommand]} 65 # if there is no option, we don't need parsing 66 if [[ -n $cmd_opts ]]; then 67 # here is declared opts= 68 zparseopts -M -E -D -Aopts ${cmd_opts} 69 if [[ $? != 0 ]]; then 70 _warning "Some error occurred during option processing." 71 exitv=127 _failure "See \"tomb help\" for more info." 72 fi 73 fi 74 #build PARAM (array of arguments) and check if there are unrecognized options 75 ok=0 76 PARAM=() 77 for arg in $*; do 78 if [[ $arg == '--' || $arg == '-' ]]; then 79 ok=1 80 continue #it shouldnt be appended to PARAM 81 elif [[ $arg[1] == '-' ]]; then 82 if [[ $ok == 0 ]]; then 83 exitv=127 _failure "Unrecognized option ::1 arg:: for subcommand ::2 subcommand::" $arg $subcommand 84 fi 85 fi 86 PARAM+=$arg 87 done 88 #first parameter actually is the subcommand: delete it and shift 89 if [[ $subcommand != '__default' ]]; then 90 PARAM[1]=() 91 shift 92 fi 93 ### End parsing command-specific options 94 if ! option_is_set --no-color; then 95 autoload colors; colors 96 fi 97 98 } 99 100 # Check an option 101 option_is_set() { 102 # First argument, the commandline flag (i.e. "-s"). 103 # Return 0 if is set, 1 otherwise 104 105 [[ -n ${(k)opts[$1]} ]]; 106 return $?; 107 108 } 109 110 # Get an option value 111 option_value() { 112 # First argument, the commandline flag (i.e. "-s"). 113 print -n - "${opts[$1]}" 114 } 115 116 # Messaging function with pretty coloring 117 function _msg() { 118 local msg="$(gettext -s "$2")" 119 for i in $(seq 3 ${#}); 120 do 121 msg=${(S)msg//::$(($i - 2))*::/$*[$i]} 122 done 123 124 local command="print -P" 125 local progname="$fg[magenta]${TOMBEXEC##*/}$reset_color" 126 local message="$fg_bold[normal]$fg_no_bold[normal]$msg$reset_color" 127 local -i returncode 128 129 case "$1" in 130 inline) 131 command+=" -n"; pchars=" > "; pcolor="yellow" 132 ;; 133 message) 134 pchars=" . "; pcolor="white"; message="$fg_no_bold[$pcolor]$msg$reset_color" 135 ;; 136 verbose) 137 pchars="[D]"; pcolor="blue" 138 ;; 139 success) 140 pchars="(*)"; pcolor="green"; message="$fg_no_bold[$pcolor]$msg$reset_color" 141 ;; 142 warning) 143 pchars="[W]"; pcolor="yellow"; message="$fg_no_bold[$pcolor]$msg$reset_color" 144 ;; 145 failure) 146 pchars="[E]"; pcolor="red"; message="$fg_no_bold[$pcolor]$msg$reset_color" 147 returncode=1 148 ;; 149 print) 150 progname="" 151 ;; 152 *) 153 pchars="[F]"; pcolor="red" 154 message="Developer oops! Usage: _msg MESSAGE_TYPE \"MESSAGE_CONTENT\"" 155 returncode=127 156 ;; 157 esac 158 ${=command} "${progname} $fg_bold[$pcolor]$pchars$reset_color ${message}$color[reset_color]" >&2 159 return $returncode 160 } 161 162 function _message say act() { 163 local notice="message" 164 [[ "$1" = "-n" ]] && shift && notice="inline" 165 option_is_set -q || _msg "$notice" $@ 166 return 0 167 } 168 169 function _verbose xxx func() { 170 option_is_set -D || [[ $DEBUG = 1 ]] && _msg verbose $@ 171 return 0 172 } 173 174 function _success yes notice() { 175 option_is_set -q || _msg success $@ 176 return 0 177 } 178 179 function _warning no warning() { 180 option_is_set -q || _msg warning $@ 181 return 1 182 } 183 184 function _failure fatal die error() { 185 typeset -i exitcode=${exitv:-1} 186 option_is_set -q || _msg failure $@ 187 return 1 188 } 189 190 function _print() { 191 option_is_set -q || _msg print $@ 192 return 0 193 }