#!/bin/bash proc stderr { echo @Argv > !2 } proc putd { stderr "$1=<$(!1)>" } proc exists { type @Argv >/dev/null !2 >/dev/null } proc test_grepq { var output = $[echo x | grep -q x] [[ $? == 0 ]] || return 1 [[ -z "$output" ]] || return 1 return 0 } proc test_greps { var output = $[echo x | grep -s x] [[ $? == 0 ]] || return 1 [[ -z "$output" ]] || return 1 return 0 } if test_grepq { proc matches { grep -q @Argv ;} } elif test_greps { proc matches { grep -s @Argv ;} } else { proc matches { grep @Argv !2 > !1 >/dev/null ;} } proc pluralize { if test -n $1 { # TODO: actually implement the inflector echo $(1)s } else { while read line { pluralize $line } } } #trim() { # trimmed="$1" # trimmed="${trimmed##*( )}" # trimmed="${trimmed%%*( )}" #} # for an explanation of this getc implementation, see # http://write.jayferd.us/blog/2011/01/12/bash-adventures-read-a-single-character-even-if-its-a-newline/ proc getc { env IFS= read -r -n1 -d '' @Argv } proc read_until { var glob = $1; shift var var = $1; shift var out = '' while getc ch { out := ""$(out)$(ch)"" matchstr $out { *$glob { global FOUND := '1' export $var="$(out%$glob)" return 0 } } } # we've hit an EOF if test -z $out { false } else { global FOUND := '0' export $var="$out" true } } proc trim_l { var str = $(!1) str := $(str##+([[:space:]])) export "$1"="$str" } proc trim_r { var str = $(!1) str := $(str%%+([[:space:]])) export "$1"="$str" } proc trim { trim_l @Argv trim_r @Argv } # usage: db_safe my_var # will quote my_var for mysql. proc db_safe { var str = ""$(!1)."" # append a . so that bash doesn't chomp off newlines at the end var escaped_quote = '"\\''" str := $[ echo $(str//\'/$escaped_quote) | while read line { echo -n "$line\\n"; }] # ^ escape ' escape \n - bash has trouble with this one. export "$1"="'$(str:0:${#str}-1)'" # enclose in single quotes, strip off the ., and export the variable } # escape ' with '\''. sorry everyone. proc bash_safe { var str = $(!1) # escape ' with (literally) '\'' - sorry everyone var escaped_quote = '"'\\'''" export "$1"="'$(str//\'/$escaped_quote)'" } proc join { var delim = $1 read line && echo -n $line while read line { echo -n $delim echo -n $line } } (CommandList children: [ (FuncDef name: stderr body: (BraceGroup children: [ (SimpleCommand words: [{(echo)} {(DQ ($ VSub_At "$@"))}] redirects: [(Redir op_id:Redir_GreatAnd fd:-1 arg_word:{(2)} spids:[16])] ) ] spids: [7] ) spids: [3 6] ) (FuncDef name: putd body: (BraceGroup children: [ (C {(stderr)} { (DQ ($ VSub_Number "$1") ("=<") (BracedVarSub token: prefix_op: VSub_Bang spids: [34 37] ) (">") ) } ) ] spids: [26] ) spids: [22 25] ) (FuncDef name: exists body: (BraceGroup children: [ (SimpleCommand words: [{(type)} {(DQ ($ VSub_At "$@"))}] redirects: [ (Redir op_id:Redir_Great fd:-1 arg_word:{(/dev/null)} spids:[57]) (Redir op_id:Redir_Great fd:2 arg_word:{(/dev/null)} spids:[60]) ] ) ] spids: [48] ) spids: [44 47] ) (FuncDef name: test_grepq body: (BraceGroup children: [ (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:output) op: Equal rhs: { (DQ (CommandSubPart command_list: (CommandList children: [ (Pipeline children: [(C {(echo)} {(x)}) (C {(grep)} {(-q)} {(x)})] negated: False ) ] ) left_token: spids: [77 89] ) ) } spids: [75] ) ] spids: [73] ) (AndOr children: [ (DBracket expr: (BoolBinary op_id:BoolBinary_GlobDEqual left:{($ VSub_QMark "$?")} right:{(0)}) ) (ControlFlow token: arg_word:{(1)}) ] op_id: Op_DPipe ) (AndOr children: [ (DBracket expr: (BoolUnary op_id:BoolUnary_z child:{(DQ ($ VSub_Name "$output"))}) ) (ControlFlow token: arg_word:{(1)}) ] op_id: Op_DPipe ) (ControlFlow token: arg_word:{(0)}) ] spids: [70] ) spids: [66 69] ) (FuncDef name: test_greps body: (BraceGroup children: [ (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:output) op: Equal rhs: { (DQ (CommandSubPart command_list: (CommandList children: [ (Pipeline children: [(C {(echo)} {(x)}) (C {(grep)} {(-s)} {(x)})] negated: False ) ] ) left_token: spids: [145 157] ) ) } spids: [143] ) ] spids: [141] ) (AndOr children: [ (DBracket expr: (BoolBinary op_id:BoolBinary_GlobDEqual left:{($ VSub_QMark "$?")} right:{(0)}) ) (ControlFlow token: arg_word:{(1)}) ] op_id: Op_DPipe ) (AndOr children: [ (DBracket expr: (BoolUnary op_id:BoolUnary_z child:{(DQ ($ VSub_Name "$output"))}) ) (ControlFlow token: arg_word:{(1)}) ] op_id: Op_DPipe ) (ControlFlow token: arg_word:{(0)}) ] spids: [138] ) spids: [134 137] ) (If arms: [ (if_arm cond: [(Sentence child:(C {(test_grepq)}) terminator:)] action: [ (FuncDef name: matches body: (BraceGroup children: [ (Sentence child: (C {(grep)} {(-q)} {(DQ ($ VSub_At "$@"))}) terminator: ) ] spids: [214] ) spids: [210 213] ) ] spids: [-1 207] ) (if_arm cond: [(Sentence child:(C {(test_greps)}) terminator:)] action: [ (FuncDef name: matches body: (BraceGroup children: [ (Sentence child: (C {(grep)} {(-s)} {(DQ ($ VSub_At "$@"))}) terminator: ) ] spids: [239] ) spids: [235 238] ) ] spids: [227 232] ) ] else_action: [ (FuncDef name: matches body: (BraceGroup children: [ (Sentence child: (SimpleCommand words: [{(grep)} {(DQ ($ VSub_At "$@"))}] redirects: [ (Redir op_id: Redir_GreatAnd fd: 2 arg_word: {(1)} spids: [267] ) (Redir op_id: Redir_Great fd: -1 arg_word: {(/dev/null)} spids: [270] ) ] ) terminator: ) ] spids: [259] ) spids: [255 258] ) ] spids: [252 276] ) (FuncDef name: pluralize body: (BraceGroup children: [ (If arms: [ (if_arm cond: [ (Sentence child: (C {(Lit_Other "[")} {(-n)} {(DQ ($ VSub_Number "$1"))} {(Lit_Other "]")}) terminator: ) ] action: [(C {(echo)} {(${ VSub_Number 1) (s)})] spids: [-1 299] ) ] else_action: [ (While cond: [(Sentence child:(C {(read)} {(line)}) terminator:)] body: (DoGroup children:[(C {(pluralize)} {($ VSub_Name "$line")})] spids:[324332]) ) ] spids: [314 335] ) ] spids: [283] ) spids: [279 282] ) (FuncDef name: getc body: (BraceGroup children: [ (SimpleCommand words: [{(read)} {(-r)} {(-n1)} {(-d)} {(SQ )} {(DQ ($ VSub_At "$@"))}] more_env: [(env_pair name:IFS val:{(SQ )} spids:[369])] ) ] spids: [366] ) spids: [362 365] ) (FuncDef name: read_until body: (BraceGroup children: [ (Sentence child: (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:glob) op: Equal rhs: {($ VSub_Number "$1")} spids: [398] ) ] spids: [396] ) terminator: ) (C {(shift)}) (Sentence child: (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:var) op: Equal rhs: {($ VSub_Number "$1")} spids: [407] ) ] spids: [405] ) terminator: ) (C {(shift)}) (Assignment keyword: Assign_Local pairs: [(assign_pair lhs:(LhsName name:out) op:Equal spids:[417])] spids: [415] ) (While cond: [(Sentence child:(C {(getc)} {(ch)}) terminator:)] body: (DoGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:out) op: Equal rhs: {(DQ (${ VSub_Name out) (${ VSub_Name ch))} spids: [431] ) ] spids: [431] ) (Case to_match: {(DQ ($ VSub_Name "$out"))} arms: [ (case_arm pat_list: [{(Lit_Other "*") ($ VSub_Name "$glob")}] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:FOUND) op: Equal rhs: {(1)} spids: [456] ) ] spids: [456] ) (C {(export)} {($ VSub_Name "$var") (Lit_Other "=") (DQ (BracedVarSub token: suffix_op: (StringUnary op_id: VOp1_Percent arg_word: {($ VSub_Name "$glob")} ) spids: [465 469] ) ) } ) (ControlFlow token: arg_word: {(0)} ) ] spids: [451 453 478 -1] ) ] spids: [442 448 481] ) ] spids: [428 484] ) ) (If arms: [ (if_arm cond: [ (Sentence child: (C {(Lit_Other "[")} {(-z)} {(DQ ($ VSub_Name "$out"))} {(Lit_Other "]")}) terminator: ) ] action: [(C {(false)})] spids: [-1 505] ) ] else_action: [ (Assignment keyword: Assign_None pairs: [(assign_pair lhs:(LhsName name:FOUND) op:Equal rhs:{(0)} spids:[514])] spids: [514] ) (C {(export)} {($ VSub_Name "$var") (Lit_Other "=") (DQ ($ VSub_Name "$out"))}) (C {(true)}) ] spids: [511 530] ) ] spids: [393] ) spids: [389 392] ) (FuncDef name: trim_l body: (BraceGroup children: [ (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:str) op: Equal rhs: {(BracedVarSub token: prefix_op:VSub_Bang spids:[545548])} spids: [544] ) ] spids: [542] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:str) op: Equal rhs: { (DQ (BracedVarSub token: suffix_op: (StringUnary op_id:VOp1_DPound arg_word:{("+([[:space:]])")}) spids: [553 557] ) ) } spids: [551] ) ] spids: [551] ) (C {(export)} {(DQ ($ VSub_Number "$1")) (Lit_Other "=") (DQ ($ VSub_Name "$str"))}) ] spids: [539] ) spids: [535 538] ) (FuncDef name: trim_r body: (BraceGroup children: [ (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:str) op: Equal rhs: {(BracedVarSub token: prefix_op:VSub_Bang spids:[584587])} spids: [583] ) ] spids: [581] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:str) op: Equal rhs: { (DQ (BracedVarSub token: suffix_op: (StringUnary op_id:VOp1_DPercent arg_word:{("+([[:space:]])")}) spids: [592 596] ) ) } spids: [590] ) ] spids: [590] ) (C {(export)} {(DQ ($ VSub_Number "$1")) (Lit_Other "=") (DQ ($ VSub_Name "$str"))}) ] spids: [578] ) spids: [574 577] ) (FuncDef name: trim body: (BraceGroup children: [(C {(trim_l)} {(DQ ($ VSub_At "$@"))}) (C {(trim_r)} {(DQ ($ VSub_At "$@"))})] spids: [617] ) spids: [613 616] ) (FuncDef name: db_safe body: (BraceGroup children: [ (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:str) op: Equal rhs: { (DQ (BracedVarSub token: prefix_op:VSub_Bang spids:[653656]) (.)) } spids: [651] ) ] spids: [649] ) (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:escaped_quote) op: Equal rhs: {(DQ (EscapedLiteralPart token:) ("'"))} spids: [666] ) ] spids: [664] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:str) op: Equal rhs: { (DQ (CommandSubPart command_list: (CommandList children: [ (Pipeline children: [ (C {(echo)} { (DQ (BracedVarSub token: suffix_op: (PatSub pat: { (EscapedLiteralPart token: ) } replace: {($ VSub_Name "$escaped_quote")} do_all: True do_prefix: False do_suffix: False ) spids: [681 688] ) ) } ) (While cond: [ (Sentence child: (C {(read)} {(line)}) terminator: ) ] body: (DoGroup children: [ (Sentence child: (C {(echo)} {(-n)} { (DQ ($ VSub_Name "$line") (EscapedLiteralPart token: ) (n) ) } ) terminator: ) ] spids: [700 713] ) ) ] negated: False ) ] ) left_token: spids: [675 714] ) ) } spids: [673] ) ] spids: [673] ) (C {(export)} {(DQ ($ VSub_Number "$1")) (Lit_Other "=") (DQ ("'") (BracedVarSub token: suffix_op: (Slice begin: (ArithWord w:{(Lit_Digits 0)}) length: (ArithBinary op_id: Arith_Minus left: (ArithWord w: { (BracedVarSub token: prefix_op: VSub_Pound spids: [735 738] ) } ) right: (ArithWord w:{(Lit_Digits 1)}) ) ) spids: [730 741] ) ("'") ) } ) ] spids: [646] ) spids: [642 645] ) (FuncDef name: bash_safe body: (BraceGroup children: [ (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:str) op: Equal rhs: {(DQ (BracedVarSub token: prefix_op:VSub_Bang spids:[765768]))} spids: [763] ) ] spids: [761] ) (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:escaped_quote) op: Equal rhs: {(DQ ("'") (EscapedLiteralPart token:) ("''"))} spids: [778] ) ] spids: [776] ) (C {(export)} {(DQ ($ VSub_Number "$1")) (Lit_Other "=") (DQ ("'") (BracedVarSub token: suffix_op: (PatSub pat: {(EscapedLiteralPart token:)} replace: {($ VSub_Name "$escaped_quote")} do_all: True do_prefix: False do_suffix: False ) spids: [794 801] ) ("'") ) } ) ] spids: [758] ) spids: [754 757] ) (FuncDef name: join body: (BraceGroup children: [ (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:delim) op: Equal rhs: {(DQ ($ VSub_Number "$1"))} spids: [817] ) ] spids: [815] ) (AndOr children: [(C {(read)} {(line)}) (C {(echo)} {(-n)} {(DQ ($ VSub_Name "$line"))})] op_id: Op_DAmp ) (While cond: [(Sentence child:(C {(read)} {(line)}) terminator:)] body: (DoGroup children: [ (C {(echo)} {(-n)} {(DQ ($ VSub_Name "$delim"))}) (C {(echo)} {(-n)} {(DQ ($ VSub_Name "$line"))}) ] spids: [845 866] ) ) ] spids: [812] ) spids: [808 811] ) ] )