pax_global_header00006660000000000000000000000064141636313100014510gustar00rootroot0000000000000052 comment=27690e8cd19e194a729e34967bb666d83ada19b0 easygen-5.1.9/000077500000000000000000000000001416363131000131575ustar00rootroot00000000000000easygen-5.1.9/.all-contributorsrc000066400000000000000000000047631416363131000170220ustar00rootroot00000000000000{ "files": [ "README.md", "README.beg.e.md", "README.end.e.md" ], "imageSize": 100, "commit": false, "contributors": [ { "login": "suntong", "name": "suntong", "avatar_url": "https://avatars.githubusercontent.com/u/422244?v=4", "profile": "https://github.com/suntong", "contributions": [ "code", "ideas", "design", "data", "test", "bug", "doc", "blog", "example", "tutorial", "tool", "platform", "review", "question", "maintenance", "infra" ] }, { "login": "grrtrr", "name": "Gerrit Renker", "avatar_url": "https://avatars.githubusercontent.com/u/5132989?v=4", "profile": "http://gerrit.sdf.org/", "contributions": [ "code", "ideas", "bug", "userTesting", "talk", "content", "blog" ] }, { "login": "bruston", "name": "Benjamin Ruston", "avatar_url": "https://avatars.githubusercontent.com/u/3519911?v=4", "profile": "https://github.com/bruston", "contributions": [ "code", "bug", "userTesting" ] }, { "login": "sanjaymsh", "name": "sanjaymsh", "avatar_url": "https://avatars.githubusercontent.com/u/66668807?v=4", "profile": "https://github.com/sanjaymsh", "contributions": [ "platform" ] }, { "login": "anthonyfok", "name": "Anthony Fok", "avatar_url": "https://avatars.githubusercontent.com/u/1274764?v=4", "profile": "https://wiki.debian.org/AnthonyFok", "contributions": [ "bug", "review", "maintenance", "userTesting" ] }, { "login": "ghost", "name": "Deleted user", "avatar_url": "https://avatars.githubusercontent.com/u/10137?v=4", "profile": "https://github.com/ghost", "contributions": [ "bug", "ideas", "userTesting" ] }, { "login": "romz-pl", "name": "Zbigniew Romanowski", "avatar_url": "https://avatars.githubusercontent.com/u/32552206?v=4", "profile": "https://github.com/romz-pl", "contributions": [ "bug", "ideas", "userTesting" ] } ], "contributorsPerLine": 7, "projectName": "easygen", "projectOwner": "go-easygen", "repoType": "github", "repoHost": "https://github.com", "skipCi": true } easygen-5.1.9/.github/000077500000000000000000000000001416363131000145175ustar00rootroot00000000000000easygen-5.1.9/.github/workflows/000077500000000000000000000000001416363131000165545ustar00rootroot00000000000000easygen-5.1.9/.github/workflows/codeql-analysis.yml000066400000000000000000000050241416363131000223700ustar00rootroot00000000000000# For most projects, this workflow file will not need changing; you simply need # to commit it to your repository. # # You may wish to alter this file to override the set of languages analyzed, # or to provide custom queries or build logic. # # ******** NOTE ******** # We have attempted to detect the languages in your repository. Please check # the `language` matrix defined below to confirm you have the correct set of # supported CodeQL languages. # name: "CodeQL" on: push: # branches: [ main ] paths-ignore: - '**/*.md' pull_request: # The branches below must be a subset of the branches above # branches: [ main ] paths-ignore: - '**/*.md' schedule: # The default branch at 14:32 UTC on the 1st of every month - cron: '32 14 1 * *' jobs: analyze: name: Analyze runs-on: ubuntu-latest permissions: actions: read contents: read security-events: write strategy: fail-fast: false matrix: language: [ 'go' ] # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] # Learn more: # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed steps: - name: Checkout repository uses: actions/checkout@v2 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@v1 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. # By default, queries listed here will override any specified in a config file. # Prefix the list here with "+" to use these queries and those in the config file. # queries: ./path/to/local/query, your-org/your-repo/queries@main # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild uses: github/codeql-action/autobuild@v1 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl # âœī¸ If the Autobuild fails above, remove it and uncomment the following three lines # and modify them (or add more) to build your code if your project # uses a compiled language #- run: | # make bootstrap # make release - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v1 easygen-5.1.9/.github/workflows/go-release-build.yml000066400000000000000000000042531416363131000224230ustar00rootroot00000000000000name: build on: push: branches: - 'master' tags: - 'v*' env: GO111MODULE: off jobs: build: runs-on: ubuntu-latest steps: - name: Set up Go uses: actions/setup-go@v2 with: go-version: 1.16 - name: Install Cloudsmith CLI run: pip install --upgrade cloudsmith-cli # Cloudsmith CLI tooling for pushing releases # See https://help.cloudsmith.io/docs/cli - name: Checkout uses: actions/checkout@v2 with: fetch-depth: 0 - name: Tests run: | export GOPATH=/home/runner/go mkdir -p $GOPATH/src/github.com/$GITHUB_ACTOR mv $GITHUB_WORKSPACE $GOPATH/src/github.com/$GITHUB_ACTOR ln -s $GOPATH/src/github.com/$GITHUB_REPOSITORY $GITHUB_WORKSPACE # go mod tidy go get -v ./... go test -v ./... - name: Run GoReleaser uses: goreleaser/goreleaser-action@v2 if: success() && startsWith(github.ref, 'refs/tags/') with: version: latest args: release --rm-dist env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Publish to cloudsmith repo - name: Publish package to cloudsmith if: success() && startsWith(github.ref, 'refs/tags/') env: CLOUDSMITH_API_KEY: ${{ secrets.CLOUDSMITH_API_KEY }} run: | for filepath in dist/*; do echo "== Analyzing '$filepath' for publishing" filename=$(basename -- "$filepath") extension="${filename##*.}" filename="${filename%.*}" case "$extension" in 'apk') echo "Pushing '$filepath' to cloudsmith repo" cloudsmith push alpine suntong/repo/alpine/any-version $filepath ;; 'deb' | 'rpm') echo "Pushing '$filepath' to cloudsmith repo" cloudsmith push $extension suntong/repo/any-distro/any-version $filepath ;; *) echo "File .$extension skipped publishing" echo ;; esac done easygen-5.1.9/.gitignore000066400000000000000000000004731416363131000151530ustar00rootroot00000000000000.all-contributorsrc # Compiled Object files, Static and Dynamic libs (Shared Objects) *.o *.a *.so # Folders _obj _test # Architecture specific extensions/prefixes *.[568vq] [568vq].out *.cgo1.go *.cgo2.c _cgo_defun.c _cgo_gotypes.go _cgo_export.* _testmain.go *.exe *.test *.prof *~ easygen-5.1.9/.goreleaser.yml000066400000000000000000000013101416363131000161030ustar00rootroot00000000000000project_name: easygen archives: - format: tar.gz wrap_in_directory: true format_overrides: - goos: windows format: zip # remove README and LICENSE files: - none* builds: - env: [CGO_ENABLED=0] goos: - linux - windows - darwin goarch: - amd64 - arm64 # Path to main.go file or main package. # Notice: when used with `gomod.proxy`, this must be a package. # # Default is `.`. main: ./cmd/easygen nfpms: - maintainer: Tong Sun description: easygen - Easy to use universal code/text generator homepage: https://github.com/go-easygen/easygen license: MIT formats: - deb - rpm - apk easygen-5.1.9/LICENSE000066400000000000000000000020631416363131000141650ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2015 suntong Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. easygen-5.1.9/README.beg.e.md000066400000000000000000000016751416363131000154260ustar00rootroot00000000000000# {{.Name}} [![All Contributors](https://img.shields.io/badge/all_contributors-7-orange.svg?style=flat-square)](#contributors-) {{render "license/shields" . "License" "MIT"}} {{template "badge/godoc" .}} {{template "badge/goreport" .}} [![Build Status](https://github.com/{{.User}}/{{.Name}}/actions/workflows/go-release-build.yml/badge.svg?branch=master)](https://github.com/{{.User}}/{{.Name}}/actions/workflows/go-release-build.yml) [![PoweredBy WireFrame](https://github.com/go-easygen/wireframe/blob/master/PoweredBy-WireFrame-B.svg)](http://godoc.org/github.com/go-easygen/wireframe) {{pkgdoc}} The easy to use universal code/text generator > _`easygen` is to `json` what `xslt` is to `xml`, but much more powerful and versatile._ > _`easygen` has been such a great help to us, making so many mundane tasks easier (and fun) to do._ easygen-5.1.9/README.e.md000066400000000000000000000057041416363131000146670ustar00rootroot00000000000000 ## {{toc 5}} - [Download/install binaries](#downloadinstall-binaries) - [The binary executables](#the-binary-executables) - [Distro package](#distro-package) - [Debian package](#debian-package) - [Install Source](#install-source) - [Author](#author) - [Contributors](#contributors-) ## {{.Name}} - Easy to use universal code/text generator Command `{{.Name}}` is an easy to use universal code/text generator. It can be used as a text or html generator for _arbitrary_ purposes with _arbitrary_ data and templates. It is a good [GSL](https://github.com/imatix/gsl) replacement, as it - is more easy to define driving data, in form of YML instead of XML - has more powerful template engine that based on Go template. You can also write your own function in Go to customize your template. - there are lots of transformation support functions builtin inside it, check out the full list with sample usages and results [here](https://github.com/go-easygen/easygen/issues/25). - apart from the above sample usages, it has extensive documentations like [this](https://github.com/go-easygen/easygen/wiki/Docs:-Easygen-usage). Check out the [wiki](https://github.com/go-easygen/easygen/wiki/) for the full list. You can even use easygen as [a generic Go template testing tool](https://github.com/go-easygen/easygen/wiki/Tip:-Testing-the-templates-on-the-fly) using the `-ts` commandline option, and much more. Note this document is for `{{.Name}}` versions 4.0+. For historic versions check out the [Different Versions](https://github.com/go-easygen/easygen/wiki/Docs:-Different-Versions) section. ## Usage ### $ {{exec "easygen" | color "sh"}} ## Details It can be used as a code generator, for example, command line parameter handling code generator, or anything that is structurally repetitive, like the following: - [Introduction to easygen and its philosophy ](https://suntong.github.io/blogs/2016/01/01/easygen---easy-to-use-universal-code/text-generator) - [What is the "XSLT" equivalent for JSON? Here is the new answer](https://dev.to/suntong/what-is-the-xslt-equivalent-for-json-here-is-the-new-answer-7la) - [Transforming json data with easygen](https://dev.to/suntong/transforming-json-data-with-easygen-4g2i) - [Easygen is now coding itself ](https://sfxpt.wordpress.com/2015/07/04/easygen-is-now-coding-itself/) - [Showcasing the power of easygen with ffcvt ](https://sfxpt.wordpress.com/2015/08/02/showcasing-the-power-of-easygen-with-ffcvt/) - [Easygen for HTML mock-up ](https://sfxpt.wordpress.com/2015/07/10/easygen-for-mock-up/) - [Moving beyond code-gen and mock-up, using easygen in real life creating GPT partitions](https://suntong.github.io/blogs/2015/12/26/creating-gpt-partitions-easily-on-the-command-line) Ready to get started? Then check out [Getting Started](https://github.com/go-easygen/easygen/wiki/Getting-Started) to start building your way to turn your data into any form, any way you want. ## Install Debian/Ubuntu package apt install {{.Name}} easygen-5.1.9/README.end.e.md000066400000000000000000000160531416363131000154330ustar00rootroot00000000000000 ## Download/install binaries - The latest binary executables are available as the result of the Continuous-Integration (CI) process. - I.e., they are built automatically right from the source code at every git release by [GitHub Actions](https://docs.github.com/en/actions). - There are two ways to get/install such binary executables * Using the **binary executables** directly, or * Using **packages** for your distro ### The binary executables - The latest binary executables are directly available under https://github.com/{{.User}}/{{.Name}}/releases/latest - Pick & choose the one that suits your OS and its architecture. E.g., for Linux, it would be the `{{.Name}}_verxx_linux_amd64.tar.gz` file. - Available OS for binary executables are * Linux * Mac OS (darwin) * Windows - If your OS and its architecture is not available in the download list, please let me know and I'll add it. - The manual installation is just to unpack it and move/copy the binary executable to somewhere in `PATH`. For example, ``` sh tar -xvf {{.Name}}_*_linux_amd64.tar.gz sudo mv -v {{.Name}}_*_linux_amd64/{{.Name}} /usr/local/bin/ rmdir -v {{.Name}}_*_linux_amd64 ``` ### Distro package - Packages available for Linux distros are * [Alpine Linux](https://cloudsmith.io/~suntong/repos/repo/setup/#formats-alpine) * [Debian](https://cloudsmith.io/~suntong/repos/repo/setup/#formats-deb) * [RedHat](https://cloudsmith.io/~suntong/repos/repo/setup/#formats-rpm) The repo setup instruction url has been given above. For example, for [Debian](https://cloudsmith.io/~suntong/repos/repo/setup/#formats-deb) -- ### Debian package ```sh curl -1sLf \ 'https://dl.cloudsmith.io/public/suntong/repo/setup.deb.sh' \ | sudo -E bash # That's it. You then can do your normal operations, like sudo apt-get update apt-cache policy {{.Name}} sudo apt-get install -y {{.Name}} ``` ## Install Source To install the source code instead: ``` go get -v -u {{.ProjectURL}} ``` ## Author Tong SUN ![suntong from cpan.org](https://img.shields.io/badge/suntong-%40cpan.org-lightgrey.svg "suntong from cpan.org") _Powered by_ [**WireFrame**](https://github.com/go-easygen/wireframe) [![PoweredBy WireFrame](https://github.com/go-easygen/wireframe/blob/master/PoweredBy-WireFrame-Y.svg)](http://godoc.org/github.com/go-easygen/wireframe) the _one-stop wire-framing solution_ for Go cli based projects, from _init_ to _deploy_. ## Contributors ✨ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):

suntong

đŸ’ģ 🤔 🎨 đŸ”Ŗ âš ī¸ 🐛 📖 📝 💡 ✅ 🔧 đŸ“Ļ 👀 đŸ’Ŧ 🚧 🚇

Gerrit Renker

đŸ’ģ 🤔 🐛 📓 đŸ“ĸ 🖋 📝

Benjamin Ruston

đŸ’ģ 🐛 📓

sanjaymsh

đŸ“Ļ

Anthony Fok

🐛 👀 🚧 📓

Deleted user

🐛 🤔 📓

Zbigniew Romanowski

🐛 🤔 📓
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! easygen-5.1.9/README.md000066400000000000000000000306611416363131000144440ustar00rootroot00000000000000# easygen [![All Contributors](https://img.shields.io/badge/all_contributors-7-orange.svg?style=flat-square)](#contributors-) [![MIT License](http://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) [![GoDoc](https://godoc.org/github.com/go-easygen/easygen?status.svg)](http://godoc.org/github.com/go-easygen/easygen) [![Go Report Card](https://goreportcard.com/badge/github.com/go-easygen/easygen)](https://goreportcard.com/report/github.com/go-easygen/easygen) [![Build Status](https://github.com/go-easygen/easygen/actions/workflows/go-release-build.yml/badge.svg?branch=master)](https://github.com/go-easygen/easygen/actions/workflows/go-release-build.yml) [![PoweredBy WireFrame](https://github.com/go-easygen/wireframe/blob/master/PoweredBy-WireFrame-B.svg)](http://godoc.org/github.com/go-easygen/wireframe) The easy to use universal code/text generator > _`easygen` is to `json` what `xslt` is to `xml`, but much more powerful and versatile._ > _`easygen` has been such a great help to us, making so many mundane tasks easier (and fun) to do._ ## TOC - [easygen - Easy to use universal code/text generator](#easygen---easy-to-use-universal-codetext-generator) - [Usage](#usage) - [$ easygen](#-easygen) - [Details](#details) - [Install Debian/Ubuntu package](#install-debianubuntu-package) - [Download/install binaries](#downloadinstall-binaries) - [The binary executables](#the-binary-executables) - [Distro package](#distro-package) - [Debian package](#debian-package) - [Install Source](#install-source) - [Author](#author) - [Contributors](#contributors-) ## easygen - Easy to use universal code/text generator Command `easygen` is an easy to use universal code/text generator. It can be used as a text or html generator for _arbitrary_ purposes with _arbitrary_ data and templates. It is a good [GSL](https://github.com/imatix/gsl) replacement, as it - is more easy to define driving data, in form of YML instead of XML - has more powerful template engine that based on Go template. You can also write your own function in Go to customize your template. - there are lots of transformation support functions builtin inside it, check out the full list with sample usages and results [here](https://github.com/go-easygen/easygen/issues/25). - apart from the above sample usages, it has extensive documentations like [this](https://github.com/go-easygen/easygen/wiki/Docs:-Easygen-usage). Check out the [wiki](https://github.com/go-easygen/easygen/wiki/) for the full list. You can even use easygen as [a generic Go template testing tool](https://github.com/go-easygen/easygen/wiki/Tip:-Testing-the-templates-on-the-fly) using the `-ts` commandline option, and much more. Note this document is for `easygen` versions 4.0+. For historic versions check out the [Different Versions](https://github.com/go-easygen/easygen/wiki/Docs:-Different-Versions) section. ## Usage ### $ easygen ```sh easygen version 5.1.9 Usage: easygen [flags] template_name [data_filename [data_filename...]] Flags: -debug level debugging level -ej extension extension of json file (default ".json") -et extension extension of template file (default ".tmpl") -ey extension extension of yaml file (default ".yaml") -ts string template string (in text) template_name: The name for the template file. - Can have the extension (specified by -et) or without it. - Can include the path as well. - Can be a comma-separated list giving many template files, in which case at least one data_filename must be given. data_filename(s): The name for the .yaml or .json data. - If omitted derive from the template_name. - Can have the extension or without it. If withot extension, will try the .yaml file first then .json - Can include the path as well. - If there is a single data_filename, and it is "-", then read the data (.yaml or .json format) from stdin. Flag defaults can be overridden by corresponding environment variable, e.g.: EASYGEN_EY=.yml EASYGEN_ET=.tpl easygen ... ``` ## Details It can be used as a code generator, for example, command line parameter handling code generator, or anything that is structurally repetitive, like the following: - [Introduction to easygen and its philosophy ](https://suntong.github.io/blogs/2016/01/01/easygen---easy-to-use-universal-code/text-generator) - [What is the "XSLT" equivalent for JSON? Here is the new answer](https://dev.to/suntong/what-is-the-xslt-equivalent-for-json-here-is-the-new-answer-7la) - [Transforming json data with easygen](https://dev.to/suntong/transforming-json-data-with-easygen-4g2i) - [Easygen is now coding itself ](https://sfxpt.wordpress.com/2015/07/04/easygen-is-now-coding-itself/) - [Showcasing the power of easygen with ffcvt ](https://sfxpt.wordpress.com/2015/08/02/showcasing-the-power-of-easygen-with-ffcvt/) - [Easygen for HTML mock-up ](https://sfxpt.wordpress.com/2015/07/10/easygen-for-mock-up/) - [Moving beyond code-gen and mock-up, using easygen in real life creating GPT partitions](https://suntong.github.io/blogs/2015/12/26/creating-gpt-partitions-easily-on-the-command-line) Ready to get started? Then check out [Getting Started](https://github.com/go-easygen/easygen/wiki/Getting-Started) to start building your way to turn your data into any form, any way you want. ## Install Debian/Ubuntu package apt install easygen ## Download/install binaries - The latest binary executables are available as the result of the Continuous-Integration (CI) process. - I.e., they are built automatically right from the source code at every git release by [GitHub Actions](https://docs.github.com/en/actions). - There are two ways to get/install such binary executables * Using the **binary executables** directly, or * Using **packages** for your distro ### The binary executables - The latest binary executables are directly available under https://github.com/go-easygen/easygen/releases/latest - Pick & choose the one that suits your OS and its architecture. E.g., for Linux, it would be the `easygen_verxx_linux_amd64.tar.gz` file. - Available OS for binary executables are * Linux * Mac OS (darwin) * Windows - If your OS and its architecture is not available in the download list, please let me know and I'll add it. - The manual installation is just to unpack it and move/copy the binary executable to somewhere in `PATH`. For example, ``` sh tar -xvf easygen_*_linux_amd64.tar.gz sudo mv -v easygen_*_linux_amd64/easygen /usr/local/bin/ rmdir -v easygen_*_linux_amd64 ``` ### Distro package - Packages available for Linux distros are * [Alpine Linux](https://cloudsmith.io/~suntong/repos/repo/setup/#formats-alpine) * [Debian](https://cloudsmith.io/~suntong/repos/repo/setup/#formats-deb) * [RedHat](https://cloudsmith.io/~suntong/repos/repo/setup/#formats-rpm) The repo setup instruction url has been given above. For example, for [Debian](https://cloudsmith.io/~suntong/repos/repo/setup/#formats-deb) -- ### Debian package ```sh curl -1sLf \ 'https://dl.cloudsmith.io/public/suntong/repo/setup.deb.sh' \ | sudo -E bash # That's it. You then can do your normal operations, like sudo apt-get update apt-cache policy easygen sudo apt-get install -y easygen ``` ## Install Source To install the source code instead: ``` go get -v -u github.com/go-easygen/easygen ``` ## Author Tong SUN ![suntong from cpan.org](https://img.shields.io/badge/suntong-%40cpan.org-lightgrey.svg "suntong from cpan.org") _Powered by_ [**WireFrame**](https://github.com/go-easygen/wireframe) [![PoweredBy WireFrame](https://github.com/go-easygen/wireframe/blob/master/PoweredBy-WireFrame-Y.svg)](http://godoc.org/github.com/go-easygen/wireframe) the _one-stop wire-framing solution_ for Go cli based projects, from _init_ to _deploy_. ## Contributors ✨ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):

suntong

đŸ’ģ 🤔 🎨 đŸ”Ŗ âš ī¸ 🐛 📖 📝 💡 ✅ 🔧 đŸ“Ļ 👀 đŸ’Ŧ 🚧 🚇

Gerrit Renker

đŸ’ģ 🤔 🐛 📓 đŸ“ĸ 🖋 📝

Benjamin Ruston

đŸ’ģ 🐛 📓

sanjaymsh

đŸ“Ļ

Anthony Fok

🐛 👀 🚧 📓

Deleted user

🐛 🤔 📓

Zbigniew Romanowski

