1#! /usr/bin/env modernish 2#! use safe -k 3#! use sys/cmd/harden 4#! use var/loop/find -B 5#! use sys/base/mktemp 6harden cat 7harden -e '>1' cmp 8harden paste 9harden LC_ALL=C sed 10harden LC_ALL=C sort 11 12# This is a helper script I use to maintain the 'unalias' commands at the top 13# of every lib/modernish/mdl/**/*.mm module file. They are mainly inserted for 14# the benefit of interactive shell users, where aliases are not unlikely to 15# interfere with function definitions, causing spurious syntax errors. 16# Ref.: https://github.com/modernish/modernish/issues/5 17# 18# This script greps function names in module files, sorts them, and combines 19# them on one line. Without options, it adds or updates unalias commands on the 20# second line of each module file, only updating the file if something actually 21# changed. With the -r option, it removes these unalias commands. 22# 23# It is a nice demonstration of the use of the 'find' loop, as well as the 24# auto-cleanup option of modernish 'mktemp'. 25 26# --- Parse options --- 27showusage() { putln "Usage: $ME [ -r ]" "See comments in script for info."; } 28unset -v opt_r 29while getopts 'r' opt; do 30 case $opt in 31 ( r ) opt_r= ;; 32 ( * ) exit -u 1 ;; 33 esac 34done 35shift $((OPTIND-1)) 36let $# && exit -u 1 'Excess arguments.' 37 38# --- Make sure we're in a modernish tree --- 39mdl_reldir=${MSH_MDL#"$MSH_PREFIX/"} 40is dir $mdl_reldir || chdir $MSH_PREFIX 41putln "Updating unalias for modules in $PWD/$mdl_reldir" 42 43# --- Prepare temp file --- 44mktemp -sCCt unalias_update # 2x -C = auto-cleanup even on Ctrl+C 45mytempfile=$REPLY 46 47# --- Main loop --- 48changed=0 total=0 49LOOP find modulefile in $mdl_reldir -type f -name *.mm; DO 50 let "total += 1" 51 # Eliminate comments, get function names from lines like "funcname() {", 52 # as well as alias names from lines like 'alias name=...', 53 # and make make "_" sort last (change to "~"). 54 fn_al_names=$( 55 export LC_ALL=C 56 sed -n 's/#.*// 57 /[[:alpha:]_][[:alnum:]_]*()[[:blank:]]*[{(]/ { 58 h 59 s/().*// 60 s/^.*[^[:alnum:]_]// 61 s/^_/~/ 62 p 63 g 64 } 65 /alias[[:blank:]]\{1,\}[[:alnum:]_!%,@]\{1,\}=/ { 66 s/^.*alias // 67 s/=.*// 68 s/^_/~/ 69 p 70 }' $modulefile | 71 sort -u | 72 sed 's/^~/_/' | 73 paste -s -d ' ' - # combine on one line 74 ) 75 str empty $fn_al_names && continue 76 if isset opt_r; then 77 message="- Removing unalias from $PWD/$modulefile" 78 script="2 { /^\\\\command unalias/ d; }" 79 else 80 message="- Updating $PWD/$modulefile:${CCn} $fn_al_names" 81 script="2 i\\${CCn}\\\\command unalias $fn_al_names 2>/dev/null 82 2 { /^\\\\command unalias/ d; }" 83 fi 84 # (The >| operator bypasses the safe mode's noclobber check: we *want* 85 # to overwrite. Redirections cannot be covered by 'harden', so check.) 86 sed $script $modulefile >| $mytempfile || die 87 if ! cmp -s $modulefile $mytempfile; then 88 putln $message 89 cat $mytempfile >| $modulefile || die 90 let "changed += 1" 91 fi 92DONE 93putln "$changed out of $total modules updated." 94