diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..d58eb07 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,17 @@ +root = true + +[*] +insert_final_newline = true +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true + +[Makefile] +insert_final_newline = true +indent_style = tab +indent_size = 4 + +[*.go] +insert_final_newline = true +indent_style = tab +indent_size = 4 diff --git a/.github/linters/.markdown-lint.yml b/.github/linters/.markdown-lint.yml new file mode 100644 index 0000000..7453638 --- /dev/null +++ b/.github/linters/.markdown-lint.yml @@ -0,0 +1,6 @@ +--- +default: true + +# Line length +# https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md#md013 +MD013: false diff --git a/.github/linters/.yamllint.yml b/.github/linters/.yamllint.yml new file mode 100644 index 0000000..75da2b7 --- /dev/null +++ b/.github/linters/.yamllint.yml @@ -0,0 +1,5 @@ +--- +extends: default + +rules: + line-length: disable diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..fb6b968 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,69 @@ +--- +name: "lint" + +# yamllint disable-line rule:truthy +on: + pull_request: + branches: + - "*" + push: + branches: + - "main" + +jobs: + hadolint: + name: hadolint + runs-on: ubuntu-22.04 + steps: + - name: Clone + uses: actions/checkout@v4 + - name: Run hadolint + uses: hadolint/hadolint-action@54c9adbab1582c2ef04b2016b760714a4bfde3cf + + markdown-lint: + name: markdown-lint + runs-on: ubuntu-22.04 + steps: + - name: Clone + uses: actions/checkout@v4 + - name: Run markdown-lint + uses: avto-dev/markdown-lint@04d43ee9191307b50935a753da3b775ab695eceb + with: + config: ".github/linters/.markdown-lint.yml" + args: "./README.md" + + shellcheck: + name: shellcheck + runs-on: ubuntu-22.04 + steps: + - name: Clone + uses: actions/checkout@v4 + - name: Run shellcheck + uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38 + env: + SHELLCHECK_OPTS: -s bash + shfmt: + name: shfmt + runs-on: ubuntu-22.04 + steps: + - name: Clone + uses: actions/checkout@v4 + - name: Run shfmt + uses: luizm/action-sh-checker@c6edb3de93e904488b413636d96c6a56e3ad671a + env: + GITHUB_TOKEN: ${{ secrets.GH_ACCESS_TOKEN }} + SHFMT_OPTS: -l -d -i 2 + with: + sh_checker_shellcheck_disable: true + sh_checker_comment: true + + yamllint: + name: yamllint + runs-on: ubuntu-22.04 + steps: + - name: Clone + uses: actions/checkout@v4 + - name: Run yamllint + uses: ibiqlik/action-yamllint@2576378a8e339169678f9939646ee3ee325e845c + with: + config_file: ".github/linters/.yamllint.yml" diff --git a/Dockerfile.build b/Dockerfile similarity index 100% rename from Dockerfile.build rename to Dockerfile diff --git a/Makefile b/Makefile index a69bc82..1ed5ba4 100644 --- a/Makefile +++ b/Makefile @@ -53,7 +53,7 @@ build: prebuild @$(MAKE) build/deb/$(NAME)_$(VERSION)_arm64.deb build-docker-image: - docker build --rm -q -f Dockerfile.build -t $(IMAGE_NAME):build . + docker build --rm -q -f Dockerfile -t $(IMAGE_NAME):build . $(targets): %-in-docker: .env.docker docker run \ diff --git a/README.md b/README.md index 673319b..75a0523 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,12 @@ # Sigil -[![IRC Channel](https://img.shields.io/badge/irc-%23gliderlabs-blue.svg)](https://kiwiirc.com/client/irc.freenode.net/#gliderlabs) - Standalone string interpolator and template processor +```shell +echo '${name} is{{ range seq ${count:-3} }} cool{{ end }}!' | sigil -p name=Sigil ``` -$ echo '${name} is{{ range seq ${count:-3} }} cool{{ end }}!' | sigil -p name=Sigil + +```text Sigil is cool cool cool! ``` @@ -28,8 +29,8 @@ Template text can be provided via STDIN or from a file if provided with the `-f` flag. Any other arguments are key-values in the form `=`. They are used as variables. - * `echo 'Hello, $name' | sigil -p name=Jeff` - * `sigil -p -f config.tmpl var1=foo "var2=Hello world"` +* `echo 'Hello, $name' | sigil -p name=Jeff` +* `sigil -p -f config.tmpl var1=foo "var2=Hello world"` ### Variables @@ -38,9 +39,9 @@ used as variables. There are two forms of variable syntax in Sigil. The first is POSIX style, which among other features allows default values or enforces required values: - * `$variable` - normal POSIX style - * `${variable:-"default"}` - expansion with default value - * `${variable:?}` - fails when not set +* `$variable` - normal POSIX style +* `${variable:-"default"}` - expansion with default value +* `${variable:?}` - fails when not set Environment variables are also available as POSIX style variables. This makes Sigil great for quick and simple string interpolation. @@ -51,7 +52,7 @@ The other syntax to use variables is consistent with the rest of the templating syntax. It uses `{{` and `}}` to define template expressions. Variable expansion in this form is simply used as: - * `{{ $variable }}` +* `{{ $variable }}` You can do much more with this syntax, such as modifier pipelines. All of which is explained below. @@ -66,7 +67,7 @@ Instead of replacing all `{{` with `{{“{{”}}`, you can change the delimiters by setting the `SIGIL_DELIMS` environment variable. It is the left and right delimiter strings, separated by a coma. -``` +```shell SIGIL_DELIMS={{{,}}} sigil -i 'hello {{{ $name }}}' name=packer ``` @@ -76,26 +77,26 @@ There are a number of builtin functions that can be used as modifiers, conditional tests, expansion data sources, and more. There are two references for functions available: - * [Sigil builtins](http://godoc.org/github.com/gliderlabs/sigil/builtin) - * [Go template builtins](http://golang.org/pkg/text/template/#hdr-Functions) +* [Sigil builtins](http://godoc.org/github.com/gliderlabs/sigil/builtin) +* [Go template builtins](http://golang.org/pkg/text/template/#hdr-Functions) Here are a few examples: - * `{{ $variable | capitalize }}` - * `{{ include "file.tmpl" "var1=foo" "var2=bar" }}` - * `{{ file "example.txt" | replace "old" "new" }}` - * `{{ json "file.json" | pointer "/Widgets/0/Name" }}` +* `{{ $variable | capitalize }}` +* `{{ include "file.tmpl" "var1=foo" "var2=bar" }}` +* `{{ file "example.txt" | replace "old" "new" }}` +* `{{ json "file.json" | pointer "/Widgets/0/Name" }}` ### Conditionals - * `{{ if expr }} true {{ end }}` - * `{{ if expr }} true {{ else }} false {{ end }}` - * `{{ if expr }} true {{ else if expr }} also true {{ end }}` +* `{{ if expr }} true {{ end }}` +* `{{ if expr }} true {{ else }} false {{ end }}` +* `{{ if expr }} true {{ else if expr }} also true {{ end }}` ### Loops / Iteration - * `{{ range expr }} element: {{.}} {{ end }}` - * `{{ range expr }} elements {{ else }} no elements {{ end }}` +* `{{ range expr }} element: {{.}} {{ end }}` +* `{{ range expr }} elements {{ else }} no elements {{ end }}` ### Full Syntax @@ -106,4 +107,4 @@ documentation there. ## License BSD - +![beacon](https://ga-beacon.appspot.com/UA-58928488-2/sigil/readme?pixel "beacon") diff --git a/tests/sigil.bash b/tests/sigil.bash index 1b16790..8f90cde 100644 --- a/tests/sigil.bash +++ b/tests/sigil.bash @@ -1,3 +1,4 @@ +# shellcheck disable=all GOOS=$(go env GOOS) export SIGIL="${SIGIL:-build/${GOOS}/gliderlabs-sigil}-amd64" @@ -17,7 +18,7 @@ T_posix_var_check() { } T_posix_var_check_unset() { - echo 'Hello, ${name:?}' | $SIGIL -p &> /dev/null + echo 'Hello, ${name:?}' | $SIGIL -p &>/dev/null [[ $? -ne 0 ]] } @@ -87,52 +88,53 @@ T_splitkv_joinkv() { } T_json() { - result=$(echo '{"one": "two"}' | $SIGIL -i '{{ stdin | json | tojson }}') - [[ "$result" == "{\"one\":\"two\"}" ]] + result=$(echo '{"one": "two"}' | $SIGIL -i '{{ stdin | json | tojson }}') + [[ "$result" == "{\"one\":\"two\"}" ]] } T_json_deep() { - result=$(echo '{"foo": {"one": "two"}}' | $SIGIL -i '{{ stdin | json | tojson }}') - [[ "$result" == '{"foo":{"one":"two"}}' ]] + result=$(echo '{"foo": {"one": "two"}}' | $SIGIL -i '{{ stdin | json | tojson }}') + [[ "$result" == '{"foo":{"one":"two"}}' ]] } T_yaml() { - yaml="$(echo -e "one: two\nthree:\n- four\n- five")" - result="$(echo -e "$yaml" | $SIGIL -i '{{ stdin | yaml | toyaml }}')" - [[ "$result" == "$yaml" ]] + yaml="$(echo -e "one: two\nthree:\n- four\n- five")" + result="$(echo -e "$yaml" | $SIGIL -i '{{ stdin | yaml | toyaml }}')" + [[ "$result" == "$yaml" ]] } T_shell() { result="$($SIGIL -i '{{ sh "date +%m-%d-%Y" }}')" - [[ "$result" == "$(date +%m-%d-%Y)" ]] + [[ "$result" == "$(date +%m-%d-%Y)" ]] } T_httpget() { result="$($SIGIL -i '{{ httpget "https://httpbin.org/get" | json | pointer "/url" }}')" - [[ "$result" == "https://httpbin.org/get" ]] + [[ "$result" == "https://httpbin.org/get" ]] } T_custom_delim() { result="$(SIGIL_DELIMS={{{,}}} $SIGIL -i '{{ hello {{{ $name }}} }}' name=packer)" - [[ "$result" == "{{ hello packer }}" ]] + [[ "$result" == "{{ hello packer }}" ]] } T_substr() { result="$($SIGIL -i '{{ "abcdefgh" | substr "1:4" }}')" - [[ "$result" == "bcd" ]] + [[ "$result" == "bcd" ]] } T_substr_single_index() { result="$($SIGIL -i '{{ "abcdefgh" | substr ":4" }}')" - [[ "$result" == "abcd" ]] + [[ "$result" == "abcd" ]] } T_yamltojson() { result="$(printf 'joe:\n age: 32\n color: red' | $SIGIL -i '{{ stdin | yaml | tojson }}')" - [[ "$result" == '{"joe":{"age":32,"color":"red"}}' ]] + [[ "$result" == '{"joe":{"age":32,"color":"red"}}' ]] } T_yamltojsondeep() { - result="$( $SIGIL -i '{{ stdin | yaml | tojson }}' <= `30`].name | reverse(@)" | join ","}}')" - [[ "$result" == 'joe,jim' ]] + [[ "$result" == 'joe,jim' ]] } T_base64enc() { result="$(echo 'happybirthday' | $SIGIL -i '{{ stdin | base64enc }}')" - [[ "$result" == "aGFwcHliaXJ0aGRheQo=" ]] + [[ "$result" == "aGFwcHliaXJ0aGRheQo=" ]] } T_base64dec() { result="$(echo 'aGFwcHliaXJ0aGRheQo=' | $SIGIL -i '{{ stdin | base64dec }}')" - [[ "$result" == "happybirthday" ]] + [[ "$result" == "happybirthday" ]] }