🐛 🤔 📓
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! easygen-5.1.9/cmd/000077500000000000000000000000001416363131000137225ustar00rootroot00000000000000easygen-5.1.9/cmd/easygen/000077500000000000000000000000001416363131000153555ustar00rootroot00000000000000easygen-5.1.9/cmd/easygen/.gitignore000066400000000000000000000000101416363131000173340ustar00rootroot00000000000000easygen easygen-5.1.9/cmd/easygen/config.tmpl000066400000000000000000000007671416363131000175320ustar00rootroot00000000000000// !!! !!! // WARNING: Code automatically generated. Editing discouraged. // !!! !!! package {{.PackageName}} //////////////////////////////////////////////////////////////////////////// // Constant and data type/structure definitions const progname = "{{.ProgramName}}" // os.Args[0] // The {{.StructName}} struct defines the structure to hold the commandline values type {{.StructName}} struct { {{range .Options}}{{if ne .Name "SEPARATOR" }} {{.Name}} {{.Type}} // {{.Usage}}{{end}}{{end}} } easygen-5.1.9/cmd/easygen/easygen.1.ronn000066400000000000000000000040631416363131000200500ustar00rootroot00000000000000# easygen -- Easy to use universal code/text generator ## SYNOPSIS easygen [flags] template_name [data_filename [data_filename...]] data_filename(s): The name for the .yaml or .json data. - If omitted derive from the template_name. - Can have the extension or without it. If withot extension, will try .yaml first then .json - Can include the path as well. template_name: The name for the template file. - Can have the extension or without it. - Can include the path as well. - Can be a comma-separated list giving many template files, in which case at least one data_filename must be given. ## DESCRIPTION Command `easygen` is an easy to use universal code/text generator. It can be used as a text or html generator for _arbitrary_ purposes with _arbitrary_ data and templates. It is a good GSL replacement, as it - is more easy to define driving data, in form of YML instead of XML - has more powerful template engine that based on Go template. You can even write your own function in Go to customize your template. You can even use easygen as a generic Go template testing tool using the `-ts` commandline option, and much more. ## Usage It's very easy to use -- just type `easygen` and following the inline help. Or try the following example to get started: export PATH=$PATH:$GOPATH/bin $ easygen $GOPATH/src/github.com/go-easygen/easygen/test/list0 The colors are: red, blue, white, . cd $GOPATH/src/github.com/go-easygen/easygen $ easygen test/list1 The quoted colors are: "red", "blue", "white", . $ easygen -tf test/listfunc1 test/list0 red, blue, white. ## EXAMPLES `easygen` comes with comprehensive online documents. For further details, please go to: https://github.com/go-easygen/easygen https://suntong.github.io/blogs/2016/01/01/easygen---easy-to-use-universal-code/text-generator https://github.com/go-easygen/easygen/blob/master/using_easygen.md https://github.com/go-easygen/easygen/wiki/Getting-Started https://godoc.org/github.com/go-easygen/easygen#pkg-examples easygen-5.1.9/cmd/easygen/easygen.gen.sh000077500000000000000000000002051416363131000201140ustar00rootroot00000000000000 easygen config easygen | gofmt > ../../config.go easygen flags easygen | sed 's/^package easygen/package main/' | gofmt > flags.go easygen-5.1.9/cmd/easygen/easygen.yaml000066400000000000000000000046401416363131000177000ustar00rootroot00000000000000# program name, name for the executable ProgramName: easygen # package name # - For standalone program that does not belong to any package, e.g., # https://github.com/suntong/easygen/blob/7791e4f0e5605543d27da1671a21376cdb9dcf2a/easygen/easygen.go # just ignore the first line, the `package` output, and copy the rest # - If you don't mind using a separated file to handle commandline paramters, # then name the package as "main". see the spin-out "TF-minus1.go" file under # https://github.com/suntong/easygen/tree/d1ab0b5fe80ddac57fe9ef51f6ccb3ab998cd5ee # - If you are using it in a pacakge, look no further than # https://github.com/suntong/easygen/blob/master/easygenapi/config.go # which was a direct dump: easygen test/commandlineFlag | gofmt > easygenapi/config.go # PackageName: easygen # Name of the structure to hold the values for/from commandline StructName: Options # The actual variable that hold the commandline paramter values StructVar: Opts Options: - Name: TemplateStr Type: string Flag: ts Value: '""' Usage: "template string (in text)" - Name: ExtYaml Type: string Flag: ey Value: '".yaml"' Usage: "`extension` of yaml file" - Name: ExtJson Type: string Flag: ej Value: '".json"' Usage: "`extension` of json file" - Name: ExtTmpl Type: string Flag: et Value: '".tmpl"' Usage: "`extension` of template file" - Name: Debug Type: int Flag: debug Value: 0 Usage: "debugging `level`" # Whether to use the USAGE_SUMMARY in Usage help UsageSummary: "" UsageLead: "\\nUsage:\\n %s [flags] template_name [data_filename [data_filename...]]\\n\\nFlags:\\n\\n" UsageEnd: | template_name: The name for the template file. - Can have the extension (specified by -et) or without it. - Can include the path as well. - Can be a comma-separated list giving many template files, in which case at least one data_filename must be given. data_filename(s): The name for the .yaml or .json data. - If omitted derive from the template_name. - Can have the extension or without it. If withot extension, will try the .yaml file first then .json - Can include the path as well. - If there is a single data_filename, and it is "-", then read the data (.yaml or .json format) from stdin. Flag defaults can be overridden by corresponding environment variable, e.g.: EASYGEN_EY=.yml EASYGEN_ET=.tpl easygen ... easygen-5.1.9/cmd/easygen/flags.go000066400000000000000000000051261416363131000170040ustar00rootroot00000000000000// !!! !!! // WARNING: Code automatically generated. Editing discouraged. // !!! !!! package main import ( "flag" "fmt" "os" "github.com/go-easygen/easygen" ) //////////////////////////////////////////////////////////////////////////// // Constant and data type/structure definitions //const progname = "easygen" // os.Args[0] //////////////////////////////////////////////////////////////////////////// // Global variables definitions //////////////////////////////////////////////////////////////////////////// // Commandline definitions func init() { // set default values for command line parameters flag.StringVar(&easygen.Opts.TemplateStr, "ts", "", "template string (in text)") flag.StringVar(&easygen.Opts.ExtYaml, "ey", ".yaml", "`extension` of yaml file") flag.StringVar(&easygen.Opts.ExtJson, "ej", ".json", "`extension` of json file") flag.StringVar(&easygen.Opts.ExtTmpl, "et", ".tmpl", "`extension` of template file") flag.IntVar(&easygen.Opts.Debug, "debug", 0, "debugging `level`") // Now override those default values from environment variables if len(easygen.Opts.TemplateStr) == 0 || len(os.Getenv("EASYGEN_TS")) != 0 { easygen.Opts.TemplateStr = os.Getenv("EASYGEN_TS") } if len(easygen.Opts.ExtYaml) == 0 || len(os.Getenv("EASYGEN_EY")) != 0 { easygen.Opts.ExtYaml = os.Getenv("EASYGEN_EY") } if len(easygen.Opts.ExtJson) == 0 || len(os.Getenv("EASYGEN_EJ")) != 0 { easygen.Opts.ExtJson = os.Getenv("EASYGEN_EJ") } if len(easygen.Opts.ExtTmpl) == 0 || len(os.Getenv("EASYGEN_ET")) != 0 { easygen.Opts.ExtTmpl = os.Getenv("EASYGEN_ET") } } // Usage function shows help on commandline usage func Usage() { fmt.Fprintf(os.Stderr, "%s version %s\n\nUsage:\n %s [flags] template_name [data_filename [data_filename...]]\n\nFlags:\n\n", progname, version, progname) flag.PrintDefaults() fmt.Fprintf(os.Stderr, ` template_name: The name for the template file. - Can have the extension (specified by -et) or without it. - Can include the path as well. - Can be a comma-separated list giving many template files, in which case at least one data_filename must be given. data_filename(s): The name for the .yaml or .json data. - If omitted derive from the template_name. - Can have the extension or without it. If withot extension, will try the .yaml file first then .json - Can include the path as well. - If there is a single data_filename, and it is "-", then read the data (.yaml or .json format) from stdin. Flag defaults can be overridden by corresponding environment variable, e.g.: EASYGEN_EY=.yml EASYGEN_ET=.tpl easygen ... `) os.Exit(0) } easygen-5.1.9/cmd/easygen/flags.tmpl000066400000000000000000000033621416363131000173530ustar00rootroot00000000000000// !!! !!! // WARNING: Code automatically generated. Editing discouraged. // !!! !!! package {{.PackageName}} import ( "flag" "fmt" "os" "github.com/go-easygen/easygen" ) //////////////////////////////////////////////////////////////////////////// // Constant and data type/structure definitions //const progname = "{{.ProgramName}}" // os.Args[0] //////////////////////////////////////////////////////////////////////////// // Global variables definitions //////////////////////////////////////////////////////////////////////////// // Commandline definitions func init() { // set default values for command line parameters{{range .Options}}{{if eq .Name "SEPARATOR" }} {{else}} flag.{{clk2uc .Type}}Var(&easygen.{{$.StructVar}}.{{.Name}}, "{{.Flag}}", {{.Value}}, "{{.Usage}}"){{end}}{{end}} // Now override those default values from environment variables{{range .Options}}{{if eq .Name "SEPARATOR" }} {{else}}{{if eq .Type "string" }}{{$envVar := printf "%s_%s" (clk2ss $.ProgramName) (clk2ss .Flag)}} if len(easygen.{{$.StructVar}}.{{.Name}}) == 0 || len(os.Getenv("{{$envVar}}")) != 0 { easygen.{{$.StructVar}}.{{.Name}} = os.Getenv("{{$envVar}}") }{{end}}{{end}}{{end}} } {{if eqf .UsageSummary "True" }} const USAGE_SUMMARY = "{{range .Options}}{{if eq .Name "SEPARATOR" }}\n{{else}}{{$envVar := printf "%s_%s" (clk2ss $.ProgramName) (clk2ss .Flag)}} -{{.Flag}}\t{{.Usage}} ({{$envVar}})\n{{end}}{{end}}\nDetails:\n\n" {{end}} // Usage function shows help on commandline usage func Usage() { fmt.Fprintf(os.Stderr, "%s version %s\n{{.UsageLead}}", progname, version, progname){{if eq .UsageSummary "TRUE" }} fmt.Fprintf(os.Stderr, USAGE_SUMMARY){{end}} flag.PrintDefaults() fmt.Fprintf(os.Stderr, `{{.UsageEnd}}`) os.Exit(0) } easygen-5.1.9/cmd/easygen/main.go000066400000000000000000000044641416363131000166400ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////////////// // Porgram: easygen // Purpose: Easy to use universal code/text generator // Authors: Tong Sun (c) 2015-2021, All rights reserved //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// // Program start /* Command easygen is an easy to use universal code/text generator. It can be used as a text or html generator for arbitrary purposes with arbitrary data and templates. It can be used as a code generator, or anything that is structurally repetitive. Some command line parameter handling code generator are provided as examples, including the Go's built-in flag package, and the viper & cobra package. You can even use easygen as a generic Go template testing tool using the -ts commandline option. */ package main import ( "flag" "os" "strings" "github.com/go-easygen/easygen" "github.com/go-easygen/easygen/egCal" "github.com/go-easygen/easygen/egFilePath" "github.com/go-easygen/easygen/egVar" ) //go:generate sh -v easygen.gen.sh //////////////////////////////////////////////////////////////////////////// // Constant and data type/structure definitions //////////////////////////////////////////////////////////////////////////// // Global variables definitions var ( progname = "easygen" version = "5.1.9" date = "2021-12-31" ) //////////////////////////////////////////////////////////////////////////// // Main func main() { flag.Usage = Usage flag.Parse() // One mandatory non-flag arguments if flag.NArg() < 1 { Usage() } args := flag.Args() // There is only one command line argument if len(args) == 1 { // when template_name is comma-separated list, data_filename must be given if strings.Contains(args[0], ",") { Usage() } // else, dup template_name as data_filename args = append(args, args[0]) } tmpl0 := easygen.NewTemplate().Customize() tmpl := tmpl0.Funcs(easygen.FuncDefs()). Funcs(egVar.FuncDefs()).Funcs(egCal.FuncDefs()).Funcs(egFilePath.FuncDefs()) var err error if len(easygen.Opts.TemplateStr) > 0 { err = easygen.Process0(tmpl, os.Stdout, easygen.Opts.TemplateStr, args...) } else { err = easygen.Process2(tmpl, os.Stdout, args[0], args[1:]...) } if err != nil { panic(err) } } easygen-5.1.9/cmd/easygen/main_test.go000066400000000000000000000070271416363131000176750ustar00rootroot00000000000000package main_test import ( "bytes" "os" "os/exec" "strings" "testing" ) const ( cmdEasygen = "easygen" dirTest = "../../test/" extRef = ".ref" // extension for reference file extGot = ".got" // extension for generated file ) // testEasygen runs @cmdEasyGen with @argv and compares the generated // output for @name with the corresponding @extRef func testEasygen(t *testing.T, name string, argv ...string) { var ( diffOut bytes.Buffer generatedOutput = name + extGot cmd = exec.Command(cmdEasygen, argv...) ) t.Logf("Testing %s:\n\t%s %s", name, cmdEasygen, strings.Join(argv, " ")) // open the out file for writing outfile, err := os.Create(generatedOutput) if err != nil { t.Errorf("write error [%s: %s] %s.", name, argv, err) } defer outfile.Close() cmd.Stdout = outfile err = cmd.Start() if err != nil { t.Errorf("start error [%s: %s] %s.", name, argv, err) } err = cmd.Wait() if err != nil { t.Errorf("exit error [%s: %s] %s.", name, argv, err) } cmd = exec.Command("diff", "-U1", name+extRef, generatedOutput) cmd.Stdout = &diffOut err = cmd.Start() if err != nil { t.Errorf("start error %s [%s: %s]", err, name, argv) } err = cmd.Wait() if err != nil { t.Errorf("cmp error %s [%s: %s]\n%s", err, name, argv, diffOut.String()) } os.Remove(generatedOutput) } func TestExec(t *testing.T) { os.Chdir(dirTest) //Test Basic Functions testEasygen(t, "list0", "list0") // Filename suffixes are optional testEasygen(t, "list0", "list0.yaml") testEasygen(t, "list0", "list0", "list0") testEasygen(t, "list0", "list0.tmpl", "list0") testEasygen(t, "list0", "list0.tmpl", "list0.yaml") //testEasygen(t, "list0E", "list0E", "list0") testEasygen(t, "list1", "list1") testEasygen(t, "listfunc1", "listfunc1") testEasygen(t, "listfunc2", "listfunc2") //Test Basic Json Functions testEasygen(t, "list0j", "list0j") testEasygen(t, "list0j", "list0j", "list0j") testEasygen(t, "list0j", "list0j", "list0j.json") // template_name can be a comma-separated list testEasygen(t, "list01", "list0,listfunc1", "list0") //Test HTML testEasygen(t, "list1HTML", "list1HTML", "list1") // varcaser string functions testEasygen(t, "var0", "-ts", "{{.Name}}", "var0") testEasygen(t, "var1", "-ts", "{{clk2uc .Name}}", "var0") testEasygen(t, "var2", "-ts", "{{clk2ss .Name}}", "var0") //Test Bigger files testEasygen(t, "commandlineCLI-024", "commandlineCLI-024") testEasygen(t, "commandlineCLI-027", "commandlineCLI-027") testEasygen(t, "commandlineCLI-027s", "commandlineCLI-027", "commandlineCLI-027s") testEasygen(t, "commandlineCVFull", "commandlineCVFull") testEasygen(t, "commandlineCV", "commandlineCV") testEasygen(t, "commandlineFlag", "commandlineFlag") // Enum generation: (a) run template with multiple data inputs, // (b) run the same input with multiple template files: testEasygen(t, "enum_multiple_data_files", "enum_c-header", "raid_type", "raid_driver") testEasygen(t, "enum_multiple_template_files", "enum_c-header,enum_c-source", "raid_type.yaml") testEasygen(t, "enum_multiple_template_and_data", "enum_c-header,enum_c-to_str", "raid_type", "raid_driver.yaml") //Test nested templates //testEasygen(t, "nested_header_footer", "nested_header.tmpl,nested_footer.tmpl,nested_thanks.tmpl", "nested_data.yaml") testEasygen(t, "nested_demo_argsa", "nested_demo_argsa", "nested_data.yaml") testEasygen(t, "nested_demo_argsm", "nested_demo_argsm", "nested_data.yaml") testEasygen(t, "nested_demo_argsm_iterate", "nested_demo_argsm_iterate", "nested_data.yaml") } easygen-5.1.9/config.go000066400000000000000000000011401416363131000147470ustar00rootroot00000000000000// !!! !!! // WARNING: Code automatically generated. Editing discouraged. // !!! !!! package easygen //////////////////////////////////////////////////////////////////////////// // Constant and data type/structure definitions const progname = "easygen" // os.Args[0] // The Options struct defines the structure to hold the commandline values type Options struct { TemplateStr string // template string (in text) ExtYaml string // `extension` of yaml file ExtJson string // `extension` of json file ExtTmpl string // `extension` of template file Debug int // debugging `level` } easygen-5.1.9/easygen.go000066400000000000000000000177501416363131000151530ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////////////// // Package: easygen // Purpose: Easy to use universal code/text generator // Authors: Tong Sun (c) 2015-2021, All rights reserved //////////////////////////////////////////////////////////////////////////// /* Package easygen is an easy to use universal code/text generator library. It can be used as a text or html generator for arbitrary purposes with arbitrary data and templates. It can be used as a code generator, or anything that is structurally repetitive. Some command line parameter handling code generator are provided as examples, including the Go's built-in flag package, and the viper & cobra package. Many examples have been provided to showcase its functionality, and different ways to use it. */ package easygen import ( "encoding/json" "fmt" "io" "io/ioutil" "os" "path/filepath" "regexp" "strings" "gopkg.in/yaml.v2" ) //////////////////////////////////////////////////////////////////////////// // Constant and data type/structure definitions //////////////////////////////////////////////////////////////////////////// // Global variables definitions // EgData -- EasyGen driven Data type EgData interface{} // Opts holds the actual values from the command line parameters var Opts = Options{ExtYaml: ".yaml", ExtJson: ".json", ExtTmpl: ".tmpl"} //////////////////////////////////////////////////////////////////////////// // Function definitions // ReadDataFile reads in the driving data from the given file, which can // be optionally without the defined extension func ReadDataFile(fileName string) EgData { if IsExist(fileName + Opts.ExtYaml) { return ReadYamlFile(fileName + Opts.ExtYaml) } else if IsExist(fileName + Opts.ExtJson) { return ReadJsonFile(fileName + Opts.ExtJson) } else if IsExist(fileName) { verbose("Reading exist Data File", 2) fext := filepath.Ext(fileName) fext = fext[1:] // ignore the leading "." if regexp.MustCompile(`(?i)^y`).MatchString(fext) { verbose("Reading YAML file", 2) return ReadYamlFile(fileName) } else if regexp.MustCompile(`(?i)^j`).MatchString(fext) { return ReadJsonFile(fileName) } else { checkError(fmt.Errorf("Unsupported file extension for DataFile '%s'", fileName)) } } else if fileName == "-" { // from stdin // Yaml format is a superset of JSON, it read Json file just as fine return ReadYamlFile(fileName) } checkError(fmt.Errorf("DataFile '%s' cannot be found", fileName)) return nil } // ReadYamlFile reads given YAML file as EgData func ReadYamlFile(fileName string) EgData { var source []byte var err error if fileName == "-" { source, err = ioutil.ReadAll(os.Stdin) checkError(err) } else { source, err = ioutil.ReadFile(fileName) checkError(err) } m := make(map[interface{}]interface{}) err = yaml.Unmarshal(source, &m) checkError(err) return m } // ReadJsonFile reads given JSON file as EgData func ReadJsonFile(fileName string) EgData { source, err := ioutil.ReadFile(fileName) checkError(err) m := make(map[string]interface{}) err = json.Unmarshal(source, &m) checkError(err) //fmt.Printf("] Input %v\n", m) return m } // IsExist checks if the given file exist func IsExist(fileName string) bool { //fmt.Printf("] Checking %s\n", fileName) _, err := os.Stat(fileName) return err == nil || os.IsExist(err) // CAUTION! os.IsExist(err) != !os.IsNotExist(err) // https://gist.github.com/mastef/05f46d3ab2f5ed6a6787#file-isexist_vs_isnotexist-go-L35-L56 } // Process will process the standard easygen input: the `fileName` is for both template and data file name, and produce output from the template according to the corresponding driving data. // Process() is using the V3's calling convention and *only* works properly in V4+ in the case that there is only one fileName passed to it. If need to pass more files, use Process2() instead. func Process(t Template, wr io.Writer, fileNames ...string) error { return Process2(t, wr, fileNames[0], fileNames[:1]...) } // Process2 will process the case that *both* template and data file names are given, and produce output according to the given template and driving data files, // specified via fileNameTempl and fileNames respectively. // fileNameTempl can be a comma-separated string giving many template files func Process2(t Template, wr io.Writer, fileNameTempl string, fileNames ...string) error { for _, dataFn := range fileNames { for _, templateFn := range strings.Split(fileNameTempl, ",") { err := Process1(t, wr, templateFn, dataFn) checkError(err) } } return nil } // Process1 will process a *single* case where both template and data file names are given, and produce output according to the given template and driving data files, // specified via fileNameTempl and fileName respectively. // fileNameTempl is not a comma-separated string, but for a single template file. func Process1(t Template, wr io.Writer, fileNameTempl string, fileName string) error { m := ReadDataFile(fileName) //fmt.Printf("] %+v\n", m) // template file fileName = fileNameTempl fileNameT := fileNameTempl if IsExist(fileName + Opts.ExtTmpl) { fileNameT = fileName + Opts.ExtTmpl } else { // guard against that fileNameTempl passed with Opts.ExtYaml extension if fileName[len(fileName)-len(Opts.ExtYaml):] == Opts.ExtYaml { idx := strings.LastIndex(fileName, ".") fileName = fileName[:idx] if IsExist(fileName + Opts.ExtTmpl) { fileNameT = fileName + Opts.ExtTmpl } } else if IsExist(fileName) { // fileNameTempl passed with Opts.ExtTmpl already fileNameT = fileName } } return Execute(t, wr, fileNameT, m) } // Execute0 will execute the Template given as strTempl with the given data map `m` (i.e., no template file and no data file). // It parses text template strTempl then applies it to to the specified data // object m, and writes the output to wr. If an error occurs executing the // template or writing its output, execution stops, but partial results may // already have been written to the output writer. A template may be // executed safely in parallel, although if parallel executions share a // Writer the output may be interleaved. func Execute0(t Template, wr io.Writer, strTempl string, m EgData) error { verbose("Execute with template string: "+strTempl, 1) tmpl, err := t.Parse(strTempl) checkError(err) return tmpl.Execute(wr, m) } // Execute will execute the Template from fileNameT on the given data map `m`. func Execute(t Template, wr io.Writer, fileNameT string, m EgData) error { // 1. Check locally verbose("Checking for template locally: "+fileNameT, 1) if !IsExist(fileNameT) { // 2. Check under /etc/ command := filepath.Base(os.Args[0]) templateFile := fmt.Sprintf("/etc/%s/%s", command, fileNameT) verbose("Checking at "+templateFile, 1) if IsExist(templateFile) { fileNameT = templateFile } else { // 3. Check where executable is ex, e := os.Executable() if e != nil { return e } fileNameT = filepath.Dir(ex) + string(filepath.Separator) + fileNameT verbose("Checking at "+fileNameT, 1) if !IsExist(fileNameT) { checkError(fmt.Errorf("Template file '%s' cannot be found", fileNameT)) } } } tn, err := t.ParseFiles(fileNameT) checkError(err) return tn.ExecuteTemplate(wr, filepath.Base(fileNameT), m) } // Process0 will produce output according to the driving data *without* a template file, using the string from strTempl as the template func Process0(t Template, wr io.Writer, strTempl string, fileNames ...string) error { fileName := fileNames[0] m := ReadDataFile(fileName) tmpl, err := t.Parse(strTempl) checkError(err) return tmpl.Execute(wr, m) } //////////////////////////////////////////////////////////////////////////// // Support Function definitions // Exit if error occurs func checkError(err error) { if err != nil { fmt.Fprintf(os.Stderr, "[%s] Fatal error - %s\n", progname, err) os.Exit(1) } } // verbose will print info to stderr according to the verbose level setting func verbose(step string, level int) { if Opts.Debug >= level { print("[", progname, "] ", step, "\n") } } easygen-5.1.9/easygen_test.go000066400000000000000000000042411416363131000162010ustar00rootroot00000000000000package easygen_test import ( "os" "text/template" "github.com/go-easygen/easygen" ) var tmpl *template.Template func init() { tmpl = easygen.NewTemplate().Funcs(easygen.FuncDefs()) } //////////////////////////////////////////////////////////////////////////// // Lists //========================================================================== // list0 data + string template // I.e.: EasyGen -ts "{{range .Colors}}{{.}}, {{end}}" test/list0 // Test string template with list0 data func ExampleProcess0_list0StrTemplate() { // Equivalent testing on commandline: // easygen -ts '{{range .Colors}}{{.}}, {{end}}' test/list0 easygen.Process0(tmpl, os.Stdout, "{{range .Colors}}{{.}}, {{end}}", "test/list0") // Output: // red, blue, white, } // Test HTML template with list1 data func ExampleProcess2_html() { // Equivalent testing on commandline: // easygen -tf test/list1HTML test/list1 easygen.Process2(tmpl, os.Stdout, "test/list1HTML", "test/list1") // Output: // The quoted colors are: "red", "blue", "white", . } //////////////////////////////////////////////////////////////////////////// // Strings Test // Test string comparison in template func ExampleProcess0_stringsCmp() { // Equivalent testing on commandline: // easygen -ts '{{The {{if ... {{end}}.' test/strings0 easygen.Process0(tmpl, os.Stdout, `The {{if eq .StrTest "-AB-axxb- HTML Html html"}}eq says Yea{{else}}eq says Nay{{end}} but {{if eqf .StrTest "-AB-axxb- HTML Html html"}}eqf says Yea{{else}}eqf says Nay{{end}}.`, "test/strings0") // Output: // The eq says Nay but eqf says Yea. } // Test the string split function in template func ExampleProcess0_split0() { // Equivalent testing on commandline: // easygen -ts '{{split .Colorlist}}' test/list0 easygen.Process0(tmpl, os.Stdout, `{{split .Colorlist}}`, "test/list0") // Output: // [red blue white] } // Test the string split function in template again func ExampleProcess0_split1() { // Equivalent testing on commandline: // easygen -ts '{{range ... {{end}}' test/list0 easygen.Process0(tmpl, os.Stdout, `{{range (split .Colorlist)}}{{.}} {{end}}`, "test/list0") // Output: // red blue white } easygen-5.1.9/egCal/000077500000000000000000000000001416363131000141725ustar00rootroot00000000000000easygen-5.1.9/egCal/EgCal.go000066400000000000000000000024601416363131000154760ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////////////// // Package: egCal // Purpose: easygen generic calculation functionalities // Authors: Tong Sun (c) 2017, All rights reserved //////////////////////////////////////////////////////////////////////////// /* Package egCal provides generic calculation functionalities. egCal provides the generic calculation functionalities from consul template functions https://github.com/hashicorp/consul-template / template_functions.go */ package egCal import ( "text/template" "github.com/go-easygen/easygen" ) //////////////////////////////////////////////////////////////////////////// // Constant and data type/structure definitions // EgCal -- EasyGen Calculation /* add is template function for Add subtract is template function for Subtract multiply is template function for Multiply divide is template function for Divide */ type EgCal struct { *easygen.EgBase } var egFuncMap = easygen.FuncMap{ "add": Add, "subtract": Subtract, "multiply": Multiply, "divide": Divide, } //////////////////////////////////////////////////////////////////////////// // Function definitions // FuncDefs returns the custom definition mapping for this specific package. func FuncDefs() template.FuncMap { return template.FuncMap(egFuncMap) } easygen-5.1.9/egCal/LICENSE000066400000000000000000000371471416363131000152130ustar00rootroot00000000000000Mozilla Public License, version 2.0 1. Definitions 1.1. “Contributor” means each individual or legal entity that creates, contributes to the creation of, or owns Covered Software. 1.2. “Contributor Version” means the combination of the Contributions of others (if any) used by a Contributor and that particular Contributor’s Contribution. 1.3. “Contribution” means Covered Software of a particular Contributor. 1.4. “Covered Software” means Source Code Form to which the initial Contributor has attached the notice in Exhibit A, the Executable Form of such Source Code Form, and Modifications of such Source Code Form, in each case including portions thereof. 1.5. “Incompatible With Secondary Licenses” means a. that the initial Contributor has attached the notice described in Exhibit B to the Covered Software; or b. that the Covered Software was made available under the terms of version 1.1 or earlier of the License, but not also under the terms of a Secondary License. 1.6. “Executable Form” means any form of the work other than Source Code Form. 1.7. “Larger Work” means a work that combines Covered Software with other material, in a separate file or files, that is not Covered Software. 1.8. “License” means this document. 1.9. “Licensable” means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently, any and all of the rights conveyed by this License. 1.10. “Modifications” means any of the following: a. any file in Source Code Form that results from an addition to, deletion from, or modification of the contents of Covered Software; or b. any new file in Source Code Form that contains any Covered Software. 1.11. “Patent Claims” of a Contributor means any patent claim(s), including without limitation, method, process, and apparatus claims, in any patent Licensable by such Contributor that would be infringed, but for the grant of the License, by the making, using, selling, offering for sale, having made, import, or transfer of either its Contributions or its Contributor Version. 1.12. “Secondary License” means either the GNU General Public License, Version 2.0, the GNU Lesser General Public License, Version 2.1, the GNU Affero General Public License, Version 3.0, or any later versions of those licenses. 1.13. “Source Code Form” means the form of the work preferred for making modifications. 1.14. “You” (or “Your”) means an individual or a legal entity exercising rights under this License. For legal entities, “You” includes any entity that controls, is controlled by, or is under common control with You. For purposes of this definition, “control” means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. 2. License Grants and Conditions 2.1. Grants Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license: a. under intellectual property rights (other than patent or trademark) Licensable by such Contributor to use, reproduce, make available, modify, display, perform, distribute, and otherwise exploit its Contributions, either on an unmodified basis, with Modifications, or as part of a Larger Work; and b. under Patent Claims of such Contributor to make, use, sell, offer for sale, have made, import, and otherwise transfer either its Contributions or its Contributor Version. 2.2. Effective Date The licenses granted in Section 2.1 with respect to any Contribution become effective for each Contribution on the date the Contributor first distributes such Contribution. 2.3. Limitations on Grant Scope The licenses granted in this Section 2 are the only rights granted under this License. No additional rights or licenses will be implied from the distribution or licensing of Covered Software under this License. Notwithstanding Section 2.1(b) above, no patent license is granted by a Contributor: a. for any code that a Contributor has removed from Covered Software; or b. for infringements caused by: (i) Your and any other third party’s modifications of Covered Software, or (ii) the combination of its Contributions with other software (except as part of its Contributor Version); or c. under Patent Claims infringed by Covered Software in the absence of its Contributions. This License does not grant any rights in the trademarks, service marks, or logos of any Contributor (except as may be necessary to comply with the notice requirements in Section 3.4). 2.4. Subsequent Licenses No Contributor makes additional grants as a result of Your choice to distribute the Covered Software under a subsequent version of this License (see Section 10.2) or under the terms of a Secondary License (if permitted under the terms of Section 3.3). 2.5. Representation Each Contributor represents that the Contributor believes its Contributions are its original creation(s) or it has sufficient rights to grant the rights to its Contributions conveyed by this License. 2.6. Fair Use This License is not intended to limit any rights You have under applicable copyright doctrines of fair use, fair dealing, or other equivalents. 2.7. Conditions Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in Section 2.1. 3. Responsibilities 3.1. Distribution of Source Form All distribution of Covered Software in Source Code Form, including any Modifications that You create or to which You contribute, must be under the terms of this License. You must inform recipients that the Source Code Form of the Covered Software is governed by the terms of this License, and how they can obtain a copy of this License. You may not attempt to alter or restrict the recipients’ rights in the Source Code Form. 3.2. Distribution of Executable Form If You distribute Covered Software in Executable Form then: a. such Covered Software must also be made available in Source Code Form, as described in Section 3.1, and You must inform recipients of the Executable Form how they can obtain a copy of such Source Code Form by reasonable means in a timely manner, at a charge no more than the cost of distribution to the recipient; and b. You may distribute such Executable Form under the terms of this License, or sublicense it under different terms, provided that the license for the Executable Form does not attempt to limit or alter the recipients’ rights in the Source Code Form under this License. 3.3. Distribution of a Larger Work You may create and distribute a Larger Work under terms of Your choice, provided that You also comply with the requirements of this License for the Covered Software. If the Larger Work is a combination of Covered Software with a work governed by one or more Secondary Licenses, and the Covered Software is not Incompatible With Secondary Licenses, this License permits You to additionally distribute such Covered Software under the terms of such Secondary License(s), so that the recipient of the Larger Work may, at their option, further distribute the Covered Software under the terms of either this License or such Secondary License(s). 3.4. Notices You may not remove or alter the substance of any license notices (including copyright notices, patent notices, disclaimers of warranty, or limitations of liability) contained within the Source Code Form of the Covered Software, except that You may alter any license notices to the extent required to remedy known factual inaccuracies. 3.5. Application of Additional Terms You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Software. However, You may do so only on Your own behalf, and not on behalf of any Contributor. You must make it absolutely clear that any such warranty, support, indemnity, or liability obligation is offered by You alone, and You hereby agree to indemnify every Contributor for any liability incurred by such Contributor as a result of warranty, support, indemnity or liability terms You offer. You may include additional disclaimers of warranty and limitations of liability specific to any jurisdiction. 4. Inability to Comply Due to Statute or Regulation If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Software due to statute, judicial order, or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be placed in a text file included with all distributions of the Covered Software under this License. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it. 5. Termination 5.1. The rights granted under this License will terminate automatically if You fail to comply with any of its terms. However, if You become compliant, then the rights granted under this License from a particular Contributor are reinstated (a) provisionally, unless and until such Contributor explicitly and finally terminates Your grants, and (b) on an ongoing basis, if such Contributor fails to notify You of the non-compliance by some reasonable means prior to 60 days after You have come back into compliance. Moreover, Your grants from a particular Contributor are reinstated on an ongoing basis if such Contributor notifies You of the non-compliance by some reasonable means, this is the first time You have received notice of non-compliance with this License from such Contributor, and You become compliant prior to 30 days after Your receipt of the notice. 5.2. If You initiate litigation against any entity by asserting a patent infringement claim (excluding declaratory judgment actions, counter-claims, and cross-claims) alleging that a Contributor Version directly or indirectly infringes any patent, then the rights granted to You by any and all Contributors for the Covered Software under Section 2.1 of this License shall terminate. 5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user license agreements (excluding distributors and resellers) which have been validly granted by You or Your distributors under this License prior to termination shall survive termination. 6. Disclaimer of Warranty Covered Software is provided under this License on an “as is” basis, without warranty of any kind, either expressed, implied, or statutory, including, without limitation, warranties that the Covered Software is free of defects, merchantable, fit for a particular purpose or non-infringing. The entire risk as to the quality and performance of the Covered Software is with You. Should any Covered Software prove defective in any respect, You (not any Contributor) assume the cost of any necessary servicing, repair, or correction. This disclaimer of warranty constitutes an essential part of this License. No use of any Covered Software is authorized under this License except under this disclaimer. 7. Limitation of Liability Under no circumstances and under no legal theory, whether tort (including negligence), contract, or otherwise, shall any Contributor, or anyone who distributes Covered Software as permitted above, be liable to You for any direct, indirect, special, incidental, or consequential damages of any character including, without limitation, damages for lost profits, loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses, even if such party shall have been informed of the possibility of such damages. This limitation of liability shall not apply to liability for death or personal injury resulting from such party’s negligence to the extent applicable law prohibits such limitation. Some jurisdictions do not allow the exclusion or limitation of incidental or consequential damages, so this exclusion and limitation may not apply to You. 8. Litigation Any litigation relating to this License may be brought only in the courts of a jurisdiction where the defendant maintains its principal place of business and such litigation shall be governed by laws of that jurisdiction, without reference to its conflict-of-law provisions. Nothing in this Section shall prevent a party’s ability to bring cross-claims or counter-claims. 9. Miscellaneous This License represents the complete agreement concerning the subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not be used to construe this License against a Contributor. 10. Versions of the License 10.1. New Versions Mozilla Foundation is the license steward. Except as provided in Section 10.3, no one other than the license steward has the right to modify or publish new versions of this License. Each version will be given a distinguishing version number. 10.2. Effect of New Versions You may distribute the Covered Software under the terms of the version of the License under which You originally received the Covered Software, or under the terms of any subsequent version published by the license steward. 10.3. Modified Versions If you create software not governed by this License, and you want to create a new license for such software, you may create and use a modified version of this License if you rename the license and remove any references to the name of the license steward (except to note that such modified license differs from this License). 10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses If You choose to distribute Source Code Form that is Incompatible With Secondary Licenses under the terms of this version of the License, the notice described in Exhibit B of this License must be attached. Exhibit A - Source Code Form License Notice This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. If it is not possible or desirable to put the notice in a particular file, then You may include the notice in a location (such as a LICENSE file in a relevant directory) where a recipient would be likely to look for such a notice. You may add additional accurate notices of copyright ownership. Exhibit B - “Incompatible With Secondary Licenses” Notice This Source Code Form is “Incompatible With Secondary Licenses”, as defined by the Mozilla Public License, v. 2.0.easygen-5.1.9/egCal/consul-template_functions.go000066400000000000000000000165031416363131000217320ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////////////// // Package: egCal // Purpose: easygen generic calculation functionalities // Authors: @HashiCorp (c) 2013-17, All rights reserved // https://github.com/hashicorp/consul-template/blob/de2ebf4/template_functions.go#L727-L901 //////////////////////////////////////////////////////////////////////////// package egCal import ( "fmt" "reflect" ) // Add returns the sum of a and b. func Add(a, b interface{}) (interface{}, error) { av := reflect.ValueOf(a) bv := reflect.ValueOf(b) switch av.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: switch bv.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return av.Int() + bv.Int(), nil case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: return av.Int() + int64(bv.Uint()), nil case reflect.Float32, reflect.Float64: return float64(av.Int()) + bv.Float(), nil default: return nil, fmt.Errorf("add: unknown type for %q (%T)", bv, b) } case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: switch bv.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return int64(av.Uint()) + bv.Int(), nil case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: return av.Uint() + bv.Uint(), nil case reflect.Float32, reflect.Float64: return float64(av.Uint()) + bv.Float(), nil default: return nil, fmt.Errorf("add: unknown type for %q (%T)", bv, b) } case reflect.Float32, reflect.Float64: switch bv.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return av.Float() + float64(bv.Int()), nil case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: return av.Float() + float64(bv.Uint()), nil case reflect.Float32, reflect.Float64: return av.Float() + bv.Float(), nil default: return nil, fmt.Errorf("add: unknown type for %q (%T)", bv, b) } default: return nil, fmt.Errorf("add: unknown type for %q (%T)", av, a) } } // Subtract returns the difference of b from a. func Subtract(a, b interface{}) (interface{}, error) { av := reflect.ValueOf(a) bv := reflect.ValueOf(b) switch av.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: switch bv.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return av.Int() - bv.Int(), nil case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: return av.Int() - int64(bv.Uint()), nil case reflect.Float32, reflect.Float64: return float64(av.Int()) - bv.Float(), nil default: return nil, fmt.Errorf("subtract: unknown type for %q (%T)", bv, b) } case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: switch bv.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return int64(av.Uint()) - bv.Int(), nil case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: return av.Uint() - bv.Uint(), nil case reflect.Float32, reflect.Float64: return float64(av.Uint()) - bv.Float(), nil default: return nil, fmt.Errorf("subtract: unknown type for %q (%T)", bv, b) } case reflect.Float32, reflect.Float64: switch bv.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return av.Float() - float64(bv.Int()), nil case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: return av.Float() - float64(bv.Uint()), nil case reflect.Float32, reflect.Float64: return av.Float() - bv.Float(), nil default: return nil, fmt.Errorf("subtract: unknown type for %q (%T)", bv, b) } default: return nil, fmt.Errorf("subtract: unknown type for %q (%T)", av, a) } } // Multiply returns the product of a and b. func Multiply(a, b interface{}) (interface{}, error) { av := reflect.ValueOf(a) bv := reflect.ValueOf(b) switch av.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: switch bv.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return av.Int() * bv.Int(), nil case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: return av.Int() * int64(bv.Uint()), nil case reflect.Float32, reflect.Float64: return float64(av.Int()) * bv.Float(), nil default: return nil, fmt.Errorf("multiply: unknown type for %q (%T)", bv, b) } case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: switch bv.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return int64(av.Uint()) * bv.Int(), nil case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: return av.Uint() * bv.Uint(), nil case reflect.Float32, reflect.Float64: return float64(av.Uint()) * bv.Float(), nil default: return nil, fmt.Errorf("multiply: unknown type for %q (%T)", bv, b) } case reflect.Float32, reflect.Float64: switch bv.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return av.Float() * float64(bv.Int()), nil case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: return av.Float() * float64(bv.Uint()), nil case reflect.Float32, reflect.Float64: return av.Float() * bv.Float(), nil default: return nil, fmt.Errorf("multiply: unknown type for %q (%T)", bv, b) } default: return nil, fmt.Errorf("multiply: unknown type for %q (%T)", av, a) } } // Divide returns the division of b from a. func Divide(a, b interface{}) (interface{}, error) { av := reflect.ValueOf(a) bv := reflect.ValueOf(b) switch av.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: switch bv.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return av.Int() / bv.Int(), nil case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: return av.Int() / int64(bv.Uint()), nil case reflect.Float32, reflect.Float64: return float64(av.Int()) / bv.Float(), nil default: return nil, fmt.Errorf("divide: unknown type for %q (%T)", bv, b) } case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: switch bv.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return int64(av.Uint()) / bv.Int(), nil case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: return av.Uint() / bv.Uint(), nil case reflect.Float32, reflect.Float64: return float64(av.Uint()) / bv.Float(), nil default: return nil, fmt.Errorf("divide: unknown type for %q (%T)", bv, b) } case reflect.Float32, reflect.Float64: switch bv.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return av.Float() / float64(bv.Int()), nil case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: return av.Float() / float64(bv.Uint()), nil case reflect.Float32, reflect.Float64: return av.Float() / bv.Float(), nil default: return nil, fmt.Errorf("divide: unknown type for %q (%T)", bv, b) } default: return nil, fmt.Errorf("divide: unknown type for %q (%T)", av, a) } } easygen-5.1.9/egCal/example_test.go000066400000000000000000000013721416363131000172160ustar00rootroot00000000000000package egCal_test import ( "os" "github.com/go-easygen/easygen" "github.com/go-easygen/easygen/egCal" "github.com/go-easygen/easygen/egVar" ) // for standalone test, change package to `main` and the next func def to, // func main() { func Example() { tmpl0 := easygen.NewTemplate().Customize() tmpl := tmpl0.Funcs(easygen.FuncDefs()).Funcs(egVar.FuncDefs()).Funcs(egCal.FuncDefs()) err := easygen.Process0(tmpl, os.Stdout, "{{.Name}}: {{clk2uc .Name}} {{clk2ss .Name}}\n"+ "Cal: {{add 2 3}}, {{multiply 2 3}}, {{subtract 9 2}}, {{divide 24 3}}\n", "../test/var0") // Output: // some-init-method: SomeInitMethod SOME_INIT_METHOD // Cal: 5, 6, 7, 8 if err != nil { panic(err) } } // To show the full code in GoDoc type dummy struct { } easygen-5.1.9/egFilePath/000077500000000000000000000000001416363131000151675ustar00rootroot00000000000000easygen-5.1.9/egFilePath/EgFilePath.go000066400000000000000000000054551416363131000174770ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////////////// // Package: egFilePath // Purpose: EasyGen Generic FilePath Functionalities // Authors: Tong Sun (c) 2019, All rights reserved //////////////////////////////////////////////////////////////////////////// /* Package egFilePath provides filepath manupilation functionalities. egFilePath provides filepath manupilation manipulation, provided by "path/filepath". */ package egFilePath import ( "os" "path/filepath" "strings" "text/template" "github.com/go-easygen/easygen" ) //////////////////////////////////////////////////////////////////////////// // Constant and data type/structure definitions // EgFilePath -- EasyGen FilePath manupilation functionalities /* fpAbs is wrapper for filepath.Abs fpBase is wrapper for filepath.Base fpClean is wrapper for filepath.Clean fpDir is wrapper for filepath.Dir fpEvalSymlinks is wrapper for filepath.EvalSymlinks fpExt is wrapper for filepath.Ext fpFromSlash is wrapper for filepath.FromSlash fpGlob is wrapper for filepath.Glob fpHasPrefix is wrapper for filepath.HasPrefix fpIsAbs is wrapper for filepath.IsAbs fpJoin is wrapper for filepath.Join fpMatch is wrapper for filepath.Match fpRel is wrapper for filepath.Rel fpSplitList is wrapper for filepath.SplitList fpToSlash is wrapper for filepath.ToSlash fpVolumeName is wrapper for filepath.VolumeName isDir is template function for IsDir basename is template function for Basename */ type EgFilePath struct { *easygen.EgBase } var egFuncMap = easygen.FuncMap{ "fpAbs": filepath.Abs, "fpBase": filepath.Base, "fpClean": filepath.Clean, "fpDir": filepath.Dir, "fpEvalSymlinks": filepath.EvalSymlinks, "fpExt": filepath.Ext, "fpFromSlash": filepath.FromSlash, "fpGlob": filepath.Glob, "fpHasPrefix": filepath.HasPrefix, "fpIsAbs": filepath.IsAbs, "fpJoin": filepath.Join, "fpMatch": filepath.Match, "fpRel": filepath.Rel, "fpSplitList": filepath.SplitList, "fpToSlash": filepath.ToSlash, "fpVolumeName": filepath.VolumeName, "isDir": IsDir, "basename": Basename, } //////////////////////////////////////////////////////////////////////////// // Function definitions // FuncDefs returns the custom definition mapping for this specific package. func FuncDefs() template.FuncMap { return template.FuncMap(egFuncMap) } //========================================================================== // support functions // IsDir returns true if path is dir func IsDir(path string) bool { info, _ := os.Stat(path) return info.IsDir() } // Basename returns basename(path) func Basename(s string) string { s = filepath.Base(s) n := strings.LastIndexByte(s, '.') if n > 0 { return s[:n] } return s } easygen-5.1.9/egFilePath/example_test.go000066400000000000000000000027161416363131000202160ustar00rootroot00000000000000package egFilePath_test import ( "os" "github.com/go-easygen/easygen" "github.com/go-easygen/easygen/egFilePath" ) // for standalone test, change package to `main` and the next func def to, // func main() { func Example() { tmpl0 := easygen.NewTemplate().Customize() tmpl := tmpl0.Funcs(easygen.FuncDefs()).Funcs(egFilePath.FuncDefs()) err := easygen.Process0(tmpl, os.Stdout, // https://godoc.org/path/filepath "Base: {{fpBase `/a/b.c`}}, {{fpBase `/b.c/`}}, {{fpBase `./b.c`}}, {{fpBase `b.c`}}\n"+ "Clean: {{fpClean `/a//b.c/./..`}}, {{fpClean `//b.c///`}}, {{fpClean `/../b.c`}}\n"+ "Dir: {{fpDir `/a/b/c`}}, {{fpDir `/b/c/`}}, {{fpDir `./b/c`}}, {{fpDir `b.c`}}\n"+ "Ext: {{fpExt `index`}}, {{fpExt `index.js`}}, {{fpExt `main.test.js`}}\n"+ "Join: {{fpJoin `/a` `b` `c` `a//` `//b////c`}}, {{fpJoin `a` `b/c`}}, {{fpJoin `a/b` `c`}}\n"+ "Rel: {{fpRel `/a` `/a/b/c`}}, {{fpRel `/a` `/b/c`}}\n"+ // Two error cases, uncomment to verify // "{{fpRel `/a` `./b/c`}}, {{isDir `not-exist`}}.\n"+ "IsDir: {{isDir `.`}}.\n"+ "Basename: {{basename `/a/b.c`}}, {{basename `/b.c/`}}, {{basename `b.c`}}, {{basename `bc`}}", "../test/var0") // Output: // Base: b.c, b.c, b.c, b.c // Clean: /a, /b.c, /b.c // Dir: /a/b, /b/c, b, . // Ext: , .js, .js // Join: /a/b/c/a/b/c, a/b/c, a/b/c // Rel: b/c, ../b/c // IsDir: true. // Basename: b, b, b, bc if err != nil { panic(err) } } // To show the full code in GoDoc type dummy struct { } easygen-5.1.9/egVar/000077500000000000000000000000001416363131000142235ustar00rootroot00000000000000easygen-5.1.9/egVar/EgVar.go000066400000000000000000000103711416363131000155600ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////////////// // Package: egVar // Purpose: easygen variable naming functionalities // Authors: Tong Sun (c) 2016-17, All rights reserved //////////////////////////////////////////////////////////////////////////// /* Package egVar provides variable naming functionalities. egVar provides variable naming manipulation, available from danverbraganza/varcaser. */ package egVar import ( "text/template" "github.com/danverbraganza/varcaser/varcaser" "github.com/go-easygen/easygen" ) //////////////////////////////////////////////////////////////////////////// // Constant and data type/structure definitions // EgVar -- EasyGen variable naming // // pre-configed varcaser caser converters // the names are self-explanatory from their definitions // https://github.com/danverbraganza/varcaser/ /* ls - LowerSnakeCase: lower_snake_case ss - ScreamingSnakeCase: SCREAMING_SNAKE_CASE lk - KebabCase: kebab-case ScreamingKebabCase: SCREAMING-KEBAB-CASE hh - HttpHeaderCase: HTTP-Header-Case UpperCamelCase: UpperCamelCase (renders HTTP as Http) LowerCamelCase: lowerCamelCase (renders HTTP as Http) uc - UpperCamelCaseKeepCaps: UpperCamelCaseKeepCaps (renders HTTP as HTTP) lc - LowerCamelCaseKeepCaps: lowerCamelCaseKeepCaps (renders HTTP as hTTP) */ type EgVar struct { *easygen.EgBase } var ( cls2lc = varcaser.Caser{ From: varcaser.LowerSnakeCase, To: varcaser.LowerCamelCaseKeepCaps} cls2uc = varcaser.Caser{ From: varcaser.LowerSnakeCase, To: varcaser.UpperCamelCaseKeepCaps} cls2ss = varcaser.Caser{ From: varcaser.LowerSnakeCase, To: varcaser.ScreamingSnakeCase} cls2lk = varcaser.Caser{ From: varcaser.LowerSnakeCase, To: varcaser.KebabCase} cls2hh = varcaser.Caser{ From: varcaser.LowerSnakeCase, To: varcaser.HttpHeaderCase} css2lc = varcaser.Caser{ From: varcaser.ScreamingSnakeCase, To: varcaser.LowerCamelCaseKeepCaps} css2uc = varcaser.Caser{ From: varcaser.ScreamingSnakeCase, To: varcaser.UpperCamelCaseKeepCaps} css2ls = varcaser.Caser{ From: varcaser.ScreamingSnakeCase, To: varcaser.LowerSnakeCase} css2lk = varcaser.Caser{ From: varcaser.ScreamingSnakeCase, To: varcaser.KebabCase} css2hh = varcaser.Caser{ From: varcaser.ScreamingSnakeCase, To: varcaser.HttpHeaderCase} clk2lc = varcaser.Caser{From: varcaser.KebabCase, To: varcaser.LowerCamelCaseKeepCaps} clk2uc = varcaser.Caser{From: varcaser.KebabCase, To: varcaser.UpperCamelCaseKeepCaps} clk2ls = varcaser.Caser{From: varcaser.KebabCase, To: varcaser.LowerSnakeCase} clk2ss = varcaser.Caser{ From: varcaser.KebabCase, To: varcaser.ScreamingSnakeCase} clc2uc = varcaser.Caser{ From: varcaser.LowerCamelCase, To: varcaser.UpperCamelCaseKeepCaps} clc2ls = varcaser.Caser{ From: varcaser.LowerCamelCase, To: varcaser.LowerSnakeCase} clc2ss = varcaser.Caser{ From: varcaser.LowerCamelCase, To: varcaser.ScreamingSnakeCase} cuc2lc = varcaser.Caser{ From: varcaser.UpperCamelCase, To: varcaser.LowerCamelCase} cuc2ls = varcaser.Caser{ From: varcaser.UpperCamelCase, To: varcaser.LowerSnakeCase} cuc2ss = varcaser.Caser{ From: varcaser.UpperCamelCase, To: varcaser.ScreamingSnakeCase} ) var egFuncMap = easygen.FuncMap{ "cls2lc": cls2lc.String, "cls2uc": cls2uc.String, "cls2ss": cls2ss.String, "cls2lk": cls2lk.String, "cls2hh": cls2hh.String, "css2lc": css2lc.String, "css2uc": css2uc.String, "css2ls": css2ls.String, "css2lk": css2lk.String, "css2hh": css2hh.String, "clk2lc": clk2lc.String, "clk2uc": clk2uc.String, "clk2ls": clk2ls.String, "clk2ss": clk2ss.String, "clc2uc": clc2uc.String, "clc2ls": clc2ls.String, "clc2ss": clc2ss.String, "cuc2lc": cuc2lc.String, "cuc2ls": cuc2ls.String, "cuc2ss": cuc2ss.String, // Aliases, for backwards-compatibility with earlier (>= v1) versions "ck2lc": clk2lc.String, "ck2uc": clk2uc.String, "ck2ls": clk2ls.String, "ck2ss": clk2ss.String, } //////////////////////////////////////////////////////////////////////////// // Function definitions // FuncDefs returns the custom definition mapping for this specific package. func FuncDefs() template.FuncMap { return template.FuncMap(egFuncMap) } // NewTemplate returns a new Template for this specific package. func NewTemplate() *EgVar { return &EgVar{&easygen.EgBase{template.New("EgVar")}} } easygen-5.1.9/egVar/EgVar_test.go000066400000000000000000000073361416363131000166260ustar00rootroot00000000000000package egVar_test import ( "fmt" "os" "github.com/go-easygen/easygen" "github.com/go-easygen/easygen/egVar" ) func ExampleEgVar_output() { // EgVar variable names converting full coverage test tmpl0 := egVar.NewTemplate().Customize() tmpl := tmpl0.Funcs(easygen.FuncDefs()).Funcs(egVar.FuncDefs()) fmt.Println("\n## From lk - KebabCase => CamelCase/SnakeCase") easygen.Process0(tmpl, os.Stdout, "{{.Name}}: {{clk2lc .Name}} {{clk2uc .Name}}\n", "../test/listfunc2") easygen.Process0(tmpl, os.Stdout, "{{.Name}}: {{clk2ls .Name}} {{clk2ss .Name}}\n", "../test/listfunc2") fmt.Println("\n## From ls/ss - LowerSnakeCase/ScreamingSnakeCase") easygen.Process0(tmpl, os.Stdout, "{{clk2ls .Name}} {{clk2ss .Name}} =>\n", "../test/listfunc2") fmt.Println("### From ls") easygen.Process0(tmpl, os.Stdout, " {{clk2ls .Name | cls2lc}} {{clk2ls .Name | cls2uc}}\n", "../test/listfunc2") easygen.Process0(tmpl, os.Stdout, " {{clk2ls .Name | cls2ss}} {{clk2ls .Name | cls2lk}} {{clk2ls .Name | cls2hh}}\n", "../test/listfunc2") easygen.Process0(tmpl, os.Stdout, " {{clk2ls .NameHTTP | cls2lc}} {{clk2ls .NameHTTP | cls2uc}}\n", "../test/listfunc2") easygen.Process0(tmpl, os.Stdout, " {{clk2ls .NameHTTP | cls2ss}} {{clk2ls .NameHTTP | cls2lk}} {{clk2ls .NameHTTP | cls2hh}}\n", "../test/listfunc2") fmt.Println("### From ss") easygen.Process0(tmpl, os.Stdout, " {{clk2ss .Name | css2lc}} {{clk2ss .Name | css2uc}}\n", "../test/listfunc2") easygen.Process0(tmpl, os.Stdout, " {{clk2ss .Name | css2ls}} {{clk2ss .Name | css2lk}} {{clk2ss .Name | css2hh}}\n", "../test/listfunc2") easygen.Process0(tmpl, os.Stdout, " {{clk2ss .NameHTTP | css2lc}} {{clk2ss .NameHTTP | css2uc}}\n", "../test/listfunc2") easygen.Process0(tmpl, os.Stdout, " {{clk2ss .NameHTTP | css2ls}} {{clk2ss .NameHTTP | css2lk}} {{clk2ss .NameHTTP | css2hh}}\n", "../test/listfunc2") fmt.Println("\n## From lc/uc - LowerCamelCase/UpperCamelCaseKeepCaps") easygen.Process0(tmpl, os.Stdout, "{{clk2lc .Name}} {{clk2uc .Name}} =>\n", "../test/listfunc2") easygen.Process0(tmpl, os.Stdout, "{{clk2lc .Name}}: {{clk2lc .Name | clc2uc}} {{clk2lc .Name | clc2ls}} {{clk2lc .Name | clc2ss}}\n", "../test/listfunc2") easygen.Process0(tmpl, os.Stdout, "{{clk2uc .Name}}: {{clk2uc .Name | cuc2lc}} {{clk2uc .Name | cuc2ls}} {{clk2uc .Name | cuc2ss}}\n", "../test/listfunc2") easygen.Process0(tmpl, os.Stdout, "{{.NameMixed}}: {{clc2uc .NameMixed}} {{clc2uc .NameMixed | cuc2lc}} {{clc2ls .NameMixed}} {{clc2ls .NameMixed | cls2lc}}\n", "../test/listfunc2") easygen.Process0(tmpl, os.Stdout, "{{.NameMixed}}: {{clc2ls .NameMixed | cls2ss}} {{clc2ls .NameMixed | cls2lk}} {{clc2ls .NameMixed | cls2hh}}\n", "../test/listfunc2") // Output: // // ## From lk - KebabCase => CamelCase/SnakeCase // some-init-method: someInitMethod SomeInitMethod // some-init-method: some_init_method SOME_INIT_METHOD // // ## From ls/ss - LowerSnakeCase/ScreamingSnakeCase // some_init_method SOME_INIT_METHOD => // ### From ls // someInitMethod SomeInitMethod // SOME_INIT_METHOD some-init-method Some-Init-Method // httpHeaderCase HttpHeaderCase // HTTP_HEADER_CASE http-header-case HTTP-Header-Case // ### From ss // someINITMETHOD SOMEINITMETHOD // some_init_method some-init-method Some-Init-Method // httpHEADERCASE HTTPHEADERCASE // http_header_case http-header-case HTTP-Header-Case // // ## From lc/uc - LowerCamelCase/UpperCamelCaseKeepCaps // someInitMethod SomeInitMethod => // someInitMethod: SomeInitMethod some_init_method SOME_INIT_METHOD // SomeInitMethod: someInitMethod some_init_method SOME_INIT_METHOD // some_InitMethod: Some_InitMethod some_InitMethod some__init_method someInitMethod // some_InitMethod: SOME__INIT_METHOD some--init-method Some--Init-Method } easygen-5.1.9/egVar/example_test.go000066400000000000000000000011531416363131000172440ustar00rootroot00000000000000package egVar_test import ( "os" "github.com/go-easygen/easygen" "github.com/go-easygen/easygen/egVar" ) // for standalone test, change package to `main` and the next func def to, // func main() { func Example() { // Equivalent testing on commandline: // easygen test/listfunc2 tmpl0 := egVar.NewTemplate().Customize() tmpl := tmpl0.Funcs(easygen.FuncDefs()).Funcs(egVar.FuncDefs()) err := easygen.Process(tmpl, os.Stdout, "../test/listfunc2") // Output: // some-init-method 5 5 someInitMethod SomeInitMethod if err != nil { panic(err) } } // To show the full code in GoDoc type dummy struct { } easygen-5.1.9/example0_test.go000066400000000000000000000013311416363131000162560ustar00rootroot00000000000000package easygen_test import ( "os" "github.com/go-easygen/easygen" "github.com/go-easygen/easygen/egCal" "github.com/go-easygen/easygen/egVar" ) // for standalone test, change package to `main` and the next func def to, // func main() { func ExampleProcess0() { tmpl0 := easygen.NewTemplate().Customize() tmpl := tmpl0.Funcs(easygen.FuncDefs()).Funcs(egVar.FuncDefs()).Funcs(egCal.FuncDefs()) easygen.Process0(tmpl, os.Stdout, "{{.Name}}: {{clk2uc .Name}} {{clk2ss .Name}}\n"+ "Cal: {{add 2 3}}, {{multiply 2 3}}, {{subtract 9 2}}, {{divide 24 3}}\n", "test/var0") // Output: // some-init-method: SomeInitMethod SOME_INIT_METHOD // Cal: 5, 6, 7, 8 } // To show the full code in GoDoc type dummy0 struct { } easygen-5.1.9/example_execute0_test.go000066400000000000000000000021031416363131000177760ustar00rootroot00000000000000package easygen_test import ( "fmt" "os" "strings" "github.com/go-easygen/easygen" ) // for standalone test, change package to `main` and the next func def to, // func main() { func ExampleExecute0() { easygen.Opts.Debug = 1 tmpl := easygen.NewTemplate().Funcs(easygen.FuncDefs()) // define driving data of any type v0 := "some-init-method" // https://godoc.org/github.com/go-easygen/easygen#Execute0 // provide template string, not file name easygen.Execute0(tmpl, os.Stdout, "{{stringsToUpper .}}\n", v0) // Demo of using driving data of pure slice/array v1 := []string{"red", "blue", "white"} easygen.Execute0(tmpl, os.Stdout, "The colors are: {{range .}}{{.}}, {{end}}.\n", v1) // Demo output to string var b strings.Builder easygen.Execute0(tmpl, &b, "The colors are: {{range $i, $color := .}}{{$color}}{{if lt $i ($ | len | minus1)}}, {{end}}{{end}}.\n", v1) fmt.Print(b.String()) // Output: // SOME-INIT-METHOD // The colors are: red, blue, white, . // The colors are: red, blue, white. } // To show the full code in GoDoc type dummyExecute0 struct { } easygen-5.1.9/example_execute_test.go000066400000000000000000000023551416363131000177270ustar00rootroot00000000000000package easygen_test import ( "fmt" "os" "strings" "github.com/go-easygen/easygen" "github.com/go-easygen/easygen/egCal" "github.com/go-easygen/easygen/egFilePath" "github.com/go-easygen/easygen/egVar" ) type variable struct { Name string } // for standalone test, change package to `main` and the next func def to, // func main() { func ExampleExecute() { easygen.Opts.Debug = 1 tmpl0 := easygen.NewTemplate().Customize() tmpl := tmpl0.Funcs(easygen.FuncDefs()).Funcs(egFilePath.FuncDefs()). Funcs(egVar.FuncDefs()).Funcs(egCal.FuncDefs()) // define driving data of any type v0 := variable{"some-init-method"} // https://godoc.org/github.com/go-easygen/easygen#Execute // provide full template file name with extension easygen.Execute(tmpl, os.Stdout, "test/var0.tmpl", v0) // Demo of using driving data of pure slice/array v1 := []string{"red", "blue", "white"} easygen.Execute(tmpl, os.Stdout, "test/list00.tmpl", v1) // Demo output to string var b strings.Builder easygen.Execute(tmpl, &b, "test/list00f.tmpl", v1) fmt.Print(b.String()) // Output: // Input: "some-init-method" // Output 1: "SomeInitMethod" // Output 2: "SOME_INIT_METHOD" // The colors are: red, blue, white, . // The colors are: red, blue, white. } easygen-5.1.9/example_test.go000066400000000000000000000017461416363131000162100ustar00rootroot00000000000000package easygen_test import ( "os" "github.com/go-easygen/easygen" "github.com/go-easygen/easygen/egVar" ) // for standalone test, change package to `main` and the next func def to, // func main() { func ExampleProcess() { tmpl0 := easygen.NewTemplate().Customize() tmpl := tmpl0.Funcs(easygen.FuncDefs()).Funcs(egVar.FuncDefs()) tmplFileName := "test/var0" easygen.Process(tmpl, os.Stdout, tmplFileName) easygen.Process2(tmpl, os.Stdout, tmplFileName, tmplFileName) // To use Execute(), TemplateFileName has to be exact m := easygen.ReadDataFile(tmplFileName + ".yaml") easygen.Execute(tmpl, os.Stdout, tmplFileName+".tmpl", m) // Output: // Input: "some-init-method" // Output 1: "SomeInitMethod" // Output 2: "SOME_INIT_METHOD" // Input: "some-init-method" // Output 1: "SomeInitMethod" // Output 2: "SOME_INIT_METHOD" // Input: "some-init-method" // Output 1: "SomeInitMethod" // Output 2: "SOME_INIT_METHOD" } // To show the full code in GoDoc type dummy struct { } easygen-5.1.9/t_readdatafile_test.go000066400000000000000000000023531416363131000175000ustar00rootroot00000000000000package easygen_test import ( "os" "github.com/go-easygen/easygen" "github.com/go-easygen/easygen/egVar" ) // for standalone test, change package to `main` and the next func def to, // func main() { func ExampleReadDataFile() { tmplFileName := "test/var0" tmpl0 := easygen.NewTemplate().Customize() tmpl := tmpl0.Funcs(easygen.FuncDefs()).Funcs(egVar.FuncDefs()) // To use Execute(), TemplateFileName has to be exact tmplFileNameFull := tmplFileName + ".tmpl" m := easygen.ReadDataFile(tmplFileName) easygen.Execute(tmpl, os.Stdout, tmplFileNameFull, m) easygen.Opts.Debug = 0 m = easygen.ReadDataFile(tmplFileName + ".yaml") easygen.Execute(tmpl, os.Stdout, tmplFileNameFull, m) tmplFileName = "test/list0j" tmplFileNameFull = tmplFileName + ".tmpl" m = easygen.ReadDataFile(tmplFileName) easygen.Execute(tmpl, os.Stdout, tmplFileNameFull, m) m = easygen.ReadDataFile(tmplFileName + ".json") easygen.Execute(tmpl, os.Stdout, tmplFileNameFull, m) // Output: // Input: "some-init-method" // Output 1: "SomeInitMethod" // Output 2: "SOME_INIT_METHOD" // Input: "some-init-method" // Output 1: "SomeInitMethod" // Output 2: "SOME_INIT_METHOD" // The colors are: red, blue, white, . // The colors are: red, blue, white, . } easygen-5.1.9/t_strings_test.go000066400000000000000000000105351416363131000165650ustar00rootroot00000000000000package easygen_test import ( "bytes" "testing" "github.com/go-easygen/easygen" ) type testItem struct { tmplStr, expected string } //var tmpl *template.Template func testStringManipulation(t *testing.T, d []testItem) { tmpl = easygen.NewTemplate().Funcs(easygen.FuncDefs()) for _, tc := range d { buf := bytes.NewBufferString("") easygen.Process0(tmpl, buf, tc.tmplStr, "test/strings") v := buf.String() //t.Log(v) if v != tc.expected { t.Errorf("'%s' expects '%s', got '%s'", tc.tmplStr, tc.expected, v) } } } // for standalone test, change package to `main` and the next func def to, // func main() { func TestStringManipulation(t *testing.T) { testData := []testItem{ // == standard strings functions { `{{ stringsContains "seafood" "foo" }}`, "true", }, { `{{ stringsContains "seafood" "bar" }}`, "false", }, { `{{ stringsContainsAny "team" "i" }}`, "false", }, { `{{ stringsContainsAny "failure" "u & i" }}`, "true", }, { `{{ stringsCount "cheese" "e" }}`, "3", }, { `{{ stringsEqualFold "Go" "go" }}`, "true", }, { `{{ stringsFields " foo bar baz " }}`, "[foo bar baz]", }, { `{{ stringsIndex "go gopher" "go" }}`, "0", }, { `{{ stringsLastIndex "go gopher" "go" }}`, "3", }, { `ba{{ stringsRepeat "na" 2 }}`, "banana", }, { `{{ stringsReplace "oink oink oink" "k" "ky" 2 }}`, "oinky oinky oink", }, { `{{ stringsReplace "oink oink oink" "oink" "moo" -1 }}`, "moo moo moo", }, { `{{ stringsSplitN "a,b,c" "," 0 }}`, `[]`, }, { `{{ stringsSplitAfter "a,b,c" "," }}`, `[a, b, c]`, }, { `{{ stringsSplitAfterN "a,b,c" "," 2 }}`, `[a, b,c]`, }, { `{{ stringsTitle "her royal highness" }}`, "Her Royal Highness", }, { `{{ stringsToLower "Gopher" }}`, "gopher", }, { `{{ stringsToUpper "Gopher" }}`, "GOPHER", }, { `{{ stringsTrimSpace " \t\n a lone gopher \n\t\r\n" }}`, "a lone gopher", }, { `{{ stringsTrim " !!! Achtung !!! " "! " }}`, "Achtung", }, { `{{ stringsTrimPrefix "Goodbye,, world!" "Goodbye," }}`, ", world!", }, { `{{ stringsTrimSuffix "Hello, goodbye, etc!" "goodbye, etc!" }}`, "Hello, ", }, // aliases { `The {{if eq .StrTest "these rights belong to those people"}}eq says Yea{{else}}eq says Nay{{end}} but {{if eqf .StrTest "these rights belong to those people"}}eqf says Yea{{else}}eqf says Nay{{end}}.`, "The eq says Nay but eqf says Yea.", }, { `{{$s := sprintf .StrTest}} {{$s}}`, " These rights belong to those people", }, { `{{$s := sprintf "%s, %.2f" .StrTest 12.3456}} {{$s}}`, " These rights belong to those people, 12.35", }, // == standard regexp functions { `{{ regexpFindString "peach punch" "p([a-z]+)ch" }}`, "peach", }, { `{{ regexpFindAllString "peach punch" "p([a-z]+)ch" -1 }}`, "[peach punch]", }, { `{{ regexpFindAllString "peach punch" "p([a-z]+)ch" 1 }}`, "[peach]", }, { `{{ regexpFindStringIndex "peach punch" "p([a-z]+)ch" }}`, "[0 5]", }, { `{{ regexpFindStringSubmatch "peach punch" "p([a-z]+)ch" }}`, "[peach ea]", }, { `{{ regexpFindStringSubmatchIndex "peach punch" "p([a-z]+)ch" }}`, "[0 5 1 3]", }, // { `{{ regexpMatchString "HTTPS://site/" "(?i)^http" }}`, "true", }, // { `{{ regexpReplaceAllLiteralString "html HTML Html aa uml bb Uml" "(?i)html|uml" "XML" }}`, "XML XML XML aa XML bb XML", }, { `{{ regexpReplaceAllString .StrTest "(?i)th[eo]se" "the" }}`, "the rights belong to the people", }, { `{{ regexpReplaceAllString "This and these are for THOSE people" "(?i)(this|th[eo]se)" "${1}" }}`, "This and these are for THOSE people", }, // { // `{{ regexpReplaceAllStringFunc "a peach" "p([a-z]+)ch" stringsToUpper }}`, // "a PEACH", // }, // == my added strings functions { `{{ coalesce "a" }}`, "a", }, { `{{ coalesce "" "b" }}`, "b", }, { `{{ coalesce "" "" "c" }}`, "c", }, { `{{ coalesce "" "" "" "" }}`, "", }, { `{{ coalesce "" }}`, "", }, { `{{ coalesce .StrTest "Something else" }}`, "These rights belong to those people", }, { `{{ coalesce .StrEmpty "Something else" }}`, "Something else", }, } testStringManipulation(t, testData) } /* { `{{ }}`, "", }, */ easygen-5.1.9/template.go000066400000000000000000000203731416363131000153260ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////////////// // Package: easygen // Purpose: Easy to use universal code/text generator // Authors: Tong Sun (c) 2015-2021, All rights reserved //////////////////////////////////////////////////////////////////////////// package easygen import ( "fmt" "io" "os" "strings" "text/template" ) //////////////////////////////////////////////////////////////////////////// // Constant and data type/structure definitions // The Template defines the common ground for both text and html Template type Template interface { Execute(wr io.Writer, data interface{}) error ExecuteTemplate(wr io.Writer, name string, data interface{}) error Parse(text string) (*template.Template, error) ParseFiles(filenames ...string) (*template.Template, error) Name() string } // EgBase -- EasyGen Template Base /* stringsCompare is wrapper for strings.Compare stringsContains is wrapper for strings.Contains stringsContainsAny is wrapper for strings.ContainsAny stringsContainsRune is wrapper for strings.ContainsRune stringsCount is wrapper for strings.Count stringsEqualFold is wrapper for strings.EqualFold stringsFields is wrapper for strings.Fields stringsFieldsFunc is wrapper for strings.FieldsFunc stringsHasPrefix is wrapper for strings.HasPrefix stringsHasSuffix is wrapper for strings.HasSuffix stringsIndex is wrapper for strings.Index stringsIndexAny is wrapper for strings.IndexAny stringsIndexByte is wrapper for strings.IndexByte stringsIndexFunc is wrapper for strings.IndexFunc stringsIndexRune is wrapper for strings.IndexRune stringsJoin is wrapper for strings.Join stringsLastIndex is wrapper for strings.LastIndex stringsLastIndexAny is wrapper for strings.LastIndexAny stringsLastIndexByte is wrapper for strings.LastIndexByte stringsLastIndexFunc is wrapper for strings.LastIndexFunc stringsMap is wrapper for strings.Map stringsRepeat is wrapper for strings.Repeat stringsReplace is wrapper for strings.Replace stringsSplit is wrapper for strings.Split stringsSplitAfter is wrapper for strings.SplitAfter stringsSplitAfterN is wrapper for strings.SplitAfterN stringsSplitN is wrapper for strings.SplitN stringsTitle is wrapper for strings.Title stringsToLower is wrapper for strings.ToLower stringsToLowerSpecial is wrapper for strings.ToLowerSpecial stringsToTitle is wrapper for strings.ToTitle stringsToTitleSpecial is wrapper for strings.ToTitleSpecial stringsToUpper is wrapper for strings.ToUpper stringsToUpperSpecial is wrapper for strings.ToUpperSpecial stringsTrim is wrapper for strings.Trim stringsTrimFunc is wrapper for strings.TrimFunc stringsTrimLeft is wrapper for strings.TrimLeft stringsTrimLeftFunc is wrapper for strings.TrimLeftFunc stringsTrimPrefix is wrapper for strings.TrimPrefix stringsTrimRight is wrapper for strings.TrimRight stringsTrimRightFunc is wrapper for strings.TrimRightFunc stringsTrimSpace is wrapper for strings.TrimSpace stringsTrimSuffix is wrapper for strings.TrimSuffix eqf is wrapper for strings.EqualFold split is wrapper for strings.Fields sprintf is wrapper for fmt.Sprintf regexpFindAllString is template function for RegexpFindAllString regexpFindAllStringIndex is template function for RegexpFindAllStringIndex regexpFindAllStringSubmatch is template function for RegexpFindAllStringSubmatch regexpFindAllStringSubmatchIndex is template function for RegexpFindAllStringSubmatchIndex regexpFindString is template function for RegexpFindString regexpFindStringIndex is template function for RegexpFindStringIndex regexpFindStringSubmatch is template function for RegexpFindStringSubmatch regexpFindStringSubmatchIndex is template function for RegexpFindStringSubmatchIndex regexpMatchString is template function for RegexpMatchString regexpReplaceAllLiteralString is template function for RegexpReplaceAllLiteralString regexpReplaceAllString is template function for RegexpReplaceAllString regexpReplaceAllStringFunc is template function for RegexpReplaceAllStringFunc regexpSplit is template function for RegexpSplit ENV is template function for os.Getenv substr is template function for Substr coalesce is template function for Coalesce quote4shell is template function for Quote4shell minus1 is template function for Minus1 date is template function for Date timestamp is template function for Timestamp */ type EgBase struct { *template.Template } // The FuncMap defined in easygen will shield the dependency of either // text or html template, giving an implementation agnostic abstraction // that will works for both cases. type FuncMap map[string]interface{} var egFuncMap = FuncMap{ // == standard strings function definitions "stringsCompare": strings.Compare, "stringsContains": strings.Contains, "stringsContainsAny": strings.ContainsAny, "stringsContainsRune": strings.ContainsRune, "stringsCount": strings.Count, "stringsEqualFold": strings.EqualFold, "stringsFields": strings.Fields, "stringsFieldsFunc": strings.FieldsFunc, "stringsHasPrefix": strings.HasPrefix, "stringsHasSuffix": strings.HasSuffix, "stringsIndex": strings.Index, "stringsIndexAny": strings.IndexAny, "stringsIndexByte": strings.IndexByte, "stringsIndexFunc": strings.IndexFunc, "stringsIndexRune": strings.IndexRune, "stringsJoin": strings.Join, "stringsLastIndex": strings.LastIndex, "stringsLastIndexAny": strings.LastIndexAny, "stringsLastIndexByte": strings.LastIndexByte, "stringsLastIndexFunc": strings.LastIndexFunc, "stringsMap": strings.Map, "stringsRepeat": strings.Repeat, "stringsReplace": strings.Replace, "stringsSplit": strings.Split, "stringsSplitAfter": strings.SplitAfter, "stringsSplitAfterN": strings.SplitAfterN, "stringsSplitN": strings.SplitN, "stringsTitle": strings.Title, "stringsToLower": strings.ToLower, "stringsToLowerSpecial": strings.ToLowerSpecial, "stringsToTitle": strings.ToTitle, "stringsToTitleSpecial": strings.ToTitleSpecial, "stringsToUpper": strings.ToUpper, "stringsToUpperSpecial": strings.ToUpperSpecial, "stringsTrim": strings.Trim, "stringsTrimFunc": strings.TrimFunc, "stringsTrimLeft": strings.TrimLeft, "stringsTrimLeftFunc": strings.TrimLeftFunc, "stringsTrimPrefix": strings.TrimPrefix, "stringsTrimRight": strings.TrimRight, "stringsTrimRightFunc": strings.TrimRightFunc, "stringsTrimSpace": strings.TrimSpace, "stringsTrimSuffix": strings.TrimSuffix, // aliases "eqf": strings.EqualFold, "split": strings.Fields, "sprintf": fmt.Sprintf, // == standard regexp function definitions "regexpFindAllString": RegexpFindAllString, "regexpFindAllStringIndex": RegexpFindAllStringIndex, "regexpFindAllStringSubmatch": RegexpFindAllStringSubmatch, "regexpFindAllStringSubmatchIndex": RegexpFindAllStringSubmatchIndex, "regexpFindString": RegexpFindString, "regexpFindStringIndex": RegexpFindStringIndex, "regexpFindStringSubmatch": RegexpFindStringSubmatch, "regexpFindStringSubmatchIndex": RegexpFindStringSubmatchIndex, "regexpMatchString": RegexpMatchString, "regexpReplaceAllLiteralString": RegexpReplaceAllLiteralString, "regexpReplaceAllString": RegexpReplaceAllString, "regexpReplaceAllStringFunc": RegexpReplaceAllStringFunc, "regexpSplit": RegexpSplit, // == my added functions "ENV": os.Getenv, "substr": Substr, "coalesce": Coalesce, "quote4shell": Quote4shell, "iterate": Iterate, "argsa": ArgsA, "argsm": ArgsM, "minus1": Minus1, "date": Date, "timestamp": Timestamp, } //////////////////////////////////////////////////////////////////////////// // Function definitions // FuncDefs returns the custom definition mapping for this specific package. func FuncDefs() template.FuncMap { return template.FuncMap(egFuncMap) } // NewTemplate returns a new Template for this specific package. func NewTemplate() *EgBase { return &EgBase{template.New("EgBase")} } // Customize allows customization for this specific package. func (t *EgBase) Customize() *EgBase { return t } easygen-5.1.9/test/000077500000000000000000000000001416363131000141365ustar00rootroot00000000000000easygen-5.1.9/test/.gitignore000066400000000000000000000001101416363131000161160ustar00rootroot00000000000000# Generated output, to be compared with the .ref reference output *.got easygen-5.1.9/test/IntelliJ-Emacs.tmpl000066400000000000000000000004421416363131000175740ustar00rootroot00000000000000{{range .Action -}} {{if eq "map[string]interface {}" (printf "%T" .Shortcut) }}{{.Shortcut.FirstKS}}{{if .Shortcut.SecondKS}} {{.Shortcut.SecondKS}}{{end}} {{.Id}} {{else}}{{ $Id := .Id -}} {{range .Shortcut}}{{.FirstKS}}{{if .SecondKS}} {{.SecondKS}}{{end}} {{$Id}} {{end}}{{end}}{{end}} easygen-5.1.9/test/commandlineCLI-024.ref000066400000000000000000000070611416363131000177610ustar00rootroot00000000000000// -*- go -*- //////////////////////////////////////////////////////////////////////////// // Program: gogo // Purpose: Golang package manager //////////////////////////////////////////////////////////////////////////// package main import ( "github.com/mkideal/cli" ) var app = &cli.Register(&cli.Command{ Name: "gogo", Desc: "Golang package manager", Text: " gogo is a new golang package manager\n very very good", Argv: func() interface{} { return new(gogoT) }, Fn: gogo, NumArg: cli.ExactN(1), }) type gogoT struct { cli.Helper Version bool `cli:"v,version" usage:"display version"` List bool `cli:"l,list" usage:"list all sub commands or not"` } func gogo(ctx *cli.Context) error { argv := ctx.Argv().(*gogoT) ctx.String("%s: %v", ctx.Path(), jsonIndent(argv)) ctx.String("[gogo]: %v\n", ctx.Args()) return nil } //////////////////////////////////////////////////////////////////////////// // Program: build // Purpose: Build golang application //////////////////////////////////////////////////////////////////////////// package main import ( "github.com/mkideal/cli" ) var buildCmd = app.Register(&cli.Command{ Name: "build", Desc: "Build golang application", Text: "Usage:\n gogo build [Options] Arch(i386|amd64)", Argv: func() interface{} { return new(buildT) }, Fn: build, NumArg: cli.ExactN(1), CanSubRoute: true, }) type buildT struct { cli.Helper Dir string `cli:"dir" usage:"source code root dir" dft:"./"` Suffix string `cli:"suffix" usage:"source file suffix" dft:".go,.c,.s"` Out string `cli:"o,out" usage:"output filename"` } func build(ctx *cli.Context) error { argv := ctx.Argv().(*buildT) ctx.String("%s: %v", ctx.Path(), jsonIndent(argv)) ctx.String("[build]: %v\n", ctx.Args()) return nil } //////////////////////////////////////////////////////////////////////////// // Program: install // Purpose: Install golang application //////////////////////////////////////////////////////////////////////////// package main import ( "github.com/mkideal/cli" ) var installCmd = app.Register(&cli.Command{ Name: "install", Desc: "Install golang application", Text: "Usage:\n gogo install [Options] package [package...]", Argv: func() interface{} { return new(installT) }, Fn: install, NumArg: cli.AtLeast(1), CanSubRoute: true, }) type installT struct { cli.Helper Dir string `cli:"dir" usage:"source code root dir" dft:"./"` Suffix string `cli:"suffix" usage:"source file suffix" dft:".go,.c,.s"` Out string `cli:"o,out" usage:"output filename"` } func install(ctx *cli.Context) error { argv := ctx.Argv().(*installT) ctx.String("%s: %v", ctx.Path(), jsonIndent(argv)) ctx.String("[install]: %v\n", ctx.Args()) return nil } //////////////////////////////////////////////////////////////////////////// // Program: publish // Purpose: Publish golang application //////////////////////////////////////////////////////////////////////////// package main import ( "github.com/mkideal/cli" ) var publishCmd = app.Register(&cli.Command{ Name: "publish", Desc: "Publish golang application", Argv: func() interface{} { return new(publishT) }, Fn: publish, }) type publishT struct { cli.Helper Dir string `cli:"dir" usage:"source code root dir" dft:"./"` Suffix string `cli:"suffix" usage:"source file suffix" dft:".go,.c,.s"` Out string `cli:"o,out" usage:"output filename"` List bool `cli:"l,list" usage:"list all sub commands"` } func publish(ctx *cli.Context) error { argv := ctx.Argv().(*publishT) ctx.String("%s: %v", ctx.Path(), jsonIndent(argv)) ctx.String("[publish]: %v\n", ctx.Args()) return nil } easygen-5.1.9/test/commandlineCLI-024.tmpl000066400000000000000000000033671416363131000201660ustar00rootroot00000000000000// -*- go -*- //////////////////////////////////////////////////////////////////////////// // Program: {{.Name}} // Purpose: {{.Desc}} //////////////////////////////////////////////////////////////////////////// package {{$.PackageName}} import ( "github.com/mkideal/cli" ) var {{.Var}} = &cli.Register(&cli.Command{ Name: "{{.Name}}", Desc: "{{.Desc}}", {{if .Text}} Text: "{{.Text}}", {{end}} Argv: func() interface{} { return new({{.Name}}T) }, Fn: {{.Name}}, {{if .NumArg}} NumArg: {{.NumArg}}, {{end}}}) type {{.Name}}T struct { cli.Helper{{range .Options}} {{.Name}} {{.Type}} `cli:"{{.Flag}}" usage:"{{.Usage}}"{{if .Value}} dft:{{.Value}}{{end}}`{{end}} } func {{.Name}}(ctx *cli.Context) error { argv := ctx.Argv().(*{{.Name}}T) ctx.String("%s: %v", ctx.Path(), jsonIndent(argv)) ctx.String("[{{.Name}}]: %v\n", ctx.Args()) return nil } {{range .Command}} //////////////////////////////////////////////////////////////////////////// // Program: {{.Name}} // Purpose: {{.Desc}} //////////////////////////////////////////////////////////////////////////// package {{$.PackageName}} import ( "github.com/mkideal/cli" ) var {{.Name}}Cmd = {{$.Var}}.Register(&cli.Command{ Name: "{{.Name}}", Desc: "{{.Desc}}", {{if .Text}} Text: "{{.Text}}", {{end}} Argv: func() interface{} { return new({{.Name}}T) }, Fn: {{.Name}}, {{if .NumArg}} NumArg: {{.NumArg}}, CanSubRoute: true, {{end}}}) type {{.Name}}T struct { cli.Helper{{range .Options}} {{.Name}} {{.Type}} `cli:"{{.Flag}}" usage:"{{.Usage}}"{{if .Value}} dft:{{.Value}}{{end}}`{{end}} } func {{.Name}}(ctx *cli.Context) error { argv := ctx.Argv().(*{{.Name}}T) ctx.String("%s: %v", ctx.Path(), jsonIndent(argv)) ctx.String("[{{.Name}}]: %v\n", ctx.Args()) return nil } {{end}} easygen-5.1.9/test/commandlineCLI-024.yaml000066400000000000000000000051261416363131000201470ustar00rootroot00000000000000# program name, name for the executable ProgramName: gogo # package name # - For standalone program that does not belong to any package, e.g., # https://github.com/suntong/easygen/blob/7791e4f0e5605543d27da1671a21376cdb9dcf2a/easygen/easygen.go # just ignore the first line, the `package` output, and copy the rest # - If you don't mind using a separated file to handle commandline paramters, # then name the package as "main". see the spin-out "TF-minus1.go" file under # https://github.com/suntong/easygen/tree/d1ab0b5fe80ddac57fe9ef51f6ccb3ab998cd5ee # - If you are using it in a pacakge, look no further than # https://github.com/suntong/easygen/blob/master/easygenapi/config.go # which was a direct dump: easygen test/commandlineFlag | gofmt > easygenapi/config.go # PackageName: main Name: gogo Var: app Desc: "Golang package manager" Text: ' gogo is a new golang package manager\n very very good' NumArg: cli.ExactN(1) Options: - Name: Version Type: bool Flag: v,version Usage: display version - Name: List Type: bool Flag: l,list Usage: list all sub commands or not Command: - Name: build Desc: "Build golang application" Text: 'Usage:\n gogo build [Options] Arch(i386|amd64)' NumArg: cli.ExactN(1) Options: - Name: Dir Type: string Flag: dir Value: '"./"' Usage: source code root dir - Name: Suffix Type: string Flag: suffix Value: '".go,.c,.s"' Usage: "source file suffix" - Name: Out Type: string Flag: o,out Usage: "output filename" - Name: install Desc: "Install golang application" Text: 'Usage:\n gogo install [Options] package [package...]' NumArg: cli.AtLeast(1) Options: - Name: Dir Type: string Flag: dir Value: '"./"' Usage: source code root dir - Name: Suffix Type: string Flag: suffix Value: '".go,.c,.s"' Usage: "source file suffix" - Name: Out Type: string Flag: o,out Usage: "output filename" - Name: publish Desc: "Publish golang application" Options: - Name: Dir Type: string Flag: dir Value: '"./"' Usage: source code root dir - Name: Suffix Type: string Flag: suffix Value: '".go,.c,.s"' Usage: "source file suffix" - Name: Out Type: string Flag: o,out Usage: "output filename" - Name: List Type: bool Flag: l,list Usage: "list all sub commands" easygen-5.1.9/test/commandlineCLI-027.ref000066400000000000000000000072121416363131000177620ustar00rootroot00000000000000// -*- go -*- //////////////////////////////////////////////////////////////////////////// // Program: redo // Purpose: global option redo //////////////////////////////////////////////////////////////////////////// package main import ( "github.com/mkideal/cli" ) //////////////////////////////////////////////////////////////////////////// // redo type rootT struct { cli.Helper Self *rootT `cli:"c,config" usage:"config file" json:"-" parser:"jsonfile" dft:"redo.json"` Host string `cli:"H,host" usage:"host address" dft:"$HOST"` Port int `cli:"p,port" usage:"listening port" dft:"80"` } var root = &cli.Command{ Name: "redo", Desc: "global option redo", Text: " redo global option via automatic code-gen", Global: true, Argv: func() interface{} { t := new(rootT); t.Self = t; return t }, Fn: redo, NumArg: cli.ExactN(1), } // func main() { // cli.SetUsageStyle(cli.ManualStyle) // up-down, for left-right, use NormalStyle // //NOTE: You can set any writer implements io.Writer // // default writer is os.Stdout // if err := cli.Root(root, // cli.Tree(buildDef), // cli.Tree(installDef), // cli.Tree(publishDef)).Run(os.Args[1:]); err != nil { // fmt.Fprintln(os.Stderr, err) // } // fmt.Println("") // } // func redo(ctx *cli.Context) error { // ctx.JSON(ctx.RootArgv()) // ctx.JSON(ctx.Argv()) // fmt.Println() // return nil // } //////////////////////////////////////////////////////////////////////////// // build // func buildCLI(ctx *cli.Context) error { // rootArgv := ctx.RootArgv().(*rootT) // argv := ctx.Argv().(*buildT) // fmt.Printf("[build]:\n %+v\n %+v\n %v\n", rootArgv, argv, ctx.Args()) // return nil // } type buildT struct { Dir string `cli:"dir" usage:"source code root dir" dft:"./"` Suffix string `cli:"suffix" usage:"source file suffix" dft:".go,.c,.s"` Out string `cli:"o,out" usage:"output filename"` } var buildDef = &cli.Command{ Name: "build", Desc: "Build the network application", Text: "Usage:\n redo build [Options] Arch(i386|amd64)", Argv: func() interface{} { return new(buildT) }, Fn: buildCLI, NumArg: cli.ExactN(1), CanSubRoute: true, } //////////////////////////////////////////////////////////////////////////// // install // func installCLI(ctx *cli.Context) error { // rootArgv := ctx.RootArgv().(*rootT) // argv := ctx.Argv().(*installT) // fmt.Printf("[install]:\n %+v\n %+v\n %v\n", rootArgv, argv, ctx.Args()) // return nil // } type installT struct { Dir string `cli:"dir" usage:"source code root dir" dft:"./"` Suffix string `cli:"suffix" usage:"source file suffix" dft:".go,.c,.s"` Out string `cli:"o,out" usage:"output filename"` } var installDef = &cli.Command{ Name: "install", Desc: "Install the network application", Text: "Usage:\n redo install [Options] package [package...]", Argv: func() interface{} { return new(installT) }, Fn: installCLI, NumArg: cli.AtLeast(1), CanSubRoute: true, } //////////////////////////////////////////////////////////////////////////// // publish // func publishCLI(ctx *cli.Context) error { // rootArgv := ctx.RootArgv().(*rootT) // argv := ctx.Argv().(*publishT) // fmt.Printf("[publish]:\n %+v\n %+v\n %v\n", rootArgv, argv, ctx.Args()) // return nil // } type publishT struct { Dir string `cli:"*d,dir" usage:"publish dir"` Suffix string `cli:"suffix" usage:"source file suffix" dft:".go,.c,.s"` Out string `cli:"o,out" usage:"output filename"` List bool `cli:"l,list" usage:"list all sub commands"` } var publishDef = &cli.Command{ Name: "publish", Desc: "Publish the network application", Argv: func() interface{} { return new(publishT) }, Fn: publishCLI, NumOption: cli.AtLeast(1), } easygen-5.1.9/test/commandlineCLI-027.tmpl000066400000000000000000000051571416363131000201700ustar00rootroot00000000000000// -*- go -*- //////////////////////////////////////////////////////////////////////////// // Program: {{.Name}} // Purpose: {{.Desc}} //////////////////////////////////////////////////////////////////////////// package {{$.PackageName}} import ( "github.com/mkideal/cli" ) //////////////////////////////////////////////////////////////////////////// // {{.Name}} type rootT struct { cli.Helper{{range .Options}} {{.Name}} {{.Type}} `cli:"{{.Flag}}" usage:"{{.Usage}}"{{if eq .Name "Self" }} json:"-" parser:"jsonfile"{{end}}{{if .Value}} dft:"{{.Value}}"{{end}}`{{end}} } var root = &cli.Command{ Name: "{{.Name}}", Desc: "{{.Desc}}", {{if .Text}} Text: "{{.Text}}", {{end}}{{if .Global}} Global: {{.Global}}, {{end}}{{if .Self}} Argv: func() interface{} { t := new(rootT); t.Self = t; return t }, {{else}} Argv: func() interface{} { return new(rootT) }, {{end}} Fn: {{.Name}}, {{if .NumOption}} NumOption: {{.NumOption}}, {{end}}{{if .NumArg}} NumArg: {{.NumArg}}, {{end}}{{if .CanSubRoute}} CanSubRoute: {{.CanSubRoute}}, {{end}}} // func main() { // cli.SetUsageStyle(cli.ManualStyle) // up-down, for left-right, use NormalStyle // //NOTE: You can set any writer implements io.Writer // // default writer is os.Stdout // if err := cli.Root(root,{{range $i, $cmd := .Command}} // cli.Tree({{$cmd.Name}}Def){{if lt $i ($.Command | len | minus1)}},{{end}}{{end}}).Run(os.Args[1:]); err != nil { // fmt.Fprintln(os.Stderr, err) // } // fmt.Println("") // } // func {{.Name}}(ctx *cli.Context) error { // ctx.JSON(ctx.RootArgv()) // ctx.JSON(ctx.Argv()) // fmt.Println() // return nil // } {{range .Command}} //////////////////////////////////////////////////////////////////////////// // {{.Name}} // func {{.Name}}CLI(ctx *cli.Context) error { // rootArgv := ctx.RootArgv().(*rootT) // argv := ctx.Argv().(*{{.Name}}T) // fmt.Printf("[{{.Name}}]:\n %+v\n %+v\n %v\n", rootArgv, argv, ctx.Args()) // return nil // } type {{.Name}}T struct { {{range .Options}} {{.Name}} {{.Type}} `cli:"{{.Flag}}" usage:"{{.Usage}}"{{if eq .Name "Self" }} json:"-" parser:"jsonfile"{{end}}{{if .Value}} dft:"{{.Value}}"{{end}}`{{end}} } var {{.Name}}Def = &cli.Command{ Name: "{{.Name}}", Desc: "{{.Desc}}", {{if .Text}} Text: "{{.Text}}", {{end}}{{if .Self}} Argv: func() interface{} { t := new({{.Name}}T); t.Self = t; return t }, {{else}} Argv: func() interface{} { return new({{.Name}}T) }, {{end}} Fn: {{.Name}}CLI, {{if .NumOption}} NumOption: {{.NumOption}}, {{end}}{{if .NumArg}} NumArg: {{.NumArg}}, CanSubRoute: true, {{end}}{{if .CanSubRoute}} CanSubRoute: {{.CanSubRoute}}, {{end}}} {{end}} easygen-5.1.9/test/commandlineCLI-027.yaml000066400000000000000000000053121416363131000201470ustar00rootroot00000000000000# program name, name for the executable ProgramName: redo # package name # - For standalone program that does not belong to any package, e.g., # https://github.com/suntong/easygen/blob/7791e4f0e5605543d27da1671a21376cdb9dcf2a/easygen/easygen.go # just ignore the first line, the `package` output, and copy the rest # - If you don't mind using a separated file to handle commandline paramters, # then name the package as "main". see the spin-out "TF-minus1.go" file under # https://github.com/suntong/easygen/tree/d1ab0b5fe80ddac57fe9ef51f6ccb3ab998cd5ee # - If you are using it in a pacakge, look no further than # https://github.com/suntong/easygen/blob/master/easygenapi/config.go # which was a direct dump: easygen test/commandlineFlag | gofmt > easygenapi/config.go # PackageName: main Name: redo Desc: "global option redo" Text: ' redo global option via automatic code-gen' Global: true NumArg: cli.ExactN(1) Self: true Options: - Name: Self Type: '*rootT' Flag: c,config Usage: config file Value: redo.json - Name: Host Type: string Flag: H,host Usage: host address Value: "$HOST" - Name: Port Type: int Flag: p,port Usage: listening port Value: 80 Command: - Name: build Desc: "Build the network application" Text: 'Usage:\n redo build [Options] Arch(i386|amd64)' NumArg: cli.ExactN(1) Options: - Name: Dir Type: string Flag: dir Value: "./" Usage: source code root dir - Name: Suffix Type: string Flag: suffix Value: ".go,.c,.s" Usage: "source file suffix" - Name: Out Type: string Flag: o,out Usage: "output filename" - Name: install Desc: "Install the network application" Text: 'Usage:\n redo install [Options] package [package...]' NumArg: cli.AtLeast(1) Options: - Name: Dir Type: string Flag: dir Value: "./" Usage: source code root dir - Name: Suffix Type: string Flag: suffix Value: ".go,.c,.s" Usage: "source file suffix" - Name: Out Type: string Flag: o,out Usage: "output filename" - Name: publish Desc: "Publish the network application" NumOption: cli.AtLeast(1) Options: - Name: Dir Type: string Flag: '*d,dir' Usage: publish dir - Name: Suffix Type: string Flag: suffix Value: ".go,.c,.s" Usage: "source file suffix" - Name: Out Type: string Flag: o,out Usage: "output filename" - Name: List Type: bool Flag: l,list Usage: "list all sub commands" easygen-5.1.9/test/commandlineCLI-027s.ref000066400000000000000000000072141416363131000201470ustar00rootroot00000000000000// -*- go -*- //////////////////////////////////////////////////////////////////////////// // Program: redo // Purpose: global option redo //////////////////////////////////////////////////////////////////////////// package main import ( "github.com/mkideal/cli" ) //////////////////////////////////////////////////////////////////////////// // redo type rootT struct { cli.Helper Host string `cli:"H,host" usage:"host address" dft:"$HOST"` Port int `cli:"p,port" usage:"listening port" dft:"80"` } var root = &cli.Command{ Name: "redo", Desc: "global option redo", Text: " redo global option via automatic code-gen", Global: true, Argv: func() interface{} { return new(rootT) }, Fn: redo, NumArg: cli.ExactN(1), } // func main() { // cli.SetUsageStyle(cli.ManualStyle) // up-down, for left-right, use NormalStyle // //NOTE: You can set any writer implements io.Writer // // default writer is os.Stdout // if err := cli.Root(root, // cli.Tree(buildDef), // cli.Tree(installDef), // cli.Tree(publishDef)).Run(os.Args[1:]); err != nil { // fmt.Fprintln(os.Stderr, err) // } // fmt.Println("") // } // func redo(ctx *cli.Context) error { // ctx.JSON(ctx.RootArgv()) // ctx.JSON(ctx.Argv()) // fmt.Println() // return nil // } //////////////////////////////////////////////////////////////////////////// // build // func buildCLI(ctx *cli.Context) error { // rootArgv := ctx.RootArgv().(*rootT) // argv := ctx.Argv().(*buildT) // fmt.Printf("[build]:\n %+v\n %+v\n %v\n", rootArgv, argv, ctx.Args()) // return nil // } type buildT struct { Self *buildT `cli:"c,config" usage:"config file" json:"-" parser:"jsonfile" dft:"build.json"` Dir string `cli:"dir" usage:"source code root dir" dft:"./"` Suffix string `cli:"suffix" usage:"source file suffix" dft:".go,.c,.s"` Out string `cli:"o,out" usage:"output filename"` } var buildDef = &cli.Command{ Name: "build", Desc: "Build the network application", Text: "Usage:\n redo build [Options] Arch(i386|amd64)", Argv: func() interface{} { t := new(buildT); t.Self = t; return t }, Fn: buildCLI, NumArg: cli.ExactN(1), CanSubRoute: true, } //////////////////////////////////////////////////////////////////////////// // install // func installCLI(ctx *cli.Context) error { // rootArgv := ctx.RootArgv().(*rootT) // argv := ctx.Argv().(*installT) // fmt.Printf("[install]:\n %+v\n %+v\n %v\n", rootArgv, argv, ctx.Args()) // return nil // } type installT struct { Dir string `cli:"dir" usage:"source code root dir" dft:"./"` Suffix string `cli:"suffix" usage:"source file suffix" dft:".go,.c,.s"` Out string `cli:"o,out" usage:"output filename"` } var installDef = &cli.Command{ Name: "install", Desc: "Install the network application", Text: "Usage:\n redo install [Options] package [package...]", Argv: func() interface{} { return new(installT) }, Fn: installCLI, NumArg: cli.AtLeast(1), CanSubRoute: true, } //////////////////////////////////////////////////////////////////////////// // publish // func publishCLI(ctx *cli.Context) error { // rootArgv := ctx.RootArgv().(*rootT) // argv := ctx.Argv().(*publishT) // fmt.Printf("[publish]:\n %+v\n %+v\n %v\n", rootArgv, argv, ctx.Args()) // return nil // } type publishT struct { Dir string `cli:"*d,dir" usage:"publish dir"` Suffix string `cli:"suffix" usage:"source file suffix" dft:".go,.c,.s"` Out string `cli:"o,out" usage:"output filename"` List bool `cli:"l,list" usage:"list all sub commands"` } var publishDef = &cli.Command{ Name: "publish", Desc: "Publish the network application", Argv: func() interface{} { return new(publishT) }, Fn: publishCLI, NumOption: cli.AtLeast(1), } easygen-5.1.9/test/commandlineCLI-027s.yaml000066400000000000000000000053441416363131000203370ustar00rootroot00000000000000# program name, name for the executable ProgramName: redo # package name # - For standalone program that does not belong to any package, e.g., # https://github.com/suntong/easygen/blob/7791e4f0e5605543d27da1671a21376cdb9dcf2a/easygen/easygen.go # just ignore the first line, the `package` output, and copy the rest # - If you don't mind using a separated file to handle commandline paramters, # then name the package as "main". see the spin-out "TF-minus1.go" file under # https://github.com/suntong/easygen/tree/d1ab0b5fe80ddac57fe9ef51f6ccb3ab998cd5ee # - If you are using it in a pacakge, look no further than # https://github.com/suntong/easygen/blob/master/easygenapi/config.go # which was a direct dump: easygen test/commandlineFlag | gofmt > easygenapi/config.go # PackageName: main Name: redo Desc: "global option redo" Text: ' redo global option via automatic code-gen' Global: true NumArg: cli.ExactN(1) Options: - Name: Host Type: string Flag: H,host Usage: host address Value: "$HOST" - Name: Port Type: int Flag: p,port Usage: listening port Value: 80 Command: - Name: build Desc: "Build the network application" Text: 'Usage:\n redo build [Options] Arch(i386|amd64)' NumArg: cli.ExactN(1) Self: true Options: - Name: Self Type: '*buildT' Flag: c,config Usage: config file Value: build.json - Name: Dir Type: string Flag: dir Value: "./" Usage: source code root dir - Name: Suffix Type: string Flag: suffix Value: ".go,.c,.s" Usage: "source file suffix" - Name: Out Type: string Flag: o,out Usage: "output filename" - Name: install Desc: "Install the network application" Text: 'Usage:\n redo install [Options] package [package...]' NumArg: cli.AtLeast(1) Options: - Name: Dir Type: string Flag: dir Value: "./" Usage: source code root dir - Name: Suffix Type: string Flag: suffix Value: ".go,.c,.s" Usage: "source file suffix" - Name: Out Type: string Flag: o,out Usage: "output filename" - Name: publish Desc: "Publish the network application" NumOption: cli.AtLeast(1) Options: - Name: Dir Type: string Flag: '*d,dir' Usage: publish dir - Name: Suffix Type: string Flag: suffix Value: ".go,.c,.s" Usage: "source file suffix" - Name: Out Type: string Flag: o,out Usage: "output filename" - Name: List Type: bool Flag: l,list Usage: "list all sub commands" easygen-5.1.9/test/commandlineCV.ref000066400000000000000000000013361416363131000173560ustar00rootroot00000000000000 flags.Bool("debug", false, "Turn on debugging.") viper.BindPFlag("debug", flags.Lookup("debug")) flags.String("addr", "localhost:5002", "Address of the service.") viper.BindPFlag("addr", flags.Lookup("addr")) flags.String("smtp-addr", "localhost:25", "Address of the SMTP server.") viper.BindPFlag("smtp-addr", flags.Lookup("smtp-addr")) flags.String("smtp-user", "", "User for the SMTP server.") viper.BindPFlag("smtp-user", flags.Lookup("smtp-user")) flags.String("smtp-password", "", "Password for the SMTP server.") viper.BindPFlag("smtp-password", flags.Lookup("smtp-password")) flags.String("email-from", "noreply@abc.com", "The from email address.") viper.BindPFlag("email-from", flags.Lookup("email-from")) easygen-5.1.9/test/commandlineCV.tmpl000066400000000000000000000002141416363131000175500ustar00rootroot00000000000000{{range .Options}} flags.{{.Type}}("{{.Name}}", {{.Value}}, "{{.Usage}}") viper.BindPFlag("{{.Name}}", flags.Lookup("{{.Name}}")) {{end}} easygen-5.1.9/test/commandlineCV.yaml000066400000000000000000000011111416363131000175330ustar00rootroot00000000000000Options: - Name: debug Type: Bool Value: false Usage: Turn on debugging. - Name: addr Type: String Value: '"localhost:5002"' Usage: Address of the service. - Name: smtp-addr Type: String Value: '"localhost:25"' Usage: Address of the SMTP server. - Name: smtp-user Type: String Value: '""' Usage: User for the SMTP server. - Name: smtp-password Type: String Value: '""' Usage: Password for the SMTP server. - Name: email-from Type: String Value: '"noreply@abc.com"' Usage: The from email address. easygen-5.1.9/test/commandlineCVFull.ref000066400000000000000000000031001416363131000201700ustar00rootroot00000000000000func init() { viper.SetEnvPrefix("DISPATCH") viper.AutomaticEnv() /* When AutomaticEnv called, Viper will check for an environment variable any time a viper.Get request is made. It will apply the following rules. It will check for a environment variable with a name matching the key uppercased and prefixed with the EnvPrefix if set. */ flags := mainCmd.Flags() flags.Bool("Debug", false, "Turn on debugging.") viper.BindPFlag("Debug", flags.Lookup("Debug")) flags.String("addr", "localhost:5002", "Address of the service.") viper.BindPFlag("addr", flags.Lookup("addr")) flags.String("smtp-addr", "localhost:25", "Address of the SMTP server.") viper.BindPFlag("smtp-addr", flags.Lookup("smtp-addr")) flags.String("smtp-user", "", "User for the SMTP server.") viper.BindPFlag("smtp-user", flags.Lookup("smtp-user")) flags.String("smtp-password", "", "Password for the SMTP server.") viper.BindPFlag("smtp-password", flags.Lookup("smtp-password")) flags.String("email-from", "noreply@abc.com", "The from email address.") viper.BindPFlag("email-from", flags.Lookup("email-from")) // Viper supports reading from yaml, toml and/or json files. Viper can // search multiple paths. Paths will be searched in the order they are // provided. Searches stopped once Config File found. viper.SetConfigName("CommandLineCV") // name of config file (without extension) viper.AddConfigPath("/tmp") viper.AddConfigPath(".") err := viper.ReadInConfig() if err != nil { println("No config file found. Using built-in defaults.") } } easygen-5.1.9/test/commandlineCVFull.tmpl000066400000000000000000000017631416363131000204050ustar00rootroot00000000000000func init() { viper.SetEnvPrefix("{{.CmdPrefix}}") viper.AutomaticEnv() /* When AutomaticEnv called, Viper will check for an environment variable any time a viper.Get request is made. It will apply the following rules. It will check for a environment variable with a name matching the key uppercased and prefixed with the EnvPrefix if set. */ flags := {{.CmdMain}}.Flags() {{range .Options}} flags.{{.Type}}("{{.Name}}", {{.Value}}, "{{.Usage}}") viper.BindPFlag("{{.Name}}", flags.Lookup("{{.Name}}")) {{end}} // Viper supports reading from yaml, toml and/or json files. Viper can // search multiple paths. Paths will be searched in the order they are // provided. Searches stopped once Config File found. viper.SetConfigName("{{.ConfigName}}") // name of config file (without extension) {{range .ConfigPath}} viper.AddConfigPath("{{.}}"){{end}} err := viper.ReadInConfig() if err != nil { println("No config file found. Using built-in defaults.") } } easygen-5.1.9/test/commandlineCVFull.yaml000066400000000000000000000012461416363131000203670ustar00rootroot00000000000000CmdMain: mainCmd CmdPrefix: DISPATCH Options: - Name: Debug Type: Bool Value: false Usage: Turn on debugging. - Name: addr Type: String Value: '"localhost:5002"' Usage: Address of the service. - Name: smtp-addr Type: String Value: '"localhost:25"' Usage: Address of the SMTP server. - Name: smtp-user Type: String Value: '""' Usage: User for the SMTP server. - Name: smtp-password Type: String Value: '""' Usage: Password for the SMTP server. - Name: email-from Type: String Value: '"noreply@abc.com"' Usage: The from email address. ConfigName: CommandLineCV ConfigPath: - /tmp - . easygen-5.1.9/test/commandlineFlag000066400000000000000000000001671416363131000171450ustar00rootroot00000000000000something invalid for .yaml file, to verify that it is preferable to pick the .yaml file with the full extension first easygen-5.1.9/test/commandlineFlag.ref000066400000000000000000000067601416363131000177250ustar00rootroot00000000000000// !!! !!! // WARNING: Code automatically generated. Editing discouraged. // !!! !!! package easygenapi import ( "flag" "fmt" "os" ) //////////////////////////////////////////////////////////////////////////// // Constant and data type/structure definitions const progname = "easygen" // os.Args[0] // The Options struct defines the structure to hold the commandline values type Options struct { HTML bool // treat the template file as html instead of text TemplateStr string // template string (in text) TemplateFile string // .tmpl (comma-separated) template file `name(s)` (default: same as .yaml file) ExtYaml string // `extension` of yaml file ExtTmpl string // `extension` of template file StrFrom string // replace from, the from string used for the replace function StrTo string // replace to, the to string used for the replace function Debug int // debugging `level` } //////////////////////////////////////////////////////////////////////////// // Global variables definitions // Opts holds the actual values from the command line parameters var Opts Options //////////////////////////////////////////////////////////////////////////// // Commandline definitions func initVars() { // set default values for command line parameters flag.BoolVar(&Opts.HTML, "html", false, "treat the template file as html instead of text") flag.StringVar(&Opts.TemplateStr, "ts", "", "template string (in text)") flag.StringVar(&Opts.TemplateFile, "f", "", ".tmpl (comma-separated) template file `name(s)` (default: same as .yaml file)") flag.StringVar(&Opts.TemplateFile, "tf", "", ".tmpl (comma-separated) template file `name(s)` (default: same as .yaml file)") flag.StringVar(&Opts.ExtYaml, "ey", ".yaml", "`extension` of yaml file") flag.StringVar(&Opts.ExtTmpl, "et", ".tmpl", "`extension` of template file") flag.StringVar(&Opts.StrFrom, "rf", "", "replace from, the from string used for the replace function") flag.StringVar(&Opts.StrTo, "rt", "", "replace to, the to string used for the replace function") flag.IntVar(&Opts.Debug, "d", 0, "debugging `level`") flag.IntVar(&Opts.Debug, "debug", 0, "debugging `level`") } func initVals() { exists := false // Now override those default values from environment variables if _, exists = os.LookupEnv("EASYGEN_HTML"); Opts.HTML|| exists { Opts.HTML = true } if len(Opts.TemplateStr) == 0 || len(os.Getenv("EASYGEN_TS")) != 0 { Opts.TemplateStr = os.Getenv("EASYGEN_TS") } if len(Opts.TemplateFile) == 0 || len(os.Getenv("EASYGEN_F")) != 0 { Opts.TemplateFile = os.Getenv("EASYGEN_F") } if len(Opts.TemplateFile) == 0 || len(os.Getenv("EASYGEN_TF")) != 0 { Opts.TemplateFile = os.Getenv("EASYGEN_TF") } if len(Opts.ExtYaml) == 0 || len(os.Getenv("EASYGEN_EY")) != 0 { Opts.ExtYaml = os.Getenv("EASYGEN_EY") } if len(Opts.ExtTmpl) == 0 || len(os.Getenv("EASYGEN_ET")) != 0 { Opts.ExtTmpl = os.Getenv("EASYGEN_ET") } if len(Opts.StrFrom) == 0 || len(os.Getenv("EASYGEN_RF")) != 0 { Opts.StrFrom = os.Getenv("EASYGEN_RF") } if len(Opts.StrTo) == 0 || len(os.Getenv("EASYGEN_RT")) != 0 { Opts.StrTo = os.Getenv("EASYGEN_RT") } } // Usage function shows help on commandline usage func Usage() { fmt.Fprintf(os.Stderr, "\nUsage:\n %s [flags] YamlFileName [YamlFileName...]\n\nFlags:\n\n", progname) flag.PrintDefaults() fmt.Fprintf(os.Stderr, "\nYamlFileName(s): The name for the .yaml data and .tmpl template file\n\tOnly the name part, without extension. Can include the path as well.\n") os.Exit(0) } easygen-5.1.9/test/commandlineFlag.tmpl000066400000000000000000000052401416363131000201150ustar00rootroot00000000000000// !!! !!! // WARNING: Code automatically generated. Editing discouraged. // !!! !!! package {{.PackageName}} import ( "flag" "fmt" "os" ) //////////////////////////////////////////////////////////////////////////// // Constant and data type/structure definitions const progname = "{{.ProgramName}}" // os.Args[0] // The {{.StructName}} struct defines the structure to hold the commandline values type {{.StructName}} struct { {{range .Options}}{{if ne .Name "SEPARATOR" }} {{.Name}} {{.Type}} // {{.Usage}}{{end}}{{end}} } //////////////////////////////////////////////////////////////////////////// // Global variables definitions // {{.StructVar}} holds the actual values from the command line parameters var {{.StructVar}} {{.StructName}} //////////////////////////////////////////////////////////////////////////// // Commandline definitions func initVars() { // set default values for command line parameters{{range .Options}}{{if eq .Name "SEPARATOR" }} {{else}}{{if (stringsContains .Flag ",")}}{{$cf := .}}{{range (stringsSplit .Flag ",")}} flag.{{clk2uc $cf.Type}}Var(&{{$.StructVar}}.{{$cf.Name}}, "{{.}}", {{$cf.Value}}, "{{$cf.Usage}}"){{end}}{{else}} flag.{{clk2uc .Type}}Var(&{{$.StructVar}}.{{.Name}}, "{{.Flag}}", {{.Value}}, "{{.Usage}}"){{end}}{{end}}{{end}} } func initVals() { exists := false // Now override those default values from environment variables{{range .Options}}{{if eq .Name "SEPARATOR" }} {{else}}{{$envVar := printf "%s_%s" (clk2ss $.ProgramName) (clk2ss .Flag)}}{{if eq .Type "string" }}{{if (stringsContains .Flag ",")}}{{$cf := .}}{{range (stringsSplit .Flag ",")}}{{$envVar := printf "%s_%s" (clk2ss $.ProgramName) (clk2ss .)}} if len({{$.StructVar}}.{{$cf.Name}}) == 0 || len(os.Getenv("{{$envVar}}")) != 0 { {{$.StructVar}}.{{$cf.Name}} = os.Getenv("{{$envVar}}") }{{end}}{{else}} if len({{$.StructVar}}.{{.Name}}) == 0 || len(os.Getenv("{{$envVar}}")) != 0 { {{$.StructVar}}.{{.Name}} = os.Getenv("{{$envVar}}") }{{end}}{{else}}{{if eq .Type "bool" }} if _, exists = os.LookupEnv("{{$envVar}}"); {{$.StructVar}}.{{.Name}}|| exists { {{$.StructVar}}.{{.Name}} = true }{{end}}{{end}}{{end}}{{end}} } {{if eqf .UsageSummary "True" }} const usageSummary = "{{range .Options}}{{if eq .Name "SEPARATOR" }}\n{{else}}{{$envVar := printf "%s_%s" (clk2ss $.ProgramName) (clk2ss .Flag)}} -{{.Flag}}\t{{.Usage}} ({{$envVar}})\n{{end}}{{end}}\nDetails:\n\n" {{end}} // Usage function shows help on commandline usage func Usage() { fmt.Fprintf(os.Stderr, "{{.UsageLead}}", progname){{if eq .UsageSummary "TRUE" }} fmt.Fprintf(os.Stderr, usageSummary){{end}} flag.PrintDefaults() fmt.Fprintf(os.Stderr, "{{.UsageEnd}}") os.Exit(0) } easygen-5.1.9/test/commandlineFlag.yaml000066400000000000000000000043501416363131000201040ustar00rootroot00000000000000# program name, name for the executable ProgramName: easygen # package name # - For standalone program that does not belong to any package, e.g., # https://github.com/suntong/easygen/blob/7791e4f0e5605543d27da1671a21376cdb9dcf2a/easygen/easygen.go # just ignore the first line, the `package` output, and copy the rest # - If you don't mind using a separated file to handle commandline paramters, # then name the package as "main". see the spin-out "TF-minus1.go" file under # https://github.com/suntong/easygen/tree/d1ab0b5fe80ddac57fe9ef51f6ccb3ab998cd5ee # - If you are using it in a pacakge, look no further than # https://github.com/suntong/easygen/blob/master/easygenapi/config.go # which was a direct dump: easygen test/commandlineFlag | gofmt > easygenapi/config.go # PackageName: easygenapi # Name of the structure to hold the values for/from commandline StructName: Options # The actual variable that hold the commandline paramter values StructVar: Opts Options: - Name: HTML Type: bool Flag: html Value: false Usage: treat the template file as html instead of text - Name: TemplateStr Type: string Flag: ts Value: '""' Usage: "template string (in text)" - Name: TemplateFile Type: string Flag: f,tf Value: '""' Usage: ".tmpl (comma-separated) template file `name(s)` (default: same as .yaml file)" - Name: ExtYaml Type: string Flag: ey Value: '".yaml"' Usage: "`extension` of yaml file" - Name: ExtTmpl Type: string Flag: et Value: '".tmpl"' Usage: "`extension` of template file" - Name: StrFrom Type: string Flag: rf Value: '""' Usage: "replace from, the from string used for the replace function" - Name: StrTo Type: string Flag: rt Value: '""' Usage: "replace to, the to string used for the replace function" - Name: Debug Type: int Flag: d,debug Value: 0 Usage: "debugging `level`" # Whether to use the USAGE_SUMMARY in Usage help UsageSummary: "" UsageLead: "\\nUsage:\\n %s [flags] YamlFileName [YamlFileName...]\\n\\nFlags:\\n\\n" UsageEnd: "\\nYamlFileName(s): The name for the .yaml data and .tmpl template file\\n\\tOnly the name part, without extension. Can include the path as well.\\n" easygen-5.1.9/test/enum_c-header.tmpl000066400000000000000000000005121416363131000175260ustar00rootroot00000000000000{{- if .EnumComments -}} {{- range .EnumComments }} // {{.}} {{- end -}} {{- end }} enum {{.EnumName}} { {{- range $i, $val := .Values -}} {{- if .Comment }} {{- if gt $i 0 }} {{ end }} // {{.Comment}} {{- end -}} {{- if .Value }} {{ .Name }} = {{.Value }}, {{- else }} {{ .Name }}, {{- end -}} {{- end }} }; easygen-5.1.9/test/enum_c-source.tmpl000066400000000000000000000016611416363131000176040ustar00rootroot00000000000000{{/* Randomly pick the first element if no EnumDefault is set. */}} {{ with $DEFAULT := or (.EnumDefault) (index .Values 0 "Name") -}} /** Try to extract an enum {{$.EnumName}} value from @str; fall back to "{{$DEFAULT}}". */ const enum {{$.EnumName}} str_to_{{$.EnumName}}(const char const *str) { {{- range $i, $val := $.Values }} {{ if gt $i 0 -}}} else {{end -}}if (strcasecmp(str, "{{ if .String }}{{.String}}{{else}}{{.Name}}{{end}}") == 0) { return {{ .Name }}; {{- range .AltString }} } else if (strcasecmp(str, "{{.}}") == 0) { return {{ $val.Name }}; {{- end }} {{- if eq (len $.Values|minus1) ($i)}}{{/* Sentinel */}} } {{- end -}} {{- end }} return {{$DEFAULT}}; } {{- end }} /** Stringer function for {{.EnumName}}. */ const char * {{.EnumName}}_to_str(const enum {{.EnumName}} val) { switch (val) { {{- range .Values }} case {{.Name}}: return "{{ if .String }}{{.String}}{{else}}{{.Name}}{{end}}"; {{- end }} } } easygen-5.1.9/test/enum_c-to_str.tmpl000066400000000000000000000003661416363131000176170ustar00rootroot00000000000000 /** Stringer function for {{.EnumName}}. */ const char * {{.EnumName}}_to_str(const enum {{.EnumName}} val) { switch (val) { {{- range .Values }} case {{.Name}}: return "{{ if .String }}{{.String}}{{else}}{{.Name}}{{end}}"; {{- end }} } } easygen-5.1.9/test/enum_go.tmpl000066400000000000000000000062641416363131000164750ustar00rootroot00000000000000{{/* NOTE: This produces the _same_ enum values as for C enums, as long the input format is one of: a) enum first { a, b, c} b) enum second { a = 0x5, b, c } The first is handled by iota, the other uses https://golang.org/ref/spec#ConstSpec Currently NOT supported is a mixed form: enum mixed { a, b=0x20, c, d=0x30, e } */}} import ( "database/sql/driver" "encoding/json" "fmt" ) {{ if .EnumComments -}} {{- range .EnumComments -}} // {{.}} {{- end -}} {{- else -}} // {{ cls2uc .EnumName }} is the representation of {{.EnumName -}} {{- end }} type {{ cls2uc .EnumName}} uint32 const ( {{- range $i, $j := .Values -}} {{- if .Comment }} {{- if gt $i 0 }}{{/* insert newline */}} {{ end }} // {{.Comment}} {{- end -}} {{- if eq $i 0 }} {{ .Name }} {{ cls2uc $.EnumName }} = {{if .Value}}{{.Value}} + {{end}}iota {{- else }} {{ .Name }}{{if .Value}} {{ cls2uc $.EnumName }} = {{ .Value }}{{end}} {{- end }} {{- end }} ) {{ with $type := cls2uc $.EnumName -}} {{ with $m := index (clk2ls $type) 0 | printf "%c" -}} // Implements encoding.TextMarshaler func ({{$m}} {{$type}}) MarshalText() ([]byte, error) { switch {{$m}} { {{- range $.Values }} case {{.Name}}: return []byte("{{if .String}}{{.String}}{{else}}{{.Name}}{{end}}"), nil {{- end }} } return nil, fmt.Errorf("invalid {{$type}} %d", {{$m}}) } // Implements encoding.TextUnmarshaler func ({{$m}} *{{$type}}) UnmarshalText(data []byte) error { switch string(data) { {{- range $i, $val := $.Values }} case "{{ if .String }}{{.String}}{{else}}{{.Name}}{{end}}": *{{$m}} = {{ .Name }} {{- range .AltString }} case "{{.}}": *{{$m}} = {{ $val.Name }} {{- end }} {{- end }} default: return fmt.Errorf("invalid {{$type}} %q", string(data)) } return nil } // Implements fmt.Stringer func ({{$m}} {{$type}}) String() string { if b, err := {{$m}}.MarshalText(); err != nil { return err.Error() } else { return string(b) } } // Implements database/sql/driver.Valuer func ({{$m}} {{$type}}) Value() (driver.Value, error) { return {{$m}}.String(), nil } // Implements database/sql.Scanner func ({{$m}} *{{$type}}) Scan(src interface{}) error { switch src := src.(type) { case int64: *{{$m}} = {{$type}}(src) return nil case []byte: return {{$m}}.UnmarshalText(src) case string: return {{$m}}.UnmarshalText([]byte(src)) } return fmt.Errorf("unable to convert %T to {{$type}}", src) } // Implements json.Marshaler func ({{$m}} {{$type}}) MarshalJSON() ([]byte, error) { return json.Marshal({{$m}}.String()) } // Implements json.Unmarshaler func ({{$m}} *{{$type}}) UnmarshalJSON(data []byte) error { var s string if err := json.Unmarshal(data, &s); err != nil { return fmt.Errorf("failed to parse '%s' as {{$type}}: %s", string(data), err) } return {{$m}}.UnmarshalText([]byte(s)) } // Implements yaml.Marshaler func ({{$m}} {{$type}}) MarshalYAML() (interface{}, error) { return {{$m}}.String(), nil } // Implements yaml.Unmarshaler func ({{$m}} *{{$type}}) UnmarshalYAML(unmarshal func(interface{}) error) error { var s string if err := unmarshal(&s); err != nil { return fmt.Errorf("failed to unmarshal {{$type}} from YAML: %s", err) } return {{$m}}.UnmarshalText([]byte(s)) } {{- end}} {{- end}} easygen-5.1.9/test/enum_java.tmpl000066400000000000000000000006361416363131000170060ustar00rootroot00000000000000{{- if .EnumComments -}} /** {{- range .EnumComments }} * {{.}} {{- end }} */ {{- else -}} /** {{ cls2uc .EnumName }} is the representation of {{.EnumName}} */ {{- end }} public enum {{cls2uc .EnumName}} { {{- range $i, $val := .Values -}} {{- if .Comment }} {{- if gt $i 0 }} {{ end }} // {{.Comment}} {{- end }} {{ .Name }}{{if eq (len $.Values|minus1) ($i)}};{{else}},{{end}} {{- end }} } easygen-5.1.9/test/enum_multiple_data_files.ref000066400000000000000000000002001416363131000216560ustar00rootroot00000000000000 // Simplified enumeration of available RAID devices enum raid_type { RAID0 = 100, RAID1, }; enum raid_driver { HW, SW, }; easygen-5.1.9/test/enum_multiple_template_and_data.ref000066400000000000000000000007761416363131000232330ustar00rootroot00000000000000 // Simplified enumeration of available RAID devices enum raid_type { RAID0 = 100, RAID1, }; /** Stringer function for raid_type. */ const char * raid_type_to_str(const enum raid_type val) { switch (val) { case RAID0: return "RAID0"; case RAID1: return "RAID1"; } } enum raid_driver { HW, SW, }; /** Stringer function for raid_driver. */ const char * raid_driver_to_str(const enum raid_driver val) { switch (val) { case HW: return "Hardware-RAID"; case SW: return "Software-RAID"; } } easygen-5.1.9/test/enum_multiple_template_files.ref000066400000000000000000000012501416363131000225660ustar00rootroot00000000000000 // Simplified enumeration of available RAID devices enum raid_type { RAID0 = 100, RAID1, }; /** Try to extract an enum raid_type value from @str; fall back to "RAID0". */ const enum raid_type str_to_raid_type(const char const *str) { if (strcasecmp(str, "RAID0") == 0) { return RAID0; } else if (strcasecmp(str, "RAID-0") == 0) { return RAID0; } else if (strcasecmp(str, "RAID1") == 0) { return RAID1; } else if (strcasecmp(str, "RAID-1") == 0) { return RAID1; } return RAID0; } /** Stringer function for raid_type. */ const char * raid_type_to_str(const enum raid_type val) { switch (val) { case RAID0: return "RAID0"; case RAID1: return "RAID1"; } } easygen-5.1.9/test/example.yaml000066400000000000000000000002711416363131000164550ustar00rootroot00000000000000ColorRed: red ColorBlue: blue ColorWhite: white Colorlist: red blue white Colors: - red - blue - white Cars: - Make: Ford Module: T1 - Make: GM Module: T2 easygen-5.1.9/test/html-Checkbox-Group.tmpl000066400000000000000000000111601416363131000206150ustar00rootroot00000000000000 Multiple Checkbox Select/Deselect - DEMO

