diff --git a/.gitignore b/.gitignore index b25c15b..7931c15 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ *~ +*swp +.* diff --git a/tests/common.sh b/tests/common.sh new file mode 100644 index 0000000..5da0173 --- /dev/null +++ b/tests/common.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +error_count=0 +test_error() { + (( error_count++ )) + echo "$1" +} + +test_done(){ + if (( error_count == 0 )); then + echo "Success" + else + echo "Failed " $error_count " tests" + fi +} diff --git a/tests/delete.sh b/tests/delete.sh deleted file mode 100755 index 761e8d7..0000000 --- a/tests/delete.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -. ../ticktick.sh - -`` key = {"value": 1} `` - -echo ``key.value`` -``key.value.delete()`` -echo ``key.value`` - diff --git a/tests/delete.test.sh b/tests/delete.test.sh new file mode 100755 index 0000000..9097184 --- /dev/null +++ b/tests/delete.test.sh @@ -0,0 +1,11 @@ +#!/bin/bash +. ../ticktick.sh +. ./common.sh + +`` key = {"value": 1} `` + +[ "``key.value``" == "1" ] || test_error "Key Assignment wrong" +``key.value.delete()`` +[ -z "``key.value``" ] || test_error "Key Not Deleted" + +test_done diff --git a/tests/dict.test.sh b/tests/dict.test.sh new file mode 100755 index 0000000..5b49b65 --- /dev/null +++ b/tests/dict.test.sh @@ -0,0 +1,12 @@ +#!/bin/bash +. ../ticktick.sh + +# This is reference to issue (1), +# (test case) e.g., parser goes to infinite loop on dicts + +# This should parse ok +`` data = { "x" : "y" } `` + +# This is a bug in code, but +# it should say so +`` data = { "x" : "y", } `` diff --git a/tests/runall.sh b/tests/runall.sh new file mode 100755 index 0000000..09a5d43 --- /dev/null +++ b/tests/runall.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +for i in *.test.sh; do + echo "$i {" + ./$i | sed "s/^/ /g" + echo "}" + echo +done diff --git a/tests/runtime.sh b/tests/runtime.sh deleted file mode 100755 index 0c6535e..0000000 --- a/tests/runtime.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -. ../ticktick.sh - -DATA=`cat data.json` - -tickParse "$DATA" - -echo ``pathname`` -echo ``headers["user-agent"]`` diff --git a/tests/runtime.test.sh b/tests/runtime.test.sh new file mode 100755 index 0000000..3a87c13 --- /dev/null +++ b/tests/runtime.test.sh @@ -0,0 +1,12 @@ +#!/bin/bash +. ../ticktick.sh +. ./common.sh + +DATA=`cat data.json` + +tickParse "$DATA" + +[ "``pathname``" == "/echo/request.json" ] || test_error "Pathname wrong" +[ "``headers["user-agent"]``" == "curl/7.21.6 (i686-pc-linux-gnu) libcurl/7.21.6 OpenSSL/1.0.0e zlib/1.2.3.4 libidn/1.22 librtmp/2.3" ] || test_error "User-agent wrong" + +test_done diff --git a/ticktick.sh b/ticktick.sh index 3f8d2ca..645017a 100644 --- a/ticktick.sh +++ b/ticktick.sh @@ -1,5 +1,10 @@ #!/usr/bin/env bash ARGV=$@ + +__tick_error() { + echo "TICKTICK PARSING ERROR: "$1 +} + # This is from https://github.com/dominictarr/JSON.sh # See LICENSE for more info. {{{ __tick_json_tokenize() { @@ -50,12 +55,20 @@ __tick_json_parse_object() { *) while : do + # The key, it should be valid case "$Token" in '"'*'"'|\$[A-Za-z0-9_]*) key=$Token ;; + # If we get here then we aren't on a valid key + *) + __tick_error "Object without a Key" + break + ;; esac + # A colon read -r Token + # The value read -r Token __tick_json_parse_value "$1" "$key" obj+="$key:$Value" @@ -205,6 +218,18 @@ __tick_fun_parse_expression() { fi } +__tick_fun_parse_tickcount_reset() { + # If the tick count is 1 then the backtick we encountered was a + # shell code escape. These ticks need to be preserved for the script. + if (( ticks == 1 )); then + code+='`' + fi + + # This resets the backtick counter so that `some shell code` doesn't + # trip up the tokenizer + ticks=0 +} + # The purpose of this function is to separate out the Bash code from the # special "tick tick" code. We do this by hijacking the IFS and reading # in a single character at a time @@ -241,6 +266,8 @@ __tick_fun_parse() { ;; '') + __tick_fun_parse_tickcount_reset + # this is a newline. If we are in ticktick, then we want to consume # them for the parser later on. If we are in bash, then we want to # preserve them. We do this by emitting our buffer and then clearing @@ -249,12 +276,11 @@ __tick_fun_parse() { echo "$code" unset code fi + ;; *) - # This resets the backtick counter so that `some shell code` doesn't - # trip up the tokenizer - ticks=0 + __tick_fun_parse_tickcount_reset # This is a buffer of the current code, either bash or backtick code+="$token" @@ -273,8 +299,26 @@ __tick_fun_tokenize() { # then cat the calling program and push it through our parser local code=$(cat `caller 1 | cut -d ' ' -f 3` | __tick_fun_parse) - # Take the output and then execute it - bash -c "$code" -- $ARGV + # Before the execution we search to see if we emitted any parsing errors + hasError=`echo "$code" | grep "TICKTICK PARSING ERROR" | wc -l` + + if [ $__tick_var_debug ]; then + printf "%s\n" "$code" + exit 0 + fi + + # If there are no errors, then we go ahead + if (( hasError == 0 )); then + # Take the output and then execute it + + bash -c "$code" -- $ARGV + else + echo "Parsing Error Detected, see below" + + # printf observes the new lines + printf "%s\n" "$code" + echo "Parsing stopped here." + fi exit }