easygen-5.3.0/0000755000175000017500000000000014513322135012477 5ustar nileshnilesheasygen-5.3.0/example_test.go0000644000175000017500000000174614513322135015530 0ustar nileshnileshpackage 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.3.0/egVar/0000755000175000017500000000000014513322135013543 5ustar nileshnilesheasygen-5.3.0/egVar/example_test.go0000644000175000017500000000115314513322135016564 0ustar nileshnileshpackage 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.3.0/egVar/EgVar.go0000644000175000017500000001037114513322135015100 0ustar nileshnilesh//////////////////////////////////////////////////////////////////////////// // 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.3.0/egVar/EgVar_test.go0000644000175000017500000000733614513322135016146 0ustar nileshnileshpackage 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.3.0/test/0000755000175000017500000000000014513322135013456 5ustar nileshnilesheasygen-5.3.0/test/commandlineCLI-027.yaml0000644000175000017500000000531214513322135017467 0ustar nileshnilesh# 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.3.0/test/lists.tmpl0000644000175000017500000000010214513322135015503 0ustar nileshnileshThe {{clk2uc .Name}} colors are: {{range .Colors}}{{.}}, {{end}}. easygen-5.3.0/test/sgdisk.sh0000644000175000017500000000112514513322135015275 0ustar nileshnilesh # 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.3.0/test/enum_c-to_str.tmpl0000644000175000017500000000036614513322135017137 0ustar nileshnilesh /** 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.3.0/test/enum_multiple_data_files.ref0000644000175000017500000000020014513322135021176 0ustar nileshnilesh // Simplified enumeration of available RAID devices enum raid_type { RAID0 = 100, RAID1, }; enum raid_driver { HW, SW, }; easygen-5.3.0/test/strings0.ref0000644000175000017500000000010714513322135015723 0ustar nileshnilesh-ab-axxb- HTML Html html -W-xxW- HTML Html html -W-xxW- HTML Html html easygen-5.3.0/test/list0.yaml0000644000175000017500000000007714513322135015401 0ustar nileshnileshColors: - red - blue - white Colorlist: red blue white easygen-5.3.0/test/commandlineCVFull.yaml0000644000175000017500000000124614513322135017707 0ustar nileshnileshCmdMain: 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.3.0/test/html-Table-RWD.tmpl0000644000175000017500000000464214513322135017005 0ustar nileshnilesh {{range .phone}}{{$phoneType := clk2ls .Type}}

{{.Type}} Cell phones