Multiple Checkbox Group Select/Deselect - DEMO

This extends the Multiple Checkbox Select/Deselect Using JQuery which has an Online Demo here, which demonstrates the functionality of selecting multiple items from a list to process them.

This extends the demo further -- it now includes several groups instead merely a single one.

{{range .phone}}{{$phoneType := clk2ls .Type}} {{range .Modules}} {{end}} {{end}}
{{.Type}} Cell phones
{{.}}

FYI, this full working html source code is generated automatically by easygen with this template. This html test code is the reason that I wrote easygen, to make it easy to write whatever test cases whatever the way I like. Further, changing is a breeze, you just change once and the script will do a "replace-all" for you, however complicated it can be. No any other tools can do such complicated "replace-all" for you.

easygen-5.1.9/test/html-Checkbox-Group.yaml000066400000000000000000000004411416363131000206030ustar00rootroot00000000000000phone: - Type: Android Modules: - Samsung Galaxy - Droid X - HTC Desire - Type: iPhone Modules: - Apple iPhone 4 - Apple iPhone 5 - Apple iPhone 6 - Type: BlackBerry Modules: - BlackBerry Bold 9650 - BlackBerry 10 easygen-5.1.9/test/html-Checkbox-Post.tmpl000066400000000000000000000055351416363131000204570ustar00rootroot00000000000000 Multiple Checkbox Select/Deselect - DEMO

