shell dot on steroids https://pagure.io/shellfu

core.sh 5.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. #!/bin/bash
  2. ffoo import exits
  3. ffoo import mkpretty
  4. ##--------------------##
  5. ## PRINTING FRONT-END ##
  6. ##--------------------##
  7. debug() {
  8. #
  9. # You already know what it does
  10. #
  11. # BTW, following are equivalent:
  12. #
  13. # debug "var1=$var1" "var2=$var2" "result=$result"
  14. # debug -v var1 var2 result
  15. # debug -v "var@ result"
  16. #
  17. $FFOO_DEBUG || return 0
  18. __echo "$@"
  19. }
  20. debug_pipe() {
  21. #
  22. # Debug the whole pipe.
  23. #
  24. grep . \
  25. | while IFS= read line;
  26. do
  27. debug "|$1: '$line'"
  28. echos "$line"
  29. done
  30. }
  31. die() {
  32. #
  33. # A fatal error
  34. #
  35. __echo -t
  36. __echo "$@"
  37. exits_error
  38. }
  39. echos() {
  40. #
  41. # Safer version of echo able to echo "-n"
  42. #
  43. # Traditional echo is broken in that it does not
  44. # distinguish between string to print and its own switches
  45. # (-e, -E or -n), leading to unexpected behavior.
  46. #
  47. # This echo version circumvents this by using printf.
  48. #
  49. printf -- '%s\n' "$@"
  50. }
  51. usage_is() {
  52. #
  53. # Echo out usage patterns and (by default) exit 2
  54. #
  55. # Specify -e STATUS for exit status, or "-E" to prevent
  56. # exiting. Use "--" to delimit end of arguments processed
  57. # by usage_is.
  58. #
  59. # Recommended usage is to define usage() in your script and
  60. # use this in body.
  61. #
  62. local es=$FFOO_EXITS_OK
  63. while true; do case "$1" in
  64. -e) es="$2"; shift 2 ;;
  65. -E) es=""; shift ;;
  66. *) break ;;
  67. esac done
  68. __echo -u "$@";
  69. test -n "$es" && exits "$es"
  70. }
  71. think() {
  72. #
  73. # If verose is on, think loud
  74. #
  75. # Use "-l" to split every parameter to separate line, (useful
  76. # or longer warnings)
  77. #
  78. $FFOO_VERBOSE || return 0
  79. __echo "$@"
  80. }
  81. warn() {
  82. #
  83. # Warn them
  84. #
  85. # Use "-l" to split every parameter to separate line, (useful
  86. # or longer warnings)
  87. #
  88. # Resist temptation to prefix "warning" or similar BS here.
  89. # STDERR is *made* for warnings.
  90. #
  91. __echo "$@"
  92. }
  93. ##----------##
  94. ## BACK-END ##
  95. ##----------##
  96. __cat() {
  97. # cat without starting a process
  98. while IFS= read line;
  99. do echos "$line"; done
  100. }
  101. __cut_stack() {
  102. #
  103. # call stack except the head that fits pattern $1
  104. #
  105. local patt=${1:-"^__"}
  106. echos "${FUNCNAME[@]}" \
  107. | perl -ne "
  108. my \$checking = 1;
  109. while (<>) {
  110. next if (\$checking and m/$patt/);
  111. \$checking = 0;
  112. print qq/\$_\\n/;
  113. }
  114. "
  115. }
  116. __echo() {
  117. #
  118. # A smarter echo backend
  119. #
  120. # A smarter backend for debug, warn, think, die and
  121. # usage_is.
  122. #
  123. # -c cmd echo output of a command
  124. # -f file echo output of a file (- for stdin)
  125. # -l line [line...] echo each line separately
  126. # -t add stack trace to output
  127. # -u patt [patt...] convert each patt to usage pattern
  128. # -v var [var...] show contents of each var
  129. #
  130. local frontend # who (of core.sh) was called (=> prettyprinter choice)
  131. local caller # which user's function (or script) called it
  132. frontend="$(__cut_stack '^__echo' | head -1 )"
  133. caller="$(
  134. __cut_stack \
  135. '^__echo|^warn$|^debug$|^die$|^usage$|^usage_is$|^think$' \
  136. | head -1
  137. )"
  138. test "$frontend" == "main" && frontend=$(basename $0)
  139. test "$caller" == "main" && caller=$(basename $0)
  140. test "$frontend" == "usage" && frontend=usage_is
  141. local prettyfn=__cat
  142. local src # which source, or "producer" (__echo_*()) to use
  143. while true; do case $1 in
  144. -c|--cmd) src=cmd; shift; break ;;
  145. -f|--files) src=files; shift; break ;;
  146. -l|--lines) src=lines; shift; break ;;
  147. -t|--trace) src=trace; shift; break ;;
  148. -u|--usage) src=usage; shift; break ;;
  149. -v|--vars) src=vars; shift; break ;;
  150. *) src=args; break ;;
  151. esac done
  152. prettyfn=mkpretty_$frontend
  153. case $frontend in
  154. warn|debug|die|usage_is) __echo_$src "$@" | $prettyfn >&2 ;;
  155. think) __echo_$src "$@" | $prettyfn ;;
  156. *) echo "do not call __echo* directly: $frontend" >&2;
  157. exits_usage ;;
  158. esac
  159. }
  160. __echo_args() {
  161. echos "$@"
  162. }
  163. __echo_cmd() {
  164. local c=\$
  165. test $(id -u) -eq 0 && c=\#
  166. echo "$c $*"
  167. $@
  168. echo "^ exit status: $?"
  169. }
  170. __echo_files() {
  171. local fp
  172. for fp in "$@";
  173. do
  174. test -s "$fp" || continue
  175. echo "-- $fp --"
  176. cat $fp
  177. done
  178. }
  179. __echo_lines() {
  180. local l;
  181. for l in "$@"; do __echo "$l"; done
  182. }
  183. __echo_trace() {
  184. $FFOO_DEBUG || return 0
  185. echo "== trace =="
  186. caller | sed -e 's/^/-> /g'
  187. }
  188. __echo_usage() {
  189. local u
  190. for u in "$@";
  191. do echo "usage: $caller $u"
  192. done
  193. }
  194. __echo_vars() {
  195. local vn
  196. for vn in "$@";
  197. do
  198. local heel="${vn:0-1}" # last char
  199. local toes="${vn%%$heel}" # all but last char
  200. case "$heel" in
  201. @)
  202. # FIXME: review+fix the eval (even at cost of
  203. # dropping the feature)
  204. local vars="$(eval "echos \"\${!$toes$heel}\"")"
  205. __echo_vars "$vars"
  206. ;;
  207. *)
  208. __echo "$vn='$(echos "${!vn}")'"
  209. ;;
  210. esac
  211. done
  212. }