From c48a74ea970afe39eb5c62699f92acf76b0332ed Mon Sep 17 00:00:00 2001 From: Frank Vumbaca Date: Fri, 7 Jun 2019 21:48:24 -0400 Subject: [PATCH] v0.2.0 - Closes #8 - Now supports lists in query language --- .gitignore | 8 +++++- README.md | 20 +++++++-------- _static/_get/index.html | 2 +- src/ysh.sh | 24 ++++++++++------- test/test.sh | 57 +++++++++++++++++++++++++++++++++-------- ysh | 20 ++++++++++----- 6 files changed, 93 insertions(+), 38 deletions(-) diff --git a/.gitignore b/.gitignore index 98b0ad0..75316c3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,8 @@ _gen -*.todo \ No newline at end of file +*.todo + + +# Emacs +*~ +\#*\# +.\#* \ No newline at end of file diff --git a/README.md b/README.md index d194eac..e042910 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ YSH_LIB=1;source /usr/local/bin/ysh If you want the internet as your only dependency: ```bash -$ YSH_LIB=1;source /dev/stdin <<< "$(curl -s https://raw.githubusercontent.com/azohra/yaml.sh/v0.1.5/ysh)" +$ YSH_LIB=1;source /dev/stdin <<< "$(curl -s https://raw.githubusercontent.com/azohra/yaml.sh/v0.2.0/ysh)" ``` ## Cook Book @@ -60,39 +60,39 @@ block_no: 1 ### Read from a file: ```bash -ysh -f input.yaml -Q block_no +ysh -f input.yaml -Q "block_no" ``` ### Re-use an already transpiled file ```bash file=$(ysh -f input.yaml) -ysh -T $file -Q block_no +ysh -T $file -Q "block_no" ``` ### Query piped yaml ```bash -cat input.yaml | ysh -Q block_no +cat input.yaml | ysh -Q "block_no" ``` ### Query for a value ```bash -ysh -f file.yaml -Q block_no +ysh -f file.yaml -Q "block_no" ``` ### Query from a stored sub structure ```bash -sub=$(ysh -f file.yaml -s level_one) -ysh -T $sub -Q level_two.key +sub=$(ysh -f file.yaml -s "level_one") +ysh -T $sub -Q "level_two.key" ``` ### Query i'th item from a simple list ```bash -ysh -f input.yaml -l level_one.level_two.simple_lists -I 1 +ysh -f input.yaml -Q "level_one.level_two.simple_lists[1]" ``` ### Query i'th item from a complex list ```bash -ysh -f input.yaml -l level_one.level_two.expanded_lists -i 1 -Q name +ysh -f input.yaml -Q "level_one.level_two.expanded_lists[1].name" ``` ### Print value from each block @@ -102,7 +102,7 @@ YSH_LIB=1; source /usr/local/bin/ysh file=$(ysh -f input.yaml) while [ -n "${file}" ]; do - echo "Block Number:" $(ysh -T "${file}" -Q block_no) + echo "Block Number:" $(ysh -T "${file}" -Q "block_no") file=$(ysh -T "${file}" -n) done ``` diff --git a/_static/_get/index.html b/_static/_get/index.html index a45d82e..3c39520 100644 --- a/_static/_get/index.html +++ b/_static/_get/index.html @@ -1,2 +1,2 @@ -curl -s -L https://raw.githubusercontent.com/azohra/yaml.sh/v0.1.5/ysh --output /usr/local/bin/ysh; +curl -s -L https://raw.githubusercontent.com/azohra/yaml.sh/v0.2.0/ysh --output /usr/local/bin/ysh; chmod u+x /usr/local/bin/ysh diff --git a/src/ysh.sh b/src/ysh.sh index 5695681..cbc721a 100755 --- a/src/ysh.sh +++ b/src/ysh.sh @@ -1,10 +1,14 @@ #! /bin/bash # shellcheck source=/dev/null -YSH_version='0.1.5' +YSH_version='0.2.0' # Will be replaced by builder with minified awk parser program YAML_AWK_PARSER=$(cat src/ysh.awk) +YSH_escape_query() { + sed -e "s/\\[/.\\\\[/" -e "s/\\]/\\\\]/" -e "s/^\\.//" <<< "$1" +} + YSH_parse() { awk "${YAML_AWK_PARSER}" "${1}" } @@ -14,15 +18,18 @@ YSH_parse_sdin() { } YSH_query() { - grep -E "^${2}" <<< "${1}" | sed -E "s/^${2}[\\.=]?//" + q=$(YSH_escape_query "${2}") + grep -E "^${q}" <<< "${1}" | sed -E "s/^${q}[\\.=]?//" } YSH_safe_query() { - grep -E "^${2}=\".*\"$" <<< "${1}" | sed -E "s/^${2}=\"//" | sed -E "s/\"$//" + q=$(YSH_escape_query "${2}") + grep -E "^${q}=\".*\"$" <<< "${1}" | sed -E "s/^${q}=\"//" | sed -E "s/\"$//" } YSH_sub() { - grep -E "^${2}[^=]" <<< "${1}" | sed "s/^$2\\.//" + q=$(YSH_escape_query "${2}") + grep -E "^${q}[^=]" <<< "${1}" | sed "s/^$2\\.//" } YSH_list() { @@ -38,15 +45,15 @@ YSH_count() { } YSH_index() { - YSH_query "${1}" "\\[${2}\\]" + YSH_query "${1}" "[${2}]" } YSH_safe_index() { - YSH_safe_query "${1}" "\\[${2}\\]" + YSH_safe_query "${1}" "[${2}]" } YSH_safe_index() { - YSH_safe_query "${1}" "\\[${2}\\]" + YSH_safe_query "${1}" "[${2}]" } YSH_tops() { @@ -57,7 +64,6 @@ YSH_next_block() { grep -E "^-.*" <<< "${1}" | sed -E "s/^-\\.?//g" } - YSH_usage() { echo "" echo "Usage: ysh [-fT input] [queries]" @@ -147,7 +153,7 @@ ysh() { exit 1 ;; *) - echo "Unknown Ussage!" > /dev/stdout + echo "Error: invalid use" > /dev/stdout exit 1 ;; esac diff --git a/test/test.sh b/test/test.sh index a1af9cd..8c5cabd 100755 --- a/test/test.sh +++ b/test/test.sh @@ -55,6 +55,7 @@ testSimpleList() { assertEquals 4 $(wc -l <<< "${result}") } + testSimpleListValues() { result=$(ysh -T "${file}" -L simple_list.list) assertContains "${result}" "one" @@ -92,8 +93,20 @@ testExpandedList() { assertEquals 6 $(wc -l <<< "${result}") } +testGetValueFromSimpleExpandedList() { + result=$(ysh -T "$file" -l "simple_list.list" -I 2) + assertEquals "three" "$result" +} + +testGetValueFromComplexExpandedList() { + result=$(ysh -T "$file" -l "object_list.list" -i 2) + assertContains "${result}" 'name="three"' + assertContains "${result}" 'value="3"' + assertEquals 2 $(wc -l <<< "${result}") +} + testArrayIndexAccess() { - result=$(ysh -T "$file" -l simple_list.list -i 1) + result=$(ysh -T "$file" -q "simple_list.list[1]") assertEquals "\"two\"" "${result}" result=$(ysh -T "$file" -l object_list.list -i 1) @@ -102,20 +115,20 @@ testArrayIndexAccess() { } testSafeArrayIndexAccess() { - result=$(ysh -T "$file" -l simple_list.list -I 1) + result=$(ysh -T "$file" -Q "simple_list.list[1]") assertEquals "two" "${result}" - result=$(ysh -T "$file" -l object_list.list -I 1) + result=$(ysh -T "$file" -l "object_list.list[1]") assertContains "name=two" "${result}" assertContains "value=2" "${result}" } testArraySafeIndexAccess() { - result=$(ysh -T "$file" -l simple_list.list -I 1) + result=$(ysh -T "$file" -Q "simple_list.list[1]") assertEquals "two" "${result}" - result=$(ysh -T "$file" -l object_list.list -I 1) + result=$(ysh -T "$file" -Q "object_list.list[1]") assertNull "${result}" } @@ -136,13 +149,37 @@ testNextBlock() { result=$(ysh -T "$file" -Q key) assertEquals "value" "${result}" - file=$(ysh -T "$file" -n) - result=$(ysh -T "$file" -Q key) + file2=$(ysh -T "$file" -n) + result=$(ysh -T "$file2" -Q key) assertEquals "block_2_value" "${result}" - file=$(ysh -T "$file" -n) - result=$(ysh -T "$file" -Q key) + file2=$(ysh -T "$file2" -n) + result=$(ysh -T "$file2" -Q key) assertEquals "block_3_value" "${result}" } -. ./test/shunit2 \ No newline at end of file +testEscapeLiteralListQuery() { + assertEquals "simple_list.list.\[2\]" $(YSH_escape_query "simple_list.list[2]") +} + +testEscapeComplexListItemQuery() { + assertEquals "simple_list.list.\[2\].key" $(YSH_escape_query "simple_list.list[2].key") +} + +testEscapeExpandedListItemQuery() { + assertEquals "\[2\]" $(YSH_escape_query "[2]") +} + +testSafeQueryWithListQuery() { + result=$(ysh -T "$file" -Q "simple_list.list[2]") + assertEquals "three" "$result" +} + +testSubSupportsEscapedQueries() { + result=$(ysh -T "$file" -s "object_list.list[2]") + assertContains "$result" 'object_list.list.[2].name="three"' + assertContains "$result" 'object_list.list.[2].value="3"' + assertEquals 2 $(wc -l <<< "$result") +} + +. ./test/shunit2 diff --git a/ysh b/ysh index 17cafd6..68fedee 100755 --- a/ysh +++ b/ysh @@ -1,5 +1,5 @@ #! /bin/bash -YSH_version='0.1.5' +YSH_version='0.2.0' YAML_AWK_PARSER=' function raise(msg) { print msg > "/dev/stderr"; if (force_complete) { exit_status = 1; } else { exit 1; };}; function level() { match($0, /^[[:space:]]*/); if (RLENGTH % 2 != 0) { raise("Bad indentation on line "NR". Number of spaces uneven."); }; return RLENGTH / 2;}; @@ -20,6 +20,9 @@ function check_started() { if (started == 0) { raise("Keys must be added before /^[[:space:]]*$/ { next }; 0 ' +YSH_escape_query() { + sed -e "s/\\[/.\\\\[/" -e "s/\\]/\\\\]/" -e "s/^\\.//" <<< "$1" +} YSH_parse() { awk "${YAML_AWK_PARSER}" "${1}" } @@ -27,13 +30,16 @@ YSH_parse_sdin() { awk "${YAML_AWK_PARSER}" } YSH_query() { - grep -E "^${2}" <<< "${1}" | sed -E "s/^${2}[\\.=]?//" + q=$(YSH_escape_query "${2}") + grep -E "^${q}" <<< "${1}" | sed -E "s/^${q}[\\.=]?//" } YSH_safe_query() { - grep -E "^${2}=\".*\"$" <<< "${1}" | sed -E "s/^${2}=\"//" | sed -E "s/\"$//" + q=$(YSH_escape_query "${2}") + grep -E "^${q}=\".*\"$" <<< "${1}" | sed -E "s/^${q}=\"//" | sed -E "s/\"$//" } YSH_sub() { - grep -E "^${2}[^=]" <<< "${1}" | sed "s/^$2\\.//" + q=$(YSH_escape_query "${2}") + grep -E "^${q}[^=]" <<< "${1}" | sed "s/^$2\\.//" } YSH_list() { YSH_sub "${1}" "${2}" | grep -E "^\\[[0-9]+\\]" @@ -45,13 +51,13 @@ YSH_count() { YSH_sub "${1}" "${2}" | grep -oE "^\\[[0-9]+\\]" | uniq | wc -l } YSH_index() { - YSH_query "${1}" "\\[${2}\\]" + YSH_query "${1}" "[${2}]" } YSH_safe_index() { - YSH_safe_query "${1}" "\\[${2}\\]" + YSH_safe_query "${1}" "[${2}]" } YSH_safe_index() { - YSH_safe_query "${1}" "\\[${2}\\]" + YSH_safe_query "${1}" "[${2}]" } YSH_tops() { sed -E "s/[\\[\\.=].*$//" <<< "${1}" | uniq