Multiple Checkbox Group Select/Deselect - DEMO

{{range .phone}}{{$phoneType := clk2ls .Type}} {{range .Modules}} {{end}} {{end}}
{{.Type}} Cell phones
{{.}}

easygen-5.1.9/test/html-Table-RWD.html000066400000000000000000000065651416363131000174630ustar00rootroot00000000000000

Android Cell phones

Module A Module B Module C
Samsung Galaxy A Samsung Galaxy B Samsung Galaxy C
Droid X A Droid X B Droid X C
HTC Desire A HTC Desire B HTC Desire C

iPhone Cell phones

Module A Module B Module C
Apple iPhone 4 A Apple iPhone 4 B Apple iPhone 4 C
Apple iPhone 5 A Apple iPhone 5 B Apple iPhone 5 C
Apple iPhone 6 A Apple iPhone 6 B Apple iPhone 6 C

BlackBerry Cell phones

Module A Module B Module C
BlackBerry Bold 9650 A BlackBerry Bold 9650 B BlackBerry Bold 9650 C
BlackBerry 10 A BlackBerry 10 B BlackBerry 10 C
easygen-5.1.9/test/html-Table-RWD.tmpl000066400000000000000000000046421416363131000174650ustar00rootroot00000000000000 {{range .phone}}{{$phoneType := clk2ls .Type}}