{{range .Modules}} {{end}}
Module A Module B Module C
{{.}} A {{.}} B {{.}} C
{{end}} easygen-5.3.0/test/mcx-vscode-emacs.tmpl0000644000175000017500000000033314513322135017511 0ustar nileshnilesh{{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.3.0/test/commandlineCLI-027s.yaml0000644000175000017500000000534414513322135017657 0ustar nileshnilesh# 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.3.0/test/IntelliJ-Emacs.tmpl0000644000175000017500000000044214513322135017114 0ustar nileshnilesh{{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.3.0/test/nested_demo_argsm.ref0000644000175000017500000000006414513322135017633 0ustar nileshnilesha=1, b=somestring, c.Shipped=true, c.Price=1234.56 easygen-5.3.0/test/sgdisk.tmpl0000644000175000017500000000042314513322135015637 0ustar nileshnilesh # 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.3.0/test/var1.ref0000644000175000017500000000001614513322135015022 0ustar nileshnileshSomeInitMethodeasygen-5.3.0/test/strings0.yaml0000644000175000017500000000004414513322135016111 0ustar nileshnileshStrTest: "-ab-axxb- HTML Html html" easygen-5.3.0/test/var0.tmpl0000644000175000017500000000015714513322135015227 0ustar nileshnileshInput: {{printf "%q" .Name}} Output 1: {{clk2uc .Name | printf "%q"}} Output 2: {{clk2ss .Name | printf "%q"}} easygen-5.3.0/test/nested_demo_argsm_iterate.ref0000644000175000017500000000073614513322135021356 0ustar nileshnileshApe 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.3.0/test/.gitignore0000644000175000017500000000011014513322135015436 0ustar nileshnilesh# Generated output, to be compared with the .ref reference output *.got easygen-5.3.0/test/commandlineGoFlags.ityped.tmpl0000644000175000017500000000214414513322135021403 0ustar nileshnilesh{{- define "type_struct" -}} // The {{.typeName}} type defines all the configurable options from cli. {{.Prefix}}type {{.typeName}} struct { {{- range .Options}} {{- if eq .Name "Args" }} {{$.Prefix}} {{$.Prefix}} {{.Args}} {{- else }}{{$f := stringsSplit .Flag ","}}{{ $flen := len $f }} {{$.Prefix}} {{.Name}} {{.Type}} ` {{- if gt $flen 1}}short:"{{index $f 0}}" long:"{{index $f 1}}" {{- else}} {{- if le ((index $f 0) | len) 1 }}short:"{{index $f 0}}" {{- else}}long:"{{index $f 0}}"{{end}} {{- end}} {{- if .EnvV}} env:"{{printf "%s_%s" (clk2ss $.ProgramName) (clk2ss .Name)}}"{{end}} description:"{{.Usage}}" {{- if .Value}} default:"{{.Value}}"{{end}} {{- if .Choices}}{{range .Choices}} choice:"{{.}}"{{end}}{{end}} {{- if .Required}} required:"true"{{end}}`{{end}} {{- end}} {{- if .Verbose}} {{$.Prefix}} Verbflg func() `short:"v" long:"verbose" description:"Verbose mode (Multiple -v options increase the verbosity)"` {{$.Prefix}} Verbose int {{- end}} {{- if .Version}} {{$.Prefix}} Version func() `short:"V" long:"version" description:"Show program version and exit"` {{- end}} {{$.Prefix -}} } {{- end}} easygen-5.3.0/test/example.yaml0000644000175000017500000000027114513322135015775 0ustar nileshnileshColorRed: red ColorBlue: blue ColorWhite: white Colorlist: red blue white Colors: - red - blue - white Cars: - Make: Ford Module: T1 - Make: GM Module: T2 easygen-5.3.0/test/enum_java.tmpl0000644000175000017500000000063614513322135016326 0ustar nileshnilesh{{- 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.3.0/test/sgdisk-fstab.tmpl0000644000175000017500000000015014513322135016731 0ustar nileshnilesh{{range .Partitions}} LABEL={{.Name}} /mnt/{{.Name}} auto noauto,defaults,noatime,nodiratime 0 2{{end}} easygen-5.3.0/test/html-Checkbox-Post.tmpl0000644000175000017500000000553514513322135017777 0ustar nileshnilesh 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.3.0/test/nested_thanks.tmpl0000644000175000017500000000026114513322135017205 0ustar nileshnilesh{{ 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.3.0/test/commandlineCV.tmpl0000644000175000017500000000021414513322135017070 0ustar nileshnilesh{{range .Options}} flags.{{.Type}}("{{.Name}}", {{.Value}}, "{{.Usage}}") viper.BindPFlag("{{.Name}}", flags.Lookup("{{.Name}}")) {{end}} easygen-5.3.0/test/jq-test_jq.tmpl0000644000175000017500000000312514513322135016436 0ustar nileshnilesh// 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.3.0/test/nested_demo_argsa.ref0000644000175000017500000000004214513322135017613 0ustar nileshnileshGot: 543 false 0.1234 Sam 123456 easygen-5.3.0/test/commandlineFlag.tmpl0000644000175000017500000000643214513322135017441 0ustar nileshnilesh// !!! !!! // 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}} {{ if eq .Type "duration" }}time.Duration{{else}}{{.Type}}{{end}} // {{.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 }{{else}}{{if eq .Type "int" }}{{if (stringsContains .Flag ",")}}{{$cf := .}}{{range (stringsSplit .Flag ",")}}{{$envVar := printf "%s_%s" (clk2ss $.ProgramName) (clk2ss .)}} if {{$.StructVar}}.{{$cf.Name}} == 0 && len(os.Getenv("{{$envVar}}")) != 0 { if i, err := strconv.Atoi(os.Getenv("{{$envVar}}")); err == nil { {{$.StructVar}}.{{$cf.Name}} = i } }{{end}}{{else}} if {{$.StructVar}}.{{.Name}} == 0 && len(os.Getenv("{{$envVar}}")) != 0 { if i, err := strconv.Atoi(os.Getenv("{{$envVar}}")); err == nil { {{$.StructVar}}.{{.Name}} = i } }{{end}}{{end}}{{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.3.0/test/jq-test_0.yaml0000644000175000017500000000131214513322135016145 0ustar nileshnileshCases: - 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.3.0/test/nested_data.yaml0000644000175000017500000000014414513322135016614 0ustar nileshnileshName: Sam OrderNumber: 123456 Price: 1234.56 Shipped: true ShipDate: "Wednesday, January 06, 2021" easygen-5.3.0/test/commandlineCLI-027.ref0000644000175000017500000000721214513322135017302 0ustar nileshnilesh// -*- 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.3.0/test/nested_demo_argsm.tmpl0000644000175000017500000000024014513322135020027 0ustar nileshnilesh{{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.3.0/test/enum_go.tmpl0000644000175000017500000000626414513322135016015 0ustar nileshnilesh{{/* 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.3.0/test/list1.ref0000644000175000017500000000006114513322135015205 0ustar nileshnileshThe quoted colors are: "red", "blue", "white", . easygen-5.3.0/test/tf-calc.tmpl0000644000175000017500000000021414513322135015662 0ustar nileshnilesh{{.Name}} {{6 | minus1}} {{minus1 6}} {{6 | minus 1}} {{minus 1 6}} {{5 | minus 2}} {{minus 2 5}} {{5 | minus 3}} {{minus 3 5}} {{add 2 6}} easygen-5.3.0/test/list1HTML.ref0000644000175000017500000000011114513322135015666 0ustar nileshnileshThe quoted colors are: "red", "blue", "white", . easygen-5.3.0/test/enum_multiple_template_and_data.ref0000644000175000017500000000077614513322135022553 0ustar nileshnilesh // 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.3.0/test/var0.ref0000644000175000017500000000002014513322135015014 0ustar nileshnileshsome-init-methodeasygen-5.3.0/test/list1.yaml0000644000175000017500000000006214513322135015374 0ustar nileshnileshColors: - '"red"' - '"blue"' - '"white"' easygen-5.3.0/test/commandlineFlag.ref0000644000175000017500000001017514513322135017240 0ustar nileshnilesh// !!! !!! // 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 IntV int // int var Batch time.Duration // batch interval 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.IntV, "intv", 0, "int var") flag.DurationVar(&Opts.Batch, "batch", 120*time.Second, "batch interval") 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") } if Opts.IntV == 0 && len(os.Getenv("EASYGEN_INTV")) != 0 { if i, err := strconv.Atoi(os.Getenv("EASYGEN_INTV")); err == nil { Opts.IntV = i } } if Opts.Debug == 0 && len(os.Getenv("EASYGEN_D")) != 0 { if i, err := strconv.Atoi(os.Getenv("EASYGEN_D")); err == nil { Opts.Debug = i } } if Opts.Debug == 0 && len(os.Getenv("EASYGEN_DEBUG")) != 0 { if i, err := strconv.Atoi(os.Getenv("EASYGEN_DEBUG")); err == nil { Opts.Debug = i } } } // 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.3.0/test/commandlineCV.yaml0000644000175000017500000000111114513322135017053 0ustar nileshnileshOptions: - 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.3.0/test/enum_c-header.tmpl0000644000175000017500000000051214513322135017046 0ustar nileshnilesh{{- 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.3.0/test/list01.ref0000644000175000017500000000006614513322135015272 0ustar nileshnileshThe colors are: red, blue, white, . red, blue, white. easygen-5.3.0/test/list0.ref0000644000175000017500000000004414513322135015205 0ustar nileshnileshThe colors are: red, blue, white, . easygen-5.3.0/test/list0j.json0000644000175000017500000000010014513322135015545 0ustar nileshnilesh{ "Colors": [ "red", "blue", "white" ] }easygen-5.3.0/test/list1HTML.tmpl0000644000175000017500000000007714513322135016101 0ustar nileshnileshThe quoted colors are: {{range .Colors}}{{. | html}}, {{end}}. easygen-5.3.0/test/commandlineEnv.ref0000644000175000017500000000167014513322135017117 0ustar nileshnileshpackage main // import "github.com/caarlos0/env" ////////////////////////////////////////////////////////////////////////// // Constant and data type/structure definitions /* Custom environment settings: - **EVD_HOST**: Host address (string="localhost") - **EVD_PORT**: Listening port (int="80") - **EVD_FRCE**: Force start (bool) - **EVD_VERB**: Verbose mode (higher numbers increase the verbosity) (int) */ type envConfig struct { Host string `env:"EVD_HOST" envDefault:"localhost"` // Host address Port int `env:"EVD_PORT" envDefault:"80"` // Listening port Force bool `env:"EVD_FRCE"` // Force start Verbose int `env:"EVD_VERB"` // Verbose mode (higher numbers increase the verbosity) } //////////////////////////////////////////////////////////////////////////// // Global variables definitions // var ( // progname = "evdemo" // version = "0.1.0" // date = "2022-01-30" // e envConfig // ) easygen-5.3.0/test/sgdisk-mp.tmpl0000644000175000017500000000016714513322135016256 0ustar nileshnilesh{{range .Partitions}} mkdir /mnt/{{.Name}}{{end}} {{range .Partitions}} mount LABEL={{.Name}} /mnt/{{.Name}}{{end}} easygen-5.3.0/test/nested_header.tmpl0000644000175000017500000000012214513322135017141 0ustar nileshnilesh{{define "header"}} WidgetCo, Ltd. 463 Shoe Factory Rd. Hamford, VT 20202 {{end}} easygen-5.3.0/test/commandlineGoFlags.header.tmpl0000644000175000017500000000050014513322135021327 0ustar nileshnilesh{{- define "header" -}} //////////////////////////////////////////////////////////////////////////// // Program: {{.Name}} // Purpose: {{.Desc}} // Authors: {{or .Authors "Author"}} (c) {{$.Since}}-{{date "Y4"}}, All rights reserved //////////////////////////////////////////////////////////////////////////// {{- end}} easygen-5.3.0/test/raid_driver.yaml0000644000175000017500000000016114513322135016632 0ustar nileshnileshEnumName: raid_driver Values: - Name: HW String: "Hardware-RAID" - Name: SW String: "Software-RAID" easygen-5.3.0/test/commandlineCLI-027.tmpl0000644000175000017500000000515714513322135017510 0ustar nileshnilesh// -*- 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.3.0/test/tf-calc.yaml0000777000175000017500000000000014513322135020445 2listfunc2.yamlustar nileshnilesheasygen-5.3.0/test/commandlineGoFlags.yaml0000644000175000017500000000422314513322135020074 0ustar nileshnilesh# program name, name for the executable ProgramName: redo Authors: Myself Since: 2022 # For the complete demo, refer to the finished code at # https://github.com/suntong/lang/tree/master/lang/Go/src/sys/go-flags/wireframed # and the wiki at # https://github.com/go-easygen/easygen/issues/46 # PackageName: main Name: redo Desc: "global option redo" Text: Redo global option via automatic code-gen Verbose: true Version: true Options: - Name: Host Type: string Flag: H,host EnvV: true Usage: Host address Value: localhost - Name: Port Type: int Flag: p,port EnvV: true Usage: Listening port Value: 80 - Name: Force Type: bool Flag: f,force EnvV: true Usage: Force start Command: - Name: build Desc: "Build the network application" Text: 'Usage:\n redo build [Options] Arch(i386|amd64)' Options: - Name: Dir Type: string Flag: dir Value: "./" Usage: source code root dir - Name: install Desc: "Install the network application" Text: 'The add command adds a file to the repository. Use -a to add all files' Options: - Name: Dir Type: string Flag: d Value: "./" Usage: source code root dir - Name: Suffix Type: string Flag: suffix Value: ".go,.c,.s" Usage: "source file suffix" - Name: publish Desc: Publish the network application Text: Publish the built network application to central repo Options: - Name: Dir Type: string Flag: 'd,dir' Usage: publish dir Required: true - Name: Suffix Type: '[]string' Flag: s,suffix Usage: "source file suffix for publish" Choices: - .go - .c - .h - Name: Out Type: string Flag: o,out Usage: "output filename" - Name: Args Args: |- // Example of positional arguments // Args struct { // ID string // Num int // Rest []string // } `positional-args:"yes" required:"yes"` easygen-5.3.0/test/listfunc2.tmpl0000644000175000017500000000011014513322135016255 0ustar nileshnilesh{{.Name}} {{6 | minus1}} {{minus1 6}} {{clk2lc .Name}} {{clk2uc .Name}} easygen-5.3.0/test/commandlineCV.ref0000644000175000017500000000133614513322135016676 0ustar nileshnilesh 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.3.0/test/commandlineGoFlags.tmpl0000644000175000017500000000743314513322135020114 0ustar nileshnilesh// {{.Name}} - {{.Desc}} // // {{.Text}} package {{$.PackageName}} {{template "header" $ }} import ( // "fmt" // "os" // "github.com/go-easygen/go-flags" ) // Template for main starts here ////////////////////////////////////////////////////////////////////////// // Constant and data type/structure definitions //////////////////////////////////////////////////////////////////////////// // Global variables definitions // var ( // progname = "{{.Name}}" // version = "0.1.0" // date = "{{ date "I" }}" // // opts store all the configurable options // opts optsT // ) // // var gfParser = flags.NewParser(&opts, flags.Default) //////////////////////////////////////////////////////////////////////////// // Function definitions //========================================================================== // Function main // func main() { {{- if .Version }} // opts.Version = showVersion {{- end }} {{- if .Verbose }} // opts.Verbflg = func() { // opts.Verbose++ // } {{- end }} // // if _, err := gfParser.Parse(); err != nil { // fmt.Println() // gfParser.WriteHelp(os.Stdout) // os.Exit(1) // } // fmt.Println() // //Do{{stringsTitle .Name}}() // } // // //========================================================================== // // support functions // {{- if .Version }} // func showVersion() { // fmt.Fprintf(os.Stderr, "{{.Name}} - {{.Desc}}, version %s\n", version) // fmt.Fprintf(os.Stderr, "Built on %s\n", date) // fmt.Fprintf(os.Stderr, "Copyright (C) {{$.Since}}-{{ date "Y4" }}, {{or $.Authors "The Author(s) "}}\n\n") // fmt.Fprintf(os.Stderr, "{{.Text}}\n") // os.Exit(0) // } {{- end }} // Template for main ends here // Do{{stringsTitle .Name}} implements the business logic of command `{{.Name}}` // func Do{{stringsTitle .Name}}() error { // return nil // } // Template for type define starts here {{template "type_struct" argsm "ProgramName" .ProgramName "Options" .Options "Verbose" .Verbose "Version" .Version "typeName" "optsT" "Prefix" "" }} // Template for type define ends here {{range .Command}} // Template for "{{.Name}}" CLI handling starts here {{template "header" $ }} // package {{$.PackageName}} // import ( // "fmt" // "os" // // "github.com/go-easygen/go-flags/clis" // ) // *** Sub-command: {{.Name}} *** //////////////////////////////////////////////////////////////////////////// // Constant and data type/structure definitions {{template "type_struct" argsm "ProgramName" $.ProgramName "Options" .Options "typeName" (print (stringsTitle .Name) "Command") "Prefix" "// " }} // // var {{.Name}}Command {{stringsTitle .Name}}Command // // //////////////////////////////////////////////////////////////////////////// // // Function definitions // // func init() { // gfParser.AddCommand("{{.Name}}", // "{{.Desc}}", // "{{.Text}}", // &{{.Name}}Command) // } // // func (x *{{stringsTitle .Name}}Command) Execute(args []string) error { // fmt.Fprintf(os.Stderr, "{{.Desc}}\n") // // fmt.Fprintf(os.Stderr, "Copyright (C) {{$.Since}}-{{ date "Y4" }}, {{or $.Authors "The Author(s) "}}\n\n") // clis.Setup("{{$.Name}}::{{.Name}}", opts.Verbose) // clis.Verbose(1, "Doing {{stringsTitle .Name}}, with %+v, %+v", opts, args) // {{$opts := .Options}}// fmt.Println({{range $i, $opt := .Options}}x.{{$opt.Name}}{{if lt $i ($opts | len | minus1)}}, {{end}}{{end}}) // return x.Exec(args) // } // // // Exec implements the business logic of command `{{.Name}}` // func (x *{{stringsTitle .Name}}Command) Exec(args []string) error { // // err := ... // // clis.WarnOn("{{.Name}}::Exec", err) // // or, // // clis.AbortOn("{{.Name}}::Exec", err) // return nil // } // Template for "{{.Name}}" CLI handling ends here {{end}} easygen-5.3.0/test/strings1.ref0000644000175000017500000000010714513322135015724 0ustar nileshnilesh-ab-axxb- HTML Html html -ab-axxb- XML Html html -ab-axxb- XML XML XML easygen-5.3.0/test/html-Checkbox-Group.yaml0000644000175000017500000000044114513322135020123 0ustar nileshnileshphone: - 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.3.0/test/html-Checkbox-Group.tmpl0000644000175000017500000001116014513322135020135 0ustar nileshnilesh 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.

  • There is a select all checkbox for each group (in the table header). If user select/deselect the selectall checkbox, all the checkbox withing that group will get selected or deselected accordingly. Other groups are not affected.
  • Also,
    • if user select all the checkbox one by one then the selectall checkbox should be automatically gets selected.
    • And if user click selectall first and then unchecks any of the checkbox, then the selectall also should be unchecked automatically.
    • Again, this is for withing that group. Other groups are not affected.

{{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.3.0/test/nested_demo_argsm_opt.yaml0000644000175000017500000000137014513322135020704 0ustar nileshnileshCommand: - Name: publish Desc: "Publish application" Text: 'Publish the network application"' 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" - Name: Args Args: | // Example of positional arguments Args struct { ID string Num int Rest []string "} `positional-args:"yes" required:"yes"`" easygen-5.3.0/test/list0j.tmpl0000777000175000017500000000000014513322135017507 2list0.tmplustar nileshnilesheasygen-5.3.0/test/list00.tmpl0000644000175000017500000000005414513322135015466 0ustar nileshnileshThe colors are: {{range .v}}{{.}}, {{end}}. easygen-5.3.0/test/enum_multiple_template_files.ref0000644000175000017500000000125014513322135022106 0ustar nileshnilesh // 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.3.0/test/var2.ref0000644000175000017500000000002014513322135015016 0ustar nileshnileshSOME_INIT_METHODeasygen-5.3.0/test/strings1.tmpl0000644000175000017500000000007014513322135016123 0ustar nileshnilesh{{.StrTest}} {{replacec .StrTest}} {{replace .StrTest}} easygen-5.3.0/test/sgdisk.yaml0000644000175000017500000000114114513322135015623 0ustar nileshnileshDisk: /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.3.0/test/commandlineFlag.yaml0000644000175000017500000000464414513322135017432 0ustar nileshnilesh# 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: IntV Type: int Flag: intv Value: 0 Usage: "int var" - Name: Batch Type: duration Flag: batch Value: '120*time.Second' Usage: "batch interval" - 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.3.0/test/sgdisk-emb.tmpl0000644000175000017500000000013014513322135016373 0ustar nileshnilesh{{define "sgdisk_cmd"}} sgdisk -n 0:0:{{.Size}} -t 0:{{.Type}} -c 0:"{{.Name}}"{{end}} easygen-5.3.0/test/lists.ref0000644000175000017500000000006314513322135015311 0ustar nileshnileshThe SomeInitMethod colors are: red, blue, white, . easygen-5.3.0/test/raid_type.yaml0000644000175000017500000000106014513322135016317 0ustar nileshnilesh# 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.3.0/test/example-lowercase.tmpl0000644000175000017500000000014114513322135017765 0ustar nileshnilesh{{.micros.engine}} ver: {{.v}} {{.micros.name}} {{index .micros.include 0}}: {{.micros.primary}} easygen-5.3.0/test/listfunc1.tmpl0000644000175000017500000000014114513322135016260 0ustar nileshnilesh{{range $i, $color := .Colors}}{{$color}}{{if lt $i ($.Colors | len | minus1)}}, {{end}}{{end}}. easygen-5.3.0/test/commandlineCVFull.ref0000644000175000017500000000310014513322135017510 0ustar nileshnileshfunc 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.3.0/test/commandlineEnv.tmpl0000644000175000017500000000157614513322135017324 0ustar nileshnileshpackage {{$.PackageName}} // import "github.com/caarlos0/env" ////////////////////////////////////////////////////////////////////////// // Constant and data type/structure definitions /*{{- $prefix := .Prefix}} Custom environment settings: {{range .Options}} - **{{$prefix}} {{- if .EVar}}{{.EVar}} {{- else}}{{clk2ss .Name}} {{- end}}**: {{.Usage}} ({{.Type}}{{- if .Value}}="{{.Value}}"{{end}}) {{- end}} */ type envConfig struct { {{- range .Options}} {{.Name}} {{.Type}} `env:"{{$prefix}} {{- if .EVar}}{{.EVar}} {{- else}}{{clk2ss .Name}} {{- end}}" {{- if .Value}} envDefault:"{{.Value}}"{{end}}` // {{.Usage}} {{- end}} } //////////////////////////////////////////////////////////////////////////// // Global variables definitions // var ( // progname = "{{.Name}}" // version = "0.1.0" // date = "{{ date "I" }}" // e envConfig // ) easygen-5.3.0/test/listfunc1.ref0000644000175000017500000000002214513322135016056 0ustar nileshnileshred, blue, white. easygen-5.3.0/test/commandlineCLI-024.yaml0000644000175000017500000000512614513322135017467 0ustar nileshnilesh# 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.3.0/test/listfunc2.ref0000644000175000017500000000006314513322135016064 0ustar nileshnileshsome-init-method 5 5 someInitMethod SomeInitMethod easygen-5.3.0/test/example-lowercase.ref0000644000175000017500000000004214513322135017565 0ustar nileshnileshcustom ver: 0 go-app server: true easygen-5.3.0/test/tf-calc.ref0000644000175000017500000000004314513322135015462 0ustar nileshnileshsome-init-method 5 5 5 5 3 3 2 2 8 easygen-5.3.0/test/list0.tmpl0000644000175000017500000000006114513322135015404 0ustar nileshnileshThe colors are: {{range .Colors}}{{.}}, {{end}}. easygen-5.3.0/test/nested_demo_argsm_opt.tmpl0000644000175000017500000000161014513322135020713 0ustar nileshnilesh{{define "type_struct" -}} // The {{.typeName}} type defines all the configurable options from cli. type {{.typeName}} struct { {{- range .Options}} {{- if eq .Name "Args" }} {{.Args}} {{- else }}{{$f := stringsSplit .Flag ","}}{{ $flen := len $f }} {{.Name}} {{.Type}} `short:"{{index $f 0}}"{{if gt $flen 1}} long:"{{index $f 1}}"{{end}}{{if .EnvV}} env:"{{printf "%s_%s" (clk2ss $.ProgramName) (clk2ss .Name)}}"{{end}} description:"{{.Usage}}"{{if .Value}} default:"{{.Value}}"{{end}}`{{end}} {{- end}} {{- if .Verbose}} Verbflg func() `short:"v" long:"verbose" description:"Verbose mode (Multiple -v options increase the verbosity)"` Verbose uint {{end}} {{- end -}} {{range .Command}} //////////////////////////////////////////////////////////////////////////// // {{.Name}} {{template "type_struct" argsm "Options" .Options "typeName" (print (stringsTitle .Name) "Command") }} } {{end}} easygen-5.3.0/test/enum_c-source.tmpl0000644000175000017500000000166114513322135017124 0ustar nileshnilesh{{/* 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.3.0/test/list0j.ref0000777000175000017500000000000014513322135017107 2list0.refustar nileshnilesheasygen-5.3.0/test/commandlineCVFull.tmpl0000644000175000017500000000176314513322135017725 0ustar nileshnileshfunc 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.3.0/test/commandlineEnv.yaml0000644000175000017500000000115614513322135017304 0ustar nileshnilesh# program name, name for the executable # ProgramName: redo # Authors: Myself # PackageName: main Name: evdemo # Desc: "global option redo" # Text: Redo global option via automatic code-gen # prefix string before every environment variable Prefix: EVD_ Options: - Name: Host Type: string Usage: Host address Value: localhost - Name: Port Type: int Usage: Listening port Value: 80 - Name: Force Type: bool EVar: FRCE Usage: Force start - Name: Verbose Type: int EVar: VERB Usage: Verbose mode (higher numbers increase the verbosity) Value: 0 easygen-5.3.0/test/commandlineCLI-024.ref0000644000175000017500000000706114513322135017301 0ustar nileshnilesh// -*- 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.3.0/test/var0.yaml0000644000175000017500000000002714513322135015211 0ustar nileshnileshName: some-init-method easygen-5.3.0/test/sgdisk.txt0000644000175000017500000000336514513322135015512 0ustar nileshnilesh$ 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.3.0/test/commandlineGoFlags.ref0000644000175000017500000002061314513322135017707 0ustar nileshnilesh // redo - global option redo // // Redo global option via automatic code-gen package main //////////////////////////////////////////////////////////////////////////// // Program: redo // Purpose: global option redo // Authors: Myself (c) 2022-2023, All rights reserved //////////////////////////////////////////////////////////////////////////// import ( // "fmt" // "os" // "github.com/go-easygen/go-flags" ) // Template for main starts here ////////////////////////////////////////////////////////////////////////// // Constant and data type/structure definitions //////////////////////////////////////////////////////////////////////////// // Global variables definitions // var ( // progname = "redo" // version = "0.1.0" // date = "2023-01-23" // // opts store all the configurable options // opts optsT // ) // // var gfParser = flags.NewParser(&opts, flags.Default) //////////////////////////////////////////////////////////////////////////// // Function definitions //========================================================================== // Function main // func main() { // opts.Version = showVersion // opts.Verbflg = func() { // opts.Verbose++ // } // // if _, err := gfParser.Parse(); err != nil { // fmt.Println() // gfParser.WriteHelp(os.Stdout) // os.Exit(1) // } // fmt.Println() // //DoRedo() // } // // //========================================================================== // // support functions // // func showVersion() { // fmt.Fprintf(os.Stderr, "redo - global option redo, version %s\n", version) // fmt.Fprintf(os.Stderr, "Built on %s\n", date) // fmt.Fprintf(os.Stderr, "Copyright (C) 2022-2023, Myself \n\n") // fmt.Fprintf(os.Stderr, "Redo global option via automatic code-gen\n") // os.Exit(0) // } // Template for main ends here // DoRedo implements the business logic of command `redo` // func DoRedo() error { // return nil // } // Template for type define starts here // The optsT type defines all the configurable options from cli. type optsT struct { Host string `short:"H" long:"host" env:"REDO_HOST" description:"Host address" default:"localhost"` Port int `short:"p" long:"port" env:"REDO_PORT" description:"Listening port" default:"80"` Force bool `short:"f" long:"force" env:"REDO_FORCE" description:"Force start"` Verbflg func() `short:"v" long:"verbose" description:"Verbose mode (Multiple -v options increase the verbosity)"` Verbose int Version func() `short:"V" long:"version" description:"Show program version and exit"` } // Template for type define ends here // Template for "build" CLI handling starts here //////////////////////////////////////////////////////////////////////////// // Program: redo // Purpose: global option redo // Authors: Myself (c) 2022-2023, All rights reserved //////////////////////////////////////////////////////////////////////////// // package main // import ( // "fmt" // "os" // // "github.com/go-easygen/go-flags/clis" // ) // *** Sub-command: build *** //////////////////////////////////////////////////////////////////////////// // Constant and data type/structure definitions // The BuildCommand type defines all the configurable options from cli. // type BuildCommand struct { // Dir string `long:"dir" description:"source code root dir" default:"./"` // } // // var buildCommand BuildCommand // // //////////////////////////////////////////////////////////////////////////// // // Function definitions // // func init() { // gfParser.AddCommand("build", // "Build the network application", // "Usage:\n redo build [Options] Arch(i386|amd64)", // &buildCommand) // } // // func (x *BuildCommand) Execute(args []string) error { // fmt.Fprintf(os.Stderr, "Build the network application\n") // // fmt.Fprintf(os.Stderr, "Copyright (C) 2022-2023, Myself \n\n") // clis.Setup("redo::build", opts.Verbose) // clis.Verbose(1, "Doing Build, with %+v, %+v", opts, args) // // fmt.Println(x.Dir) // return x.Exec(args) // } // // // Exec implements the business logic of command `build` // func (x *BuildCommand) Exec(args []string) error { // // err := ... // // clis.WarnOn("build::Exec", err) // // or, // // clis.AbortOn("build::Exec", err) // return nil // } // Template for "build" CLI handling ends here // Template for "install" CLI handling starts here //////////////////////////////////////////////////////////////////////////// // Program: redo // Purpose: global option redo // Authors: Myself (c) 2022-2023, All rights reserved //////////////////////////////////////////////////////////////////////////// // package main // import ( // "fmt" // "os" // // "github.com/go-easygen/go-flags/clis" // ) // *** Sub-command: install *** //////////////////////////////////////////////////////////////////////////// // Constant and data type/structure definitions // The InstallCommand type defines all the configurable options from cli. // type InstallCommand struct { // Dir string `short:"d" description:"source code root dir" default:"./"` // Suffix string `long:"suffix" description:"source file suffix" default:".go,.c,.s"` // } // // var installCommand InstallCommand // // //////////////////////////////////////////////////////////////////////////// // // Function definitions // // func init() { // gfParser.AddCommand("install", // "Install the network application", // "The add command adds a file to the repository. Use -a to add all files", // &installCommand) // } // // func (x *InstallCommand) Execute(args []string) error { // fmt.Fprintf(os.Stderr, "Install the network application\n") // // fmt.Fprintf(os.Stderr, "Copyright (C) 2022-2023, Myself \n\n") // clis.Setup("redo::install", opts.Verbose) // clis.Verbose(1, "Doing Install, with %+v, %+v", opts, args) // // fmt.Println(x.Dir, x.Suffix) // return x.Exec(args) // } // // // Exec implements the business logic of command `install` // func (x *InstallCommand) Exec(args []string) error { // // err := ... // // clis.WarnOn("install::Exec", err) // // or, // // clis.AbortOn("install::Exec", err) // return nil // } // Template for "install" CLI handling ends here // Template for "publish" CLI handling starts here //////////////////////////////////////////////////////////////////////////// // Program: redo // Purpose: global option redo // Authors: Myself (c) 2022-2023, All rights reserved //////////////////////////////////////////////////////////////////////////// // package main // import ( // "fmt" // "os" // // "github.com/go-easygen/go-flags/clis" // ) // *** Sub-command: publish *** //////////////////////////////////////////////////////////////////////////// // Constant and data type/structure definitions // The PublishCommand type defines all the configurable options from cli. // type PublishCommand struct { // Dir string `short:"d" long:"dir" description:"publish dir" required:"true"` // Suffix []string `short:"s" long:"suffix" description:"source file suffix for publish" choice:".go" choice:".c" choice:".h"` // Out string `short:"o" long:"out" description:"output filename"` // // // Example of positional arguments // Args struct { // ID string // Num int // Rest []string // } `positional-args:"yes" required:"yes"` // } // // var publishCommand PublishCommand // // //////////////////////////////////////////////////////////////////////////// // // Function definitions // // func init() { // gfParser.AddCommand("publish", // "Publish the network application", // "Publish the built network application to central repo", // &publishCommand) // } // // func (x *PublishCommand) Execute(args []string) error { // fmt.Fprintf(os.Stderr, "Publish the network application\n") // // fmt.Fprintf(os.Stderr, "Copyright (C) 2022-2023, Myself \n\n") // clis.Setup("redo::publish", opts.Verbose) // clis.Verbose(1, "Doing Publish, with %+v, %+v", opts, args) // // fmt.Println(x.Dir, x.Suffix, x.Out, x.Args) // return x.Exec(args) // } // // // Exec implements the business logic of command `publish` // func (x *PublishCommand) Exec(args []string) error { // // err := ... // // clis.WarnOn("publish::Exec", err) // // or, // // clis.AbortOn("publish::Exec", err) // return nil // } // Template for "publish" CLI handling ends here easygen-5.3.0/test/strings.yaml0000644000175000017500000000007414513322135016034 0ustar nileshnileshStrTest: "These rights belong to those people" StrEmpty: "" easygen-5.3.0/test/html-Table-RWD.html0000644000175000017500000000656514513322135017003 0ustar nileshnilesh

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.3.0/test/sgdisk-inc.tmpl0000644000175000017500000000012014513322135016400 0ustar nileshnilesh sgdisk -Z {{.Disk}} {{range .Partitions}} {{ template "sgdisk_cmd" .}}{{end}} easygen-5.3.0/test/jq-test_1.go_0000644000175000017500000012260014513322135015754 0ustar nileshnilesh// 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.3.0/test/list00f.tmpl0000644000175000017500000000014714513322135015637 0ustar nileshnileshThe colors are: {{range $i, $color := .v}}{{$color}}{{if lt $i ($.v | len | minus1)}}, {{end}}{{end}}. easygen-5.3.0/test/nested_footer.tmpl0000644000175000017500000000023314513322135017212 0ustar nileshnilesh{{define "footer"}} {{date "I"}} Thank you for your business, WidgetCo Order Fulfillment Department Ph: 818-555-0123 Email: orders@widgetco.com {{end}} easygen-5.3.0/test/jq-test_1.yaml0000644000175000017500000012744014513322135016161 0ustar nileshnilesh# 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.3.0/test/commandlineCLI-024.tmpl0000644000175000017500000000336714513322135017506 0ustar nileshnilesh// -*- 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.3.0/test/jq-test_1.y00000644000175000017500000000151714513322135015543 0ustar nileshnilesh# 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.3.0/test/list0E.ref0000644000175000017500000000010314513322135015306 0ustar nileshnileshThe colors are: red, blue, white, . The system shell is: /bin/bash easygen-5.3.0/test/jq-test_0.go_0000644000175000017500000000367514513322135015765 0ustar nileshnilesh// 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.3.0/test/nested_demo_argsm_iterate.tmpl0000644000175000017500000000101014513322135021540 0ustar nileshnilesh{{- 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.3.0/test/nested_demo_argsa.tmpl0000644000175000017500000000025014513322135020014 0ustar nileshnilesh{{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.3.0/test/nested_header_footer.ref0000644000175000017500000000046214513322135020326 0ustar nileshnilesh 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.3.0/test/list0E.tmpl0000644000175000017500000000016314513322135015514 0ustar nileshnileshThe colors are: {{range .Colors}}{{.}}, {{end}}. The system shell is: {{stringsReplace (ENV "SHELL") "/usr" "" 1}} easygen-5.3.0/test/listfunc2.yaml0000644000175000017500000000011514513322135016250 0ustar nileshnileshName: some-init-method NameHTTP: HTTP-header-case NameMixed: some_InitMethod easygen-5.3.0/test/list1.tmpl0000644000175000017500000000007014513322135015405 0ustar nileshnileshThe quoted colors are: {{range .Colors}}{{.}}, {{end}}. easygen-5.3.0/test/strings0.tmpl0000644000175000017500000000007114513322135016123 0ustar nileshnilesh{{.StrTest}} {{replace .StrTest}} {{.StrTest | replace}} easygen-5.3.0/test/commandlineCLI-027s.ref0000644000175000017500000000721414513322135017467 0ustar nileshnilesh// -*- 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.3.0/test/listfunc1.yaml0000777000175000017500000000000014513322135020166 2list0.yamlustar nileshnilesheasygen-5.3.0/test/commandlineFlag0000644000175000017500000000016714513322135016465 0ustar nileshnileshsomething invalid for .yaml file, to verify that it is preferable to pick the .yaml file with the full extension first easygen-5.3.0/test/example-lowercase.yaml0000644000175000017500000000022314513322135017754 0ustar nileshnileshv: 0 micros: name: go-app src: . engine: custom primary: true commands: - go build -o server include: - server run: ./server easygen-5.3.0/README.end2.e.md0000644000175000017500000001124714513322135015035 0ustar nileshnilesh ## 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.3.0/.gitignore0000644000175000017500000000050214513322135014464 0ustar nileshnilesh.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 *~ .idea/ easygen-5.3.0/template.go0000644000175000017500000002053014513322135014641 0ustar nileshnilesh//////////////////////////////////////////////////////////////////////////// // 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, "indent": Indent, "pindent": PIndent, "coalesce": Coalesce, "quote4shell": Quote4shell, "iterate": Iterate, "argsa": ArgsA, "argsm": ArgsM, "add": Add, "minus": Minus, "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.3.0/.all-contributorsrc0000644000175000017500000000476414513322135016343 0ustar nileshnilesh{ "files": [ "README.md", "README.beg.e.md", "README.end2.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.3.0/tf-strings.go0000644000175000017500000001310414513322135015125 0ustar nileshnileshpackage 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 // Indent will indent the following lines according to the specified spaces func Indent(spaces int, v string) string { pad := strings.Repeat(" ", spaces) return strings.Replace(v, "\n", "\n"+pad, -1) } // PIndent will indent all lines according to the specified spaces func PIndent(spaces int, v string) string { pad := strings.Repeat(" ", spaces) return pad + Indent(spaces, v) } // 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 ...interface{}) string { // https://go.dev/play/p/C2-f7B0eCwx for _, v := range s { str := fmt.Sprint(v) 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, "'"), `'\''`) + "'" } easygen-5.3.0/LICENSE0000644000175000017500000000206314513322135013505 0ustar nileshnileshThe 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.3.0/tf-calc.go0000644000175000017500000000271514513322135014344 0ustar nileshnileshpackage 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 func Add(b, a int) int { return a + b } func Minus(b, a int) int { return a - b } // 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.3.0/README.beg.e.md0000644000175000017500000000167514513322135014746 0ustar nileshnilesh# {{.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.3.0/.goreleaser.yml0000644000175000017500000000140014513322135015423 0ustar nileshnileshproject_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 ignore: - goos: windows goarch: 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.3.0/README.e.md0000644000175000017500000000560614513322135014210 0ustar nileshnilesh ## {{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. easygen-5.3.0/tf-datetime.go0000644000175000017500000000250714513322135015235 0ustar nileshnileshpackage 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.3.0/t_readdatafile_test.go0000644000175000017500000000235314513322135017020 0ustar nileshnileshpackage 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.3.0/example_execute_test.go0000644000175000017500000000233014513322135017240 0ustar nileshnileshpackage 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" ) // 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 v0 := easygen.EgData{"Name": "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 slice/array v1 := easygen.EgData{"v": []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.3.0/example_execute0_test.go0000644000175000017500000000214114513322135017320 0ustar nileshnileshpackage 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 v0 := easygen.EgData{"v": "some-init-method"} // https://godoc.org/github.com/go-easygen/easygen#Execute0 // provide template string, not file name easygen.Execute0(tmpl, os.Stdout, "{{stringsToUpper .v}}\n", v0) // Demo of using driving data of slice/array v1 := easygen.EgData{"v": []string{"red", "blue", "white"}} easygen.Execute0(tmpl, os.Stdout, "The colors are: {{range .v}}{{.}}, {{end}}.\n", v1) // Demo output to string var b strings.Builder easygen.Execute0(tmpl, &b, "The colors are: {{range $i, $color := .v}}{{$color}}{{if lt $i ($.v | 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.3.0/easygen.go0000644000175000017500000002117414513322135014466 0ustar nileshnilesh//////////////////////////////////////////////////////////////////////////// // 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.v3" ) //////////////////////////////////////////////////////////////////////////// // Constant and data type/structure definitions //////////////////////////////////////////////////////////////////////////// // Global variables definitions // EgData, EasyGen key type type EgKey = string // EgData, EasyGen driven Data type EgData map[EgKey]interface{} // Opts holds the actual values from the command line parameters var Opts = Options{ExtYaml: ".yaml", ExtJson: ".json", ExtTmpl: ".tmpl"} //////////////////////////////////////////////////////////////////////////// // Function definitions // ReadDataFiles reads in the driving data from the given file, which can // be optionally without the defined extension, and can be a comma-separated // string for multiple data files. func ReadDataFiles(fileName string) EgData { var m EgData for _, dataFn := range strings.Split(fileName, ",") { m = ReadDataFile(dataFn, m) if Opts.Debug >= 1 { fmt.Fprintf(os.Stderr, "[%s] After reading file %s:\n %+v\n", progname, dataFn, m) } } return m } // ReadDataFile reads in the driving data from the given file, which can // be optionally without the defined extension func ReadDataFile(fileName string, ms ...EgData) EgData { if IsExist(fileName + Opts.ExtYaml) { return ReadYamlFile(fileName+Opts.ExtYaml, ms...) } else if IsExist(fileName + Opts.ExtJson) { return ReadJsonFile(fileName+Opts.ExtJson, ms...) } else if IsExist(fileName) { verbose("Reading exist Data File", 3) fext := filepath.Ext(fileName) fext = fext[1:] // ignore the leading "." if regexp.MustCompile(`(?i)^y`).MatchString(fext) { verbose("Reading YAML file", 3) return ReadYamlFile(fileName, ms...) } else if regexp.MustCompile(`(?i)^j`).MatchString(fext) { return ReadJsonFile(fileName, ms...) } 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, ms ...EgData) 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 := EgData{} if len(ms) > 0 { m = ms[0] } err = yaml.Unmarshal(source, &m) checkError(err) return m } // ReadJsonFile reads given JSON file as EgData func ReadJsonFile(fileName string, ms ...EgData) EgData { source, err := ioutil.ReadFile(fileName) checkError(err) m := EgData{} if len(ms) > 0 { m = ms[0] } 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. // However, the fileName can be a comma-separated string for multiple data files. func Process1(t Template, wr io.Writer, fileNameTempl string, fileName string) error { m := ReadDataFiles(fileName) // 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, 2) 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, 2) 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, 2) 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, 2) 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 := ReadDataFiles(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.3.0/t_strings_test.go0000644000175000017500000001126214513322135016103 0ustar nileshnileshpackage 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 { `{{ indent 2 "a" }}`, "a", }, { `{{ indent 2 "a\nb\nc" }}`, "a\n b\n c", }, { `{{ pindent 2 "a" }}`, " a", }, { `{{ pindent 2 "a\nb\nc" }}`, " a\n b\n c", }, { `{{ 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", }, // The following failed the template.Execute before but now fixed { `{{ coalesce .StrNone "Not exist" }}`, "Not exist", }, } testStringManipulation(t, testData) } /* { `{{ }}`, "", }, */ easygen-5.3.0/egCal/0000755000175000017500000000000014513322135013512 5ustar nileshnilesheasygen-5.3.0/egCal/example_test.go0000644000175000017500000000137214513322135016536 0ustar nileshnileshpackage 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.3.0/egCal/LICENSE0000644000175000017500000003714714513322135014533 0ustar nileshnileshMozilla 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.3.0/egCal/EgCal.go0000644000175000017500000000246014513322135015016 0ustar nileshnilesh//////////////////////////////////////////////////////////////////////////// // 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.3.0/egCal/consul-template_functions.go0000644000175000017500000001650314513322135021252 0ustar nileshnilesh//////////////////////////////////////////////////////////////////////////// // 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.3.0/example0_test.go0000644000175000017500000000133114513322135015576 0ustar nileshnileshpackage 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.3.0/cmd/0000755000175000017500000000000014513322135013242 5ustar nileshnilesheasygen-5.3.0/cmd/easygen/0000755000175000017500000000000014513322135014675 5ustar nileshnilesheasygen-5.3.0/cmd/easygen/main.go0000644000175000017500000000455314513322135016157 0ustar nileshnilesh//////////////////////////////////////////////////////////////////////////// // 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.3.0" date = "2022-07-10" ) //////////////////////////////////////////////////////////////////////////// // 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, and is template if len(args) == 1 && len(easygen.Opts.TemplateStr) == 0 { // 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.3.0/cmd/easygen/easygen.gen.sh0000755000175000017500000000020514513322135017434 0ustar nileshnilesh easygen config easygen | gofmt > ../../config.go easygen flags easygen | sed 's/^package easygen/package main/' | gofmt > flags.go easygen-5.3.0/cmd/easygen/.gitignore0000644000175000017500000000001014513322135016654 0ustar nileshnilesheasygen easygen-5.3.0/cmd/easygen/config.tmpl0000644000175000017500000000076714513322135017052 0ustar nileshnilesh// !!! !!! // 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.3.0/cmd/easygen/main_test.go0000644000175000017500000000755514513322135017223 0ustar nileshnileshpackage 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") testEasygen(t, "tf-calc", "tf-calc") //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") //Test lowercase keys testEasygen(t, "example-lowercase", "example-lowercase") // 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 with multiple data inputs files: testEasygen(t, "lists", "lists", "list0.yaml,listfunc2.yaml") testEasygen(t, "lists", "lists", "list0,listfunc2") testEasygen(t, "lists", "lists", "listfunc2.yaml,list0.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.3.0/cmd/easygen/easygen.1.ronn0000644000175000017500000000406314513322135017370 0ustar nileshnilesh# 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.3.0/cmd/easygen/flags.go0000644000175000017500000000556014513322135016326 0ustar nileshnilesh// !!! !!! // 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. - Can have more than one data files given on cli, separated by spaces, in which case multiple outputs will be produced based on the inputs. - Can be a comma-separated list giving many data files, in which case data will be merged together as if provided from a single file. - 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.3.0/cmd/easygen/flags.tmpl0000644000175000017500000000336214513322135016673 0ustar nileshnilesh// !!! !!! // 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.3.0/cmd/easygen/easygen.yaml0000644000175000017500000000530214513322135017214 0ustar nileshnilesh# 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. - Can have more than one data files given on cli, separated by spaces, in which case multiple outputs will be produced based on the inputs. - Can be a comma-separated list giving many data files, in which case data will be merged together as if provided from a single file. - 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.3.0/config.go0000644000175000017500000000114014513322135014267 0ustar nileshnilesh// !!! !!! // 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.3.0/egFilePath/0000755000175000017500000000000014513322135014507 5ustar nileshnilesheasygen-5.3.0/egFilePath/example_test.go0000644000175000017500000000271614513322135017536 0ustar nileshnileshpackage 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.3.0/egFilePath/EgFilePath.go0000644000175000017500000000545514513322135017017 0ustar nileshnilesh//////////////////////////////////////////////////////////////////////////// // 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.3.0/README.md0000644000175000017500000003130614513322135013761 0ustar nileshnilesh# 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) - [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.3.0 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. - Can have more than one data files given on cli, separated by spaces, in which case multiple outputs will be produced based on the inputs. - Can be a comma-separated list giving many data files, in which case data will be merged together as if provided from a single file. - 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 sudo apt install -y 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](https://cloudsmith.io/~suntong/repos/repo/packages/) 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 update apt-cache policy easygen sudo apt install -y easygen ``` ## Install Source To install the source code instead: ``` go install github.com/go-easygen/easygen@latest ``` ## 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.3.0/easygen_test.go0000644000175000017500000000424114513322135015521 0ustar nileshnileshpackage 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.3.0/README.end.e.md0000644000175000017500000000477514513322135014763 0ustar nileshnilesh ## Install Debian/Ubuntu package sudo apt install -y {{.Name}} ## 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](https://cloudsmith.io/~suntong/repos/repo/packages/) 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 update apt-cache policy {{.Name}} sudo apt install -y {{.Name}} ``` ## Install Source To install the source code instead: ``` go install {{.ProjectURL}}@latest ``` ## 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_.