From: Erich Smith Date: Wed, 9 May 2012 03:48:01 +0000 (-0400) Subject: update composure X-Git-Url: https://source.supwisdom.com/gerrit/gitweb?a=commitdiff_plain;h=635c380a91505f26d78a311f11326a1f59cfc968;p=common%2Fbash_it.git update composure --- diff --git a/lib/composure.sh b/lib/composure.sh index 1bbf400..d21281d 100644 --- a/lib/composure.sh +++ b/lib/composure.sh @@ -1,24 +1,186 @@ # composure - by erichs -# light-hearted shell functions for intuitive shell programming +# light-hearted functions for intuitive shell programming # install: source this script in your ~/.profile or ~/.${SHELL}rc script # latest source available at http://git.io/composure # known to work on bash, zsh, and ksh93 -# define default metadata keywords: -about () { :; } -group () { :; } -param () { :; } -author () { :; } -example () { :; } +# 'plumbing' functions + +composure_keywords () +{ + echo "about author example group param version" +} + +letterpress () +{ + typeset rightcol="$1" leftcol="${2:- }" + + if [ -z "$rightcol" ]; then + return + fi + + printf "%-20s%s\n" "$leftcol" "$rightcol" +} + +transcribe () +{ + typeset func=$1 + typeset file=$2 + typeset operation="$3" + + if git --version >/dev/null 2>&1; then + if [ -d ~/.composure ]; then + ( + cd ~/.composure + if git rev-parse 2>/dev/null; then + if [ ! -f $file ]; then + printf "%s\n" "Oops! Couldn't find $file to version it for you..." + return + fi + cp $file ~/.composure/$func.inc + git add --all . + git commit -m "$operation $func" + fi + ) + else + if [ "$USE_COMPOSURE_REPO" = "0" ]; then + return # if you say so... + fi + printf "%s\n" "I see you don't have a ~/.composure repo..." + typeset input + typeset valid=0 + while [ $valid != 1 ]; do + printf "\n%s" 'would you like to create one? y/n: ' + read input + case $input in + y|yes|Y|Yes|YES) + ( + echo 'creating git repository for your functions...' + mkdir ~/.composure + cd ~/.composure + git init + echo "composure stores your function definitions here" > README.txt + git add README.txt + git commit -m 'initial commit' + ) + # if at first you don't succeed... + transcribe "$func" "$file" "$operation" + valid=1 + ;; + n|no|N|No|NO) + printf "%s\n" "ok. add 'export USE_COMPOSURE_REPO=0' to your startup script to disable this message." + valid=1 + ;; + *) + printf "%s\n" "sorry, didn't get that..." + ;; + esac + done + fi + fi +} + +transcribe () +{ + typeset func=$1 + typeset file=$2 + typeset operation="$3" + + if git --version >/dev/null 2>&1; then + if [ -d ~/.composure ]; then + ( + cd ~/.composure + if git rev-parse 2>/dev/null; then + if [ ! -f $file ]; then + printf "%s\n" "Oops! Couldn't find $file to version it for you..." + return + fi + cp $file ~/.composure/$func.inc + git add --all . + git commit -m "$operation $func" + fi + ) + else + if [ "$USE_COMPOSURE_REPO" = "0" ]; then + return # if you say so... + fi + printf "%s\n" "I see you don't have a ~/.composure repo..." + typeset input + typeset valid=0 + while [ $valid != 1 ]; do + printf "\n%s" 'would you like to create one? y/n: ' + read input + case $input in + y|yes|Y|Yes|YES) + ( + echo 'creating git repository for your functions...' + mkdir ~/.composure + cd ~/.composure + git init + echo "composure stores your function definitions here" > README.txt + git add README.txt + git commit -m 'initial commit' + ) + # if at first you don't succeed... + transcribe "$func" "$file" "$operation" + valid=1 + ;; + n|no|N|No|NO) + printf "%s\n" "ok. add 'export USE_COMPOSURE_REPO=0' to your startup script to disable this message." + valid=1 + ;; + *) + printf "%s\n" "sorry, didn't get that..." + ;; + esac + done + fi + fi +} + +typeset_functions () +{ + # unfortunately, there does not seem to be a easy, portable way to list just the + # names of the defined shell functions... + + # here's a hack I modified from a StackOverflow post: + # we loop over the ps listing for the current process ($$), and print the last column (CMD) + # stripping any leading hyphens bash sometimes throws in there + + typeset x ans + typeset this=$(for x in $(ps -p $$); do ans=$x; done; printf "%s\n" $ans | sed 's/^-*//') + typeset shell=$(basename $this) # e.g. /bin/bash => bash + case "$shell" in + bash) + typeset -F | awk '{print $3}' + ;; + *) + # trim everything following '()' in ksh + typeset +f | sed 's/().*$//' + ;; + esac +} + + +# bootstrap metadata keywords for porcelain functions +for f in $(composure_keywords) +do + eval "$f() { :; }" +done +unset f + + +# 'porcelain' functions cite () { - about creates a new meta keyword for use in your functions - param 1: keyword - example $ cite url - example $ url http://somewhere.com + about creates one or more meta keywords for use in your functions + param one or more keywords + example '$ cite url username' + example '$ url http://somewhere.com' + example '$ username alice' group composure # this is the storage half of the 'metadata' system: @@ -27,30 +189,52 @@ cite () # anything following a keyword will get parsed as a positional # parameter, but stay resident in the ENV. As opposed to shell - # comments, '#', which do not get parsed, thus are not available + # comments, '#', which do not get parsed and are not available # at runtime. # a BIG caveat--your metadata must be roughly parsable: do not use # contractions, and consider single or double quoting if it contains # non-alphanumeric characters + if [ -z "$1" ]; then + printf '%s\n' 'missing parameter(s)' + reference cite + return + fi + typeset keyword for keyword in $*; do - eval "function $keyword { :; }" + eval "$keyword() { :; }" done } draft () { - about wraps last command into a new function + about wraps command from history into a new function, default is last command param 1: name to give function - example $ ls - example $ draft list - example $ list + param 2: optional history line number + example '$ ls' + example '$ draft list' + example '$ draft newfunc 1120 # wraps command at history line 1120 in newfunc()' group composure typeset func=$1 - eval 'function ' $func ' { ' $(fc -ln -1) '; }' + typeset num=$2 + typeset cmd + + if [ -z "$func" ]; then + printf '%s\n' 'missing parameter(s)' + reference draft + return + fi + + if [ -z "$num" ]; then + cmd=$(fc -ln -1 | head -1 | sed 's/^[[:blank:]]*//') + else + # parse command from history line number + cmd=$(eval "history | grep '^[[:blank:]]*$num' | head -1" | sed 's/^[[:blank:][:digit:]]*//') + fi + eval "$func() { $cmd; }" typeset file=$(mktemp /tmp/draft.XXXX) typeset -f $func > $file transcribe $func $file draft @@ -61,16 +245,16 @@ glossary () { about displays help summary for all functions, or summary for a group of functions param 1: optional, group name - example $ glossary - example $ glossary misc + example '$ glossary' + example '$ glossary misc' group composure typeset targetgroup=${1:-} - for func in $(listfunctions); do - typeset about="$(metafor $func about)" + for func in $(typeset_functions); do + typeset about="$(typeset -f $func | metafor about)" if [ -n "$targetgroup" ]; then - typeset group="$(metafor $func group)" + typeset group="$(typeset -f $func | metafor group)" if [ "$group" != "$targetgroup" ]; then continue # skip non-matching groups, if specified fi @@ -79,81 +263,71 @@ glossary () done } -letterpress () -{ - typeset metadata=$1 leftcol=${2:- } rightcol - - if [ -z "$metadata" ]; then - return - fi - - OLD=$IFS; IFS=$'\n' - for rightcol in $metadata; do - printf "%-20s%s\n" $leftcol $rightcol - done - IFS=$OLD -} - -listfunctions () -{ - # unfortunately, there does not seem to be a easy, portable way to list just the - # names of the defined shell functions... - - # here's a hack I modified from a StackOverflow post: - # we loop over the ps listing for the current process ($$), and print the last column (CMD) - # stripping any leading hyphens bash sometimes throws in there - - typeset x ans - typeset this=$(for x in $(ps -p $$); do ans=$x; done; printf "%s\n" $ans | sed 's/^-*//') - case "$this" in - bash) - typeset -F | awk '{print $3}' - ;; - *) - # trim everything following '()' in ksh - typeset +f | sed 's/().*$//' - ;; - esac -} - metafor () { about prints function metadata associated with keyword - param 1: function name - param 2: meta keyword - example $ metafor glossary example + param 1: meta keyword + example '$ typeset -f glossary | metafor example' group composure - typeset func=$1 keyword=$2 + + typeset keyword=$1 + + if [ -z "$keyword" ]; then + printf '%s\n' 'missing parameter(s)' + reference metafor + return + fi # this sed-fu is the retrieval half of the 'metadata' system: - # first 'cat' the function definition, - # then 'grep' for the metadata keyword, and - # then parse and massage the matching line - typeset -f $func | sed -n "s/;$//;s/^[ ]*$keyword \([^([].*\)*$/\1/p" + # 'grep' for the metadata keyword, and then parse/filter the matching line + + # strip ending ; # ignore thru keyword # print remainder # strip start/end quotes + sed -n "s/;$//;s/^[ ]*$keyword \([^([].*\)*$/\1/p" | sed "s/^['\"]*//;s/['\"]*$//" } reference () { about displays apidoc help for a specific function param 1: function name - example $ reference revise + example '$ reference revise' group composure typeset func=$1 + if [ -z "$func" ]; then + printf '%s\n' 'missing parameter(s)' + reference reference + return + fi + + typeset line - typeset about="$(metafor $func about)" + typeset about="$(typeset -f $func | metafor about)" letterpress "$about" $func - typeset params="$(metafor $func param)" - if [ -n "$params" ]; then + typeset author="$(typeset -f $func | metafor author)" + if [ -n "$author" ]; then + letterpress "$author" 'author:' + fi + + typeset version="$(typeset -f $func | metafor version)" + if [ -n "$version" ]; then + letterpress "$version" 'version:' + fi + + if [ -n "$(typeset -f $func | metafor param)" ]; then printf "parameters:\n" - letterpress "$params" + typeset -f $func | metafor param | while read line + do + letterpress "$line" + done fi - typeset examples="$(metafor $func example)" - if [ -n "$examples" ]; then + if [ -n "$(typeset -f $func | metafor example)" ]; then printf "examples:\n" - letterpress "$examples" + typeset -f $func | metafor example | while read line + do + letterpress "$line" + done fi } @@ -161,12 +335,18 @@ revise () { about loads function into editor for revision param 1: name of function - example $ revise myfunction + example '$ revise myfunction' group composure typeset func=$1 typeset temp=$(mktemp /tmp/revise.XXXX) + if [ -z "$func" ]; then + printf '%s\n' 'missing parameter(s)' + reference revise + return + fi + # populate tempfile... if [ -f ~/.composure/$func.inc ]; then # ...with contents of latest git revision... @@ -182,68 +362,37 @@ revise () fi $EDITOR $temp - source $temp + . $temp # source edited file transcribe $func $temp revise rm $temp } -transcribe () +write () { - typeset func=$1 - typeset file=$2 - typeset operation="$3" + about writes one or more composed function definitions to stdout + param one or more function names + example '$ write finddown foo' + example '$ write finddown' + group composure - if git --version >/dev/null 2>&1; then - if [ -d ~/.composure ]; then - ( - cd ~/.composure - if git rev-parse 2>/dev/null; then - if [ ! -f $file ]; then - printf "%s\n" "Oops! Couldn't find $file to version it for you..." - return - fi - cp $file ~/.composure/$func.inc - git add --all . - git commit -m "$operation $func" - fi - ) - else - if [ "$USE_COMPOSURE_REPO" = "0" ]; then - return # if you say so... - fi - printf "%s\n" "I see you don't have a ~/.composure repo..." - typeset input - typeset valid=0 - while [ $valid != 1 ]; do - printf "\n%s" 'would you like to create one? y/n: ' - read input - case $input in - y|yes|Y|Yes|YES) - ( - echo 'creating git repository for your functions...' - mkdir ~/.composure - cd ~/.composure - git init - echo "composure stores your function definitions here" > README.txt - git add README.txt - git commit -m 'initial commit' - ) - # if at first you don't succeed... - transcribe "$func" "$file" "$operation" - valid=1 - ;; - n|no|N|No|NO) - printf "%s\n" "ok. add 'export USE_COMPOSURE_REPO=0' to your startup script to disable this message." - valid=1 - ;; - *) - printf "%s\n" "sorry, didn't get that..." - ;; - esac - done - fi + if [ -z "$1" ]; then + printf '%s\n' 'missing parameter(s)' + reference write + return fi + +# bootstrap metadata +cat <