{{.Type}} Cell phones

{{range .Modules}} {{end}}
Module A Module B Module C
{{.}} A {{.}} B {{.}} C
{{end}} easygen-5.1.9/test/jq-test_0.go_000066400000000000000000000036751416363131000164450ustar00rootroot00000000000000// Copyright (c) 2016 Matt Ho // // Test cases code automatically generated by easygen: // https://github.com/go-easygen/easygen // Editing discouraged. // Test cases code Copyright (c) 2016 of project // https://github.com/stedolan/jq // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jq_test import ( "testing" "github.com/savaki/jq" ) func TestParse(t *testing.T) { testCases := map[string]struct { In string Op string Expected string HasError bool }{ // Tests are groups of three lines: program, input, expected output // Blank lines and lines starting with # are ignored // // Simple value tests to check parser. Input is irrelevant // "simple": { In: `{"hello":"world"}`, Op: `.hello`, Expected: `"world"`, }, "nested": { In: `{"a":{"b":"world"}}`, Op: `.a.b`, Expected: `"world"`, }, "index": { In: `["a","b","c"]`, Op: `.[1]`, Expected: `"b"`, }, "range": { In: `["a","b","c"]`, Op: `.[1:2]`, Expected: `["b","c"]`, }, } for label, tc := range testCases { t.Run(label, func(t *testing.T) { op, err := jq.Parse(tc.Op) if err != nil { t.FailNow() } data, err := op.Apply([]byte(tc.In)) if tc.HasError { if err == nil { t.FailNow() } } else { if string(data) != tc.Expected { t.FailNow() } if err != nil { t.FailNow() } } }) } } easygen-5.1.9/test/jq-test_0.yaml000066400000000000000000000013121416363131000166250ustar00rootroot00000000000000Cases: - Comment: Str: 'Tests are groups of three lines: program, input, expected output' - Comment: Str: 'Blank lines and lines starting with # are ignored' - Comment: Str: - Comment: Str: 'Simple value tests to check parser. Input is irrelevant' - Comment: Str: - TestCase: Name: simple Op: '.hello' In: '{"hello":"world"}' Out: '"world"' - TestCase: Name: nested Op: '.a.b' In: '{"a":{"b":"world"}}' Out: '"world"' - TestCase: Name: index Op: '.[1]' In: '["a","b","c"]' Out: '"b"' - TestCase: Name: range Op: '.[1:2]' In: '["a","b","c"]' Out: '["b","c"]' easygen-5.1.9/test/jq-test_1.go_000066400000000000000000001226001416363131000164340ustar00rootroot00000000000000// Copyright (c) 2016 Matt Ho // // Test cases code automatically generated by easygen: // https://github.com/go-easygen/easygen // Editing discouraged. // Test cases code Copyright (c) 2016 of project // https://github.com/stedolan/jq // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jq_test import ( "testing" "github.com/savaki/jq" ) func TestParse(t *testing.T) { testCases := map[string]struct { In string Op string Expected string HasError bool }{ // Tests are groups of three lines: program, input, expected output // Blank lines and lines starting with # are ignored // // Simple value tests to check parser. Input is irrelevant // "case1": { In: `null`, Op: `true`, Expected: `true`, }, "case2": { In: `null`, Op: `false`, Expected: `false`, }, "case3": { In: `42`, Op: `null`, Expected: `null`, }, "case4": { In: `null`, Op: `1`, Expected: `1`, }, "case5": { In: `null`, Op: `-1`, Expected: `-1`, }, // FIXME: much more number testing needed "case6": { In: `null`, Op: `{}`, Expected: `{}`, }, "case7": { In: `null`, Op: `[]`, Expected: `[]`, }, "case8": { In: `null`, Op: `{x: -1}`, Expected: `{"x": -1}`, }, // The input line starts with a 0xFEFF (byte order mark) codepoint // No, there is no reason to have a byte order mark in UTF8 text. // But apparently people do, so jq shouldnt break on it. // We test escapes by matching them against Unicode codepoints // FIXME: more tests needed for weird unicode stuff (e.g. utf16 pairs) "case9": { In: `null`, Op: `"Aa\r\n\t\b\f\u03bc"`, Expected: `"Aa\u000d\u000a\u0009\u0008\u000c\u03bc"`, }, "case10": { In: `"Aa\r\n\t\b\f\u03bc"`, Op: `.`, Expected: `"Aa\u000d\u000a\u0009\u0008\u000c\u03bc"`, }, "case11": { In: `null`, Op: `"inter\("pol" + "ation")"`, Expected: `"interpolation"`, }, "case12": { In: `<>&'" `, Op: `@text,@json,([1,.] | (@csv, @tsv)),@html,@uri,@sh,@base64`, Expected: `<>&'" `, }, // regression test for #436 "case13": { In: `"foÃŗbar\n"`, Op: `@base64`, Expected: `"Zm/Ds2Jhcgo="`, }, "case14": { In: `"\u03bc"`, Op: `@uri`, Expected: `"%CE%BC"`, }, "case15": { In: `""`, Op: `@html "\(.)"`, Expected: `"<script>hax</script>"`, }, "case16": { In: `["foo", 1, ["a", 1, "b", 2, {"foo":"bar"}]]`, Op: `[.[]|tojson|fromjson]`, Expected: `["foo",1,["a",1,"b",2,{"foo":"bar"}]]`, }, // // Dictionary construction syntax // "case17": { In: `null`, Op: `{a: 1}`, Expected: `{"a":1}`, }, "case18": { In: `{"a":1, "b":2, "c":3, "d":"c"}`, Op: `{a,b,(.d):.a,e:.b}`, Expected: `{"a":1, "b":2, "c":1, "e":2}`, }, "case19": { In: `{"a":1, "b":2, "c":3, "a$2":4}`, Op: `{"a",b,"a$\(1+1)"}`, Expected: `{"a":1, "b":2, "a$2":4}`, }, // // Field access, piping // "case20": { In: `{"foo": 42, "bar": 43}`, Op: `.foo`, Expected: `42`, }, "case21": { In: `{"foo": {"bar": 42}, "bar": "badvalue"}`, Op: `.foo | .bar`, Expected: `42`, }, "case22": { In: `{"foo": {"bar": 42}, "bar": "badvalue"}`, Op: `.foo.bar`, Expected: `42`, }, "case23": { In: `{"foo_bar": 2}`, Op: `.foo_bar`, Expected: `2`, }, "case24": { In: `{"foo": {"bar": 42}, "bar": "badvalue"}`, Op: `.["foo"].bar`, Expected: `42`, }, "case25": { In: `{"foo": {"bar": 20}}`, Op: `."foo"."bar"`, Expected: `20`, }, "case26": { In: `[1,[2],{"foo":3,"bar":4},{},{"foo":5}]`, Op: `[.[]|.foo?]`, Expected: `[3,null,5]`, }, "case27": { In: `[1,[2],[],{"foo":3},{"foo":{"bar":4}},{}]`, Op: `[.[]|.foo?.bar?]`, Expected: `[4,null]`, }, "case28": { In: `[1,[[2]],{ "a":[1]}]`, Op: `[..]`, Expected: `[[1,[[2]],{"a":[1]}],1,[[2]],[2],2,{"a":[1]},[1],1]`, }, "case29": { In: `[1,null,[],[1,[2,[[3]]]],[{}],[{"a":[1,[2]]}]]`, Op: `[.[]|.[]?]`, Expected: `[1,[2,[[3]]],{},{"a":[1,[2]]}]`, }, "case30": { In: `[1,null,true,false,"abcdef",{},{"a":1,"b":2},[],[1,2,3,4,5],[1,2]]`, Op: `[.[]|.[1:3]?]`, Expected: `[null,"bc",[],[2,3],[2]]`, }, // // Negative array indices // "case31": { In: `null`, Op: `try (.foo[-1] = 0) catch .`, Expected: `"Out of bounds negative array index"`, }, "case32": { In: `null`, Op: `try (.foo[-2] = 0) catch .`, Expected: `"Out of bounds negative array index"`, }, "case33": { In: `[0,1,2]`, Op: `.[-1] = 5`, Expected: `[0,1,5]`, }, "case34": { In: `[0,1,2]`, Op: `.[-2] = 5`, Expected: `[0,5,2]`, }, // // Multiple outputs, iteration // "case35": { In: `[1,2,3]`, Op: `.[]`, Expected: `1`, }, "case36": { In: `[]`, Op: `1,1`, Expected: `1`, }, "case37": { In: `[]`, Op: `1,.`, Expected: `1`, }, "case38": { In: `[2]`, Op: `[.]`, Expected: `[[2]]`, }, "case39": { In: `[3]`, Op: `[[2]]`, Expected: `[[2]]`, }, "case40": { In: `[2]`, Op: `[{}]`, Expected: `[{}]`, }, "case41": { In: `["a"]`, Op: `[.[]]`, Expected: `["a"]`, }, "case42": { In: `["a","b"]`, Op: `[(.,1),((.,.[]),(2,3))]`, Expected: `[["a","b"],1,["a","b"],"a","b",2,3]`, }, "case43": { In: `[1,2,3]`, Op: `[([5,5][]),.,.[]]`, Expected: `[5,5,[1,2,3],1,2,3]`, }, "case44": { In: `null`, Op: `{x: (1,2)},{x:3} | .x`, Expected: `1`, }, "case45": { In: `[1,2,3]`, Op: `.[-2]`, Expected: `2`, }, "case46": { In: `null`, Op: `[range(0;10)]`, Expected: `[0,1,2,3,4,5,6,7,8,9]`, }, "case47": { In: `null`, Op: `[range(0,1;3,4)]`, Expected: `[0,1,2, 0,1,2,3, 1,2, 1,2,3]`, }, "case48": { In: `null`, Op: `[range(0;10;3)]`, Expected: `[0,3,6,9]`, }, "case49": { In: `null`, Op: `[range(0;10;-1)]`, Expected: `[]`, }, "case50": { In: `null`, Op: `[range(0;-5;-1)]`, Expected: `[0,-1,-2,-3,-4]`, }, "case51": { In: `null`, Op: `[range(0,1;4,5;1,2)]`, Expected: `[0,1,2,3,0,2, 0,1,2,3,4,0,2,4, 1,2,3,1,3, 1,2,3,4,1,3]`, }, "case52": { In: `1`, Op: `[while(.<100; .*2)]`, Expected: `[1,2,4,8,16,32,64]`, }, "case53": { In: `[0,1,2]`, Op: `[(label $here | .[] | if .>1 then break $here else . end), "hi!"]`, Expected: `[0,1,"hi!"]`, }, "case54": { In: `[0,2,1]`, Op: `[(label $here | .[] | if .>1 then break $here else . end), "hi!"]`, Expected: `[0,"hi!"]`, }, "case55": { In: `[1,2,3,4,5]`, Op: `[.[]|[.,1]|until(.[0] < 1; [.[0] - 1, .[1] * .[0]])|.[1]]`, Expected: `[1,2,6,24,120]`, }, "case56": { In: `[11,22,33,44,55,66,77,88,99]`, Op: `[label $out | foreach .[] as $item ([3, null]; if .[0] < 1 then break $out else [.[0] -1, $item] end; .[1])]`, Expected: `[11,22,33]`, }, "case57": { In: `null`, Op: `[foreach range(5) as $item (0; $item)]`, Expected: `[0,1,2,3,4]`, }, "case58": { In: `[[2,1], [5,3], [6,4]]`, Op: `[foreach .[] as [$i, $j] (0; . + $i - $j)]`, Expected: `[1,3,5]`, }, "case59": { In: `[{"a":1}, {"b":2}, {"a":3, "b":4}]`, Op: `[foreach .[] as {a:$a} (0; . + $a; -.)]`, Expected: `[-1, -1, -4]`, }, "case60": { In: `[11,22,33,44,55,66,77,88,99]`, Op: `[limit(3; .[])]`, Expected: `[11,22,33]`, }, "case61": { In: `10`, Op: `[first(range(.)), last(range(.)), nth(0; range(.)), nth(5; range(.)), try nth(-1; range(.)) catch .]`, Expected: `[0 9 0 5 nth doesn't support negative indices]`, }, // // Check that various builtins evalute all arguments where appropriate, // doing cartesian products where appropriate. // // Check that limit does work for each value produced by n! "case62": { In: `null`, Op: `[limit(5,7; range(9))]`, Expected: `[0,1,2,3,4,0,1,2,3,4,5,6]`, }, // Same check for nth "case63": { In: `null`, Op: `[nth(5,7; range(9;0;-1))]`, Expected: `[4,2]`, }, // Same check for range/3 "case64": { In: `null`, Op: `[range(0,1,2;4,3,2;2,3)]`, Expected: `[0,2,0,3,0,2,0,0,0,1,3,1,1,1,1,1,2,2,2,2]`, }, // Same check for range/1 "case65": { In: `null`, Op: `[range(3,5)]`, Expected: `[0,1,2,0,1,2,3,4]`, }, // Same check for index/1, rindex/1, indices/1 "case66": { In: `"a,b|c,d,e||f,g,h,|,|,i,j"`, Op: `[(index(",","|"), rindex(",","|")), indices(",","|")]`, Expected: `[1,3,22,19,[1,5,7,12,14,16,18,20,22],[3,9,10,17,19]]`, }, // Same check for join/1 "case67": { In: `["a","b","c","d"]`, Op: `join(",","/")`, Expected: `"a,b,c,d"`, }, "case68": { In: `[[],[""],["",""],["","",""]]`, Op: `[.[]|join("a")]`, Expected: `["","","a","aa"]`, }, // Same check for flatten/1 "case69": { In: `[0, [1], [[2]], [[[3]]]]`, Op: `flatten(3,2,1)`, Expected: `[0,1,2,3]`, }, // // Slices // "case70": { In: `[0,1,2,3,4,5,6]`, Op: `[.[3:2], .[-5:4], .[:-2], .[-2:], .[3:3][1:], .[10:]]`, Expected: `[[], [2,3], [0,1,2,3,4], [5,6], [], []]`, }, "case71": { In: `"abcdefghi"`, Op: `[.[3:2], .[-5:4], .[:-2], .[-2:], .[3:3][1:], .[10:]]`, Expected: `["","","abcdefg","hi","",""]`, }, "case72": { In: `[0,1,2,3,4,5,6,7]`, Op: `del(.[2:4],.[0],.[-2:])`, Expected: `[1,4,5]`, }, "case73": { In: `[0,1,2,3,4,5,6,7]`, Op: `.[2:4] = ([], ["a","b"], ["a","b","c"])`, Expected: `[0,1,4,5,6,7]`, }, // // Variables // "case74": { In: `null`, Op: `1 as $x | 2 as $y | [$x,$y,$x]`, Expected: `[1,2,1]`, }, "case75": { In: `null`, Op: `[1,2,3][] as $x | [[4,5,6,7][$x]]`, Expected: `[5]`, }, "case76": { In: `34324`, Op: `42 as $x | . | . | . + 432 | $x + 1`, Expected: `43`, }, "case77": { In: `null`, Op: `1 as $x | [$x,$x,$x as $x | $x]`, Expected: `[1,1,1]`, }, "case78": { In: `null`, Op: `[1, {c:3, d:4}] as [$a, {c:$b, b:$c}] | $a, $b, $c`, Expected: `1`, }, "case79": { In: `{"as": 1, "str": 2, "exp": 3}`, Op: `. as {as: $kw, "str": $str, ("e"+"x"+"p"): $exp} | [$kw, $str, $exp]`, Expected: `[1, 2, 3]`, }, "case80": { In: `[[1], [1, 2, 3]]`, Op: `.[] as [$a, $b] | [$b, $a]`, Expected: `[null, 1]`, }, "case81": { In: `[0]`, Op: `. as $i | . as [$i] | $i`, Expected: `0`, }, "case82": { In: `[0]`, Op: `. as [$i] | . as $i | $i`, Expected: `[0]`, }, // [.,(.[] | {x:.},.),.,.[]] // // Builtin functions // "case83": { In: `null`, Op: `1+1`, Expected: `2`, }, "case84": { In: `"wtasdf"`, Op: `1+1`, Expected: `2.0`, }, "case85": { In: `null`, Op: `2-1`, Expected: `1`, }, "case86": { In: `null`, Op: `2-(-1)`, Expected: `3`, }, "case87": { In: `"I wonder what this will be?"`, Op: `1e+0+0.001e3`, Expected: `20e-1`, }, "case88": { In: `15`, Op: `.+4`, Expected: `19.0`, }, "case89": { In: `{"a":42}`, Op: `.+null`, Expected: `{"a":42}`, }, "case90": { In: `null`, Op: `null+.`, Expected: `null`, }, "case91": { In: `{"a":42}`, Op: `.a+.b`, Expected: `42`, }, "case92": { In: `null`, Op: `[1,2,3] + [.]`, Expected: `[1,2,3,null]`, }, "case93": { In: `"asdfasdf"`, Op: `{"a":1} + {"b":2} + {"c":3}`, Expected: `{"a":1, "b":2, "c":3}`, }, "case94": { In: `"some string"`, Op: `"asdf" + "jkl;" + . + . + .`, Expected: `"asdfjkl;some stringsome stringsome string"`, }, "case95": { In: `"\u0000\u0020\u0000"`, Op: `"\u0000\u0020\u0000" + .`, Expected: `"\u0000 \u0000\u0000 \u0000"`, }, "case96": { In: `11`, Op: `42 - .`, Expected: `31`, }, "case97": { In: `1`, Op: `[1,2,3,4,1] - [.,3]`, Expected: `[2,4]`, }, "case98": { In: `4`, Op: `[10 * 20, 20 / .]`, Expected: `[200, 5]`, }, "case99": { In: `null`, Op: `1 + 2 * 2 + 10 / 2`, Expected: `10`, }, "case100": { In: `null`, Op: `[16 / 4 / 2, 16 / 4 * 2, 16 - 4 - 2, 16 - 4 + 2]`, Expected: `[2, 8, 10, 14]`, }, "case101": { In: `null`, Op: `25 % 7`, Expected: `4`, }, "case102": { In: `null`, Op: `49732 % 472`, Expected: `172`, }, "case103": { In: `4`, Op: `1 + tonumber + ("10" | tonumber)`, Expected: `15`, }, "case104": { In: `{"object": {"a":42}, "num":10.0}`, Op: `[{"a":42},.object,10,.num,false,true,null,"b",[1,4]] | .[] as $x | [$x == .[]]`, Expected: `[true, true, false, false, false, false, false, false, false]`, }, "case105": { In: `[[], {}, [1,2], {"a":42}, "asdf", "\u03bc"]`, Op: `[.[] | length]`, Expected: `[0, 0, 2, 1, 4, 1]`, }, "case106": { In: `"asdf\u03bc"`, Op: `utf8bytelength`, Expected: `6`, }, "case107": { In: `[[], {}, [1,2], 55, true, false]`, Op: `[.[] | try utf8bytelength catch .]`, Expected: `["array ([]) only strings have UTF-8 byte length","object ({}) only strings have UTF-8 byte length","array ([1,2]) only strings have UTF-8 byte length","number (55) only strings have UTF-8 byte length","boolean (true) only strings have UTF-8 byte length","boolean (false) only strings have UTF-8 byte length"]`, }, "case108": { In: `[{}, {"abcd":1,"abc":2,"abcde":3}, {"x":1, "z": 3, "y":2}]`, Op: `map(keys)`, Expected: `[[], ["abc","abcd","abcde"], ["x","y","z"]]`, }, "case109": { In: `null`, Op: `[1,2,empty,3,empty,4]`, Expected: `[1,2,3,4]`, }, "case110": { In: `[[], [1,2,3], ["a","b","c"], [[3],[4,5],[6]], [{"a":1}, {"b":2}, {"a":3}]]`, Op: `map(add)`, Expected: `[null, 6, "abc", [3,4,5,6], {"a":3, "b": 2}]`, }, "case111": { In: `[0,1,2]`, Op: `map_values(.+1)`, Expected: `[1,2,3]`, }, // // User-defined functions // Oh god. // "case112": { In: `3.0`, Op: `def f: . + 1; def g: def g: . + 100; f | g | f; (f | g), g`, Expected: `106.0`, }, "case113": { In: `123412345`, Op: `def f: (1000,2000); f`, Expected: `1000`, }, "case114": { In: `[1,2]`, Op: `def f(a;b;c;d;e;f): [a+1,b,c,d,e,f]; f(.[0];.[1];.[0];.[0];.[0];.[0])`, Expected: `[2,2,1,1,1,1]`, }, // Test precedence of def vs | "case115": { In: `null`, Op: `def a: 0; . | a`, Expected: `0`, }, // Many arguments "case116": { In: `[0,1,2,3,4,5,6,7,8,9]`, Op: `def f(a;b;c;d;e;f;g;h;i;j): [j,i,h,g,f,e,d,c,b,a]; f(.[0];.[1];.[2];.[3];.[4];.[5];.[6];.[7];.[8];.[9])`, Expected: `[9,8,7,6,5,4,3,2,1,0]`, }, "case117": { In: `[1,2,3]`, Op: `([1,2] + [4,5])`, Expected: `[1,2,4,5]`, }, "case118": { In: `[1]`, Op: `true`, Expected: `true`, }, "case119": { In: `"hello"`, Op: `null,1,null`, Expected: `null`, }, "case120": { In: `[5,6]`, Op: `[1,2,3]`, Expected: `[1,2,3]`, }, "case121": { In: `[-1.1,1.1,1.9]`, Op: `[.[]|floor]`, Expected: `[-2, 1, 1]`, }, "case122": { In: `[4,9]`, Op: `[.[]|sqrt]`, Expected: `[2,3]`, }, "case123": { In: `[2,4,4,4,5,5,7,9]`, Op: `(add / length) as $m | map((. - $m) as $d | $d * $d) | add / length | sqrt`, Expected: `2`, }, // Should write a test that calls the -lm function from C (or bc(1)) to // check that they match the corresponding jq functions. However, // theres so little template code standing between that it suffices to // test a handful of these. The results were checked by eye against // bc(1). "case124": { In: `1`, Op: `atan * 4 * 1000000|floor / 1000000`, Expected: `3.141592`, }, "case125": { In: `null`, Op: `[(3.141592 / 2) * (range(0;20) / 20)|cos * 1000000|floor / 1000000]`, Expected: `[1,0.996917,0.987688,0.972369,0.951056,0.923879,0.891006,0.85264,0.809017,0.760406,0.707106,0.649448,0.587785,0.522498,0.45399,0.382683,0.309017,0.233445,0.156434,0.078459]`, }, "case126": { In: `null`, Op: `[(3.141592 / 2) * (range(0;20) / 20)|sin * 1000000|floor / 1000000]`, Expected: `[0,0.078459,0.156434,0.233445,0.309016,0.382683,0.45399,0.522498,0.587785,0.649447,0.707106,0.760405,0.809016,0.85264,0.891006,0.923879,0.951056,0.972369,0.987688,0.996917]`, }, "case127": { In: `[1,2,3]`, Op: `def f(x): x | x; f([.], . + [42])`, Expected: `[[[1,2,3]]]`, }, // test multiple function arities and redefinition "case128": { In: `1`, Op: `def f: .+1; def g: f; def f: .+100; def f(a):a+.+11; [(g|f(20)), f]`, Expected: `[33,101]`, }, // test closures and lexical scoping "case129": { In: `"more testing"`, Op: `def id(x):x; 2000 as $x | def f(x):1 as $x | id([$x, x, x]); def g(x): 100 as $x | f($x,$x+x); g($x)`, Expected: `[1,100,2100.0,100,2100.0]`, }, // test def f($a) syntax "case130": { In: `[1,2,3]`, Op: `def x(a;b): a as $a | b as $b | $a + $b; def y($a;$b): $a + $b; def check(a;b): [x(a;b)] == [y(a;b)]; check(.[];.[]*2)`, Expected: `true`, }, // test backtracking through function calls and returns // this test is *evil* "case131": { In: `999999999`, Op: `[[20,10][1,0] as $x | def f: (100,200) as $y | def g: [$x + $y, .]; . + $x | g; f[0] | [f][0][1] | f]`, Expected: `[[110.0, 130.0], [210.0, 130.0], [110.0, 230.0], [210.0, 230.0], [120.0, 160.0], [220.0, 160.0], [120.0, 260.0], [220.0, 260.0]]`, }, // test recursion "case132": { In: `[1,2,3,4]`, Op: `def fac: if . == 1 then 1 else . * (. - 1 | fac) end; [.[] | fac]`, Expected: `[1,2,6,24]`, }, // test stack overflow and reallocation // this test is disabled for now, it takes a realllllly long time. // def f: if length > 1000 then . else .+[1]|f end; f | length // [] // 1001 "case133": { In: `[1,2,4]`, Op: `reduce .[] as $x (0; . + $x)`, Expected: `7`, }, "case134": { In: `[[2,{"j":1}], [5,{"j":3}], [6,{"j":4}]]`, Op: `reduce .[] as [$i, {j:$j}] (0; . + $i - $j)`, Expected: `5`, }, "case135": { In: `null`, Op: `reduce [[1,2,10], [3,4,10]][] as [$i,$j] (0; . + $i * $j)`, Expected: `14`, }, "case136": { In: `[1,2,3,4,true,false,1,2,3,4,5]`, Op: `. as $dot|any($dot[];not)`, Expected: `true`, }, "case137": { In: `[1,2,3,4,true]`, Op: `. as $dot|any($dot[];not)`, Expected: `false`, }, "case138": { In: `[1,2,3,4,true,false,1,2,3,4,5]`, Op: `. as $dot|all($dot[];.)`, Expected: `false`, }, "case139": { In: `[1,2,3,4,true]`, Op: `. as $dot|all($dot[];.)`, Expected: `true`, }, // // Paths // "case140": { In: `null`, Op: `path(.foo[0,1])`, Expected: `["foo", 0]`, }, "case141": { In: `[1,5,3]`, Op: `path(.[] | select(.>3))`, Expected: `[1]`, }, "case142": { In: `42`, Op: `path(.)`, Expected: `[]`, }, "case143": { In: `{"a":[{"b":0}]}`, Op: `try path(.a | map(select(.b == 0))) catch .`, Expected: `"Invalid path expression with result [{\"b\":0}]"`, }, "case144": { In: `{"a":[{"b":0}]}`, Op: `try path(.a | map(select(.b == 0)) | .[0]) catch .`, Expected: `"Invalid path expression near attempt to access element 0 of [{\"b\":0}]"`, }, "case145": { In: `{"a":[{"b":0}]}`, Op: `try path(.a | map(select(.b == 0)) | .c) catch .`, Expected: `"Invalid path expression near attempt to access element \"c\" of [{\"b\":0}]"`, }, "case146": { In: `{"a":[{"b":0}]}`, Op: `try path(.a | map(select(.b == 0)) | .[]) catch .`, Expected: `"Invalid path expression near attempt to iterate through [{\"b\":0}]"`, }, "case147": { In: `{"a":{"b":0}}`, Op: `path(.a[path(.b)[0]])`, Expected: `["a","b"]`, }, "case148": { In: `[1,[[],{"a":2}]]`, Op: `[paths]`, Expected: `[[0],[1],[1,0],[1,1],[1,1,"a"]]`, }, "case149": { In: `[1,[[],{"a":2}]]`, Op: `[leaf_paths]`, Expected: `[[0],[1,1,"a"]]`, }, "case150": { In: `{"bar": 42, "foo": ["a", "b", "c", "d"]}`, Op: `["foo",1] as $p | getpath($p), setpath($p; 20), delpaths([$p])`, Expected: `"b"`, }, "case151": { In: `[[0], [0,1], [0,1,2]]`, Op: `map(getpath([2])), map(setpath([2]; 42)), map(delpaths([[2]]))`, Expected: `[null, null, 2]`, }, "case152": { In: `[[{"foo":2, "x":1}], [{"bar":2}]]`, Op: `map(delpaths([[0,"foo"]]))`, Expected: `[[{"x":1}], [{"bar":2}]]`, }, "case153": { In: `{"bar":false}`, Op: `["foo",1] as $p | getpath($p), setpath($p; 20), delpaths([$p])`, Expected: `null`, }, "case154": { In: `[1,2,3]`, Op: `delpaths([[-200]])`, Expected: `[1,2,3]`, }, "case155": { In: `{}`, Op: `try delpaths(0) catch .`, Expected: `"Paths must be specified as an array"`, }, "case156": { In: `{"foo": [0,1,2,3,4], "bar": [0,1]}`, Op: `del(.), del(empty), del((.foo,.bar,.baz) | .[2,3,0]), del(.foo[0], .bar[0], .foo, .baz.bar[0].x)`, Expected: `null`, }, "case157": { In: `[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]`, Op: `del(.[1], .[-6], .[2], .[-3:9])`, Expected: `[0, 3, 5, 6, 9]`, }, // // Assignment // "case158": { In: `{"message": "hello"}`, Op: `.message = "goodbye"`, Expected: `{"message": "goodbye"}`, }, "case159": { In: `{"bar":42}`, Op: `.foo = .bar`, Expected: `{"foo":42, "bar":42}`, }, "case160": { In: `{"foo": 42}`, Op: `.foo |= .+1`, Expected: `{"foo": 43}`, }, "case161": { In: `[1,3,5]`, Op: `.[] += 2, .[] *= 2, .[] -= 2, .[] /= 2, .[] %=2`, Expected: `[3,5,7]`, }, "case162": { In: `[-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7]`, Op: `[.[] % 7]`, Expected: `[0,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,0]`, }, "case163": { In: `{"foo":2}`, Op: `.foo += .foo`, Expected: `{"foo":4}`, }, "case164": { In: `[{"a":1,"b":2}]`, Op: `.[0].a |= {"old":., "new":(.+1)}`, Expected: `[{"a":{"old":1, "new":2},"b":2}]`, }, "case165": { In: `[{"a":1,"b":2},{"a":2,"b":4},{"a":7,"b":8}]`, Op: `def inc(x): x |= .+1; inc(.[].a)`, Expected: `[{"a":2,"b":2},{"a":3,"b":4},{"a":8,"b":8}]`, }, "case166": { In: `[4]`, Op: `.[2][3] = 1`, Expected: `[4, null, [null, null, null, 1]]`, }, "case167": { In: `{"foo":[11], "bar":42}`, Op: `.foo[2].bar = 1`, Expected: `{"foo":[11,null,{"bar":1}], "bar":42}`, }, "case168": { In: `[{"a":0},{"a":1}]`, Op: `try ((map(select(.a == 1))[].b) = 10) catch .`, Expected: `"Invalid path expression near attempt to iterate through [{\"a\":1}]"`, }, "case169": { In: `[{"a":0},{"a":1}]`, Op: `try ((map(select(.a == 1))[].a) |= .+1) catch .`, Expected: `"Invalid path expression near attempt to iterate through [{\"a\":1}]"`, }, "case170": { In: `[0,1,2]`, Op: `def x: .[1,2]; x=10`, Expected: `[0,10,10]`, }, "case171": { In: `[0,1,2]`, Op: `try (def x: reverse; x=10) catch .`, Expected: `"Invalid path expression with result [2,1,0]"`, }, "case172": { In: `[1,null,Infinity,-Infinity,NaN,-NaN]`, Op: `.[] = 1`, Expected: `[1,1,1,1,1,1]`, }, // // Conditionals // "case173": { In: `[{"foo":0},{"foo":1},{"foo":[]},{"foo":true},{"foo":false},{"foo":null},{"foo":"foo"},{}]`, Op: `[.[] | if .foo then "yep" else "nope" end]`, Expected: `["yep","yep","yep","yep","nope","nope","yep","nope"]`, }, "case174": { In: `[{"foo":0},{"foo":1},{"foo":[]},{"foo":true},{"foo":false},{"foo":null},{"foo":"foo"},{}]`, Op: `[.[] | if .baz then "strange" elif .foo then "yep" else "nope" end]`, Expected: `["yep","yep","yep","yep","nope","nope","yep","nope"]`, }, "case175": { In: `null`, Op: `[if 1,null,2 then 3 else 4 end]`, Expected: `[3,4,3]`, }, "case176": { In: `null`, Op: `[if empty then 3 else 4 end]`, Expected: `[]`, }, "case177": { In: `null`, Op: `[if 1 then 3,4 else 5 end]`, Expected: `[3,4]`, }, "case178": { In: `null`, Op: `[if null then 3 else 5,6 end]`, Expected: `[5,6]`, }, "case179": { In: `[{"foo":[1,2], "bar": 42}, {"foo":[1], "bar": null}, {"foo":[null,false,3], "bar": 18}, {"foo":[], "bar":42}, {"foo": [null,false,null], "bar": 41}]`, Op: `[.[] | [.foo[] // .bar]]`, Expected: `[[1,2], [1], [3], [42], [41]]`, }, "case180": { In: `["hello",true,false,[false],null]`, Op: `.[] //= .[0]`, Expected: `["hello",true,"hello",[false],"hello"]`, }, "case181": { In: `[[true,[]], [false,1], [42,null], [null,false]]`, Op: `.[] | [.[0] and .[1], .[0] or .[1]]`, Expected: `[true,true]`, }, "case182": { In: `[1,0,false,null,true,"hello"]`, Op: `[.[] | not]`, Expected: `[false,false,true,true,false,false]`, }, // Check numeric comparison binops "case183": { In: `{}`, Op: `[10 > 0, 10 > 10, 10 > 20, 10 < 0, 10 < 10, 10 < 20]`, Expected: `[true,false,false,false,false,true]`, }, "case184": { In: `{}`, Op: `[10 >= 0, 10 >= 10, 10 >= 20, 10 <= 0, 10 <= 10, 10 <= 20]`, Expected: `[true,true,false,false,true,true]`, }, // And some in/equality tests "case185": { In: `{}`, Op: `[ 10 == 10, 10 != 10, 10 != 11, 10 == 11]`, Expected: `[true,false,true,false]`, }, "case186": { In: `{}`, Op: `["hello" == "hello", "hello" != "hello", "hello" == "world", "hello" != "world" ]`, Expected: `[true,false,false,true]`, }, "case187": { In: `{}`, Op: `[[1,2,3] == [1,2,3], [1,2,3] != [1,2,3], [1,2,3] == [4,5,6], [1,2,3] != [4,5,6]]`, Expected: `[true,false,false,true]`, }, "case188": { In: `{}`, Op: `[{"foo":42} == {"foo":42},{"foo":42} != {"foo":42}, {"foo":42} != {"bar":42}, {"foo":42} == {"bar":42}]`, Expected: `[true,false,true,false]`, }, // ugly complicated thing "case189": { In: `{}`, Op: `[{"foo":[1,2,{"bar":18},"world"]} == {"foo":[1,2,{"bar":18},"world"]},{"foo":[1,2,{"bar":18},"world"]} == {"foo":[1,2,{"bar":19},"world"]}]`, Expected: `[true,false]`, }, // containment operator "case190": { In: `{}`, Op: `[("foo" | contains("foo")), ("foobar" | contains("foo")), ("foo" | contains("foobar"))]`, Expected: `[true, true, false]`, }, // Try/catch and general `?` operator "case191": { In: `[0,1,2,3]`, Op: `[.[]|try if . == 0 then error("foo") elif . == 1 then .a elif . == 2 then empty else . end catch .]`, Expected: `["foo","Cannot index number with string \"a\"",3]`, }, "case192": { In: `[null,true,{"a":1}]`, Op: `[.[]|(.a, .a)?]`, Expected: `[null,null,1,1]`, }, "case193": { In: `[null,true,{"a":1}]`, Op: `[[.[]|[.a,.a]]?]`, Expected: `[]`, }, "case194": { In: `null`, Op: `try error("\($__loc__)") catch .`, Expected: `"{\"file\":\"\",\"line\":1}"`, }, // string operations "case195": { In: `["fo", "foo", "barfoo", "foobar", "barfoob"]`, Op: `[.[]|startswith("foo")]`, Expected: `[false, true, false, true, false]`, }, "case196": { In: `["fo", "foo", "barfoo", "foobar", "barfoob"]`, Op: `[.[]|endswith("foo")]`, Expected: `[false, true, true, false, false]`, }, "case197": { In: `["a,b, c, d, e,f",", a,b, c, d, e,f, "]`, Op: `[.[] | split(", ")]`, Expected: `[["a,b","c","d","e,f"],["","a,b","c","d","e,f",""]]`, }, "case198": { In: `"abc"`, Op: `split("")`, Expected: `["a","b","c"]`, }, "case199": { In: `["fo", "foo", "barfoo", "foobar", "afoo"]`, Op: `[.[]|ltrimstr("foo")]`, Expected: `["fo","","barfoo","bar","afoo"]`, }, "case200": { In: `["fo", "foo", "barfoo", "foobar", "foob"]`, Op: `[.[]|rtrimstr("foo")]`, Expected: `["fo","","bar","foobar","foob"]`, }, "case201": { In: `"a,bc,def,ghij,klmno"`, Op: `[(index(","), rindex(",")), indices(",")]`, Expected: `[1,13,[1,4,8,13]]`, }, "case202": { In: `[0,1,1,2,3,4,1,5]`, Op: `indices(1)`, Expected: `[1,2,6]`, }, "case203": { In: `[0,1,2,3,1,4,2,5,1,2,6,7]`, Op: `indices([1,2])`, Expected: `[1,8]`, }, "case204": { In: `[1]`, Op: `indices([1,2])`, Expected: `[]`, }, "case205": { In: `"a,b, cd,e, fgh, ijkl"`, Op: `indices(", ")`, Expected: `[3,9,14]`, }, "case206": { In: `["a, bc, def, ghij, jklmn, a,b, c,d, e,f", "a,b,c,d, e,f,g,h"]`, Op: `[.[]|split(",")]`, Expected: `[["a"," bc"," def"," ghij"," jklmn"," a","b"," c","d"," e","f"],["a","b","c","d"," e","f","g","h"]]`, }, "case207": { In: `["a, bc, def, ghij, jklmn, a,b, c,d, e,f", "a,b,c,d, e,f,g,h"]`, Op: `[.[]|split(", ")]`, Expected: `[["a","bc","def","ghij","jklmn","a,b","c,d","e,f"],["a,b,c,d","e,f,g,h"]]`, }, "case208": { In: `["a", "ab", "abc"]`, Op: `[.[] * 3]`, Expected: `["aaa", "ababab", "abcabcabc"]`, }, "case209": { In: `["a, bc, def, ghij, jklmn, a,b, c,d, e,f", "a,b,c,d, e,f,g,h"]`, Op: `[.[] / ","]`, Expected: `[["a"," bc"," def"," ghij"," jklmn"," a","b"," c","d"," e","f"],["a","b","c","d"," e","f","g","h"]]`, }, "case210": { In: `["a, bc, def, ghij, jklmn, a,b, c,d, e,f", "a,b,c,d, e,f,g,h"]`, Op: `[.[] / ", "]`, Expected: `[["a","bc","def","ghij","jklmn","a,b","c,d","e,f"],["a,b,c,d","e,f,g,h"]]`, }, "case211": { In: `[[[],[]], [[1,2,3], [1,2]], [[1,2,3], [3,1]], [[1,2,3], [4]], [[1,2,3], [1,4]]]`, Op: `map(.[1] as $needle | .[0] | contains($needle))`, Expected: `[true, true, true, false, false]`, }, "case212": { In: `[[["foobar", "foobaz"], ["baz", "bar"]], [["foobar", "foobaz"], ["foo"]], [["foobar", "foobaz"], ["blap"]]]`, Op: `map(.[1] as $needle | .[0] | contains($needle))`, Expected: `[true, true, false]`, }, "case213": { In: `{}`, Op: `[({foo: 12, bar:13} | contains({foo: 12})), ({foo: 12} | contains({})), ({foo: 12, bar:13} | contains({baz:14}))]`, Expected: `[true, true, false]`, }, "case214": { In: `{}`, Op: `{foo: {baz: 12, blap: {bar: 13}}, bar: 14} | contains({bar: 14, foo: {blap: {}}})`, Expected: `true`, }, "case215": { In: `{}`, Op: `{foo: {baz: 12, blap: {bar: 13}}, bar: 14} | contains({bar: 14, foo: {blap: {bar: 14}}})`, Expected: `false`, }, "case216": { In: `[42,[2,5,3,11],10,{"a":42,"b":2},{"a":42},true,2,[2,6],"hello",null,[2,5,6],{"a":[],"b":1},"abc","ab",[3,10],{},false,"abcd",null]`, Op: `sort`, Expected: `[null,null,false,true,2,10,42,"ab","abc","abcd","hello",[2,5,3,11],[2,5,6],[2,6],[3,10],{},{"a":42},{"a":42,"b":2},{"a":[],"b":1}]`, }, "case217": { In: `[{"a": 1, "b": 4, "c": 14}, {"a": 4, "b": 1, "c": 3}, {"a": 1, "b": 4, "c": 3}, {"a": 0, "b": 2, "c": 43}]`, Op: `(sort_by(.b) | sort_by(.a)), sort_by(.a, .b), sort_by(.b, .c), group_by(.b), group_by(.a + .b - .c == 2)`, Expected: `[{"a": 0, "b": 2, "c": 43}, {"a": 1, "b": 4, "c": 14}, {"a": 1, "b": 4, "c": 3}, {"a": 4, "b": 1, "c": 3}]`, }, "case218": { In: `[1,2,5,3,5,3,1,3]`, Op: `unique`, Expected: `[1,2,3,5]`, }, "case219": { In: `[]`, Op: `unique`, Expected: `[]`, }, "case220": { In: `[[4,2,"a"],[3,1,"a"],[2,4,"a"],[1,3,"a"]]`, Op: `[min, max, min_by(.[1]), max_by(.[1]), min_by(.[2]), max_by(.[2])]`, Expected: `[[1,3,"a"],[4,2,"a"],[3,1,"a"],[2,4,"a"],[4,2,"a"],[1,3,"a"]]`, }, "case221": { In: `[]`, Op: `[min,max,min_by(.),max_by(.)]`, Expected: `[null,null,null,null]`, }, "case222": { In: `{"foo":{"bar":4},"baz":"bar"}`, Op: `.foo[.baz]`, Expected: `4`, }, "case223": { In: `[{"error":true}]`, Op: `.[] | .error = "no, it's OK"`, Expected: `map[error:no, it's OK]`, }, "case224": { In: `null`, Op: `[{a:1}] | .[] | .a=999`, Expected: `{"a": 999}`, }, "case225": { In: `{"a": 1, "b": 2}`, Op: `to_entries`, Expected: `[{"key":"a", "value":1}, {"key":"b", "value":2}]`, }, "case226": { In: `[{"key":"a", "value":1}, {"Key":"b", "Value":2}, {"name":"c", "value":3}, {"Name":"d", "Value":4}]`, Op: `from_entries`, Expected: `{"a": 1, "b": 2, "c": 3, "d": 4}`, }, "case227": { In: `{"a": 1, "b": 2}`, Op: `with_entries(.key |= "KEY_" + .)`, Expected: `{"KEY_a": 1, "KEY_b": 2}`, }, "case228": { In: `[{"foo": 42}, {}]`, Op: `map(has("foo"))`, Expected: `[true, false]`, }, "case229": { In: `[[0,1], ["a","b","c"]]`, Op: `map(has(2))`, Expected: `[false, true]`, }, "case230": { In: `[42,3,35]`, Op: `keys`, Expected: `[0,1,2]`, }, "case231": { In: `1000000000000000000`, Op: `[][.]`, Expected: `null`, }, "case232": { In: `[-1, 1, 2, 3, 1000000000000000000]`, Op: `map([1,2][0:.])`, Expected: `[[1], [1], [1,2], [1,2], [1,2]]`, }, // Test recursive object merge "case233": { In: `{"k": {"a": 0,"c": 3}}`, Op: `{"k": {"a": 1, "b": 2}} * .`, Expected: `{"k": {"a": 0, "b": 2, "c": 3}}`, }, "case234": { In: `{"k": {"a": 0,"c": 3}, "hello": 1}`, Op: `{"k": {"a": 1, "b": 2}, "hello": {"x": 1}} * .`, Expected: `{"k": {"a": 0, "b": 2, "c": 3}, "hello": 1}`, }, "case235": { In: `{"k": {"a": 0,"c": 3}, "hello": {"x": 1}}`, Op: `{"k": {"a": 1, "b": 2}, "hello": 1} * .`, Expected: `{"k": {"a": 0, "b": 2, "c": 3}, "hello": {"x": 1}}`, }, "case236": { In: `{"a": {"b": 2}, "c": {"d": 3, "f": 9}}`, Op: `{"a": {"b": 1}, "c": {"d": 2}, "e": 5} * .`, Expected: `{"a": {"b": 2}, "c": {"d": 3, "f": 9}, "e": 5}`, }, "case237": { In: `[1,2,"foo",[],[3,[]],{},true,false,null]`, Op: `[.[]|arrays]`, Expected: `[[],[3,[]]]`, }, "case238": { In: `[1,2,"foo",[],[3,[]],{},true,false,null]`, Op: `[.[]|objects]`, Expected: `[{}]`, }, "case239": { In: `[1,2,"foo",[],[3,[]],{},true,false,null]`, Op: `[.[]|iterables]`, Expected: `[[],[3,[]],{}]`, }, "case240": { In: `[1,2,"foo",[],[3,[]],{},true,false,null]`, Op: `[.[]|scalars]`, Expected: `[1,2,"foo",true,false,null]`, }, "case241": { In: `[1,2,"foo",[],[3,[]],{},true,false,null]`, Op: `[.[]|values]`, Expected: `[1,2,"foo",[],[3,[]],{},true,false]`, }, "case242": { In: `[1,2,"foo",[],[3,[]],{},true,false,null]`, Op: `[.[]|booleans]`, Expected: `[true,false]`, }, "case243": { In: `[1,2,"foo",[],[3,[]],{},true,false,null]`, Op: `[.[]|nulls]`, Expected: `[null]`, }, "case244": { In: `[0, [1], [[2]], [[[3]]]]`, Op: `flatten`, Expected: `[0, 1, 2, 3]`, }, "case245": { In: `[0, [1], [[2]], [[[3]]]]`, Op: `flatten(0)`, Expected: `[0, [1], [[2]], [[[3]]]]`, }, "case246": { In: `[0, [1], [[2]], [[[3]]]]`, Op: `flatten(2)`, Expected: `[0, 1, 2, [3]]`, }, "case247": { In: `[0, [1, [2]], [1, [[3], 2]]]`, Op: `flatten(2)`, Expected: `[0, 1, 2, 1, [3], 2]`, }, "case248": { In: `[0, [1], [[2]], [[[3]]]]`, Op: `try flatten(-1) catch .`, Expected: `"flatten depth must not be negative"`, }, "case249": { In: `[[1], [2,3]]`, Op: `transpose`, Expected: `[[1,2],[null,3]]`, }, "case250": { In: `"useful but not for Ê"`, Op: `ascii_upcase`, Expected: `"USEFUL BUT NOT FOR Ê"`, }, "case251": { In: `[1,2,3]`, Op: `bsearch(4)`, Expected: `-4`, }, // strptime tests are in optional.test "case252": { In: `[2015,2,5,23,51,47,4,63]`, Op: `strftime("%Y-%m-%dT%H:%M:%SZ")`, Expected: `"2015-03-05T23:51:47Z"`, }, "case253": { In: `1435677542.822351`, Op: `strftime("%A, %B %d, %Y")`, Expected: `"Tuesday, June 30, 2015"`, }, "case254": { In: `1425599507`, Op: `gmtime`, Expected: `[2015,2,5,23,51,47,4,63]`, }, // module system "case255": { In: `null`, Op: `import "a" as foo; import "b" as bar; def fooa: foo::a; [fooa, bar::a, bar::b, foo::a]`, Expected: `["a","b","c","a"]`, }, "case256": { In: `null`, Op: `import "c" as foo; [foo::a, foo::c]`, Expected: `[0,"acmehbah"]`, }, "case257": { In: `null`, Op: `include "c"; [a, c]`, Expected: `[0,"acmehbah"]`, }, "case258": { In: `"c"`, Op: `modulemeta`, Expected: `{"whatever":null,"deps":[{"as":"foo","is_data":false,"relpath":"a"},{"search":"./","as":"d","is_data":false,"relpath":"d"},{"search":"./","as":"d2","is_data":false,"relpath":"d"},{"search":"./../lib/jq","as":"e","is_data":false,"relpath":"e"},{"search":"./../lib/jq","as":"f","is_data":false,"relpath":"f"},{"as":"d","is_data":true,"relpath":"data"}]}`, }, "case259": { In: `null`, Op: `import "test_bind_order" as check; check::check`, Expected: `true`, }, "case260": { In: `"very-long-string"`, Op: `try -. catch .`, Expected: `"string (\"very-long-...) cannot be negated"`, }, "case261": { In: `["1",2,true,false,3.4]`, Op: `join(",")`, Expected: `"1,2,true,false,3.4"`, }, "case262": { In: `[[], [null], [null,null], [null,null,null]]`, Op: `.[] | join(",")`, Expected: `""`, }, "case263": { In: `[["a",null], [null,"a"]]`, Op: `.[] | join(",")`, Expected: `"a,"`, }, "case264": { In: `["1","2",{"a":{"b":{"c":33}}}]`, Op: `try join(",") catch .`, Expected: `"string (\"1,2,\") and object ({\"a\":{\"b\":{...) cannot be added"`, }, "case265": { In: `["1","2",[3,4,5]]`, Op: `try join(",") catch .`, Expected: `"string (\"1,2,\") and array ([3,4,5]) cannot be added"`, }, "case266": { In: `null`, Op: `{if:0,and:1,or:2,then:3,else:4,elif:5,end:6,as:7,def:8,reduce:9,foreach:10,try:11,catch:12,label:13,import:14,include:15,module:16}`, Expected: `{"if":0,"and":1,"or":2,"then":3,"else":4,"elif":5,"end":6,"as":7,"def":8,"reduce":9,"foreach":10,"try":11,"catch":12,"label":13,"import":14,"include":15,"module":16}`, }, "case267": { In: `0`, Op: `try (1/.) catch .`, Expected: `"number (1) and number (0) cannot be divided because the divisor is zero"`, }, "case268": { In: `0`, Op: `try (1%.) catch .`, Expected: `"number (1) and number (0) cannot be divided (remainder) because the divisor is zero"`, }, // Basic numbers tests: integers, powers of two "case269": { In: `null`, Op: `[range(-52;52;1)] as $powers | [$powers[]|pow(2;.)|log2] == $powers`, Expected: `true`, }, "case270": { In: `null`, Op: `[range(-99/2;99/2;1)] as $orig | [$orig[]|pow(2;.)|log2] as $back | ($orig|keys)[]|. as $k | (($orig|.[$k])-($back|.[$k]))|if . < 0 then . * -1 else . end|select(.>.00005)`, Expected: ``, }, "case271": { In: `null`, Op: `(.[{}] = 0)?`, Expected: ``, }, } for label, tc := range testCases { t.Run(label, func(t *testing.T) { op, err := jq.Parse(tc.Op) if err != nil { t.FailNow() } data, err := op.Apply([]byte(tc.In)) if tc.HasError { if err == nil { t.FailNow() } } else { if string(data) != tc.Expected { t.FailNow() } if err != nil { t.FailNow() } } }) } } easygen-5.1.9/test/jq-test_1.y0000066400000000000000000000015171416363131000162230ustar00rootroot00000000000000# Test cases Copyright (c) 2016 of project # https://github.com/stedolan/jq # Test cases converted to YAML format by # Tong Sun Copyright (c) 2016 # https://github.com/go-easygen/easygen # To update, # cp jq-test_1.y0 jq-test_1.yaml # curl -s https://raw.githubusercontent.com/stedolan/jq/master/tests/jq.test | tr -d '\015' | sed '/^#/s/$/\n/' | perl -n0000e 'if (/^ *#/) { s|^ *# *||; print " - Comment:\n Str: $_" } elsif (/jq: error: |byte order mark/) { next; } else { @tc= split /\n/, $_; print " - TestCase:\n Name: case". ++$i. "\n Op: $tc[0]\n In: $tc[1]\n Out: $tc[2]\n\n" }' | sed -r "/^ Str: .*'/s/'//g; /^ Str: |^ (Op|In|Out): [^']*$/{ s/((Str|Op|In|Out): )/\1'/; s/\$/'/; }" >> jq-test_1.yaml # easygen -tf jq-test_jq jq-test_1 | sed 's|// *$|//|' | gofmt > jq-test_1.go_ Cases: easygen-5.1.9/test/jq-test_1.yaml000066400000000000000000001274401416363131000166410ustar00rootroot00000000000000# Test cases Copyright (c) 2016 of project # https://github.com/stedolan/jq # Test cases converted to YAML format by # Tong Sun Copyright (c) 2016 # https://github.com/go-easygen/easygen # To update, # cp jq-test_1.y0 jq-test_1.yaml # curl -s https://raw.githubusercontent.com/stedolan/jq/master/tests/jq.test | tr -d '\015' | sed '/^#/s/$/\n/' | perl -n0000e 'if (/^ *#/) { s|^ *# *||; print " - Comment:\n Str: $_" } elsif (/jq: error: |byte order mark/) { next; } else { @tc= split /\n/, $_; print " - TestCase:\n Name: case". ++$i. "\n Op: $tc[0]\n In: $tc[1]\n Out: $tc[2]\n\n" }' | sed -r "/^ Str: .*'/s/'//g; /^ Str: |^ (Op|In|Out): [^']*$/{ s/((Str|Op|In|Out): )/\1'/; s/\$/'/; }" >> jq-test_1.yaml # easygen -tf jq-test_jq jq-test_1 | sed 's|// *$|//|' | gofmt > jq-test_1.go_ Cases: - Comment: Str: 'Tests are groups of three lines: program, input, expected output' - Comment: Str: 'Blank lines and lines starting with # are ignored' - Comment: Str: '' - Comment: Str: 'Simple value tests to check parser. Input is irrelevant' - Comment: Str: '' - TestCase: Name: case1 Op: 'true' In: 'null' Out: 'true' - TestCase: Name: case2 Op: 'false' In: 'null' Out: 'false' - TestCase: Name: case3 Op: 'null' In: '42' Out: 'null' - TestCase: Name: case4 Op: '1' In: 'null' Out: '1' - TestCase: Name: case5 Op: '-1' In: 'null' Out: '-1' - Comment: Str: 'FIXME: much more number testing needed' - TestCase: Name: case6 Op: '{}' In: 'null' Out: '{}' - TestCase: Name: case7 Op: '[]' In: 'null' Out: '[]' - TestCase: Name: case8 Op: '{x: -1}' In: 'null' Out: '{"x": -1}' - Comment: Str: 'The input line starts with a 0xFEFF (byte order mark) codepoint' - Comment: Str: 'No, there is no reason to have a byte order mark in UTF8 text.' - Comment: Str: 'But apparently people do, so jq shouldnt break on it.' - Comment: Str: 'We test escapes by matching them against Unicode codepoints' - Comment: Str: 'FIXME: more tests needed for weird unicode stuff (e.g. utf16 pairs)' - TestCase: Name: case9 Op: '"Aa\r\n\t\b\f\u03bc"' In: 'null' Out: '"Aa\u000d\u000a\u0009\u0008\u000c\u03bc"' - TestCase: Name: case10 Op: '.' In: '"Aa\r\n\t\b\f\u03bc"' Out: '"Aa\u000d\u000a\u0009\u0008\u000c\u03bc"' - TestCase: Name: case11 Op: '"inter\("pol" + "ation")"' In: 'null' Out: '"interpolation"' - TestCase: Name: case12 Op: '@text,@json,([1,.] | (@csv, @tsv)),@html,@uri,@sh,@base64' In: "<>&'\"\t" Out: "<>&'\"\t" - Comment: Str: 'regression test for #436' - TestCase: Name: case13 Op: '@base64' In: '"foÃŗbar\n"' Out: '"Zm/Ds2Jhcgo="' - TestCase: Name: case14 Op: '@uri' In: '"\u03bc"' Out: '"%CE%BC"' - TestCase: Name: case15 Op: '@html "\(.)"' In: '""' Out: '"<script>hax</script>"' - TestCase: Name: case16 Op: '[.[]|tojson|fromjson]' In: '["foo", 1, ["a", 1, "b", 2, {"foo":"bar"}]]' Out: '["foo",1,["a",1,"b",2,{"foo":"bar"}]]' - Comment: Str: '' - Comment: Str: 'Dictionary construction syntax' - Comment: Str: '' - TestCase: Name: case17 Op: '{a: 1}' In: 'null' Out: '{"a":1}' - TestCase: Name: case18 Op: '{a,b,(.d):.a,e:.b}' In: '{"a":1, "b":2, "c":3, "d":"c"}' Out: '{"a":1, "b":2, "c":1, "e":2}' - TestCase: Name: case19 Op: '{"a",b,"a$\(1+1)"}' In: '{"a":1, "b":2, "c":3, "a$2":4}' Out: '{"a":1, "b":2, "a$2":4}' - Comment: Str: '' - Comment: Str: 'Field access, piping' - Comment: Str: '' - TestCase: Name: case20 Op: '.foo' In: '{"foo": 42, "bar": 43}' Out: '42' - TestCase: Name: case21 Op: '.foo | .bar' In: '{"foo": {"bar": 42}, "bar": "badvalue"}' Out: '42' - TestCase: Name: case22 Op: '.foo.bar' In: '{"foo": {"bar": 42}, "bar": "badvalue"}' Out: '42' - TestCase: Name: case23 Op: '.foo_bar' In: '{"foo_bar": 2}' Out: '2' - TestCase: Name: case24 Op: '.["foo"].bar' In: '{"foo": {"bar": 42}, "bar": "badvalue"}' Out: '42' - TestCase: Name: case25 Op: '."foo"."bar"' In: '{"foo": {"bar": 20}}' Out: '20' - TestCase: Name: case26 Op: '[.[]|.foo?]' In: '[1,[2],{"foo":3,"bar":4},{},{"foo":5}]' Out: '[3,null,5]' - TestCase: Name: case27 Op: '[.[]|.foo?.bar?]' In: '[1,[2],[],{"foo":3},{"foo":{"bar":4}},{}]' Out: '[4,null]' - TestCase: Name: case28 Op: '[..]' In: '[1,[[2]],{ "a":[1]}]' Out: '[[1,[[2]],{"a":[1]}],1,[[2]],[2],2,{"a":[1]},[1],1]' - TestCase: Name: case29 Op: '[.[]|.[]?]' In: '[1,null,[],[1,[2,[[3]]]],[{}],[{"a":[1,[2]]}]]' Out: '[1,[2,[[3]]],{},{"a":[1,[2]]}]' - TestCase: Name: case30 Op: '[.[]|.[1:3]?]' In: '[1,null,true,false,"abcdef",{},{"a":1,"b":2},[],[1,2,3,4,5],[1,2]]' Out: '[null,"bc",[],[2,3],[2]]' - Comment: Str: '' - Comment: Str: 'Negative array indices' - Comment: Str: '' - TestCase: Name: case31 Op: 'try (.foo[-1] = 0) catch .' In: 'null' Out: '"Out of bounds negative array index"' - TestCase: Name: case32 Op: 'try (.foo[-2] = 0) catch .' In: 'null' Out: '"Out of bounds negative array index"' - TestCase: Name: case33 Op: '.[-1] = 5' In: '[0,1,2]' Out: '[0,1,5]' - TestCase: Name: case34 Op: '.[-2] = 5' In: '[0,1,2]' Out: '[0,5,2]' - Comment: Str: '' - Comment: Str: 'Multiple outputs, iteration' - Comment: Str: '' - TestCase: Name: case35 Op: '.[]' In: '[1,2,3]' Out: '1' - TestCase: Name: case36 Op: '1,1' In: '[]' Out: '1' - TestCase: Name: case37 Op: '1,.' In: '[]' Out: '1' - TestCase: Name: case38 Op: '[.]' In: '[2]' Out: '[[2]]' - TestCase: Name: case39 Op: '[[2]]' In: '[3]' Out: '[[2]]' - TestCase: Name: case40 Op: '[{}]' In: '[2]' Out: '[{}]' - TestCase: Name: case41 Op: '[.[]]' In: '["a"]' Out: '["a"]' - TestCase: Name: case42 Op: '[(.,1),((.,.[]),(2,3))]' In: '["a","b"]' Out: '[["a","b"],1,["a","b"],"a","b",2,3]' - TestCase: Name: case43 Op: '[([5,5][]),.,.[]]' In: '[1,2,3]' Out: '[5,5,[1,2,3],1,2,3]' - TestCase: Name: case44 Op: '{x: (1,2)},{x:3} | .x' In: 'null' Out: '1' - TestCase: Name: case45 Op: '.[-2]' In: '[1,2,3]' Out: '2' - TestCase: Name: case46 Op: '[range(0;10)]' In: 'null' Out: '[0,1,2,3,4,5,6,7,8,9]' - TestCase: Name: case47 Op: '[range(0,1;3,4)]' In: 'null' Out: '[0,1,2, 0,1,2,3, 1,2, 1,2,3]' - TestCase: Name: case48 Op: '[range(0;10;3)]' In: 'null' Out: '[0,3,6,9]' - TestCase: Name: case49 Op: '[range(0;10;-1)]' In: 'null' Out: '[]' - TestCase: Name: case50 Op: '[range(0;-5;-1)]' In: 'null' Out: '[0,-1,-2,-3,-4]' - TestCase: Name: case51 Op: '[range(0,1;4,5;1,2)]' In: 'null' Out: '[0,1,2,3,0,2, 0,1,2,3,4,0,2,4, 1,2,3,1,3, 1,2,3,4,1,3]' - TestCase: Name: case52 Op: '[while(.<100; .*2)]' In: '1' Out: '[1,2,4,8,16,32,64]' - TestCase: Name: case53 Op: '[(label $here | .[] | if .>1 then break $here else . end), "hi!"]' In: '[0,1,2]' Out: '[0,1,"hi!"]' - TestCase: Name: case54 Op: '[(label $here | .[] | if .>1 then break $here else . end), "hi!"]' In: '[0,2,1]' Out: '[0,"hi!"]' - TestCase: Name: case55 Op: '[.[]|[.,1]|until(.[0] < 1; [.[0] - 1, .[1] * .[0]])|.[1]]' In: '[1,2,3,4,5]' Out: '[1,2,6,24,120]' - TestCase: Name: case56 Op: '[label $out | foreach .[] as $item ([3, null]; if .[0] < 1 then break $out else [.[0] -1, $item] end; .[1])]' In: '[11,22,33,44,55,66,77,88,99]' Out: '[11,22,33]' - TestCase: Name: case57 Op: '[foreach range(5) as $item (0; $item)]' In: 'null' Out: '[0,1,2,3,4]' - TestCase: Name: case58 Op: '[foreach .[] as [$i, $j] (0; . + $i - $j)]' In: '[[2,1], [5,3], [6,4]]' Out: '[1,3,5]' - TestCase: Name: case59 Op: '[foreach .[] as {a:$a} (0; . + $a; -.)]' In: '[{"a":1}, {"b":2}, {"a":3, "b":4}]' Out: '[-1, -1, -4]' - TestCase: Name: case60 Op: '[limit(3; .[])]' In: '[11,22,33,44,55,66,77,88,99]' Out: '[11,22,33]' - TestCase: Name: case61 Op: '[first(range(.)), last(range(.)), nth(0; range(.)), nth(5; range(.)), try nth(-1; range(.)) catch .]' In: '10' Out: [0,9,0,5,"nth doesn't support negative indices"] - Comment: Str: '' - Comment: Str: 'Check that various builtins evalute all arguments where appropriate,' - Comment: Str: 'doing cartesian products where appropriate.' - Comment: Str: '' - Comment: Str: 'Check that limit does work for each value produced by n!' - TestCase: Name: case62 Op: '[limit(5,7; range(9))]' In: 'null' Out: '[0,1,2,3,4,0,1,2,3,4,5,6]' - Comment: Str: 'Same check for nth' - TestCase: Name: case63 Op: '[nth(5,7; range(9;0;-1))]' In: 'null' Out: '[4,2]' - Comment: Str: 'Same check for range/3' - TestCase: Name: case64 Op: '[range(0,1,2;4,3,2;2,3)]' In: 'null' Out: '[0,2,0,3,0,2,0,0,0,1,3,1,1,1,1,1,2,2,2,2]' - Comment: Str: 'Same check for range/1' - TestCase: Name: case65 Op: '[range(3,5)]' In: 'null' Out: '[0,1,2,0,1,2,3,4]' - Comment: Str: 'Same check for index/1, rindex/1, indices/1' - TestCase: Name: case66 Op: '[(index(",","|"), rindex(",","|")), indices(",","|")]' In: '"a,b|c,d,e||f,g,h,|,|,i,j"' Out: '[1,3,22,19,[1,5,7,12,14,16,18,20,22],[3,9,10,17,19]]' - Comment: Str: 'Same check for join/1' - TestCase: Name: case67 Op: 'join(",","/")' In: '["a","b","c","d"]' Out: '"a,b,c,d"' - TestCase: Name: case68 Op: '[.[]|join("a")]' In: '[[],[""],["",""],["","",""]]' Out: '["","","a","aa"]' - Comment: Str: 'Same check for flatten/1' - TestCase: Name: case69 Op: 'flatten(3,2,1)' In: '[0, [1], [[2]], [[[3]]]]' Out: '[0,1,2,3]' - Comment: Str: '' - Comment: Str: 'Slices' - Comment: Str: '' - TestCase: Name: case70 Op: '[.[3:2], .[-5:4], .[:-2], .[-2:], .[3:3][1:], .[10:]]' In: '[0,1,2,3,4,5,6]' Out: '[[], [2,3], [0,1,2,3,4], [5,6], [], []]' - TestCase: Name: case71 Op: '[.[3:2], .[-5:4], .[:-2], .[-2:], .[3:3][1:], .[10:]]' In: '"abcdefghi"' Out: '["","","abcdefg","hi","",""]' - TestCase: Name: case72 Op: 'del(.[2:4],.[0],.[-2:])' In: '[0,1,2,3,4,5,6,7]' Out: '[1,4,5]' - TestCase: Name: case73 Op: '.[2:4] = ([], ["a","b"], ["a","b","c"])' In: '[0,1,2,3,4,5,6,7]' Out: '[0,1,4,5,6,7]' - Comment: Str: '' - Comment: Str: 'Variables' - Comment: Str: '' - TestCase: Name: case74 Op: '1 as $x | 2 as $y | [$x,$y,$x]' In: 'null' Out: '[1,2,1]' - TestCase: Name: case75 Op: '[1,2,3][] as $x | [[4,5,6,7][$x]]' In: 'null' Out: '[5]' - TestCase: Name: case76 Op: '42 as $x | . | . | . + 432 | $x + 1' In: '34324' Out: '43' - TestCase: Name: case77 Op: '1 as $x | [$x,$x,$x as $x | $x]' In: 'null' Out: '[1,1,1]' - TestCase: Name: case78 Op: '[1, {c:3, d:4}] as [$a, {c:$b, b:$c}] | $a, $b, $c' In: 'null' Out: '1' - TestCase: Name: case79 Op: '. as {as: $kw, "str": $str, ("e"+"x"+"p"): $exp} | [$kw, $str, $exp]' In: '{"as": 1, "str": 2, "exp": 3}' Out: '[1, 2, 3]' - TestCase: Name: case80 Op: '.[] as [$a, $b] | [$b, $a]' In: '[[1], [1, 2, 3]]' Out: '[null, 1]' - TestCase: Name: case81 Op: '. as $i | . as [$i] | $i' In: '[0]' Out: '0' - TestCase: Name: case82 Op: '. as [$i] | . as $i | $i' In: '[0]' Out: '[0]' - Comment: Str: '[.,(.[] | {x:.},.),.,.[]]' - Comment: Str: '' - Comment: Str: 'Builtin functions' - Comment: Str: '' - TestCase: Name: case83 Op: '1+1' In: 'null' Out: '2' - TestCase: Name: case84 Op: '1+1' In: '"wtasdf"' Out: '2.0' - TestCase: Name: case85 Op: '2-1' In: 'null' Out: '1' - TestCase: Name: case86 Op: '2-(-1)' In: 'null' Out: '3' - TestCase: Name: case87 Op: '1e+0+0.001e3' In: '"I wonder what this will be?"' Out: '20e-1' - TestCase: Name: case88 Op: '.+4' In: '15' Out: '19.0' - TestCase: Name: case89 Op: '.+null' In: '{"a":42}' Out: '{"a":42}' - TestCase: Name: case90 Op: 'null+.' In: 'null' Out: 'null' - TestCase: Name: case91 Op: '.a+.b' In: '{"a":42}' Out: '42' - TestCase: Name: case92 Op: '[1,2,3] + [.]' In: 'null' Out: '[1,2,3,null]' - TestCase: Name: case93 Op: '{"a":1} + {"b":2} + {"c":3}' In: '"asdfasdf"' Out: '{"a":1, "b":2, "c":3}' - TestCase: Name: case94 Op: '"asdf" + "jkl;" + . + . + .' In: '"some string"' Out: '"asdfjkl;some stringsome stringsome string"' - TestCase: Name: case95 Op: '"\u0000\u0020\u0000" + .' In: '"\u0000\u0020\u0000"' Out: '"\u0000 \u0000\u0000 \u0000"' - TestCase: Name: case96 Op: '42 - .' In: '11' Out: '31' - TestCase: Name: case97 Op: '[1,2,3,4,1] - [.,3]' In: '1' Out: '[2,4]' - TestCase: Name: case98 Op: '[10 * 20, 20 / .]' In: '4' Out: '[200, 5]' - TestCase: Name: case99 Op: '1 + 2 * 2 + 10 / 2' In: 'null' Out: '10' - TestCase: Name: case100 Op: '[16 / 4 / 2, 16 / 4 * 2, 16 - 4 - 2, 16 - 4 + 2]' In: 'null' Out: '[2, 8, 10, 14]' - TestCase: Name: case101 Op: '25 % 7' In: 'null' Out: '4' - TestCase: Name: case102 Op: '49732 % 472' In: 'null' Out: '172' - TestCase: Name: case103 Op: '1 + tonumber + ("10" | tonumber)' In: '4' Out: '15' - TestCase: Name: case104 Op: '[{"a":42},.object,10,.num,false,true,null,"b",[1,4]] | .[] as $x | [$x == .[]]' In: '{"object": {"a":42}, "num":10.0}' Out: '[true, true, false, false, false, false, false, false, false]' - TestCase: Name: case105 Op: '[.[] | length]' In: '[[], {}, [1,2], {"a":42}, "asdf", "\u03bc"]' Out: '[0, 0, 2, 1, 4, 1]' - TestCase: Name: case106 Op: 'utf8bytelength' In: '"asdf\u03bc"' Out: '6' - TestCase: Name: case107 Op: '[.[] | try utf8bytelength catch .]' In: '[[], {}, [1,2], 55, true, false]' Out: '["array ([]) only strings have UTF-8 byte length","object ({}) only strings have UTF-8 byte length","array ([1,2]) only strings have UTF-8 byte length","number (55) only strings have UTF-8 byte length","boolean (true) only strings have UTF-8 byte length","boolean (false) only strings have UTF-8 byte length"]' - TestCase: Name: case108 Op: 'map(keys)' In: '[{}, {"abcd":1,"abc":2,"abcde":3}, {"x":1, "z": 3, "y":2}]' Out: '[[], ["abc","abcd","abcde"], ["x","y","z"]]' - TestCase: Name: case109 Op: '[1,2,empty,3,empty,4]' In: 'null' Out: '[1,2,3,4]' - TestCase: Name: case110 Op: 'map(add)' In: '[[], [1,2,3], ["a","b","c"], [[3],[4,5],[6]], [{"a":1}, {"b":2}, {"a":3}]]' Out: '[null, 6, "abc", [3,4,5,6], {"a":3, "b": 2}]' - TestCase: Name: case111 Op: 'map_values(.+1)' In: '[0,1,2]' Out: '[1,2,3]' - Comment: Str: '' - Comment: Str: 'User-defined functions' - Comment: Str: 'Oh god.' - Comment: Str: '' - TestCase: Name: case112 Op: 'def f: . + 1; def g: def g: . + 100; f | g | f; (f | g), g' In: '3.0' Out: '106.0' - TestCase: Name: case113 Op: 'def f: (1000,2000); f' In: '123412345' Out: '1000' - TestCase: Name: case114 Op: 'def f(a;b;c;d;e;f): [a+1,b,c,d,e,f]; f(.[0];.[1];.[0];.[0];.[0];.[0])' In: '[1,2]' Out: '[2,2,1,1,1,1]' - Comment: Str: 'Test precedence of def vs |' - TestCase: Name: case115 Op: 'def a: 0; . | a' In: 'null' Out: '0' - Comment: Str: 'Many arguments' - TestCase: Name: case116 Op: 'def f(a;b;c;d;e;f;g;h;i;j): [j,i,h,g,f,e,d,c,b,a]; f(.[0];.[1];.[2];.[3];.[4];.[5];.[6];.[7];.[8];.[9])' In: '[0,1,2,3,4,5,6,7,8,9]' Out: '[9,8,7,6,5,4,3,2,1,0]' - TestCase: Name: case117 Op: '([1,2] + [4,5])' In: '[1,2,3]' Out: '[1,2,4,5]' - TestCase: Name: case118 Op: 'true' In: '[1]' Out: 'true' - TestCase: Name: case119 Op: 'null,1,null' In: '"hello"' Out: 'null' - TestCase: Name: case120 Op: '[1,2,3]' In: '[5,6]' Out: '[1,2,3]' - TestCase: Name: case121 Op: '[.[]|floor]' In: '[-1.1,1.1,1.9]' Out: '[-2, 1, 1]' - TestCase: Name: case122 Op: '[.[]|sqrt]' In: '[4,9]' Out: '[2,3]' - TestCase: Name: case123 Op: '(add / length) as $m | map((. - $m) as $d | $d * $d) | add / length | sqrt' In: '[2,4,4,4,5,5,7,9]' Out: '2' - Comment: Str: 'Should write a test that calls the -lm function from C (or bc(1)) to' - Comment: Str: 'check that they match the corresponding jq functions. However,' - Comment: Str: 'theres so little template code standing between that it suffices to' - Comment: Str: 'test a handful of these. The results were checked by eye against' - Comment: Str: 'bc(1).' - TestCase: Name: case124 Op: 'atan * 4 * 1000000|floor / 1000000' In: '1' Out: '3.141592' - TestCase: Name: case125 Op: '[(3.141592 / 2) * (range(0;20) / 20)|cos * 1000000|floor / 1000000]' In: 'null' Out: '[1,0.996917,0.987688,0.972369,0.951056,0.923879,0.891006,0.85264,0.809017,0.760406,0.707106,0.649448,0.587785,0.522498,0.45399,0.382683,0.309017,0.233445,0.156434,0.078459]' - TestCase: Name: case126 Op: '[(3.141592 / 2) * (range(0;20) / 20)|sin * 1000000|floor / 1000000]' In: 'null' Out: '[0,0.078459,0.156434,0.233445,0.309016,0.382683,0.45399,0.522498,0.587785,0.649447,0.707106,0.760405,0.809016,0.85264,0.891006,0.923879,0.951056,0.972369,0.987688,0.996917]' - TestCase: Name: case127 Op: 'def f(x): x | x; f([.], . + [42])' In: '[1,2,3]' Out: '[[[1,2,3]]]' - Comment: Str: 'test multiple function arities and redefinition' - TestCase: Name: case128 Op: 'def f: .+1; def g: f; def f: .+100; def f(a):a+.+11; [(g|f(20)), f]' In: '1' Out: '[33,101]' - Comment: Str: 'test closures and lexical scoping' - TestCase: Name: case129 Op: 'def id(x):x; 2000 as $x | def f(x):1 as $x | id([$x, x, x]); def g(x): 100 as $x | f($x,$x+x); g($x)' In: '"more testing"' Out: '[1,100,2100.0,100,2100.0]' - Comment: Str: 'test def f($a) syntax' - TestCase: Name: case130 Op: 'def x(a;b): a as $a | b as $b | $a + $b; def y($a;$b): $a + $b; def check(a;b): [x(a;b)] == [y(a;b)]; check(.[];.[]*2)' In: '[1,2,3]' Out: 'true' - Comment: Str: 'test backtracking through function calls and returns' - Comment: Str: 'this test is *evil*' - TestCase: Name: case131 Op: '[[20,10][1,0] as $x | def f: (100,200) as $y | def g: [$x + $y, .]; . + $x | g; f[0] | [f][0][1] | f]' In: '999999999' Out: '[[110.0, 130.0], [210.0, 130.0], [110.0, 230.0], [210.0, 230.0], [120.0, 160.0], [220.0, 160.0], [120.0, 260.0], [220.0, 260.0]]' - Comment: Str: 'test recursion' - TestCase: Name: case132 Op: 'def fac: if . == 1 then 1 else . * (. - 1 | fac) end; [.[] | fac]' In: '[1,2,3,4]' Out: '[1,2,6,24]' - Comment: Str: 'test stack overflow and reallocation' - Comment: Str: 'this test is disabled for now, it takes a realllllly long time.' - Comment: Str: 'def f: if length > 1000 then . else .+[1]|f end; f | length' - Comment: Str: '[]' - Comment: Str: '1001' - TestCase: Name: case133 Op: 'reduce .[] as $x (0; . + $x)' In: '[1,2,4]' Out: '7' - TestCase: Name: case134 Op: 'reduce .[] as [$i, {j:$j}] (0; . + $i - $j)' In: '[[2,{"j":1}], [5,{"j":3}], [6,{"j":4}]]' Out: '5' - TestCase: Name: case135 Op: 'reduce [[1,2,10], [3,4,10]][] as [$i,$j] (0; . + $i * $j)' In: 'null' Out: '14' - TestCase: Name: case136 Op: '. as $dot|any($dot[];not)' In: '[1,2,3,4,true,false,1,2,3,4,5]' Out: 'true' - TestCase: Name: case137 Op: '. as $dot|any($dot[];not)' In: '[1,2,3,4,true]' Out: 'false' - TestCase: Name: case138 Op: '. as $dot|all($dot[];.)' In: '[1,2,3,4,true,false,1,2,3,4,5]' Out: 'false' - TestCase: Name: case139 Op: '. as $dot|all($dot[];.)' In: '[1,2,3,4,true]' Out: 'true' - Comment: Str: '' - Comment: Str: 'Paths' - Comment: Str: '' - TestCase: Name: case140 Op: 'path(.foo[0,1])' In: 'null' Out: '["foo", 0]' - TestCase: Name: case141 Op: 'path(.[] | select(.>3))' In: '[1,5,3]' Out: '[1]' - TestCase: Name: case142 Op: 'path(.)' In: '42' Out: '[]' - TestCase: Name: case143 Op: 'try path(.a | map(select(.b == 0))) catch .' In: '{"a":[{"b":0}]}' Out: '"Invalid path expression with result [{\"b\":0}]"' - TestCase: Name: case144 Op: 'try path(.a | map(select(.b == 0)) | .[0]) catch .' In: '{"a":[{"b":0}]}' Out: '"Invalid path expression near attempt to access element 0 of [{\"b\":0}]"' - TestCase: Name: case145 Op: 'try path(.a | map(select(.b == 0)) | .c) catch .' In: '{"a":[{"b":0}]}' Out: '"Invalid path expression near attempt to access element \"c\" of [{\"b\":0}]"' - TestCase: Name: case146 Op: 'try path(.a | map(select(.b == 0)) | .[]) catch .' In: '{"a":[{"b":0}]}' Out: '"Invalid path expression near attempt to iterate through [{\"b\":0}]"' - TestCase: Name: case147 Op: 'path(.a[path(.b)[0]])' In: '{"a":{"b":0}}' Out: '["a","b"]' - TestCase: Name: case148 Op: '[paths]' In: '[1,[[],{"a":2}]]' Out: '[[0],[1],[1,0],[1,1],[1,1,"a"]]' - TestCase: Name: case149 Op: '[leaf_paths]' In: '[1,[[],{"a":2}]]' Out: '[[0],[1,1,"a"]]' - TestCase: Name: case150 Op: '["foo",1] as $p | getpath($p), setpath($p; 20), delpaths([$p])' In: '{"bar": 42, "foo": ["a", "b", "c", "d"]}' Out: '"b"' - TestCase: Name: case151 Op: 'map(getpath([2])), map(setpath([2]; 42)), map(delpaths([[2]]))' In: '[[0], [0,1], [0,1,2]]' Out: '[null, null, 2]' - TestCase: Name: case152 Op: 'map(delpaths([[0,"foo"]]))' In: '[[{"foo":2, "x":1}], [{"bar":2}]]' Out: '[[{"x":1}], [{"bar":2}]]' - TestCase: Name: case153 Op: '["foo",1] as $p | getpath($p), setpath($p; 20), delpaths([$p])' In: '{"bar":false}' Out: 'null' - TestCase: Name: case154 Op: 'delpaths([[-200]])' In: '[1,2,3]' Out: '[1,2,3]' - TestCase: Name: case155 Op: 'try delpaths(0) catch .' In: '{}' Out: '"Paths must be specified as an array"' - TestCase: Name: case156 Op: 'del(.), del(empty), del((.foo,.bar,.baz) | .[2,3,0]), del(.foo[0], .bar[0], .foo, .baz.bar[0].x)' In: '{"foo": [0,1,2,3,4], "bar": [0,1]}' Out: 'null' - TestCase: Name: case157 Op: 'del(.[1], .[-6], .[2], .[-3:9])' In: '[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]' Out: '[0, 3, 5, 6, 9]' - Comment: Str: '' - Comment: Str: 'Assignment' - Comment: Str: '' - TestCase: Name: case158 Op: '.message = "goodbye"' In: '{"message": "hello"}' Out: '{"message": "goodbye"}' - TestCase: Name: case159 Op: '.foo = .bar' In: '{"bar":42}' Out: '{"foo":42, "bar":42}' - TestCase: Name: case160 Op: '.foo |= .+1' In: '{"foo": 42}' Out: '{"foo": 43}' - TestCase: Name: case161 Op: '.[] += 2, .[] *= 2, .[] -= 2, .[] /= 2, .[] %=2' In: '[1,3,5]' Out: '[3,5,7]' - TestCase: Name: case162 Op: '[.[] % 7]' In: '[-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7]' Out: '[0,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,0]' - TestCase: Name: case163 Op: '.foo += .foo' In: '{"foo":2}' Out: '{"foo":4}' - TestCase: Name: case164 Op: '.[0].a |= {"old":., "new":(.+1)}' In: '[{"a":1,"b":2}]' Out: '[{"a":{"old":1, "new":2},"b":2}]' - TestCase: Name: case165 Op: 'def inc(x): x |= .+1; inc(.[].a)' In: '[{"a":1,"b":2},{"a":2,"b":4},{"a":7,"b":8}]' Out: '[{"a":2,"b":2},{"a":3,"b":4},{"a":8,"b":8}]' - TestCase: Name: case166 Op: '.[2][3] = 1' In: '[4]' Out: '[4, null, [null, null, null, 1]]' - TestCase: Name: case167 Op: '.foo[2].bar = 1' In: '{"foo":[11], "bar":42}' Out: '{"foo":[11,null,{"bar":1}], "bar":42}' - TestCase: Name: case168 Op: 'try ((map(select(.a == 1))[].b) = 10) catch .' In: '[{"a":0},{"a":1}]' Out: '"Invalid path expression near attempt to iterate through [{\"a\":1}]"' - TestCase: Name: case169 Op: 'try ((map(select(.a == 1))[].a) |= .+1) catch .' In: '[{"a":0},{"a":1}]' Out: '"Invalid path expression near attempt to iterate through [{\"a\":1}]"' - TestCase: Name: case170 Op: 'def x: .[1,2]; x=10' In: '[0,1,2]' Out: '[0,10,10]' - TestCase: Name: case171 Op: 'try (def x: reverse; x=10) catch .' In: '[0,1,2]' Out: '"Invalid path expression with result [2,1,0]"' - TestCase: Name: case172 Op: '.[] = 1' In: '[1,null,Infinity,-Infinity,NaN,-NaN]' Out: '[1,1,1,1,1,1]' - Comment: Str: '' - Comment: Str: 'Conditionals' - Comment: Str: '' - TestCase: Name: case173 Op: '[.[] | if .foo then "yep" else "nope" end]' In: '[{"foo":0},{"foo":1},{"foo":[]},{"foo":true},{"foo":false},{"foo":null},{"foo":"foo"},{}]' Out: '["yep","yep","yep","yep","nope","nope","yep","nope"]' - TestCase: Name: case174 Op: '[.[] | if .baz then "strange" elif .foo then "yep" else "nope" end]' In: '[{"foo":0},{"foo":1},{"foo":[]},{"foo":true},{"foo":false},{"foo":null},{"foo":"foo"},{}]' Out: '["yep","yep","yep","yep","nope","nope","yep","nope"]' - TestCase: Name: case175 Op: '[if 1,null,2 then 3 else 4 end]' In: 'null' Out: '[3,4,3]' - TestCase: Name: case176 Op: '[if empty then 3 else 4 end]' In: 'null' Out: '[]' - TestCase: Name: case177 Op: '[if 1 then 3,4 else 5 end]' In: 'null' Out: '[3,4]' - TestCase: Name: case178 Op: '[if null then 3 else 5,6 end]' In: 'null' Out: '[5,6]' - TestCase: Name: case179 Op: '[.[] | [.foo[] // .bar]]' In: '[{"foo":[1,2], "bar": 42}, {"foo":[1], "bar": null}, {"foo":[null,false,3], "bar": 18}, {"foo":[], "bar":42}, {"foo": [null,false,null], "bar": 41}]' Out: '[[1,2], [1], [3], [42], [41]]' - TestCase: Name: case180 Op: '.[] //= .[0]' In: '["hello",true,false,[false],null]' Out: '["hello",true,"hello",[false],"hello"]' - TestCase: Name: case181 Op: '.[] | [.[0] and .[1], .[0] or .[1]]' In: '[[true,[]], [false,1], [42,null], [null,false]]' Out: '[true,true]' - TestCase: Name: case182 Op: '[.[] | not]' In: '[1,0,false,null,true,"hello"]' Out: '[false,false,true,true,false,false]' - Comment: Str: 'Check numeric comparison binops' - TestCase: Name: case183 Op: '[10 > 0, 10 > 10, 10 > 20, 10 < 0, 10 < 10, 10 < 20]' In: '{}' Out: '[true,false,false,false,false,true]' - TestCase: Name: case184 Op: '[10 >= 0, 10 >= 10, 10 >= 20, 10 <= 0, 10 <= 10, 10 <= 20]' In: '{}' Out: '[true,true,false,false,true,true]' - Comment: Str: 'And some in/equality tests' - TestCase: Name: case185 Op: '[ 10 == 10, 10 != 10, 10 != 11, 10 == 11]' In: '{}' Out: '[true,false,true,false]' - TestCase: Name: case186 Op: '["hello" == "hello", "hello" != "hello", "hello" == "world", "hello" != "world" ]' In: '{}' Out: '[true,false,false,true]' - TestCase: Name: case187 Op: '[[1,2,3] == [1,2,3], [1,2,3] != [1,2,3], [1,2,3] == [4,5,6], [1,2,3] != [4,5,6]]' In: '{}' Out: '[true,false,false,true]' - TestCase: Name: case188 Op: '[{"foo":42} == {"foo":42},{"foo":42} != {"foo":42}, {"foo":42} != {"bar":42}, {"foo":42} == {"bar":42}]' In: '{}' Out: '[true,false,true,false]' - Comment: Str: 'ugly complicated thing' - TestCase: Name: case189 Op: '[{"foo":[1,2,{"bar":18},"world"]} == {"foo":[1,2,{"bar":18},"world"]},{"foo":[1,2,{"bar":18},"world"]} == {"foo":[1,2,{"bar":19},"world"]}]' In: '{}' Out: '[true,false]' - Comment: Str: 'containment operator' - TestCase: Name: case190 Op: '[("foo" | contains("foo")), ("foobar" | contains("foo")), ("foo" | contains("foobar"))]' In: '{}' Out: '[true, true, false]' - Comment: Str: 'Try/catch and general `?` operator' - TestCase: Name: case191 Op: '[.[]|try if . == 0 then error("foo") elif . == 1 then .a elif . == 2 then empty else . end catch .]' In: '[0,1,2,3]' Out: '["foo","Cannot index number with string \"a\"",3]' - TestCase: Name: case192 Op: '[.[]|(.a, .a)?]' In: '[null,true,{"a":1}]' Out: '[null,null,1,1]' - TestCase: Name: case193 Op: '[[.[]|[.a,.a]]?]' In: '[null,true,{"a":1}]' Out: '[]' - TestCase: Name: case194 Op: 'try error("\($__loc__)") catch .' In: 'null' Out: '"{\"file\":\"\",\"line\":1}"' - Comment: Str: 'string operations' - TestCase: Name: case195 Op: '[.[]|startswith("foo")]' In: '["fo", "foo", "barfoo", "foobar", "barfoob"]' Out: '[false, true, false, true, false]' - TestCase: Name: case196 Op: '[.[]|endswith("foo")]' In: '["fo", "foo", "barfoo", "foobar", "barfoob"]' Out: '[false, true, true, false, false]' - TestCase: Name: case197 Op: '[.[] | split(", ")]' In: '["a,b, c, d, e,f",", a,b, c, d, e,f, "]' Out: '[["a,b","c","d","e,f"],["","a,b","c","d","e,f",""]]' - TestCase: Name: case198 Op: 'split("")' In: '"abc"' Out: '["a","b","c"]' - TestCase: Name: case199 Op: '[.[]|ltrimstr("foo")]' In: '["fo", "foo", "barfoo", "foobar", "afoo"]' Out: '["fo","","barfoo","bar","afoo"]' - TestCase: Name: case200 Op: '[.[]|rtrimstr("foo")]' In: '["fo", "foo", "barfoo", "foobar", "foob"]' Out: '["fo","","bar","foobar","foob"]' - TestCase: Name: case201 Op: '[(index(","), rindex(",")), indices(",")]' In: '"a,bc,def,ghij,klmno"' Out: '[1,13,[1,4,8,13]]' - TestCase: Name: case202 Op: 'indices(1)' In: '[0,1,1,2,3,4,1,5]' Out: '[1,2,6]' - TestCase: Name: case203 Op: 'indices([1,2])' In: '[0,1,2,3,1,4,2,5,1,2,6,7]' Out: '[1,8]' - TestCase: Name: case204 Op: 'indices([1,2])' In: '[1]' Out: '[]' - TestCase: Name: case205 Op: 'indices(", ")' In: '"a,b, cd,e, fgh, ijkl"' Out: '[3,9,14]' - TestCase: Name: case206 Op: '[.[]|split(",")]' In: '["a, bc, def, ghij, jklmn, a,b, c,d, e,f", "a,b,c,d, e,f,g,h"]' Out: '[["a"," bc"," def"," ghij"," jklmn"," a","b"," c","d"," e","f"],["a","b","c","d"," e","f","g","h"]]' - TestCase: Name: case207 Op: '[.[]|split(", ")]' In: '["a, bc, def, ghij, jklmn, a,b, c,d, e,f", "a,b,c,d, e,f,g,h"]' Out: '[["a","bc","def","ghij","jklmn","a,b","c,d","e,f"],["a,b,c,d","e,f,g,h"]]' - TestCase: Name: case208 Op: '[.[] * 3]' In: '["a", "ab", "abc"]' Out: '["aaa", "ababab", "abcabcabc"]' - TestCase: Name: case209 Op: '[.[] / ","]' In: '["a, bc, def, ghij, jklmn, a,b, c,d, e,f", "a,b,c,d, e,f,g,h"]' Out: '[["a"," bc"," def"," ghij"," jklmn"," a","b"," c","d"," e","f"],["a","b","c","d"," e","f","g","h"]]' - TestCase: Name: case210 Op: '[.[] / ", "]' In: '["a, bc, def, ghij, jklmn, a,b, c,d, e,f", "a,b,c,d, e,f,g,h"]' Out: '[["a","bc","def","ghij","jklmn","a,b","c,d","e,f"],["a,b,c,d","e,f,g,h"]]' - TestCase: Name: case211 Op: 'map(.[1] as $needle | .[0] | contains($needle))' In: '[[[],[]], [[1,2,3], [1,2]], [[1,2,3], [3,1]], [[1,2,3], [4]], [[1,2,3], [1,4]]]' Out: '[true, true, true, false, false]' - TestCase: Name: case212 Op: 'map(.[1] as $needle | .[0] | contains($needle))' In: '[[["foobar", "foobaz"], ["baz", "bar"]], [["foobar", "foobaz"], ["foo"]], [["foobar", "foobaz"], ["blap"]]]' Out: '[true, true, false]' - TestCase: Name: case213 Op: '[({foo: 12, bar:13} | contains({foo: 12})), ({foo: 12} | contains({})), ({foo: 12, bar:13} | contains({baz:14}))]' In: '{}' Out: '[true, true, false]' - TestCase: Name: case214 Op: '{foo: {baz: 12, blap: {bar: 13}}, bar: 14} | contains({bar: 14, foo: {blap: {}}})' In: '{}' Out: 'true' - TestCase: Name: case215 Op: '{foo: {baz: 12, blap: {bar: 13}}, bar: 14} | contains({bar: 14, foo: {blap: {bar: 14}}})' In: '{}' Out: 'false' - TestCase: Name: case216 Op: 'sort' In: '[42,[2,5,3,11],10,{"a":42,"b":2},{"a":42},true,2,[2,6],"hello",null,[2,5,6],{"a":[],"b":1},"abc","ab",[3,10],{},false,"abcd",null]' Out: '[null,null,false,true,2,10,42,"ab","abc","abcd","hello",[2,5,3,11],[2,5,6],[2,6],[3,10],{},{"a":42},{"a":42,"b":2},{"a":[],"b":1}]' - TestCase: Name: case217 Op: '(sort_by(.b) | sort_by(.a)), sort_by(.a, .b), sort_by(.b, .c), group_by(.b), group_by(.a + .b - .c == 2)' In: '[{"a": 1, "b": 4, "c": 14}, {"a": 4, "b": 1, "c": 3}, {"a": 1, "b": 4, "c": 3}, {"a": 0, "b": 2, "c": 43}]' Out: '[{"a": 0, "b": 2, "c": 43}, {"a": 1, "b": 4, "c": 14}, {"a": 1, "b": 4, "c": 3}, {"a": 4, "b": 1, "c": 3}]' - TestCase: Name: case218 Op: 'unique' In: '[1,2,5,3,5,3,1,3]' Out: '[1,2,3,5]' - TestCase: Name: case219 Op: 'unique' In: '[]' Out: '[]' - TestCase: Name: case220 Op: '[min, max, min_by(.[1]), max_by(.[1]), min_by(.[2]), max_by(.[2])]' In: '[[4,2,"a"],[3,1,"a"],[2,4,"a"],[1,3,"a"]]' Out: '[[1,3,"a"],[4,2,"a"],[3,1,"a"],[2,4,"a"],[4,2,"a"],[1,3,"a"]]' - TestCase: Name: case221 Op: '[min,max,min_by(.),max_by(.)]' In: '[]' Out: '[null,null,null,null]' - TestCase: Name: case222 Op: '.foo[.baz]' In: '{"foo":{"bar":4},"baz":"bar"}' Out: '4' - TestCase: Name: case223 Op: .[] | .error = "no, it's OK" In: '[{"error":true}]' Out: {"error": "no, it's OK"} - TestCase: Name: case224 Op: '[{a:1}] | .[] | .a=999' In: 'null' Out: '{"a": 999}' - TestCase: Name: case225 Op: 'to_entries' In: '{"a": 1, "b": 2}' Out: '[{"key":"a", "value":1}, {"key":"b", "value":2}]' - TestCase: Name: case226 Op: 'from_entries' In: '[{"key":"a", "value":1}, {"Key":"b", "Value":2}, {"name":"c", "value":3}, {"Name":"d", "Value":4}]' Out: '{"a": 1, "b": 2, "c": 3, "d": 4}' - TestCase: Name: case227 Op: 'with_entries(.key |= "KEY_" + .)' In: '{"a": 1, "b": 2}' Out: '{"KEY_a": 1, "KEY_b": 2}' - TestCase: Name: case228 Op: 'map(has("foo"))' In: '[{"foo": 42}, {}]' Out: '[true, false]' - TestCase: Name: case229 Op: 'map(has(2))' In: '[[0,1], ["a","b","c"]]' Out: '[false, true]' - TestCase: Name: case230 Op: 'keys' In: '[42,3,35]' Out: '[0,1,2]' - TestCase: Name: case231 Op: '[][.]' In: '1000000000000000000' Out: 'null' - TestCase: Name: case232 Op: 'map([1,2][0:.])' In: '[-1, 1, 2, 3, 1000000000000000000]' Out: '[[1], [1], [1,2], [1,2], [1,2]]' - Comment: Str: 'Test recursive object merge' - TestCase: Name: case233 Op: '{"k": {"a": 1, "b": 2}} * .' In: '{"k": {"a": 0,"c": 3}}' Out: '{"k": {"a": 0, "b": 2, "c": 3}}' - TestCase: Name: case234 Op: '{"k": {"a": 1, "b": 2}, "hello": {"x": 1}} * .' In: '{"k": {"a": 0,"c": 3}, "hello": 1}' Out: '{"k": {"a": 0, "b": 2, "c": 3}, "hello": 1}' - TestCase: Name: case235 Op: '{"k": {"a": 1, "b": 2}, "hello": 1} * .' In: '{"k": {"a": 0,"c": 3}, "hello": {"x": 1}}' Out: '{"k": {"a": 0, "b": 2, "c": 3}, "hello": {"x": 1}}' - TestCase: Name: case236 Op: '{"a": {"b": 1}, "c": {"d": 2}, "e": 5} * .' In: '{"a": {"b": 2}, "c": {"d": 3, "f": 9}}' Out: '{"a": {"b": 2}, "c": {"d": 3, "f": 9}, "e": 5}' - TestCase: Name: case237 Op: '[.[]|arrays]' In: '[1,2,"foo",[],[3,[]],{},true,false,null]' Out: '[[],[3,[]]]' - TestCase: Name: case238 Op: '[.[]|objects]' In: '[1,2,"foo",[],[3,[]],{},true,false,null]' Out: '[{}]' - TestCase: Name: case239 Op: '[.[]|iterables]' In: '[1,2,"foo",[],[3,[]],{},true,false,null]' Out: '[[],[3,[]],{}]' - TestCase: Name: case240 Op: '[.[]|scalars]' In: '[1,2,"foo",[],[3,[]],{},true,false,null]' Out: '[1,2,"foo",true,false,null]' - TestCase: Name: case241 Op: '[.[]|values]' In: '[1,2,"foo",[],[3,[]],{},true,false,null]' Out: '[1,2,"foo",[],[3,[]],{},true,false]' - TestCase: Name: case242 Op: '[.[]|booleans]' In: '[1,2,"foo",[],[3,[]],{},true,false,null]' Out: '[true,false]' - TestCase: Name: case243 Op: '[.[]|nulls]' In: '[1,2,"foo",[],[3,[]],{},true,false,null]' Out: '[null]' - TestCase: Name: case244 Op: 'flatten' In: '[0, [1], [[2]], [[[3]]]]' Out: '[0, 1, 2, 3]' - TestCase: Name: case245 Op: 'flatten(0)' In: '[0, [1], [[2]], [[[3]]]]' Out: '[0, [1], [[2]], [[[3]]]]' - TestCase: Name: case246 Op: 'flatten(2)' In: '[0, [1], [[2]], [[[3]]]]' Out: '[0, 1, 2, [3]]' - TestCase: Name: case247 Op: 'flatten(2)' In: '[0, [1, [2]], [1, [[3], 2]]]' Out: '[0, 1, 2, 1, [3], 2]' - TestCase: Name: case248 Op: 'try flatten(-1) catch .' In: '[0, [1], [[2]], [[[3]]]]' Out: '"flatten depth must not be negative"' - TestCase: Name: case249 Op: 'transpose' In: '[[1], [2,3]]' Out: '[[1,2],[null,3]]' - TestCase: Name: case250 Op: 'ascii_upcase' In: '"useful but not for Ê"' Out: '"USEFUL BUT NOT FOR Ê"' - TestCase: Name: case251 Op: 'bsearch(4)' In: '[1,2,3]' Out: '-4' - Comment: Str: 'strptime tests are in optional.test' - TestCase: Name: case252 Op: 'strftime("%Y-%m-%dT%H:%M:%SZ")' In: '[2015,2,5,23,51,47,4,63]' Out: '"2015-03-05T23:51:47Z"' - TestCase: Name: case253 Op: 'strftime("%A, %B %d, %Y")' In: '1435677542.822351' Out: '"Tuesday, June 30, 2015"' - TestCase: Name: case254 Op: 'gmtime' In: '1425599507' Out: '[2015,2,5,23,51,47,4,63]' - Comment: Str: 'module system' - TestCase: Name: case255 Op: 'import "a" as foo; import "b" as bar; def fooa: foo::a; [fooa, bar::a, bar::b, foo::a]' In: 'null' Out: '["a","b","c","a"]' - TestCase: Name: case256 Op: 'import "c" as foo; [foo::a, foo::c]' In: 'null' Out: '[0,"acmehbah"]' - TestCase: Name: case257 Op: 'include "c"; [a, c]' In: 'null' Out: '[0,"acmehbah"]' - TestCase: Name: case258 Op: 'modulemeta' In: '"c"' Out: '{"whatever":null,"deps":[{"as":"foo","is_data":false,"relpath":"a"},{"search":"./","as":"d","is_data":false,"relpath":"d"},{"search":"./","as":"d2","is_data":false,"relpath":"d"},{"search":"./../lib/jq","as":"e","is_data":false,"relpath":"e"},{"search":"./../lib/jq","as":"f","is_data":false,"relpath":"f"},{"as":"d","is_data":true,"relpath":"data"}]}' - TestCase: Name: case259 Op: 'import "test_bind_order" as check; check::check' In: 'null' Out: 'true' - TestCase: Name: case260 Op: 'try -. catch .' In: '"very-long-string"' Out: '"string (\"very-long-...) cannot be negated"' - TestCase: Name: case261 Op: 'join(",")' In: '["1",2,true,false,3.4]' Out: '"1,2,true,false,3.4"' - TestCase: Name: case262 Op: '.[] | join(",")' In: '[[], [null], [null,null], [null,null,null]]' Out: '""' - TestCase: Name: case263 Op: '.[] | join(",")' In: '[["a",null], [null,"a"]]' Out: '"a,"' - TestCase: Name: case264 Op: 'try join(",") catch .' In: '["1","2",{"a":{"b":{"c":33}}}]' Out: '"string (\"1,2,\") and object ({\"a\":{\"b\":{...) cannot be added"' - TestCase: Name: case265 Op: 'try join(",") catch .' In: '["1","2",[3,4,5]]' Out: '"string (\"1,2,\") and array ([3,4,5]) cannot be added"' - TestCase: Name: case266 Op: '{if:0,and:1,or:2,then:3,else:4,elif:5,end:6,as:7,def:8,reduce:9,foreach:10,try:11,catch:12,label:13,import:14,include:15,module:16}' In: 'null' Out: '{"if":0,"and":1,"or":2,"then":3,"else":4,"elif":5,"end":6,"as":7,"def":8,"reduce":9,"foreach":10,"try":11,"catch":12,"label":13,"import":14,"include":15,"module":16}' - TestCase: Name: case267 Op: 'try (1/.) catch .' In: '0' Out: '"number (1) and number (0) cannot be divided because the divisor is zero"' - TestCase: Name: case268 Op: 'try (1%.) catch .' In: '0' Out: '"number (1) and number (0) cannot be divided (remainder) because the divisor is zero"' - Comment: Str: 'Basic numbers tests: integers, powers of two' - TestCase: Name: case269 Op: '[range(-52;52;1)] as $powers | [$powers[]|pow(2;.)|log2] == $powers' In: 'null' Out: 'true' - TestCase: Name: case270 Op: '[range(-99/2;99/2;1)] as $orig | [$orig[]|pow(2;.)|log2] as $back | ($orig|keys)[]|. as $k | (($orig|.[$k])-($back|.[$k]))|if . < 0 then . * -1 else . end|select(.>.00005)' In: 'null' Out: '' - TestCase: Name: case271 Op: '(.[{}] = 0)?' In: 'null' Out: '' easygen-5.1.9/test/jq-test_jq.tmpl000066400000000000000000000031251416363131000171160ustar00rootroot00000000000000// Copyright (c) 2016 Matt Ho // // Test cases code automatically generated by easygen: // https://github.com/go-easygen/easygen // Editing discouraged. // Test cases code Copyright (c) 2016 of project // https://github.com/stedolan/jq // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package jq_test import ( "testing" "github.com/savaki/jq" ) func TestParse(t *testing.T) { testCases := map[string]struct { In string Op string Expected string HasError bool }{ {{range .Cases}}{{if .TestCase}} "{{.TestCase.Name}}": { In: `{{.TestCase.In}}`, Op: `{{.TestCase.Op}}`, Expected: `{{.TestCase.Out}}`, },{{end}}{{if .Comment}} // {{.Comment.Str}}{{end}}{{end}} } for label, tc := range testCases { t.Run(label, func(t *testing.T) { op, err := jq.Parse(tc.Op) if err != nil { t.FailNow() } data, err := op.Apply([]byte(tc.In)) if tc.HasError { if err == nil { t.FailNow() } } else { if string(data) != tc.Expected { t.FailNow() } if err != nil { t.FailNow() } } }) } } easygen-5.1.9/test/list0.ref000066400000000000000000000000441416363131000156650ustar00rootroot00000000000000The colors are: red, blue, white, . easygen-5.1.9/test/list0.tmpl000066400000000000000000000000611416363131000160640ustar00rootroot00000000000000The colors are: {{range .Colors}}{{.}}, {{end}}. easygen-5.1.9/test/list0.yaml000066400000000000000000000000771416363131000160610ustar00rootroot00000000000000Colors: - red - blue - white Colorlist: red blue white easygen-5.1.9/test/list00.tmpl000066400000000000000000000000531416363131000161450ustar00rootroot00000000000000The colors are: {{range .}}{{.}}, {{end}}. easygen-5.1.9/test/list00f.tmpl000066400000000000000000000001441416363131000163140ustar00rootroot00000000000000The colors are: {{range $i, $color := .}}{{$color}}{{if lt $i ($ | len | minus1)}}, {{end}}{{end}}. easygen-5.1.9/test/list01.ref000066400000000000000000000000661416363131000157520ustar00rootroot00000000000000The colors are: red, blue, white, . red, blue, white. easygen-5.1.9/test/list0E.ref000066400000000000000000000001031416363131000157660ustar00rootroot00000000000000The colors are: red, blue, white, . The system shell is: /bin/bash easygen-5.1.9/test/list0E.tmpl000066400000000000000000000001631416363131000161740ustar00rootroot00000000000000The colors are: {{range .Colors}}{{.}}, {{end}}. The system shell is: {{stringsReplace (ENV "SHELL") "/usr" "" 1}} easygen-5.1.9/test/list0j.json000066400000000000000000000001001416363131000162250ustar00rootroot00000000000000{ "Colors": [ "red", "blue", "white" ] }easygen-5.1.9/test/list0j.ref000077700000000000000000000000001416363131000175652list0.refustar00rootroot00000000000000easygen-5.1.9/test/list0j.tmpl000077700000000000000000000000001416363131000201652list0.tmplustar00rootroot00000000000000easygen-5.1.9/test/list1.ref000066400000000000000000000000611416363131000156650ustar00rootroot00000000000000The quoted colors are: "red", "blue", "white", . easygen-5.1.9/test/list1.tmpl000066400000000000000000000000701416363131000160650ustar00rootroot00000000000000The quoted colors are: {{range .Colors}}{{.}}, {{end}}. easygen-5.1.9/test/list1.yaml000066400000000000000000000000621416363131000160540ustar00rootroot00000000000000Colors: - '"red"' - '"blue"' - '"white"' easygen-5.1.9/test/list1HTML.ref000066400000000000000000000001111416363131000163460ustar00rootroot00000000000000The quoted colors are: "red", "blue", "white", . easygen-5.1.9/test/list1HTML.tmpl000066400000000000000000000000771416363131000165610ustar00rootroot00000000000000The quoted colors are: {{range .Colors}}{{. | html}}, {{end}}. easygen-5.1.9/test/listfunc1.ref000066400000000000000000000000221416363131000165360ustar00rootroot00000000000000red, blue, white. easygen-5.1.9/test/listfunc1.tmpl000066400000000000000000000001411416363131000167400ustar00rootroot00000000000000{{range $i, $color := .Colors}}{{$color}}{{if lt $i ($.Colors | len | minus1)}}, {{end}}{{end}}. easygen-5.1.9/test/listfunc1.yaml000077700000000000000000000000001416363131000206442list0.yamlustar00rootroot00000000000000easygen-5.1.9/test/listfunc2.ref000066400000000000000000000000631416363131000165440ustar00rootroot00000000000000some-init-method 5 5 someInitMethod SomeInitMethod easygen-5.1.9/test/listfunc2.tmpl000066400000000000000000000001101416363131000167350ustar00rootroot00000000000000{{.Name}} {{6 | minus1}} {{minus1 6}} {{clk2lc .Name}} {{clk2uc .Name}} easygen-5.1.9/test/listfunc2.yaml000066400000000000000000000001151416363131000167300ustar00rootroot00000000000000Name: some-init-method NameHTTP: HTTP-header-case NameMixed: some_InitMethod easygen-5.1.9/test/mcx-vscode-emacs.tmpl000066400000000000000000000003331416363131000201710ustar00rootroot00000000000000{{range .Keybindings}} {{- if .Command }}{{ if ne .Command "isearchExit" -}} {{- if .Key -}}{{.Key}} {{.Command}} {{ else }}{{$Command := .Command }}{{range .Keys}}{{.}} {{$Command}} {{end}}{{end}}{{end}}{{end}}{{end}} easygen-5.1.9/test/nested_data.yaml000066400000000000000000000001441416363131000172740ustar00rootroot00000000000000Name: Sam OrderNumber: 123456 Price: 1234.56 Shipped: true ShipDate: "Wednesday, January 06, 2021" easygen-5.1.9/test/nested_demo_argsa.ref000066400000000000000000000000421416363131000202730ustar00rootroot00000000000000Got: 543 false 0.1234 Sam 123456 easygen-5.1.9/test/nested_demo_argsa.tmpl000066400000000000000000000002501416363131000204740ustar00rootroot00000000000000{{define "t1"}} {{- index . 0}} {{index . 1}} {{index . 2}} {{(index . 3).Name}} {{(index . 3).OrderNumber}} {{end -}} Got: {{template "t1" argsa 543 false 0.1234 .}} easygen-5.1.9/test/nested_demo_argsm.ref000066400000000000000000000000641416363131000203130ustar00rootroot00000000000000a=1, b=somestring, c.Shipped=true, c.Price=1234.56 easygen-5.1.9/test/nested_demo_argsm.tmpl000066400000000000000000000002401416363131000205070ustar00rootroot00000000000000{{template "image_row" argsm "a" 1 "b" "somestring" "c" .}} {{define "image_row"}}a={{$.a}}, b={{$.b}}, c.Shipped={{$.c.Shipped}}, c.Price={{$.c.Price}}{{end}} easygen-5.1.9/test/nested_demo_argsm_iterate.ref000066400000000000000000000007361416363131000220360ustar00rootroot00000000000000Ape ate Apple000000 at 1234.56 - true0 Ape ate Apple000001 at 1234.56 - true1 Ape ate Apple000002 at 1234.56 - true2 Ape ate Apple000003 at 1234.56 - true3 Ape ate Apple000004 at 1234.56 - true4 Ape ate Apple000005 at 1234.56 - true5 Ape ate Apple000000 at 1234.56 - true0 Ape ate Apple000001 at 1234.56 - true1 Ape ate Apple000002 at 1234.56 - true2 Ape ate Apple001001 at 1234.56 - true1001 Ape ate Apple001002 at 1234.56 - true1002 Ape ate Apple001003 at 1234.56 - true1003 easygen-5.1.9/test/nested_demo_argsm_iterate.tmpl000066400000000000000000000010101416363131000222200ustar00rootroot00000000000000{{- define "T1"}}Apple{{.i}} at {{.c.Price}} - {{.c.Shipped}}{{end}} {{- define "T2"}}Ape{{end}} {{- range $val := iterate "5" }} {{- template "T2"}} ate {{template "T1" argsm "c" $ "i" (printf "%06d" $val)}}{{ $val }} {{end }} {{- range $val := iterate "2" (ENV "__START") }} {{- template "T2"}} ate {{template "T1" argsm "c" $ "i" (printf "%06d" $val)}}{{ $val }} {{end }} {{- range $val := iterate "1003" "1001" }} {{- template "T2"}} ate {{template "T1" argsm "c" $ "i" (printf "%06d" $val)}}{{ $val }} {{end }} easygen-5.1.9/test/nested_footer.tmpl000066400000000000000000000002331416363131000176720ustar00rootroot00000000000000{{define "footer"}} {{date "I"}} Thank you for your business, WidgetCo Order Fulfillment Department Ph: 818-555-0123 Email: orders@widgetco.com {{end}} easygen-5.1.9/test/nested_header.tmpl000066400000000000000000000001221416363131000176210ustar00rootroot00000000000000{{define "header"}} WidgetCo, Ltd. 463 Shoe Factory Rd. Hamford, VT 20202 {{end}} easygen-5.1.9/test/nested_header_footer.ref000066400000000000000000000004621416363131000210060ustar00rootroot00000000000000 WidgetCo, Ltd. 463 Shoe Factory Rd. Hamford, VT 20202 Dear Sam, Thank you for your order! Your order number is 123456 and it has been shipped on Wednesday, January 06, 2021. 2021-09-25 Thank you for your business, WidgetCo Order Fulfillment Department Ph: 818-555-0123 Email: orders@widgetco.com easygen-5.1.9/test/nested_thanks.tmpl000066400000000000000000000002611416363131000176650ustar00rootroot00000000000000{{ template "header" }} Dear {{ .Name }}, Thank you for your order! Your order number is {{ .OrderNumber }} and it has been shipped on {{ .ShipDate }}. {{ template "footer" }} easygen-5.1.9/test/raid_driver.yaml000066400000000000000000000001611416363131000173120ustar00rootroot00000000000000EnumName: raid_driver Values: - Name: HW String: "Hardware-RAID" - Name: SW String: "Software-RAID" easygen-5.1.9/test/raid_type.yaml000066400000000000000000000010601416363131000167770ustar00rootroot00000000000000# EnumName is the type of the Enum in C (Java/Go will use CamelCase) EnumName: raid_type # EnumComments contain documentation that goes above @EnumName EnumComments: - Simplified enumeration of available RAID devices # List of enum values Values: - Name: RAID0 String: "RAID0" # stringified value (defaults to @Name as string) Value: 100 AltString: [ "RAID-0" ] # list of alternatives that translate into @Value - Name: RAID1 AltString: [ "RAID-1" ] # The default value to return if nothing else is known EnumDefault: RAID0 easygen-5.1.9/test/sgdisk-emb.tmpl000066400000000000000000000001301416363131000170530ustar00rootroot00000000000000{{define "sgdisk_cmd"}} sgdisk -n 0:0:{{.Size}} -t 0:{{.Type}} -c 0:"{{.Name}}"{{end}} easygen-5.1.9/test/sgdisk-fstab.tmpl000066400000000000000000000001501416363131000174110ustar00rootroot00000000000000{{range .Partitions}} LABEL={{.Name}} /mnt/{{.Name}} auto noauto,defaults,noatime,nodiratime 0 2{{end}} easygen-5.1.9/test/sgdisk-inc.tmpl000066400000000000000000000001201416363131000170600ustar00rootroot00000000000000 sgdisk -Z {{.Disk}} {{range .Partitions}} {{ template "sgdisk_cmd" .}}{{end}} easygen-5.1.9/test/sgdisk-mp.tmpl000066400000000000000000000001671416363131000167360ustar00rootroot00000000000000{{range .Partitions}} mkdir /mnt/{{.Name}}{{end}} {{range .Partitions}} mount LABEL={{.Name}} /mnt/{{.Name}}{{end}} easygen-5.1.9/test/sgdisk.sh000066400000000000000000000011251416363131000157550ustar00rootroot00000000000000 # format /dev/sdb as GPT, GUID Partition Table sgdisk -Z /dev/sdb sgdisk -n 0:0:+200M -t 0:ef02 -c 0:"bios_boot" /dev/sdb sgdisk -n 0:0:+20G -t 0:8300 -c 0:"linux_boot" /dev/sdb sgdisk -n 0:0:+30G -t 0:0700 -c 0:"windows" /dev/sdb sgdisk -n 0:0:+10G -t 0:8200 -c 0:"linux_swap" /dev/sdb sgdisk -n 0:0:+12G -t 0:8300 -c 0:"os1" /dev/sdb sgdisk -n 0:0:+12G -t 0:8300 -c 0:"os2" /dev/sdb sgdisk -n 0:0:+12G -t 0:8300 -c 0:"os3" /dev/sdb sgdisk -n 0:0:0 -t 0:8300 -c 0:"data" /dev/sdb sgdisk -p /dev/sdb # inform the OS of partition table changes partprobe /dev/sdb fdisk -l /dev/sdb easygen-5.1.9/test/sgdisk.tmpl000066400000000000000000000004231416363131000163170ustar00rootroot00000000000000 # format {{.Disk}} as GPT, GUID Partition Table sgdisk -Z {{.Disk}} {{range .Partitions}} sgdisk -n 0:0:{{.Size}} -t 0:{{.Type}} -c 0:"{{.Name}}" {{$.Disk}}{{end}} sgdisk -p {{.Disk}} # inform the OS of partition table changes partprobe {{.Disk}} fdisk -l {{.Disk}} easygen-5.1.9/test/sgdisk.txt000066400000000000000000000033651416363131000161720ustar00rootroot00000000000000$ sgdisk -p /dev/sdb Disk /dev/sdb: 732558336 sectors, 2.7 TiB Logical sector size: 4096 bytes Disk identifier (GUID): C4426321-9726-4022-BB20-2EF00B490465 Partition table holds up to 128 entries First usable sector is 6, last usable sector is 732558330 Partitions will be aligned on 256-sector boundaries Total free space is 250 sectors (1000.0 KiB) Number Start (sector) End (sector) Size Code Name 1 256 51455 200.0 MiB EF02 bios_boot 2 51456 5294335 20.0 GiB 8300 linux_boot 3 5294336 13158655 30.0 GiB 0700 windows 4 13158656 15780095 10.0 GiB 8200 linux_swap 5 15780096 18925823 12.0 GiB 8300 os1 6 18925824 22071551 12.0 GiB 8300 os2 7 22071552 25217279 12.0 GiB 8300 os3 8 25217280 732558330 2.6 TiB 8300 data $ fdisk -l /dev/sdb Disk /dev/sdb: 2.7 TiB, 3000558944256 bytes, 732558336 sectors Units: sectors of 1 * 4096 = 4096 bytes Sector size (logical/physical): 4096 bytes / 4096 bytes I/O size (minimum/optimal): 4096 bytes / 4096 bytes Disklabel type: gpt Disk identifier: C4426321-9726-4022-BB20-2EF00B490465 Device Start End Sectors Size Type /dev/sdb1 256 51455 51200 200M BIOS boot /dev/sdb2 51456 5294335 5242880 20G Linux filesystem /dev/sdb3 5294336 13158655 7864320 30G Microsoft basic data /dev/sdb4 13158656 15780095 2621440 10G Linux swap /dev/sdb5 15780096 18925823 3145728 12G Linux filesystem /dev/sdb6 18925824 22071551 3145728 12G Linux filesystem /dev/sdb7 22071552 25217279 3145728 12G Linux filesystem /dev/sdb8 25217280 732558330 707341051 2.7T Linux filesystem easygen-5.1.9/test/sgdisk.yaml000066400000000000000000000011411416363131000163030ustar00rootroot00000000000000Disk: /dev/sdb # Common Partitions Types # # 8300 Linux filesystem # 8200 linux swap # fd00 linux raid # ef02 BIOS boot # 0700 Microsoft basic data # # For more GPT Partitions Types, # echo L | gdisk /dev/sdb Partitions: - Name: bios_boot Type: ef02 Size: +200M - Name: linux_boot Type: 8300 Size: +20G - Name: windows Type: "0700" Size: +30G - Name: linux_swap Type: 8200 Size: +10G - Name: os1 Type: 8300 Size: +12G - Name: os2 Type: 8300 Size: +12G - Name: os3 Type: 8300 Size: +12G - Name: data Type: 8300 Size: "0" easygen-5.1.9/test/strings.yaml000066400000000000000000000000741416363131000165140ustar00rootroot00000000000000StrTest: "These rights belong to those people" StrEmpty: "" easygen-5.1.9/test/strings0.ref000066400000000000000000000001071416363131000164030ustar00rootroot00000000000000-ab-axxb- HTML Html html -W-xxW- HTML Html html -W-xxW- HTML Html html easygen-5.1.9/test/strings0.tmpl000066400000000000000000000000711416363131000166030ustar00rootroot00000000000000{{.StrTest}} {{replace .StrTest}} {{.StrTest | replace}} easygen-5.1.9/test/strings0.yaml000066400000000000000000000000441416363131000165710ustar00rootroot00000000000000StrTest: "-ab-axxb- HTML Html html" easygen-5.1.9/test/strings1.ref000066400000000000000000000001071416363131000164040ustar00rootroot00000000000000-ab-axxb- HTML Html html -ab-axxb- XML Html html -ab-axxb- XML XML XML easygen-5.1.9/test/strings1.tmpl000066400000000000000000000000701416363131000166030ustar00rootroot00000000000000{{.StrTest}} {{replacec .StrTest}} {{replace .StrTest}} easygen-5.1.9/test/var0.ref000066400000000000000000000000201416363131000154740ustar00rootroot00000000000000some-init-methodeasygen-5.1.9/test/var0.tmpl000066400000000000000000000001571416363131000157070ustar00rootroot00000000000000Input: {{printf "%q" .Name}} Output 1: {{clk2uc .Name | printf "%q"}} Output 2: {{clk2ss .Name | printf "%q"}} easygen-5.1.9/test/var0.yaml000066400000000000000000000000271416363131000156710ustar00rootroot00000000000000Name: some-init-method easygen-5.1.9/test/var1.ref000066400000000000000000000000161416363131000155020ustar00rootroot00000000000000SomeInitMethodeasygen-5.1.9/test/var2.ref000066400000000000000000000000201416363131000154760ustar00rootroot00000000000000SOME_INIT_METHODeasygen-5.1.9/tf-calc.go000066400000000000000000000025701416363131000150230ustar00rootroot00000000000000package easygen import ( "errors" "strconv" ) //========================================================================== // template function somewhat related to calculations // Iterate returns a slice whose end (& start) is controlled by the ic func Iterate(ic ...string) []int { // cannot think of a better way to report the Atoi error, other than -- end, _ := strconv.Atoi(ic[0]) start := 0 if len(ic) > 1 { start, _ = strconv.Atoi(ic[1]) } var Items []int for i := start; i <= (end); i++ { Items = append(Items, i) } return Items } // ArgsA creates an array slice from the given arguments func ArgsA(vs ...interface{}) []interface{} { return vs } // ArgsM creates a map from the given K/V argument pairs func ArgsM(kvs ...interface{}) (map[string]interface{}, error) { if len(kvs)%2 != 0 { return nil, errors.New("argsm requires even number of arguments.") } m := make(map[string]interface{}) for i := 0; i < len(kvs); i += 2 { s, ok := kvs[i].(string) if !ok { return nil, errors.New("even args to args must be strings.") } m[s] = kvs[i+1] } return m, nil } //========================================================================== // template function for calculations // By Caleb Spare @gmail.com // https://groups.google.com/d/msg/golang-nuts/gzAyBLAeUbU/LwgomgxcjQ8J // Minus1 calculates to input less 1 func Minus1(n int) int { return n - 1 } easygen-5.1.9/tf-datetime.go000066400000000000000000000025071416363131000157150ustar00rootroot00000000000000package easygen import ( "fmt" "strconv" "time" ) // now is function that represents the current time in UTC. This is here // primarily for the tests to override times. var now = func() time.Time { return time.Now() } //========================================================================== // template function for date & time // https://godoc.org/time#pkg-constants // Date returns the date or year func Date(fmt string) string { switch fmt { case "Y4": // returns the year string of length 4 return time.Now().Format("2006") case "I": // returns the output of `date -I` return time.Now().Format("2006-01-02") // for the output of `date -Iseconds` // use `timestamp` default: return time.Now().Format("2006" + fmt + "01" + fmt + "02") } } // https://github.com/hashicorp/consul-template/blob/de2ebf4/template_functions.go#L666-L682 // Timestamp returns the current UNIX timestamp in UTC. If an argument is // specified, it will be used to format the timestamp. func Timestamp(s ...string) (string, error) { switch len(s) { case 0: return now().Format(time.RFC3339), nil case 1: if s[0] == "unix" { return strconv.FormatInt(now().Unix(), 10), nil } return now().Format(s[0]), nil default: return "", fmt.Errorf("timestamp: wrong number of arguments, expected 0 or 1"+ ", but got %d", len(s)) } } easygen-5.1.9/tf-strings.go000066400000000000000000000122061416363131000156070ustar00rootroot00000000000000package easygen import ( "errors" "fmt" "regexp" "strings" ) var ( re *regexp.Regexp rec *regexp.Regexp ) //////////////////////////////////////////////////////////////////////////// // Normal String Function Definitions // Taken/adapted from hugo tpl/strings/strings.go // Substr extracts parts of a string, beginning at the character at the specified // position, and returns the specified number of characters. // // It normally takes two parameters: start and length. // It can also take one parameter: start, i.e. length is omitted, in which case // the substring starting from start until the end of the string will be returned. // // To extract characters from the end of the string, use a negative start number. // // In addition, borrowing from the extended behavior described at http://php.net/substr, // if length is given and is negative, then that many characters will be omitted from // the end of string. func Substr(a string, nums ...interface{}) (string, error) { var start, length int asRunes := []rune(a) switch len(nums) { case 0: return "", errors.New("too less arguments") case 1: start = nums[0].(int) length = len(asRunes) case 2: start = nums[0].(int) length = nums[1].(int) default: return "", errors.New("too many arguments") } if start < -len(asRunes) { start = 0 } if start > len(asRunes) { return "", fmt.Errorf("start position out of bounds for %d-byte string", len(a)) } var s, e int if start >= 0 && length >= 0 { s = start e = start + length } else if start < 0 && length >= 0 { s = len(asRunes) + start e = len(asRunes) + start + length + 1 } else if start >= 0 && length < 0 { s = start e = len(asRunes) + length } else { s = len(asRunes) + start e = len(asRunes) + length } if s > e { return "", fmt.Errorf("calculated start position greater than end position: %d > %d", s, e) } if e > len(asRunes) { e = len(asRunes) } return string(asRunes[s:e]), nil } //////////////////////////////////////////////////////////////////////////// // Regexp Function Definitions // RegexpFindAllString is wrapper for regexp.FindAllString func RegexpFindAllString(s string, regExp string, n int) []string { return regexp.MustCompile(regExp).FindAllString(s, n) } // RegexpFindAllStringIndex is wrapper for regexp.FindAllStringIndex func RegexpFindAllStringIndex(s string, regExp string, n int) [][]int { return regexp.MustCompile(regExp).FindAllStringIndex(s, n) } // RegexpFindAllStringSubmatch is wrapper for regexp.FindAllStringSubmatch func RegexpFindAllStringSubmatch(s string, regExp string, n int) [][]string { return regexp.MustCompile(regExp).FindAllStringSubmatch(s, n) } // RegexpFindAllStringSubmatchIndex is wrapper for regexp.FindAllStringSubmatchIndex func RegexpFindAllStringSubmatchIndex(s string, regExp string, n int) [][]int { return regexp.MustCompile(regExp).FindAllStringSubmatchIndex(s, n) } // RegexpFindString is wrapper for regexp.FindString func RegexpFindString(s string, regExp string) string { return regexp.MustCompile(regExp).FindString(s) } // RegexpFindStringIndex is wrapper for regexp.FindStringIndex func RegexpFindStringIndex(s string, regExp string) (loc []int) { return regexp.MustCompile(regExp).FindStringIndex(s) } // RegexpFindStringSubmatch is wrapper for regexp.FindStringSubmatch func RegexpFindStringSubmatch(s string, regExp string) []string { return regexp.MustCompile(regExp).FindStringSubmatch(s) } // RegexpFindStringSubmatchIndex is wrapper for regexp.FindStringSubmatchIndex func RegexpFindStringSubmatchIndex(s string, regExp string) []int { return regexp.MustCompile(regExp).FindStringSubmatchIndex(s) } // RegexpMatchString is wrapper for regexp.MatchString func RegexpMatchString(s string, regExp string) bool { return regexp.MustCompile(regExp).MatchString(s) } // RegexpReplaceAllLiteralString is wrapper for regexp.ReplaceAllLiteralString func RegexpReplaceAllLiteralString(src, regExp string, repl string) string { return regexp.MustCompile(regExp).ReplaceAllLiteralString(src, repl) } // RegexpReplaceAllString is wrapper for regexp.ReplaceAllString func RegexpReplaceAllString(src, regExp string, repl string) string { return regexp.MustCompile(regExp).ReplaceAllString(src, repl) } // RegexpReplaceAllStringFunc is wrapper for regexp.ReplaceAllStringFunc func RegexpReplaceAllStringFunc(src string, regExp string, repl func(string) string) string { return regexp.MustCompile(regExp).ReplaceAllStringFunc(src, repl) } // RegexpSplit is wrapper for regexp.Split func RegexpSplit(s string, regExp string, n int) []string { return regexp.MustCompile(regExp).Split(s, n) } //////////////////////////////////////////////////////////////////////////// // Misc // Coalesce function takes two or more string arguments and returns the first argument that is not empty. // The result is empty only if all the arguments are empty. func Coalesce(s ...string) string { for _, str := range s { if len(str) != 0 && str != "" { return str } } return "" } // Quote4shell -- quote file name for shell. // So "%bob's file" will be quoted as '%bob'\''s file' func Quote4shell(s string) string { return "'" + strings.Join(strings.Split(s, "'"), `'\''`) + "'" }