├── .gitattributes ├── .gitignore ├── README.md ├── blogs └── chai2010 │ ├── code-play │ └── cue-as-config │ │ ├── Makefile │ │ ├── config.cue │ │ ├── config.go │ │ ├── config.json │ │ ├── config.yml │ │ ├── go.mod │ │ ├── go.sum │ │ └── main.go │ ├── hello-mod │ └── cue.mod │ │ └── module.cue │ └── readme.md ├── examples ├── cue-module-sample-v2 │ ├── Makefile │ ├── README.md │ ├── cue.mod │ │ └── module.cue │ ├── main.cue │ └── proto │ │ ├── device │ │ ├── resource.cue │ │ └── resource.proto │ │ └── user │ │ ├── resource.cue │ │ └── resource.proto ├── cue-module-sample │ ├── Makefile │ ├── README.md │ ├── cue.mod │ │ └── module.cue │ ├── device.cue │ ├── device │ │ └── resource.proto.cue │ ├── proto │ │ ├── device │ │ │ ├── resource.proto │ │ │ └── resource.proto.cue │ │ └── user │ │ │ ├── resource.proto │ │ │ └── resource.proto.cue │ └── user │ │ └── resource.proto.cue ├── grpc-testing │ ├── .gitignore │ ├── LICENSE │ ├── Makefile │ ├── README.md │ ├── cmd │ │ ├── add.go │ │ ├── cue.go │ │ ├── grpcurl.go │ │ ├── run.go │ │ ├── test.go │ │ ├── util.go │ │ └── validate.go │ ├── example │ │ └── app │ │ │ ├── app.proto │ │ │ ├── go.mod │ │ │ ├── go.sum │ │ │ ├── main.go │ │ │ └── pb │ │ │ └── app.pb.go │ ├── go.mod │ ├── go.sum │ ├── main.go │ └── runner.conf ├── hof │ ├── cue.mod │ │ ├── go.mod │ │ └── module.cue │ └── design │ │ ├── cli │ │ ├── cmds │ │ │ ├── 0-args.cue │ │ │ ├── 0-flags.cue │ │ │ ├── add.cue │ │ │ ├── auth.cue │ │ │ ├── cmd.cue │ │ │ ├── cue.cue │ │ │ ├── cuefig.cue │ │ │ ├── datamodel.cue │ │ │ ├── dev.cue │ │ │ ├── hof.cue │ │ │ ├── label.cue │ │ │ ├── mod.cue │ │ │ ├── resources.cue │ │ │ ├── run.cue │ │ │ ├── runtimes.cue │ │ │ ├── st.cue │ │ │ ├── start.cue │ │ │ ├── test.cue │ │ │ └── workflow.cue │ │ ├── help.cue │ │ ├── main.cue │ │ ├── pflags.cue │ │ └── releases.cue │ │ └── config │ │ └── main.cue └── hofmod-cli │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── cue.mod │ └── module.cue │ ├── cue.mods │ ├── cue.sums │ ├── gen │ └── cli.cue │ ├── partials │ ├── args-parse.go │ ├── flag-init.go │ ├── flag-var.go │ ├── go-helpers.go │ ├── lib-args.go │ ├── lib-call.go │ ├── pflag-init.go │ ├── pflag-var.go │ └── test-cli-args.txt │ ├── schema │ ├── arg.cue │ ├── cli.cue │ ├── cmd.cue │ ├── common.cue │ ├── flag.cue │ └── release.cue │ └── templates │ ├── Dockerfile.cue │ ├── cmd.go │ ├── cmd_test.go │ ├── completions.go │ ├── flags.go │ ├── ga.go │ ├── goreleaser.yml │ ├── hls │ └── cli │ │ ├── cmd_help.hls │ │ └── root_help.hls │ ├── main.go │ ├── root.go │ ├── root_test.go │ ├── update.go │ ├── verinfo.go │ └── version.go ├── misc ├── cel │ └── policy-engine-for-osdu-entitlements.pdf ├── cue-slack-files │ ├── A Generic Approach to Parallel Chart Parsing with an Application to LinGO.pdf │ ├── A Library of Anti-Unification Algorithms.pdf │ ├── A Variant of Higher-Order Anti-Unification.pdf │ ├── Anti-Unification Based Learning of T-Wrappers for Information Extraction.pdf │ ├── Anti-Unification and Natural Language ProcessingAnti-Unification and Natural Language Processing.pdf │ ├── Anti-Unification for Unranked Terms and Hedges.pdf │ ├── Anti-Unification with Type Classes.pdf │ ├── Anti-unification algorithms and their applications in program analysis.pdf │ ├── Applying Anti-Unication Strategies to Matching and Generalization of Recursive Functions.pdf │ ├── Compiling Typed Attribute-Value Logic Grammars.pdf │ ├── Duplicate code detection using anti-unification.pdf │ ├── EXPLOITING PARALLELISM INUNIFICATION-BASED PARSING.pdf │ ├── Effective Exploitation of Parallelism in NLP.pdf │ ├── EfficientParsingwithLarge-ScaleUnificationGrammars.pdf │ ├── Feature Structures and How toRepresent Multiple Phenomena Simultaneously.pdf │ ├── Graph Unification and Matching.pdf │ ├── Higher-Order Pattern Anti-Unification in Linear Time.pdf │ ├── Memory-Efficient and Thread-Safe Quasi-Destructive Graph Unification.pdf │ ├── Memory-Efficient and Thread-Safe Quasi-Destructive GraphUnification.pdf │ ├── Parallel Natural Language Parsing-From Analysis to Speedup.pdf │ ├── Quasi-Destructive Graph Unification.pdf │ ├── Squibs and Discussions A Note on Typing Feature Structures.pdf │ ├── TYPED FEATU19E STRUCTURES AS DESCRIPTIONS.pdf │ ├── The Logic of Typed Feature Structures.pdf │ └── Unification ParsingTyped Feature Structures.pdf └── oopsla90.pdf └── talks ├── Deliver-Your-Cloud-Native-Application-with-Design-Pattern-as-Code.pdf ├── chai2010-cue-intro-talk ├── .gitignore ├── Makefile ├── README.md ├── code │ ├── 00-cue-is-json-01 │ │ ├── Makefile │ │ └── hello.json.cue │ ├── 00 │ │ ├── Makefile │ │ ├── hello.cue │ │ ├── hello.json │ │ ├── hello.yml │ │ └── readme.md │ ├── 01-hello │ │ ├── Makefile │ │ ├── hello.cue │ │ ├── hello.json │ │ ├── hello.yml │ │ ├── module.mod │ │ └── sub │ │ │ └── bar.cue │ ├── 01 │ │ ├── Makefile │ │ ├── a.cue │ │ ├── b.cue │ │ └── readme.md │ ├── 02 │ │ ├── Makefile │ │ ├── a.cue │ │ ├── b.cue │ │ └── readme.md │ ├── 03 │ │ ├── Makefile │ │ ├── a.cue │ │ ├── cue.mod │ │ │ ├── module.cue │ │ │ └── pkg │ │ │ │ └── abcd.com │ │ │ │ └── vv │ │ │ │ ├── 1234.com │ │ │ │ └── vv │ │ │ │ │ └── b.cue │ │ │ │ └── a.cue │ │ ├── readme.md │ │ └── sub │ │ │ ├── v1.cue │ │ │ ├── v2.cue │ │ │ └── v3.cue │ ├── 04 │ │ ├── Makefile │ │ └── cfg.cue │ ├── 05 │ │ ├── Makefile │ │ ├── a.cue │ │ └── readme.md │ ├── builtin-01 │ │ ├── Makefile │ │ ├── builtin.txt │ │ └── hello.cue │ ├── cmd-00 │ │ ├── Makefile │ │ └── hello_tool.cue │ ├── cmd-01 │ │ ├── Makefile │ │ └── hello_tool.cue │ ├── cmd-02 │ │ ├── Makefile │ │ ├── a.out.txt │ │ └── hello_tool.cue │ ├── cmd-03 │ │ ├── Makefile │ │ └── hello_tool.cue │ ├── install-01 │ │ ├── help.txt │ │ └── install.txt │ ├── json-01 │ │ ├── Makefile │ │ ├── hello.cue │ │ └── hello.json │ ├── json-02 │ │ ├── Makefile │ │ ├── cmd.txt │ │ └── hello.cue │ ├── json-03 │ │ ├── Makefile │ │ ├── hello1.cue │ │ └── hello2.cue │ ├── json-04 │ │ ├── Makefile │ │ ├── hello.check.cue │ │ └── hello.json │ ├── pkg │ │ └── 01-import │ │ │ └── main.cue │ ├── play │ │ ├── Makefile │ │ └── hello_tool.cue │ ├── prime-01 │ │ ├── Makefile │ │ ├── cmd.txt │ │ └── hello.cue │ ├── tmpl-01 │ │ ├── Makefile │ │ ├── cmd.txt │ │ └── hello.cue │ ├── tmpl-02 │ │ ├── Makefile │ │ ├── cmd.txt │ │ └── hello.cue │ ├── tmpl-03 │ │ ├── Makefile │ │ ├── cmd.txt │ │ └── hello.cue │ ├── type-01 │ │ ├── Makefile │ │ └── hello.cue │ ├── var-00 │ │ ├── Makefile │ │ ├── cmd.txt │ │ └── hello.cue │ ├── var-01 │ │ ├── Makefile │ │ └── hello.cue │ ├── var-02 │ │ ├── Makefile │ │ ├── cmd.txt │ │ └── hello.cue │ ├── var-03 │ │ ├── Makefile │ │ ├── cmd.txt │ │ └── hello.cue │ ├── var-04 │ │ ├── Makefile │ │ ├── cmd.txt │ │ └── hello.cue │ └── zz_dev │ │ └── cue.mod │ │ └── module.cue ├── cue-intro.slide ├── images │ ├── cue-logo.svg │ ├── cue-star.png │ ├── cuelang-01.png │ └── mpvl-01.png └── present │ ├── static │ ├── article.css │ ├── dir.css │ ├── dir.js │ ├── favicon.ico │ ├── jquery-ui.js │ ├── notes.css │ ├── notes.js │ ├── slides.js │ └── styles.css │ └── templates │ ├── action.tmpl │ ├── article.tmpl │ ├── dir.tmpl │ └── slides.tmpl └── k8sjp_29_002.pdf /.gitattributes: -------------------------------------------------------------------------------- 1 | *.cue linguist-language=CUE 2 | 3 | Makefile linguist-language=Go 4 | *.slide linguist-language=Go 5 | 6 | *.css linguist-vendored 7 | *.js linguist-vendored 8 | 9 | * -text 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/.gitignore -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CUE资源精选 - 中文版 2 | 3 | ![](talks/chai2010-cue-intro-talk/images/cue-logo.svg) 4 | 5 | CUE是一种开源数据约束语言,它是JSON的超集,是一种功能强大的配置语言。 6 | 7 | ## 基本信息 8 | 9 | 中文讨论: 10 | 11 | - CUE配置语言 QQ群: 837383461 12 | - CUE配置语言 微信群: 请到QQ群咨询 13 | 14 | 官方参考: 15 | 16 | - https://cuelang.org/ 17 | - https://godoc.org/cuelang.org/go/cue 18 | 19 | 20 | 相关项目: 21 | 22 | - https://github.com/tnarg/rules_cue 23 | - https://github.com/tnarg/cue_terraform 24 | - https://github.com/hofstadter-io/hof 25 | 26 | ## 幻灯片 27 | 28 | - [CUE语言简介](https://talks.godoc.org/github.com/chai2010/awesome-cue-zh/talks/chai2010-cue-intro-talk/cue-intro.slide) - [chai2010](talks/chai2010-cue-intro-talk) 29 | - [Deliver Your Cloud Native Application with Design Pattern as Code(PDF)](./talks/Deliver-Your-Cloud-Native-Application-with-Design-Pattern-as-Code.pdf) 30 | - [設定記述言語 CUE で YAML Hell に立ち向かえ](./talks/k8sjp_29_002.pdf) ([原链接](https://speakerdeck.com/ytaka23/kubernetes-meetup-tokyo-29th)) 31 | 32 | ## 精选文章 33 | 34 | CUE相关的技术文章, 根据不同的语言文类. 35 | 36 | 41 | 42 | ### 英文 43 | 44 | - [Configuring Kubernetes with CUE](https://garethr.dev/2019/04/configuring-kubernetes-with-cue/) 45 | - [Automating the CUE workflow with Tilt](https://garethr.dev/2019/04/automating-the-cue-workflow-with-tilt/) 46 | - [Testing Cue Configuration with Open Policy Agent](https://garethr.dev/2019/04/testing-cue-configuration-with-open-policy-agent/) 47 | - [Validating Cue Kubernetes Configuration with Kubeval](https://garethr.dev/2019/04/validating-cue-kubernetes-configuration-with-kubeval/) 48 | - [The Configuration Complexity Curse](https://blog.cedriccharly.com/post/20191109-the-configuration-complexity-curse/) 49 | - [Templating YAML in Kubernetes with real code](https://learnk8s.io/templating-yaml-with-code) 50 | 51 | ### 日文 52 | 53 | - [CUEを試して見る](https://future-architect.github.io/articles/20191002/) 54 | - [yamlやJsonのチェック(Lint)ができるCUEの紹介](https://qiita.com/Urotea/items/28fa6a0822de16da02f6) 55 | - [GoでCUEのバリデーション機能を利用しつつ、.cue/.json/.yaml形式の設定ファイルを読み込む](https://future-architect.github.io/articles/20191030/) 56 | - [cueで複数のprotobufファイルからschemaを読み込む](https://qiita.com/r-fujimoto/items/604fbfa03118065c8f2a) 57 | - [cuelangを使ったgrpcのテストツールを作った話](https://qiita.com/r-fujimoto/items/af9afec73999545228fb) 58 | -------------------------------------------------------------------------------- /blogs/chai2010/code-play/cue-as-config/Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | -@go fmt 3 | 4 | @go run . 5 | @go run . -conf=config.json 6 | @go run . -conf=config.yml 7 | 8 | clean: 9 | -------------------------------------------------------------------------------- /blogs/chai2010/code-play/cue-as-config/config.cue: -------------------------------------------------------------------------------- 1 | port: 123 2 | logLevel: "info" 3 | -------------------------------------------------------------------------------- /blogs/chai2010/code-play/cue-as-config/config.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "path/filepath" 7 | 8 | "cuelang.org/go/cue" 9 | "cuelang.org/go/encoding/gocode/gocodec" 10 | "cuelang.org/go/encoding/json" 11 | "cuelang.org/go/encoding/yaml" 12 | ) 13 | 14 | const schema = ` 15 | port: uint16 16 | logLevel: "debug" | *"info" | "warn" | "error" | "critical" 17 | ` 18 | 19 | type Config struct { 20 | Port uint16 `json:"port"` 21 | LogLevel string `json:"logLevel"` 22 | } 23 | 24 | func getConfig(filePath string, data []byte) (p *Config, err error) { 25 | if data == nil { 26 | data, err = ioutil.ReadFile(*flagConfigPath) 27 | if err != nil { 28 | return nil, err 29 | } 30 | } 31 | 32 | var r cue.Runtime 33 | schemaInstance, err := r.Compile("schema", schema) 34 | if err != nil { 35 | panic(err) 36 | } 37 | 38 | var valueInstance *cue.Instance 39 | switch filepath.Ext(filePath) { 40 | case ".cue": 41 | valueInstance, err = r.Compile(filePath, data) 42 | if err != nil { 43 | return nil, fmt.Errorf("Parse CUE file error: %w", err) 44 | } 45 | case ".json": 46 | valueInstance, err = json.Decode(&r, filePath, data) 47 | if err != nil { 48 | return nil, fmt.Errorf("Parse JSON file error: %w", err) 49 | } 50 | case ".yml", ".yaml": 51 | valueInstance, err = yaml.Decode(&r, filePath, data) 52 | if err != nil { 53 | return nil, fmt.Errorf("Parse YAML file error: %w", err) 54 | } 55 | default: 56 | return nil, fmt.Errorf("file extension should be .cue, .json, .yaml or .yml, but %s", filepath.Ext(filePath)) 57 | } 58 | 59 | merged := cue.Merge(schemaInstance, valueInstance) 60 | err = merged.Value().Validate() 61 | if err != nil { 62 | return nil, fmt.Errorf("Validation error: %w", err) 63 | } 64 | var config Config 65 | codec := gocodec.New(&r, &gocodec.Config{}) 66 | err = codec.Encode(merged.Value(), &config) 67 | if err != nil { 68 | return nil, fmt.Errorf("Encode error: %w", err) 69 | } 70 | return &config, nil 71 | } 72 | -------------------------------------------------------------------------------- /blogs/chai2010/code-play/cue-as-config/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "port": 456, 3 | "logLevel": "debug" 4 | } -------------------------------------------------------------------------------- /blogs/chai2010/code-play/cue-as-config/config.yml: -------------------------------------------------------------------------------- 1 | port: 123 2 | logLevel: debug 3 | 4 | -------------------------------------------------------------------------------- /blogs/chai2010/code-play/cue-as-config/go.mod: -------------------------------------------------------------------------------- 1 | module cue-code-play 2 | 3 | go 1.14 4 | 5 | require cuelang.org/go v0.2.2 6 | -------------------------------------------------------------------------------- /blogs/chai2010/code-play/cue-as-config/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "log" 7 | ) 8 | 9 | var ( 10 | flagConfigPath = flag.String("conf", "config.cue", "Config file") 11 | ) 12 | 13 | func main() { 14 | flag.Parse() 15 | 16 | if *flagConfigPath == "" { 17 | log.Fatal("empty conf pth") 18 | } 19 | 20 | cfg, err := getConfig(*flagConfigPath, nil) 21 | if err != nil { 22 | log.Fatal(err) 23 | } 24 | 25 | fmt.Printf("%s: %+v\n", *flagConfigPath, cfg) 26 | } 27 | -------------------------------------------------------------------------------- /blogs/chai2010/hello-mod/cue.mod/module.cue: -------------------------------------------------------------------------------- 1 | module: "github.com/chai2010/awesome-cue-zh/blogs/chai2010/hello-mod" 2 | -------------------------------------------------------------------------------- /blogs/chai2010/readme.md: -------------------------------------------------------------------------------- 1 | # CUE相关文章 - chai2010 2 | 3 | -------------------------------------------------------------------------------- /examples/cue-module-sample-v2/Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | cue export --out=yaml main.cue 3 | 4 | pb: 5 | cue import -I. proto/device/resource.proto 6 | cue import -I. proto/user/resource.proto 7 | 8 | clean: 9 | -------------------------------------------------------------------------------- /examples/cue-module-sample-v2/README.md: -------------------------------------------------------------------------------- 1 | # cue-module-sample -------------------------------------------------------------------------------- /examples/cue-module-sample-v2/cue.mod/module.cue: -------------------------------------------------------------------------------- 1 | module: "github.com/ryoya-fujimoto" 2 | -------------------------------------------------------------------------------- /examples/cue-module-sample-v2/main.cue: -------------------------------------------------------------------------------- 1 | import "github.com/ryoya-fujimoto/proto/device" 2 | 3 | _someDevice1: device.#Device & { 4 | id: 1 5 | user: { 6 | email: "user1@example.com" 7 | name: "user1" 8 | } 9 | } 10 | _someDevice2: device.#Device & { 11 | id: 2 12 | user: { 13 | email: "user2@example.com" 14 | name: "user2" 15 | } 16 | } 17 | 18 | for i, d in [_someDevice1, _someDevice2] { 19 | "device_\(i)": { 20 | for k, v in d { 21 | "\(k)": v 22 | } 23 | for k, v in d.user { 24 | "\(k)": v 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/cue-module-sample-v2/proto/device/resource.cue: -------------------------------------------------------------------------------- 1 | package device 2 | 3 | import user_1 "github.com/ryoya-fujimoto/proto/user" 4 | 5 | #Device: { 6 | id?: uint64 @protobuf(1) 7 | user?: user_1.#User @protobuf(2,type=user.User) 8 | } 9 | -------------------------------------------------------------------------------- /examples/cue-module-sample-v2/proto/device/resource.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package user; 4 | 5 | option go_package = "github.com/ryoya-fujimoto/proto/device;device"; 6 | 7 | import "proto/user/resource.proto"; 8 | 9 | message Device { 10 | uint64 id = 1; 11 | user.User user = 2; 12 | } 13 | -------------------------------------------------------------------------------- /examples/cue-module-sample-v2/proto/user/resource.cue: -------------------------------------------------------------------------------- 1 | package user 2 | 3 | #User: { 4 | email?: string @protobuf(1) 5 | name?: string @protobuf(2) 6 | } 7 | -------------------------------------------------------------------------------- /examples/cue-module-sample-v2/proto/user/resource.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package user; 4 | 5 | option go_package = "github.com/ryoya-fujimoto/proto/user;user"; 6 | 7 | message User { 8 | string email = 1; 9 | string name = 2; 10 | } 11 | -------------------------------------------------------------------------------- /examples/cue-module-sample/Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | cue export device.cue 3 | 4 | clean: 5 | -------------------------------------------------------------------------------- /examples/cue-module-sample/README.md: -------------------------------------------------------------------------------- 1 | # cue-module-sample -------------------------------------------------------------------------------- /examples/cue-module-sample/cue.mod/module.cue: -------------------------------------------------------------------------------- 1 | module: "github.com/ryoya-fujimoto" 2 | -------------------------------------------------------------------------------- /examples/cue-module-sample/device.cue: -------------------------------------------------------------------------------- 1 | import "github.com/ryoya-fujimoto/device" 2 | 3 | someDevice: device.Device & { 4 | id: 1 5 | user: { 6 | email: "user@example.com" 7 | name: "user1" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/cue-module-sample/device/resource.proto.cue: -------------------------------------------------------------------------------- 1 | package device 2 | 3 | import "github.com/ryoya-fujimoto/user" 4 | 5 | Device: { 6 | id?: uint64 @protobuf(1) 7 | user?: _user_.User @protobuf(2,type=user.User) 8 | } 9 | let _user_ = user 10 | -------------------------------------------------------------------------------- /examples/cue-module-sample/proto/device/resource.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package user; 4 | 5 | option go_package = "github.com/ryoya-fujimoto/device;device"; 6 | 7 | import "proto/user/resource.proto"; // <--これ 8 | 9 | message Device { 10 | uint64 id = 1; 11 | user.User user = 2; 12 | } 13 | -------------------------------------------------------------------------------- /examples/cue-module-sample/proto/device/resource.proto.cue: -------------------------------------------------------------------------------- 1 | package device 2 | 3 | import "github.com/ryoya-fujimoto/user" 4 | 5 | Device: { 6 | id?: uint64 @protobuf(1) 7 | user?: _user_.User @protobuf(2,type=user.User) 8 | } 9 | let _user_ = user 10 | -------------------------------------------------------------------------------- /examples/cue-module-sample/proto/user/resource.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package user; 4 | 5 | option go_package = "github.com/ryoya-fujimoto/user;user"; 6 | 7 | message User { 8 | string email = 1; 9 | string name = 2; 10 | } 11 | -------------------------------------------------------------------------------- /examples/cue-module-sample/proto/user/resource.proto.cue: -------------------------------------------------------------------------------- 1 | package user 2 | 3 | User: { 4 | email?: string @protobuf(1) 5 | name?: string @protobuf(2) 6 | } 7 | -------------------------------------------------------------------------------- /examples/cue-module-sample/user/resource.proto.cue: -------------------------------------------------------------------------------- 1 | package user 2 | 3 | User: { 4 | email?: string @protobuf(1) 5 | name?: string @protobuf(2) 6 | } 7 | -------------------------------------------------------------------------------- /examples/grpc-testing/.gitignore: -------------------------------------------------------------------------------- 1 | tests/ 2 | tmp/ -------------------------------------------------------------------------------- /examples/grpc-testing/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 r-fujimoto 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /examples/grpc-testing/Makefile: -------------------------------------------------------------------------------- 1 | setup: 2 | go get github.com/pilu/fresh 3 | 4 | run: 5 | fresh -c runner.conf 6 | 7 | lint: 8 | go vet ./... 9 | golint -set_exit_status ./... 10 | 11 | fmt: lint 12 | goimports -w . -------------------------------------------------------------------------------- /examples/grpc-testing/README.md: -------------------------------------------------------------------------------- 1 | # grpc-testing 2 | 3 | This is the testing and helper tool for grpc server, using [cuelang](https://github.com/cuelang/cue) and [grpcurl](https://github.com/fullstorydev/grpcurl). 4 | 5 | notice: This tool is a in progress. 6 | 7 | ## Usage 8 | 9 | ### install 10 | 11 | ```bash 12 | go get -u github.com/ryoya-fujimoto/grpc-testing 13 | ``` 14 | 15 | ### Generate test file 16 | 17 | First, create a test file using grpc-testing. 18 | 19 | ```bash 20 | grpc-testing add tests/FirstTest 21 | ``` 22 | 23 | `FirstTest` is the test file name. This command generate cuelang file like this. 24 | 25 | tests/FirstTest.cue 26 | 27 | ``` 28 | name: "FirstTest2" 29 | Input: {} 30 | Output: {} 31 | Test :: { 32 | name: string 33 | method: string 34 | proto?: [...string] 35 | import_path?: [...string] 36 | headers?: [string]: string 37 | input: Input 38 | output: Output 39 | } 40 | cases: [...Test] & [ 41 | { 42 | name: "" 43 | method: "" 44 | input: {} 45 | output: {} 46 | }, 47 | ] 48 | ``` 49 | 50 | `cases` is a test cases. You can add grpc test case to this list. 51 | The `add` command can specify protobuf files, and when specified, generate cue file is merged protobuf schemas. 52 | 53 | ```bash 54 | grpc-testing add --proto_path example/app --protofiles example/app/*.proto tests/FirstTest 55 | ``` 56 | 57 | This command generate below cue file. 58 | 59 | ``` 60 | import "github.com/ryoya-fujimoto/grpc-testing/example/app" 61 | 62 | name: "FirstTest" 63 | Input: {} 64 | Output: {} 65 | Test :: { 66 | name: string 67 | method: string 68 | proto?: [...string] 69 | import_path?: [...string] 70 | headers?: [string]: string 71 | input: Input 72 | output: Output 73 | } 74 | cases: [...Test] & [ 75 | { 76 | name: "" 77 | method: "" 78 | input: {} 79 | output: {} 80 | }, 81 | ] 82 | ``` 83 | 84 | ### Test your grpc server 85 | 86 | Edit your test case file for testing grpc server, like below (write cases param only). 87 | 88 | ``` 89 | cases: [...Test] & [{ 90 | name: "GetUser" 91 | method: "UserService.GetUser" 92 | input: app.GetUserRequest & { 93 | id: 5 94 | } 95 | output: { 96 | id: "5" 97 | name: "John Smith" 98 | } 99 | }] 100 | ``` 101 | 102 | Now, you can request to grpc server using input object. 103 | 104 | `grpc-testing run` prints response from server. 105 | 106 | ```bash 107 | $ grpc-testing run localhost:8080 tests/FirstTest.cue 108 | tests/FirstTest.cue 109 | test name: GetUser 110 | method: UserService.GetUser 111 | output: { 112 | "id": "5", 113 | "name": "John Smith" 114 | } 115 | ``` 116 | 117 | `grpc-testing test` compares between response and output parameter. 118 | 119 | ```bash 120 | $ grpc-testing test localhost:8080 tests/FirstTest.cue 121 | tests/FirstTest.cue 122 | OK: GetUser 123 | ``` 124 | 125 | ### Test your grpc server using protofile, not gRPC reflection API 126 | 127 | If your grpc server does not implement gRPC reflection API, you can use protofiles in the same way as the grpcurl `-proto` and `-import-path` options. 128 | 129 | add `proto` and `import_path` to test case setting: 130 | 131 | ``` 132 | cases: [...Test] & [{ 133 | name: "GetUser" 134 | method: "UserService.GetUser" 135 | proto: ["./example/app/app.proto"] 136 | import_path: ["./example/app/"] 137 | input: app.GetUserRequest & { 138 | id: 5 139 | } 140 | output: { 141 | id: "5" 142 | name: "John Smith" 143 | } 144 | }] 145 | ``` 146 | -------------------------------------------------------------------------------- /examples/grpc-testing/cmd/add.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "io/ioutil" 7 | "os" 8 | "path/filepath" 9 | "text/template" 10 | 11 | "github.com/urfave/cli/v2" 12 | ) 13 | 14 | // Add test case file 15 | func Add(c *cli.Context) error { 16 | if c.NArg() == 0 { 17 | fmt.Println("Please specify test case name") 18 | cli.ShowCommandHelpAndExit(c, "add", 1) 19 | return nil 20 | } 21 | 22 | targetName, outPath := extractTarget(c.Args().Get(0)) 23 | 24 | protoRoot := c.String("proto_path") 25 | if protoRoot == "" { 26 | protoRoot = "./" 27 | } 28 | protoFiles := c.StringSlice("protofiles") 29 | 30 | _, err := os.Stat(outPath) 31 | if err == nil { 32 | fmt.Printf("%s is already exists", outPath) 33 | return nil 34 | } 35 | 36 | cueImports, err := generateCUEModule(protoRoot, protoFiles) 37 | if err != nil { 38 | if err.Error() == "no protofiles" { 39 | fmt.Println("No protofiles. Will not generate schemas.") 40 | } else { 41 | return err 42 | } 43 | } 44 | 45 | tpl := template.New("schema") 46 | tpl.Parse(testCaseSchema) 47 | m := map[string]interface{}{ 48 | "Name": targetName, 49 | "Imports": cueImports, 50 | } 51 | var base bytes.Buffer 52 | _ = tpl.Execute(&base, m) 53 | 54 | err = os.MkdirAll(filepath.Dir(outPath), 0755) 55 | if err != nil { 56 | return err 57 | } 58 | 59 | err = ioutil.WriteFile(outPath, base.Bytes(), 0644) 60 | if err != nil { 61 | return err 62 | } 63 | 64 | fmt.Println("create:", outPath) 65 | return nil 66 | } 67 | 68 | const testCaseSchema = `{{range .Imports}}import "{{.}}" 69 | {{end}} 70 | name: "{{.Name}}" 71 | Input: {} 72 | Output: {} 73 | Test :: { 74 | name: string 75 | method: string 76 | proto?: [...string] 77 | import_path?: [...string] 78 | headers?: [string]: string 79 | input: Input 80 | output: Output 81 | } 82 | cases: [...Test] & [ 83 | { 84 | name: "" 85 | method: "" 86 | input: {} 87 | output: {} 88 | }, 89 | ] 90 | ` 91 | -------------------------------------------------------------------------------- /examples/grpc-testing/cmd/grpcurl.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "bytes" 5 | "context" 6 | "fmt" 7 | "io" 8 | "log" 9 | "os" 10 | "strings" 11 | 12 | "github.com/fullstorydev/grpcurl" 13 | "github.com/jhump/protoreflect/grpcreflect" 14 | "google.golang.org/grpc" 15 | "google.golang.org/grpc/codes" 16 | "google.golang.org/grpc/credentials" 17 | "google.golang.org/grpc/metadata" 18 | reflectpb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha" 19 | ) 20 | 21 | func invokeRPC(ctx context.Context, serverName, methodName string, headers map[string]string, protoFiles, importPath multiString, reqData []byte, res io.Writer) error { 22 | dial := func() *grpc.ClientConn { 23 | var creds credentials.TransportCredentials 24 | var opts []grpc.DialOption 25 | network := "tcp" 26 | cc, err := grpcurl.BlockingDial(ctx, network, serverName, creds, opts...) 27 | if err != nil { 28 | log.Fatal(err) 29 | } 30 | 31 | return cc 32 | } 33 | 34 | var cc *grpc.ClientConn 35 | var descSource grpcurl.DescriptorSource 36 | var refClient *grpcreflect.Client 37 | 38 | if len(protoFiles) > 0 { 39 | var err error 40 | descSource, err = grpcurl.DescriptorSourceFromProtoFiles(importPath, protoFiles...) 41 | if err != nil { 42 | return fmt.Errorf("create desc src: %w", err) 43 | } 44 | } else { 45 | md := grpcurl.MetadataFromHeaders([]string{}) 46 | refCtx := metadata.NewOutgoingContext(ctx, md) 47 | cc = dial() 48 | refClient = grpcreflect.NewClient(refCtx, reflectpb.NewServerReflectionClient(cc)) 49 | descSource = grpcurl.DescriptorSourceFromServer(ctx, refClient) 50 | } 51 | 52 | reset := func() { 53 | if refClient != nil { 54 | refClient.Reset() 55 | refClient = nil 56 | } 57 | if cc != nil { 58 | cc.Close() 59 | cc = nil 60 | } 61 | } 62 | defer reset() 63 | 64 | if cc == nil { 65 | cc = dial() 66 | } 67 | 68 | var in io.Reader 69 | in = bytes.NewReader(reqData) 70 | 71 | rf, formatter, err := grpcurl.RequestParserAndFormatterFor(grpcurl.FormatJSON, descSource, false, false, in) 72 | if err != nil { 73 | return err 74 | } 75 | h := grpcurl.NewDefaultEventHandler(res, descSource, formatter, false) 76 | 77 | headerStr := createHeaderStr(headers) 78 | err = grpcurl.InvokeRPC(ctx, descSource, cc, methodName, headerStr, h, rf.Next) 79 | if err != nil { 80 | return err 81 | } 82 | 83 | if h.Status.Code() != codes.OK { 84 | grpcurl.PrintStatus(os.Stderr, h.Status, formatter) 85 | return fmt.Errorf("invalid response code: %s", h.Status.Code().String()) 86 | } 87 | 88 | return nil 89 | } 90 | 91 | type multiString []string 92 | 93 | func (s *multiString) String() string { 94 | return strings.Join(*s, ",") 95 | } 96 | 97 | func (s *multiString) Set(value string) error { 98 | *s = append(*s, value) 99 | return nil 100 | } 101 | 102 | func createHeaderStr(h map[string]string) []string { 103 | headers := make([]string, len(h)) 104 | for k, v := range h { 105 | headers = append(headers, fmt.Sprintf("%s: %s", k, v)) 106 | } 107 | 108 | return headers 109 | } 110 | -------------------------------------------------------------------------------- /examples/grpc-testing/cmd/run.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "bytes" 5 | "context" 6 | "fmt" 7 | 8 | "github.com/mattn/go-zglob" 9 | 10 | "cuelang.org/go/encoding/gocode/gocodec" 11 | 12 | "github.com/urfave/cli/v2" 13 | ) 14 | 15 | // Run requests grpc to server using input in test case file. 16 | func Run(c *cli.Context) error { 17 | if c.NArg() == 0 { 18 | fmt.Println("Please specify server name") 19 | cli.ShowCommandHelpAndExit(c, "run", 1) 20 | return nil 21 | } 22 | serverName := c.Args().Get(0) 23 | if c.NArg() == 1 { 24 | fmt.Println("Please specify test name") 25 | cli.ShowCommandHelpAndExit(c, "run", 1) 26 | return nil 27 | } 28 | headers := extractHeaders(c.StringSlice("header")) 29 | testFiles, err := zglob.Glob(c.Args().Get(1)) 30 | if err != nil { 31 | return err 32 | } 33 | 34 | targetTestName := "" 35 | if c.NArg() > 2 { 36 | targetTestName = c.Args().Get(2) 37 | } 38 | 39 | for _, testFile := range testFiles { 40 | if err := run(serverName, testFile, targetTestName, headers); err != nil { 41 | return err 42 | } 43 | } 44 | 45 | return nil 46 | } 47 | 48 | func run(serverHost, testFile, testName string, headers map[string]string) error { 49 | ins, err := readCueInstance(testFile) 50 | if err != nil { 51 | return err 52 | } 53 | 54 | insVal, _ := ins.Value().Struct() 55 | cases, _ := insVal.FieldByName("cases", false) 56 | 57 | codec := gocodec.New(&r, &gocodec.Config{}) 58 | 59 | testCases := []testCase{} 60 | err = codec.Encode(cases.Value, &testCases) 61 | if err != nil { 62 | return err 63 | } 64 | 65 | fmt.Println(testFile) 66 | for _, c := range testCases { 67 | if testName != "" && testName != c.Name { 68 | continue 69 | } 70 | fmt.Printf("\ttest name: %s\n", c.Name) 71 | fmt.Printf("\tmethod: %s\n", c.Method) 72 | 73 | h := mergeMap(headers, c.Headers) 74 | 75 | res := &bytes.Buffer{} 76 | err = invokeRPC(context.Background(), serverHost, c.Method, h, c.Proto, c.ImportPath, c.Input, res) 77 | if err != nil { 78 | return fmt.Errorf("invoke grpc: %w", err) 79 | } 80 | fmt.Println("\toutput:", addTabToNewline(res.String(), 2)) 81 | } 82 | 83 | return nil 84 | } 85 | -------------------------------------------------------------------------------- /examples/grpc-testing/cmd/test.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "bytes" 5 | "context" 6 | "encoding/json" 7 | "fmt" 8 | 9 | "github.com/google/go-cmp/cmp" 10 | 11 | "github.com/mattn/go-zglob" 12 | 13 | "github.com/kylelemons/godebug/pretty" 14 | 15 | "cuelang.org/go/encoding/gocode/gocodec" 16 | "github.com/urfave/cli/v2" 17 | ) 18 | 19 | // Test runs test from test case file. 20 | func Test(c *cli.Context) error { 21 | if c.NArg() == 0 { 22 | fmt.Println("Please specify server name") 23 | cli.ShowCommandHelpAndExit(c, "run", 1) 24 | return nil 25 | } 26 | serverName := c.Args().Get(0) 27 | if c.NArg() == 1 { 28 | fmt.Println("Please specify test name") 29 | cli.ShowCommandHelpAndExit(c, "run", 1) 30 | return nil 31 | } 32 | headers := extractHeaders(c.StringSlice("header")) 33 | testFiles, err := zglob.Glob(c.Args().Get(1)) 34 | if err != nil { 35 | return err 36 | } 37 | 38 | targetTestName := "" 39 | if c.NArg() > 2 { 40 | targetTestName = c.Args().Get(2) 41 | } 42 | 43 | errs := []string{} 44 | for _, testFile := range testFiles { 45 | testFails, err := test(serverName, testFile, targetTestName, headers) 46 | if err != nil { 47 | return err 48 | } 49 | errs = append(errs, testFails...) 50 | } 51 | 52 | if len(errs) > 0 { 53 | return fmt.Errorf("test failed") 54 | } 55 | return nil 56 | } 57 | 58 | func test(serverHost, testFile, testName string, headers map[string]string) ([]string, error) { 59 | ins, err := readCueInstance(testFile) 60 | if err != nil { 61 | return nil, err 62 | } 63 | 64 | insVal, _ := ins.Value().Struct() 65 | cases, _ := insVal.FieldByName("cases", false) 66 | 67 | codec := gocodec.New(&r, &gocodec.Config{}) 68 | 69 | testCases := []testCase{} 70 | err = codec.Encode(cases.Value, &testCases) 71 | if err != nil { 72 | return nil, err 73 | } 74 | 75 | fmt.Println(testFile) 76 | errs := []string{} 77 | for _, c := range testCases { 78 | if testName != "" && testName != c.Name { 79 | continue 80 | } 81 | tName := c.Name 82 | if tName == "" { 83 | tName = c.Method 84 | } 85 | 86 | h := mergeMap(headers, c.Headers) 87 | 88 | res := &bytes.Buffer{} 89 | invokeRPC(context.Background(), serverHost, c.Method, h, c.Proto, c.ImportPath, c.Input, res) 90 | 91 | expectJSON := map[string]interface{}{} 92 | resJSON := map[string]interface{}{} 93 | 94 | if err := json.Unmarshal(c.Output, &expectJSON); err != nil { 95 | return nil, err 96 | } 97 | if err := json.Unmarshal(res.Bytes(), &resJSON); err != nil { 98 | return nil, err 99 | } 100 | 101 | if diff := compareResult(expectJSON, resJSON); diff != "" { 102 | ej, _ := json.Marshal(expectJSON) 103 | rj, _ := json.Marshal(resJSON) 104 | errs = append(errs, fmt.Sprintf("expect: %s, but: %s", string(ej), string(rj))) 105 | fmt.Printf("\tNG: %s\n\t\t%s\n", tName, addTabToNewline(pretty.Compare(expectJSON, resJSON), 2)) 106 | } else { 107 | fmt.Printf("\tOK: %s\n", tName) 108 | } 109 | } 110 | 111 | return errs, nil 112 | } 113 | 114 | func compareResult(expect, result map[string]interface{}) string { 115 | mapComparer := cmp.Comparer(func(x, y map[string]interface{}) bool { 116 | for key := range x { 117 | if _, ok := y[key]; !ok { 118 | delete(x, key) 119 | } 120 | } 121 | for key := range y { 122 | if _, ok := x[key]; !ok { 123 | delete(y, key) 124 | } 125 | } 126 | 127 | return cmp.Equal(x, y) 128 | }) 129 | filter := cmp.FilterValues(func(x, y map[string]interface{}) bool { 130 | return len(x) != len(y) 131 | }, mapComparer) 132 | 133 | return cmp.Diff(expect, result, filter) 134 | } 135 | -------------------------------------------------------------------------------- /examples/grpc-testing/cmd/util.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "path/filepath" 5 | "strings" 6 | ) 7 | 8 | func extractTarget(testName string) (baseName string, filePath string) { 9 | baseName = filepath.Base(testName) 10 | filename := baseName 11 | if !strings.HasSuffix(filename, ".cue") { 12 | filename = filename + ".cue" 13 | } 14 | return baseName, filepath.Join(filepath.Dir(testName), filename) 15 | } 16 | 17 | func addTabToNewline(str string, tabNum int) string { 18 | return strings.Replace(str, "\n", "\n\t\t", -1) 19 | } 20 | 21 | func extractHeaders(headers []string) map[string]string { 22 | h := map[string]string{} 23 | for _, headerSet := range headers { 24 | s := strings.Split(headerSet, ":") 25 | if len(s) < 2 { 26 | continue 27 | } 28 | h[strings.TrimSpace(s[0])] = strings.TrimSpace(s[1]) 29 | } 30 | 31 | return h 32 | } 33 | 34 | func mergeMap(m1, m2 map[string]string) map[string]string { 35 | result := map[string]string{} 36 | 37 | for k, v := range m1 { 38 | result[k] = v 39 | } 40 | for k, v := range m2 { 41 | result[k] = v 42 | } 43 | return (result) 44 | } 45 | -------------------------------------------------------------------------------- /examples/grpc-testing/cmd/validate.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/mattn/go-zglob" 7 | "github.com/urfave/cli/v2" 8 | ) 9 | 10 | // Validate validates test files with schemas. 11 | func Validate(c *cli.Context) error { 12 | if c.NArg() == 0 { 13 | fmt.Println("Please specify test file") 14 | cli.ShowCommandHelpAndExit(c, "validate", 1) 15 | return nil 16 | } 17 | 18 | testFiles, err := zglob.Glob(c.Args().Get(0)) 19 | if err != nil { 20 | return err 21 | } 22 | 23 | for _, testFile := range testFiles { 24 | ins, err := readCueInstance(testFile) 25 | if err != nil { 26 | return err 27 | } 28 | if err := ins.Value().Validate(); err != nil { 29 | fmt.Println("NG:", testFile) 30 | fmt.Println(err.Error()) 31 | } else { 32 | fmt.Println("OK:", testFile) 33 | } 34 | } 35 | 36 | return nil 37 | } 38 | -------------------------------------------------------------------------------- /examples/grpc-testing/example/app/app.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/ryoya-fujimoto/grpc-testing/example/app"; 4 | 5 | service UserService { 6 | rpc CreateUser(CreateUserRequest) returns (User) {} 7 | rpc GetUser(GetUserRequest) returns (User) {} 8 | } 9 | 10 | message GetUserRequest { 11 | uint64 id = 1; 12 | } 13 | 14 | message CreateUserRequest { 15 | string name = 1; 16 | } 17 | 18 | message User { 19 | uint64 id = 1; 20 | string name = 2; 21 | } 22 | -------------------------------------------------------------------------------- /examples/grpc-testing/example/app/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/ryoya-fujimoto/grpc-testing/example/app 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/golang/protobuf v1.3.2 7 | golang.org/x/net v0.0.0-20191101175033-0deb6923b6d9 // indirect 8 | golang.org/x/sys v0.0.0-20191029155521-f43be2a4598c // indirect 9 | golang.org/x/text v0.3.2 // indirect 10 | google.golang.org/genproto v0.0.0-20191028173616-919d9bdd9fe6 // indirect 11 | google.golang.org/grpc v1.24.0 12 | ) 13 | -------------------------------------------------------------------------------- /examples/grpc-testing/example/app/go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 3 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 4 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 5 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 6 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 7 | github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= 8 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 9 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 10 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 11 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 12 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 13 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 14 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 15 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 16 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 17 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 18 | golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= 19 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 20 | golang.org/x/net v0.0.0-20191101175033-0deb6923b6d9 h1:DPz9iiH3YoKiKhX/ijjoZvT0VFwK2c6CWYWQ7Zyr8TU= 21 | golang.org/x/net v0.0.0-20191101175033-0deb6923b6d9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 22 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 23 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 24 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 25 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 26 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 27 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= 28 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 29 | golang.org/x/sys v0.0.0-20191029155521-f43be2a4598c h1:S/FtSvpNLtFBgjTqcKsRpsa6aVsI6iztaz1bQd9BJwE= 30 | golang.org/x/sys v0.0.0-20191029155521-f43be2a4598c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 31 | golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= 32 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 33 | golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= 34 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 35 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 36 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 37 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 38 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 39 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 40 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 41 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 42 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc= 43 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 44 | google.golang.org/genproto v0.0.0-20191028173616-919d9bdd9fe6 h1:UXl+Zk3jqqcbEVV7ace5lrt4YdA4tXiz3f/KbmD29Vo= 45 | google.golang.org/genproto v0.0.0-20191028173616-919d9bdd9fe6/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 46 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 47 | google.golang.org/grpc v1.24.0 h1:vb/1TCsVn3DcJlQ0Gs1yB1pKI6Do2/QNwxdKqmc/b0s= 48 | google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= 49 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 50 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 51 | -------------------------------------------------------------------------------- /examples/grpc-testing/example/app/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | "net" 7 | 8 | "google.golang.org/grpc/reflection" 9 | 10 | "google.golang.org/grpc" 11 | 12 | "github.com/ryoya-fujimoto/grpc-testing/example/app/pb" 13 | ) 14 | 15 | const port = ":8080" 16 | 17 | type server struct{} 18 | 19 | func (s *server) CreateUser(ctx context.Context, req *pb.CreateUserRequest) (*pb.User, error) { 20 | log.Println("Create user:", req.GetName()) 21 | 22 | return &pb.User{Id: 1, Name: req.GetName()}, nil 23 | } 24 | 25 | func (s *server) GetUser(ctx context.Context, req *pb.GetUserRequest) (*pb.User, error) { 26 | log.Println("Get user id: ", req.GetId()) 27 | 28 | return &pb.User{Id: req.GetId(), Name: "John Smith"}, nil 29 | } 30 | 31 | func main() { 32 | l, err := net.Listen("tcp", port) 33 | if err != nil { 34 | panic(err) 35 | } 36 | 37 | s := grpc.NewServer() 38 | pb.RegisterUserServiceServer(s, &server{}) 39 | reflection.Register(s) 40 | log.Println("Listening on", port) 41 | if err := s.Serve(l); err != nil { 42 | panic(err) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /examples/grpc-testing/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/ryoya-fujimoto/grpc-testing 2 | 3 | go 1.13 4 | 5 | require ( 6 | cuelang.org/go v0.2.0 7 | github.com/emicklei/proto v1.9.0 8 | github.com/fullstorydev/grpcurl v1.4.0 9 | github.com/google/go-cmp v0.4.0 10 | github.com/jhump/protoreflect v1.6.0 11 | github.com/kylelemons/godebug v1.1.0 12 | github.com/mattn/go-zglob v0.0.1 13 | github.com/pkg/errors v0.9.1 // indirect 14 | github.com/urfave/cli/v2 v2.1.1 15 | golang.org/x/sys v0.0.0-20200219091948-cb0a6d8edb6c // indirect 16 | golang.org/x/tools v0.0.0-20200530233709-52effbd89c51 // indirect 17 | google.golang.org/genproto v0.0.0-20200218151345-dad8c97a84f5 // indirect 18 | google.golang.org/grpc v1.27.1 19 | ) 20 | -------------------------------------------------------------------------------- /examples/grpc-testing/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | "github.com/ryoya-fujimoto/grpc-testing/cmd" 8 | "github.com/urfave/cli/v2" 9 | ) 10 | 11 | func main() { 12 | app := cli.NewApp() 13 | app.Name = "grpc-testing" 14 | app.Usage = "The scenario based grpc runner and tester tool" 15 | 16 | app.Commands = []*cli.Command{ 17 | { 18 | Name: "add", 19 | Usage: "add test case file", 20 | Action: cmd.Add, 21 | ArgsUsage: "`test file`", 22 | Flags: []cli.Flag{ 23 | &cli.StringFlag{ 24 | Name: "proto_path", 25 | Usage: "Protofiles root path", 26 | }, 27 | &cli.StringSliceFlag{ 28 | Name: "protofiles", 29 | Usage: "Protofiles to include. You can use grob patterns.", 30 | }, 31 | }, 32 | }, 33 | { 34 | Name: "validate", 35 | Usage: "validate test case files with schemas", 36 | Action: cmd.Validate, 37 | ArgsUsage: "`test file(can use glob)`", 38 | }, 39 | { 40 | Name: "run", 41 | Usage: "Requests grpc to server using input in test case file, and output response.", 42 | Action: cmd.Run, 43 | ArgsUsage: "`hostname` `test file(can use glob)` `[(optional) test name]`", 44 | Flags: []cli.Flag{ 45 | &cli.StringSliceFlag{ 46 | Name: "header", 47 | Usage: "Additional RPC headers in 'name: value' format.", 48 | }, 49 | }, 50 | }, 51 | { 52 | Name: "test", 53 | Usage: "Requests grpc to server using input in test case file, and compare between response and output parameter.", 54 | Action: cmd.Test, 55 | ArgsUsage: "`hostname` `test file(can use glob)` `[(optional) test name]`", 56 | Flags: []cli.Flag{ 57 | &cli.StringSliceFlag{ 58 | Name: "header", 59 | Usage: "Additional RPC headers in 'name: value' format.", 60 | }, 61 | }, 62 | }, 63 | } 64 | 65 | err := app.Run(os.Args) 66 | if err != nil { 67 | fmt.Println(err) 68 | os.Exit(1) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /examples/grpc-testing/runner.conf: -------------------------------------------------------------------------------- 1 | build_name: grpc-testing 2 | tmp_path:./tmp -------------------------------------------------------------------------------- /examples/hof/cue.mod/go.mod: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/examples/hof/cue.mod/go.mod -------------------------------------------------------------------------------- /examples/hof/cue.mod/module.cue: -------------------------------------------------------------------------------- 1 | module: "github.com/hofstadter-io/hof" 2 | -------------------------------------------------------------------------------- /examples/hof/design/cli/cmds/0-args.cue: -------------------------------------------------------------------------------- 1 | package cmds 2 | -------------------------------------------------------------------------------- /examples/hof/design/cli/cmds/0-flags.cue: -------------------------------------------------------------------------------- 1 | package cmds 2 | -------------------------------------------------------------------------------- /examples/hof/design/cli/cmds/add.cue: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "github.com/hofstadter-io/hofmod-cli/schema" 5 | ) 6 | 7 | // cue get + hof add 8 | #AddCommand: schema.#Command & { 9 | TBD: "α" 10 | Name: "add" 11 | Usage: "add" 12 | Short: "add dependencies and new components to the current module or workspace" 13 | Long: Short 14 | } 15 | -------------------------------------------------------------------------------- /examples/hof/design/cli/cmds/auth.cue: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "github.com/hofstadter-io/hofmod-cli/schema" 5 | ) 6 | 7 | #AuthCommand: schema.#Command & { 8 | TBD: "Ø" 9 | Name: "auth" 10 | Usage: "auth" 11 | Short: "authentication subcommands" 12 | Long: Short 13 | 14 | OmitRun: true 15 | 16 | Commands: [{ 17 | TBD: "Ø" 18 | Name: "login" 19 | Usage: "login " 20 | Short: "login to an account, provider, system, or url" 21 | Long: Short 22 | Args: [ 23 | { 24 | Name: "where" 25 | Type: "string" 26 | Help: "the account, provider, system, or url you wish to authenticate with" 27 | }, 28 | ] 29 | }, { 30 | TBD: "Ø" 31 | Name: "logout" 32 | Usage: "logout " 33 | Short: "logout of an authenticated session" 34 | Long: Short 35 | }, { 36 | TBD: "Ø" 37 | Name: "list" 38 | Usage: "list" 39 | Short: "list known auth configurations and sessions" 40 | Long: Short 41 | }, { 42 | TBD: "Ø" 43 | Name: "test" 44 | Usage: "test [name]" 45 | Short: "test your auth configuration, defaults to current context" 46 | Long: Short 47 | }] 48 | } 49 | -------------------------------------------------------------------------------- /examples/hof/design/cli/cmds/cmd.cue: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "github.com/hofstadter-io/hofmod-cli/schema" 5 | ) 6 | 7 | // cue run + hof extra 8 | #CmdCommand: schema.#Command & { 9 | TBD: "α" 10 | Name: "cmd" 11 | Usage: "cmd [flags] [cmd] [args]" 12 | Short: "run commands from the scripting layer and your _tool.cue files" 13 | Long: Short 14 | } 15 | -------------------------------------------------------------------------------- /examples/hof/design/cli/cmds/cue.cue: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "github.com/hofstadter-io/hofmod-cli/schema" 5 | ) 6 | 7 | // Commands drawn from Cue with a touch of hof 8 | 9 | #DefCommand: schema.#Command & { 10 | TBD: "α" 11 | Name: "def" 12 | Usage: "def" 13 | Short: "print consolidated definitions" 14 | Long: Short 15 | } 16 | 17 | #EvalCommand: schema.#Command & { 18 | TBD: "α" 19 | Name: "eval" 20 | Usage: "eval" 21 | Short: "print consolidated definitions" 22 | Long: Short 23 | } 24 | 25 | #ExportCommand: schema.#Command & { 26 | TBD: "α" 27 | Name: "export" 28 | Usage: "export" 29 | Short: "export your data model to various formats" 30 | Long: Short 31 | } 32 | 33 | #FormatCommand: schema.#Command & { 34 | TBD: "α" 35 | Name: "fmt" 36 | Usage: "fmt" 37 | Short: "formats code and files" 38 | Long: Short 39 | } 40 | 41 | #ImportCommand: schema.#Command & { 42 | TBD: "α" 43 | Name: "import" 44 | Usage: "import" 45 | Short: "convert other formats and systems to hofland" 46 | Long: Short 47 | } 48 | 49 | #TrimCommand: schema.#Command & { 50 | TBD: "α" 51 | Name: "trim" 52 | Usage: "trim" 53 | Short: "cleanup code, configuration, and more" 54 | Long: Short 55 | } 56 | 57 | #VetCommand: schema.#Command & { 58 | TBD: "α" 59 | Name: "vet" 60 | Usage: "vet" 61 | Short: "validate data" 62 | Long: Short 63 | } 64 | -------------------------------------------------------------------------------- /examples/hof/design/cli/cmds/cuefig.cue: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "github.com/hofstadter-io/hofmod-cli/schema" 5 | ) 6 | 7 | #ContextCommand: schema.#Command & { 8 | TBD: "α" 9 | Name: "context" 10 | Usage: "context" 11 | Short: "get, set, and use contexts" 12 | Long: Short 13 | 14 | OmitRun: true 15 | 16 | Commands: [{ 17 | TBD: "β" 18 | Name: "get" 19 | Usage: "get " 20 | Short: "print a context or value(s) at path(s)" 21 | Long: Short 22 | }, { 23 | TBD: "β" 24 | Name: "set" 25 | Usage: "set [expr]" 26 | Short: "set context values with an expr" 27 | Long: Short 28 | Args: [{ 29 | Name: "expr" 30 | Type: "string" 31 | Required: true 32 | Help: "Cue expr for value you'd like to merge into your context" 33 | }] 34 | }, { 35 | TBD: "Ø" 36 | Name: "use" 37 | Usage: "use [name]" 38 | Short: "set a context as the current default" 39 | Long: Short 40 | }, { 41 | TBD: "Ø" 42 | Name: "source" 43 | Usage: "source [name]" 44 | Short: "source a context into your environment" 45 | Long: Short 46 | }, { 47 | TBD: "Ø" 48 | Name: "clear" 49 | Usage: "clear" 50 | Short: "clear your context and environment" 51 | Long: Short 52 | }] 53 | } 54 | 55 | #ConfigCommand: schema.#Command & { 56 | TBD: "β" 57 | Name: "config" 58 | Usage: "config" 59 | Short: "manage local configurations" 60 | Long: Short 61 | 62 | OmitRun: true 63 | 64 | Commands: [{ 65 | TBD: "β" 66 | Name: "get" 67 | Usage: "get " 68 | Short: "print a config or value(s) at path(s)" 69 | Long: Short 70 | }, { 71 | TBD: "β" 72 | Name: "set" 73 | Usage: "set [expr]" 74 | Short: "set config values with an expr" 75 | Long: Short 76 | Args: [{ 77 | Name: "expr" 78 | Type: "string" 79 | Required: true 80 | Help: "Cue expr for value you'd like to merge into your config" 81 | }] 82 | }, { 83 | TBD: "Ø" 84 | Name: "use" 85 | Usage: "use [name]" 86 | Short: "bring a config into the current" 87 | Long: Short 88 | }] 89 | } 90 | 91 | #SecretCommand: schema.#Command & { 92 | TBD: "β" 93 | Name: "secret" 94 | Usage: "secret" 95 | Short: "manage local secrets" 96 | Long: Short 97 | 98 | OmitRun: true 99 | 100 | Commands: [{ 101 | TBD: "β" 102 | Name: "get" 103 | Usage: "get " 104 | Short: "print a secret or value(s) at path(s)" 105 | Long: Short 106 | }, { 107 | TBD: "β" 108 | Name: "set" 109 | Usage: "set [expr]" 110 | Short: "set secret values with an expr" 111 | Long: Short 112 | Args: [{ 113 | Name: "expr" 114 | Type: "string" 115 | Required: true 116 | Help: "Cue expr for value you'd like to merge into your secret" 117 | }] 118 | }, { 119 | TBD: "Ø" 120 | Name: "use" 121 | Usage: "use [name]" 122 | Short: "bring a secret into the current" 123 | Long: Short 124 | }] 125 | } 126 | -------------------------------------------------------------------------------- /examples/hof/design/cli/cmds/datamodel.cue: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "github.com/hofstadter-io/hofmod-cli/schema" 5 | ) 6 | 7 | #DatamodelCommand: schema.#Command & { 8 | TBD: "α" 9 | Name: "datamodel" 10 | Usage: "datamodel" 11 | Aliases: ["dmod", "dm"] 12 | Short: "create, view, diff, calculate / migrate, and manage your data models" 13 | Long: Short 14 | 15 | OmitRun: true 16 | 17 | Commands: [{ 18 | TBD: "α" 19 | Name: "create" 20 | Usage: "create" 21 | Aliases: ["c"] 22 | Short: "create data models" 23 | Long: Short 24 | }, { 25 | TBD: "α" 26 | Name: "get" 27 | Usage: "get" 28 | Aliases: ["g"] 29 | Short: "find and display data models" 30 | Long: Short 31 | }, { 32 | TBD: "α" 33 | Name: "set" 34 | Usage: "set" 35 | Aliases: ["s"] 36 | Short: "find and configure data models" 37 | Long: Short 38 | }, { 39 | TBD: "α" 40 | Name: "edit" 41 | Usage: "edit" 42 | Aliases: ["e"] 43 | Short: "find and edit data models" 44 | Long: Short 45 | }, { 46 | TBD: "α" 47 | Name: "delete" 48 | Usage: "delete" 49 | Aliases: ["del"] 50 | Short: "find and delete data models" 51 | Long: Short 52 | }, { 53 | TBD: "α" 54 | Name: "status" 55 | Usage: "status" 56 | Aliases: ["st"] 57 | Short: "print the data model status" 58 | Long: Short 59 | }, { 60 | TBD: "α" 61 | Name: "visualize" 62 | Usage: "visualize" 63 | Aliases: ["v", "viz", "show"] 64 | Short: "visualize a data model" 65 | Long: Short 66 | }, { 67 | TBD: "α" 68 | Name: "diff" 69 | Usage: "diff" 70 | Aliases: ["d"] 71 | Short: "show the current diff for a data model" 72 | Long: Short 73 | }, { 74 | TBD: "α" 75 | Name: "history" 76 | Usage: "history" 77 | Aliases: ["hist", "h", "log", "l"] 78 | Short: "show the history for a data model" 79 | Long: Short 80 | }, { 81 | TBD: "α" 82 | Name: "migrate" 83 | Usage: "migrate" 84 | Aliases: ["mig", "migs", "migrations"] 85 | Short: "calculate a changeset for a data model" 86 | Long: Short 87 | }, { 88 | TBD: "α" 89 | Name: "apply" 90 | Usage: "apply" 91 | Aliases: ["a"] 92 | Short: "apply a migraion sequence against a data store" 93 | Long: Short 94 | }] 95 | } 96 | -------------------------------------------------------------------------------- /examples/hof/design/cli/cmds/dev.cue: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "github.com/hofstadter-io/hofmod-cli/schema" 5 | ) 6 | 7 | #ReproCommand: schema.#Command & { 8 | TBD: "Ø" 9 | Name: "reproduce" 10 | Usage: "reproduce" 11 | Aliases: ["repro"] 12 | Short: "Record, share, and replay reproducible environments and processes" 13 | Long: Short 14 | } 15 | 16 | #JumpCommand: schema.#Command & { 17 | TBD: "α" 18 | Name: "jump" 19 | Usage: "jump" 20 | Aliases: ["j", "leap"] 21 | Short: "Jumps help you do things with fewer keystrokes." 22 | Long: Short 23 | } 24 | 25 | #UiCommand: schema.#Command & { 26 | TBD: "Ø" 27 | Name: "ui" 28 | Usage: "ui" 29 | Short: "Run hof's local web ui" 30 | Long: Short 31 | } 32 | 33 | #TuiCommand: schema.#Command & { 34 | TBD: "Ø" 35 | Name: "tui" 36 | Usage: "tui" 37 | Short: "Run hof's terminal ui" 38 | Long: Short 39 | } 40 | 41 | #ReplCommand: schema.#Command & { 42 | TBD: "Ø" 43 | Name: "repl" 44 | Usage: "repl" 45 | Short: "Run hof's local REPL" 46 | Long: Short 47 | } 48 | -------------------------------------------------------------------------------- /examples/hof/design/cli/cmds/hof.cue: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "github.com/hofstadter-io/hofmod-cli/schema" 5 | ) 6 | 7 | #GenCommand: schema.#Command & { 8 | TBD: "✓" 9 | Name: "gen" 10 | Usage: "gen [files...]" 11 | Aliases: ["G"] 12 | Short: "generate code, data, and config from your data models and designs" 13 | Long: """ 14 | generate all the things, from code to data to config... 15 | """ 16 | 17 | Flags: [...schema.#Flag] & [ 18 | { 19 | Name: "stats" 20 | Type: "bool" 21 | Default: "false" 22 | Help: "Print generator statistics" 23 | Long: "stats" 24 | Short: "s" 25 | }, 26 | { 27 | Name: "generator" 28 | Type: "[]string" 29 | Default: "nil" 30 | Help: "Generators to run, default is all discovered" 31 | Long: "generator" 32 | Short: "g" 33 | }, 34 | ] 35 | 36 | } 37 | 38 | #FeedbackCommand: schema.#Command & { 39 | TBD: "Ø" 40 | Name: "feedback" 41 | Usage: "feedback [email] " 42 | Aliases: ["hi", "say", "from", "bug", "yo", "hello", "greetings", "support"] 43 | Short: "send feedback, bug reports, or any message :]" 44 | Long: """ 45 | send feedback, bug reports, or any message :] 46 | email: (optional) your email, if you'd like us to reply 47 | message: your message, please be respectful to the person receiving it 48 | """ 49 | } 50 | 51 | #GebCommand: schema.#Command & { 52 | Name: "geb" 53 | Usage: "_geb" 54 | Short: "" 55 | Long: "" 56 | Hidden: true 57 | OmitTests: true 58 | } 59 | 60 | #LogoCommand: schema.#Command & { 61 | Name: "logo" 62 | Usage: "_" 63 | Short: "" 64 | Long: "" 65 | Hidden: true 66 | OmitTests: true 67 | } 68 | -------------------------------------------------------------------------------- /examples/hof/design/cli/cmds/label.cue: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "github.com/hofstadter-io/hofmod-cli/schema" 5 | ) 6 | 7 | #LabelCommand: schema.#Command & { 8 | TBD: "α" 9 | Name: "label" 10 | Usage: "label" 11 | Aliases: ["l", "labels", "attrs"] 12 | Short: "manage labels for resources and more" 13 | Long: Short 14 | 15 | OmitRun: true 16 | 17 | Commands: [{ 18 | TBD: "α" 19 | Name: "info" 20 | Usage: "info" 21 | Aliases: ["i"] 22 | Short: "print info about labels in your workspace or system" 23 | Long: Short 24 | }, { 25 | TBD: "α" 26 | Name: "create" 27 | Usage: "create" 28 | Aliases: ["c"] 29 | Short: "add labels to your workspace or system" 30 | Long: Short 31 | }, { 32 | TBD: "α" 33 | Name: "get" 34 | Usage: "get" 35 | Aliases: ["g"] 36 | Short: "find and display labels from your workspace" 37 | Long: Short 38 | }, { 39 | TBD: "α" 40 | Name: "set" 41 | Usage: "set" 42 | Aliases: ["s"] 43 | Short: "find and configure labels from your workspace" 44 | Long: Short 45 | }, { 46 | TBD: "α" 47 | Name: "edit" 48 | Usage: "edit" 49 | Aliases: ["e"] 50 | Short: "edit labels in your workspace or system configurations" 51 | Long: Short 52 | }, { 53 | TBD: "α" 54 | Name: "delete" 55 | Usage: "delete" 56 | Aliases: ["del", "remove"] 57 | Short: "delete labels from your workspace or system" 58 | Long: Short 59 | }, { 60 | TBD: "α" 61 | Name: "apply" 62 | Usage: "apply" 63 | Aliases: ["a"] 64 | Short: "find and apply labels to resources" 65 | Long: Short 66 | }, { 67 | TBD: "α" 68 | Name: "remove" 69 | Usage: "remove" 70 | Aliases: ["r"] 71 | Short: "find and remove labels from resources" 72 | Long: Short 73 | }] 74 | } 75 | 76 | #LabelsetCommand: schema.#Command & { 77 | TBD: "α" 78 | Name: "labelset" 79 | Usage: "labelset" 80 | Aliases: ["L", "lset"] 81 | Short: "group resources, datamodels, labelsets, and more" 82 | Long: Short 83 | 84 | OmitRun: true 85 | 86 | Commands: [{ 87 | TBD: "α" 88 | Name: "info" 89 | Usage: "info" 90 | Aliases: ["i"] 91 | Short: "print info about labelsets in your workspace or system" 92 | Long: Short 93 | }, { 94 | TBD: "α" 95 | Name: "create" 96 | Usage: "create" 97 | Aliases: ["c"] 98 | Short: "add labelsets to your workspace or system" 99 | Long: Short 100 | }, { 101 | TBD: "α" 102 | Name: "get" 103 | Usage: "get" 104 | Aliases: ["g"] 105 | Short: "find and display labelsets from your workspace" 106 | Long: Short 107 | }, { 108 | TBD: "α" 109 | Name: "set" 110 | Usage: "set" 111 | Aliases: ["s"] 112 | Short: "find and configure labelsets from your workspace" 113 | Long: Short 114 | }, { 115 | TBD: "α" 116 | Name: "edit" 117 | Usage: "edit" 118 | Aliases: ["e"] 119 | Short: "edit labelsets in your workspace or system configurations" 120 | Long: Short 121 | }, { 122 | TBD: "α" 123 | Name: "delete" 124 | Usage: "delete" 125 | Aliases: ["del"] 126 | Short: "delete labelsets from your workspace or system" 127 | Long: Short 128 | }] 129 | } 130 | -------------------------------------------------------------------------------- /examples/hof/design/cli/cmds/resources.cue: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "github.com/hofstadter-io/hofmod-cli/schema" 5 | ) 6 | 7 | // Kubernetes inspired commands (maybe some hyper-cloud too) 8 | 9 | #InfoCommand: schema.#Command & { 10 | TBD: "α" 11 | Name: "info" 12 | Usage: "info" 13 | Aliases: ["i"] 14 | Short: "print information about known resources" 15 | Long: Short 16 | Flags: [{ 17 | Name: "builtin" 18 | Type: "bool" 19 | Default: "false" 20 | Help: "Only print builtin resources" 21 | Long: "builtin" 22 | Short: "" 23 | }, { 24 | Name: "custom" 25 | Type: "bool" 26 | Default: "false" 27 | Help: "Only print custom resources" 28 | Long: "custom" 29 | Short: "" 30 | }, { 31 | Name: "local" 32 | Type: "bool" 33 | Default: "false" 34 | Help: "Only print workspace resources" 35 | Long: "here" 36 | Short: "" 37 | }] 38 | } 39 | 40 | #CreateCommand: schema.#Command & { 41 | TBD: "α" 42 | Name: "create" 43 | Usage: "create" 44 | Aliases: ["c"] 45 | Short: "create resources" 46 | Long: Short 47 | } 48 | 49 | #GetCommand: schema.#Command & { 50 | TBD: "α" 51 | Name: "get" 52 | Usage: "get" 53 | Aliases: ["g"] 54 | Short: "find and display resources" 55 | Long: Short 56 | } 57 | 58 | #SetCommand: schema.#Command & { 59 | TBD: "α" 60 | Name: "set" 61 | Usage: "set" 62 | Aliases: ["s"] 63 | Short: "find and configure resources" 64 | Long: Short 65 | } 66 | 67 | #EditCommand: schema.#Command & { 68 | TBD: "α" 69 | Name: "edit" 70 | Usage: "edit" 71 | Aliases: ["e"] 72 | Short: "edit resources" 73 | Long: Short 74 | } 75 | 76 | #DeleteCommand: schema.#Command & { 77 | TBD: "α" 78 | Name: "delete" 79 | Usage: "delete" 80 | Aliases: ["del"] 81 | Short: "delete resources" 82 | Long: Short 83 | } 84 | -------------------------------------------------------------------------------- /examples/hof/design/cli/cmds/run.cue: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "github.com/hofstadter-io/hofmod-cli/schema" 5 | ) 6 | 7 | // TODO, JAMStack / HofKit 8 | #RunCommand: schema.#Command & { 9 | TBD: "β" 10 | Name: "run" 11 | Usage: "run" 12 | Aliases: ["r"] 13 | Short: "Hof Line Script (HLS) is a successor to bash and python based scripting" 14 | Long: #RunCommandHelp 15 | 16 | Flags: [ 17 | { 18 | Name: "list" 19 | Type: "bool" 20 | Default: "false" 21 | Help: "list matching scripts that would run" 22 | Long: "list" 23 | Short: "" 24 | ... 25 | }, 26 | { 27 | Name: "info" 28 | Type: "bool" 29 | Default: "false" 30 | Help: "view detailed info for matching scripts" 31 | Long: "info" 32 | Short: "" 33 | ... 34 | }, 35 | { 36 | Name: "suite" 37 | Type: "[]string" 38 | Default: "nil" 39 | Help: ": _ @run(suite)'s to run" 40 | Long: "suite" 41 | Short: "s" 42 | ... 43 | }, 44 | { 45 | Name: "runner" 46 | Type: "[]string" 47 | Default: "nil" 48 | Help: ": _ @run(script)'s to run" 49 | Long: "runner" 50 | Short: "r" 51 | ... 52 | }, 53 | { 54 | Name: "environment" 55 | Type: "[]string" 56 | Default: "nil" 57 | Help: "exrta environment variables for scripts" 58 | Long: "env" 59 | Short: "e" 60 | ... 61 | }, 62 | { 63 | Name: "data" 64 | Type: "[]string" 65 | Default: "nil" 66 | Help: "exrta data to include in the scripts context" 67 | Long: "data" 68 | Short: "d" 69 | ... 70 | }, 71 | { 72 | Name: "workdir" 73 | Type: "string" 74 | Default: "" 75 | Help: "working directory" 76 | Long: "workdir" 77 | Short: "w" 78 | ... 79 | }, 80 | ] 81 | 82 | } 83 | 84 | #RunCommandHelp: ##""" 85 | HofLineScript (HLS) run polyglot command and scripts seamlessly across runtimes 86 | 87 | can accept cue & flags or just a .hls file 88 | 89 | """## 90 | -------------------------------------------------------------------------------- /examples/hof/design/cli/cmds/runtimes.cue: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "github.com/hofstadter-io/hofmod-cli/schema" 5 | ) 6 | 7 | // Manage runtimes for many popular systems and languages. 8 | #RuntimesCommand: schema.#Command & { 9 | TBD: "α" 10 | Name: "runtimes" 11 | Usage: "runtimes" 12 | Short: "work with runtimes (go, js, py, bash, docker, cloud-vms, k8s, custom)" 13 | Long: Short 14 | 15 | OmitRun: true 16 | 17 | Commands: [{ 18 | TBD: "α" 19 | Name: "info" 20 | Usage: "info" 21 | Aliases: ["i"] 22 | Short: "print information about known runtimes" 23 | Long: Short 24 | }, { 25 | TBD: "α" 26 | Name: "create" 27 | Usage: "create" 28 | Aliases: ["c"] 29 | Short: "add a runtime to your system or workspace" 30 | Long: Short 31 | }, { 32 | TBD: "α" 33 | Name: "get" 34 | Usage: "get" 35 | Aliases: ["g"] 36 | Short: "find and display runtime configurations" 37 | Long: Short 38 | }, { 39 | TBD: "α" 40 | Name: "set" 41 | Usage: "set" 42 | Aliases: ["s"] 43 | Short: "find and configure runtimes" 44 | Long: Short 45 | }, { 46 | TBD: "α" 47 | Name: "edit" 48 | Usage: "edit" 49 | Aliases: ["e"] 50 | Short: "edit a runtime configuration" 51 | Long: Short 52 | }, { 53 | TBD: "α" 54 | Name: "delete" 55 | Usage: "delete" 56 | Aliases: ["del"] 57 | Short: "delete a runtime configuration" 58 | Long: Short 59 | }, { 60 | TBD: "α" 61 | Name: "install" 62 | Usage: "install" 63 | Aliases: ["I"] 64 | Short: "install a runtime" 65 | Long: Short 66 | }, { 67 | TBD: "α" 68 | Name: "uninstall" 69 | Usage: "uninstall" 70 | Short: "uninstall a runtime" 71 | Long: Short 72 | }] 73 | } 74 | 75 | //#RuntimesCommand: schema.#Command & { 76 | //Name: "runtimes" 77 | //Usage: "runtimes" 78 | //Aliases: ["r"] 79 | //Short: "manage installed runtimes, versions, and contexts" 80 | //Long: """ 81 | //manage installed runtimes, versions, and contexts 82 | //""" 83 | 84 | //Flags: [...schema.#Flag] & [ 85 | //{ 86 | //Name: "stats" 87 | //Type: "bool" 88 | //Default: "false" 89 | //Help: "Print generator statistics" 90 | //Long: "stats" 91 | //Short: "" 92 | //}, 93 | //{ 94 | //Name: "generator" 95 | //Type: "[]string" 96 | //Default: "nil" 97 | //Help: "Generators to run, default is all discovered" 98 | //Long: "generator" 99 | //Short: "g" 100 | //}, 101 | //] 102 | //} 103 | 104 | //#BuildpacksCommand: schema.#Command & { 105 | //Name: "buildpacks" 106 | //Usage: "buildpacks" 107 | //Aliases: ["r"] 108 | //Short: "manage installed buildpacks, versions, and contexts" 109 | //Long: """ 110 | //generate all the things, from code to data to config... 111 | //""" 112 | 113 | //Flags: [...schema.#Flag] & [ 114 | //{ 115 | //Name: "stats" 116 | //Type: "bool" 117 | //Default: "false" 118 | //Help: "Print generator statistics" 119 | //Long: "stats" 120 | //Short: "" 121 | //}, 122 | //{ 123 | //Name: "generator" 124 | //Type: "[]string" 125 | //Default: "nil" 126 | //Help: "Generators to run, default is all discovered" 127 | //Long: "generator" 128 | //Short: "g" 129 | //}, 130 | //] 131 | //} 132 | -------------------------------------------------------------------------------- /examples/hof/design/cli/cmds/st.cue: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "github.com/hofstadter-io/hofmod-cli/schema" 5 | ) 6 | 7 | #StLong: """ 8 | Structural diff, merge, mask, pick, and query helpers for Cue 9 | 10 | Commands generally have the form: [...entrypoints] 11 | 12 | Where can be: 13 | - Cue: expr: as: string 14 | - @filename.cue: Cue: expr: as: string 15 | 16 | If entrypoints are supplied, then an without an @filename.cue will lookup from the entrypoints. 17 | Otherwise, the is interpreted as a complete Cue value. 18 | """ 19 | 20 | #StCommand: schema.#Command & { 21 | TBD: "α" 22 | Name: "st" 23 | Usage: "st" 24 | Aliases: ["structural"] 25 | Short: "recursive diff, merge, mask, pick, and query helpers for Cue" 26 | Long: #StLong 27 | 28 | OmitRun: true 29 | 30 | Commands: [{ 31 | TBD: "α" 32 | Name: "diff" 33 | Usage: "diff [...entrypoints]" 34 | Short: "calculate the difference between two Cue values" 35 | Long: """ 36 | Calculate the difference between two Cue values 37 | """ 38 | 39 | Args: [{ 40 | Name: "orig" 41 | Type: "string" 42 | Required: true 43 | Help: "original value to calc diff from, see 'hof st --help' for format" 44 | }, { 45 | Name: "next" 46 | Type: "string" 47 | Required: true 48 | Help: "next value to calc diff to, see 'hof st --help' for format" 49 | }, { 50 | Name: "entrypoints" 51 | Type: "[]string" 52 | Rest: true 53 | Help: "Cue entrypoints" 54 | }] 55 | }, { 56 | TBD: "α" 57 | Name: "merge" 58 | Usage: "merge [...entrypoints]" 59 | Short: "merge onto , replacing values and adding new ones" 60 | Long: Short 61 | 62 | Args: [{ 63 | Name: "orig" 64 | Type: "string" 65 | Required: true 66 | Help: "original value to update, see 'hof st --help' for format" 67 | }, { 68 | Name: "update" 69 | Type: "string" 70 | Required: true 71 | Help: "update value to layer on, see 'hof st --help' for format" 72 | }, { 73 | Name: "entrypoints" 74 | Type: "[]string" 75 | Rest: true 76 | Help: "Cue entrypoints" 77 | }] 78 | }, { 79 | TBD: "α" 80 | Name: "pick" 81 | Usage: "pick [...entrypoints]" 82 | Short: "pick Cue value(s) from " 83 | Long: Short 84 | 85 | Args: [{ 86 | Name: "orig" 87 | Type: "string" 88 | Required: true 89 | Help: "original value to pick value(s) from, see 'hof st --help' for format" 90 | }, { 91 | Name: "pick" 92 | Type: "string" 93 | Required: true 94 | Help: "the Cue value shape to extract from orig, see 'hof st --help' for format" 95 | }, { 96 | Name: "entrypoints" 97 | Type: "[]string" 98 | Rest: true 99 | Help: "Cue entrypoints" 100 | }] 101 | }, { 102 | TBD: "α" 103 | Name: "mask" 104 | Usage: "mask [...entrypoints]" 105 | Short: "mask Cue value(s) from , thereby 'filtering' the original" 106 | Long: Short 107 | 108 | Args: [{ 109 | Name: "orig" 110 | Type: "string" 111 | Required: true 112 | Help: "original value to filter with mask, see 'hof st --help' for format" 113 | }, { 114 | Name: "what" 115 | Type: "string" 116 | Required: true 117 | Help: "the mask to filter orig with, see 'hof st --help' for format" 118 | }, { 119 | Name: "entrypoints" 120 | Type: "[]string" 121 | Rest: true 122 | Help: "Cue entrypoints" 123 | }] 124 | }, { 125 | TBD: "α" 126 | Name: "query" 127 | Usage: "query [...entrypoints]" 128 | Short: "query for values matching an expr and/or attributes" 129 | Long: Short 130 | 131 | Args: [{ 132 | Name: "orig" 133 | Type: "string" 134 | Required: true 135 | Help: "Cue value to query values from, see 'hof st --help' for format" 136 | }, { 137 | Name: "expr" 138 | Type: "string" 139 | Required: true 140 | Help: "Cue expression to query with, see 'hof st --help' for format" 141 | }, { 142 | Name: "entrypoints" 143 | Type: "[]string" 144 | Rest: true 145 | Help: "Cue entrypoints" 146 | }] 147 | }] 148 | } 149 | -------------------------------------------------------------------------------- /examples/hof/design/cli/cmds/start.cue: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "github.com/hofstadter-io/hofmod-cli/schema" 5 | ) 6 | 7 | #InitCommand: schema.#Command & { 8 | TBD: "β" 9 | Name: "init" 10 | Usage: "init " 11 | Short: "create an empty workspace or initialize an existing directory to one" 12 | Long: """ 13 | create an empty workspace or initialize an existing directory to one 14 | 15 | module name or path should look like github.com/hofstadter-io/hof 16 | """ 17 | 18 | Args: [{ 19 | Name: "module" 20 | Type: "string" 21 | Required: true 22 | Help: "module url or path (github.com/hofstadter-io/hof" 23 | }, 24 | { 25 | Name: "name" 26 | Type: "string" 27 | Help: "module name, defaults to last part of module" 28 | }] 29 | } 30 | 31 | #CloneCommand: schema.#Command & { 32 | TBD: "β" 33 | Name: "clone" 34 | Usage: "clone" 35 | Short: "clone a workspace or repository into a new directory" 36 | Long: Short 37 | 38 | Args: [{ 39 | Name: "module" 40 | Type: "string" 41 | Required: true 42 | Help: "module url or path (github.com/hofstadter-io/hof" 43 | }, 44 | { 45 | Name: "name" 46 | Type: "string" 47 | Help: "module name, defaults to last part of module" 48 | }] 49 | } 50 | -------------------------------------------------------------------------------- /examples/hof/design/cli/cmds/test.cue: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "github.com/hofstadter-io/hofmod-cli/schema" 5 | ) 6 | 7 | #TestCommand: schema.#Command & { 8 | TBD: "α" 9 | Name: "test" 10 | Usage: "test" 11 | Aliases: ["t"] 12 | Short: "test all sorts of things" 13 | Long: #TestCommandHelp 14 | 15 | Flags: [ 16 | { 17 | Name: "list" 18 | Type: "bool" 19 | Default: "false" 20 | Help: "list matching tests that would run" 21 | Long: "list" 22 | Short: "" 23 | ... 24 | }, 25 | { 26 | Name: "keep" 27 | Type: "bool" 28 | Default: "false" 29 | Help: "keep any generated test files" 30 | Long: "keep" 31 | Short: "" 32 | ... 33 | }, 34 | { 35 | Name: "suite" 36 | Type: "[]string" 37 | Default: "nil" 38 | Help: ": _ @test(suite)'s to run" 39 | Long: "suite" 40 | Short: "s" 41 | ... 42 | }, 43 | { 44 | Name: "tester" 45 | Type: "[]string" 46 | Default: "nil" 47 | Help: ": _ @test()'s to run" 48 | Long: "tester" 49 | Short: "t" 50 | ... 51 | }, 52 | { 53 | Name: "environment" 54 | Type: "[]string" 55 | Default: "nil" 56 | Help: "environment" 57 | Long: "env" 58 | Short: "e" 59 | ... 60 | }, 61 | ] 62 | 63 | } 64 | 65 | #TestCommandHelp: #""" 66 | hof test - \(#TestCommand.Short) 67 | 68 | hof test helps you test all the things by providing 69 | a top-level driver and sitting on top of any tool. 70 | You can group tests into Suites, nest and label them 71 | and later run only the tests you want. Several builtin 72 | Testers are available and patterns for testing your 73 | applications, top to bottom and end to end. 74 | 75 | Suites are a top level grouping attribute. You may go 76 | two levels deep for now, however there are both 77 | globs and labels to match with. 78 | 79 | Here is an example "test.cue" file (testers are omitted): 80 | 81 | ------------------------------------------ 82 | MySuite: _ @test(suite) 83 | MySuite: { 84 | 85 | // These sets will have nested testers, more on that below 86 | 87 | Unit: _ @test(suite,labelA,labelB) 88 | Unit: { ... } 89 | 90 | Regressions: _ @test(suite,labelA,frontend,backend) 91 | Regressions: { ... } 92 | 93 | "integration/frontend": _ @test(suite,frontend) 94 | "integration/frontend": {...} 95 | "integration/backend": _ @test(set,backend) 96 | "integration/backend": {...} 97 | } 98 | 99 | // These could have nested suites themselves 100 | "service-f/fast": _ @test(suite,frontend) 101 | "service-f/fast": {...} 102 | "service-f/slow": _ @test(suite,frontend) 103 | "service-f/slow": {...} 104 | 105 | "service-b/fast": _ @test(suite,backend) 106 | "service-b/fast": {...} 107 | "service-b/slow": _ @test(suite,backend) 108 | "service-b/slow": {...} 109 | ------------------------------------------ 110 | 111 | 112 | Testers are the pieces that run actual tests. They may: 113 | 114 | - delegate by running another program or script 115 | - use many of the builtin, generic testers 116 | - use one of the special purpose systems built into hof 117 | 118 | All tester implementations can be found under the "lib/test" directory. 119 | 120 | Testers: 121 | 122 | script: step based testing that can work with the terminal, http, and data 123 | table: table based testing using cue to express more cases with fewer lines 124 | http: test rest and graphql endpoints, use "hof test import" to get a jump start 125 | exec: exec out to the shell to run bash or anything available in your environment 126 | story: behaviour style tests, in the syntax of Gherkin 127 | bench: benchmark based tests, often built from other testers 128 | 129 | 130 | 131 | """# 132 | -------------------------------------------------------------------------------- /examples/hof/design/cli/cmds/workflow.cue: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "github.com/hofstadter-io/hofmod-cli/schema" 5 | ) 6 | 7 | // dev note, consider dolt, pacadyrm, ipfs, and git actions on data 8 | // (data requires a different, git like backing store) 9 | // git//obj-db/dolt as layer between datasets and data lake 10 | 11 | #StatusCommand: schema.#Command & { 12 | TBD: "α" 13 | Name: "status" 14 | Usage: "status" 15 | Alias: ["s"] 16 | Short: "show workspace information and status" 17 | Long: Short 18 | } 19 | 20 | #LogCommand: schema.#Command & { 21 | TBD: "α" 22 | Name: "log" 23 | Usage: "log" 24 | Short: "show workspace logs and history" 25 | Long: Short 26 | } 27 | 28 | #DiffCommand: schema.#Command & { 29 | TBD: "α" 30 | Name: "diff" 31 | Usage: "diff" 32 | Short: "show the difference between workspace versions" 33 | Long: Short 34 | } 35 | 36 | #BisectCommand: schema.#Command & { 37 | TBD: "α" 38 | Name: "bisect" 39 | Usage: "bisect" 40 | Short: "use binary search to find the commit that introduced a bug" 41 | Long: Short 42 | } 43 | 44 | #IncludeCommand: schema.#Command & { 45 | TBD: "α" 46 | Name: "include" 47 | Usage: "include" 48 | Alias: ["i"] 49 | Short: "include changes into the changeset" 50 | Long: Short 51 | } 52 | 53 | #BranchCommand: schema.#Command & { 54 | TBD: "α" 55 | Name: "branch" 56 | Usage: "branch" 57 | Alias: ["b"] 58 | Short: "list, create, or delete branches" 59 | Long: Short 60 | } 61 | 62 | #CheckoutCommand: schema.#Command & { 63 | TBD: "α" 64 | Name: "checkout" 65 | Usage: "checkout" 66 | Alias: ["co"] 67 | Short: "switch branches or restore working tree files" 68 | Long: Short 69 | } 70 | 71 | #CommitCommand: schema.#Command & { 72 | TBD: "α" 73 | Name: "commit" 74 | Usage: "commit" 75 | Alias: ["c"] 76 | Short: "record changes to the repository" 77 | Long: Short 78 | } 79 | 80 | #MergeCommand: schema.#Command & { 81 | TBD: "α" 82 | Name: "merge" 83 | Usage: "merge" 84 | Short: "join two or more development histories together" 85 | Long: Short 86 | } 87 | 88 | #RebaseCommand: schema.#Command & { 89 | TBD: "α" 90 | Name: "rebase" 91 | Usage: "rebase" 92 | Short: "reapply commits on top of another base tip" 93 | Long: Short 94 | } 95 | 96 | #ResetCommand: schema.#Command & { 97 | TBD: "α" 98 | Name: "reset" 99 | Usage: "reset" 100 | Short: "reset current HEAD to the specified state" 101 | Long: Short 102 | } 103 | 104 | #TagCommand: schema.#Command & { 105 | TBD: "α" 106 | Name: "tag" 107 | Usage: "tag" 108 | Short: "create, list, delete or verify a tag object signed with GPG" 109 | Long: Short 110 | } 111 | 112 | #FetchCommand: schema.#Command & { 113 | TBD: "α" 114 | Name: "fetch" 115 | Usage: "fetch" 116 | Short: "download objects and refs from another repository" 117 | Long: Short 118 | } 119 | 120 | #PullCommand: schema.#Command & { 121 | TBD: "α" 122 | Name: "pull" 123 | Usage: "pull" 124 | Short: "fetch from and integrate with another repository or a local branch" 125 | Long: Short 126 | } 127 | 128 | #PushCommand: schema.#Command & { 129 | TBD: "α" 130 | Name: "push" 131 | Usage: "push" 132 | Short: "update remote refs along with associated objects" 133 | Long: Short 134 | } 135 | 136 | #ProposeCommand: schema.#Command & { 137 | TBD: "α" 138 | Name: "propose" 139 | Usage: "propose" 140 | Short: "propose to incorporate your changeset in a repository" 141 | Long: Short 142 | } 143 | 144 | #PublishCommand: schema.#Command & { 145 | TBD: "α" 146 | Name: "publish" 147 | Usage: "publish" 148 | Short: "publish a tagged version to a repository" 149 | Long: Short 150 | } 151 | 152 | #RemotesCommand: schema.#Command & { 153 | TBD: "α" 154 | Name: "remotes" 155 | Usage: "remotes" 156 | Short: "manage remote repositories" 157 | Long: Short 158 | } 159 | -------------------------------------------------------------------------------- /examples/hof/design/cli/help.cue: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "github.com/hofstadter-io/hof/design/cli/cmds" 5 | ) 6 | 7 | // TBD: "Ø" 8 | // TBD: "α" 9 | // TBD: "β" 10 | // TBD: "✓" 11 | 12 | #RootCustomHelp: """ 13 | hof - a polyglot tool for building software 14 | 15 | Learn more at https://docs.hofstadter.io 16 | 17 | Usage: 18 | hof [flags] [command] [args] 19 | 20 | 21 | Initialize and create new hof workspaces: 22 | \(cmds.#InitCommand.Help) 23 | \(cmds.#CloneCommand.Help) 24 | 25 | Model your designs, generate implementation, run or test anything: 26 | \(cmds.#DatamodelCommand.Help) 27 | \(cmds.#GenCommand.Help) 28 | \(cmds.#RunCommand.Help) 29 | \(cmds.#TestCommand.Help) 30 | 31 | Labels are used _ for _ (see also 'hof topic labels'): 32 | \(cmds.#LabelCommand.Help) 33 | \(cmds.#LabelsetCommand.Help) 34 | 35 | Learn more about hof and the _ you can do: 36 | each command has four flags, use 'list' as their arg 37 | to see available items on a command 38 | --help print help message 39 | --topics addtional help topics 40 | --examples examples for the command 41 | --tutorials tutorials for the command 42 | 43 | Download modules, add instances or content, and manage runtimes: 44 | \(cmds.#ModCommand.Help) 45 | \(cmds.#AddCommand.Help) 46 | \(cmds.#RuntimesCommand.Help) 47 | 48 | Manage resources (see also 'hof topic resources'): 49 | \(cmds.#InfoCommand.Help) 50 | \(cmds.#CreateCommand.Help) 51 | \(cmds.#GetCommand.Help) 52 | \(cmds.#SetCommand.Help) 53 | \(cmds.#EditCommand.Help) 54 | \(cmds.#DeleteCommand.Help) 55 | 56 | Configure, Unify, Execute (see also https://cuelang.org): 57 | \(cmds.#CmdCommand.Help) 58 | \(cmds.#DefCommand.Help) 59 | \(cmds.#EvalCommand.Help) 60 | \(cmds.#ExportCommand.Help) 61 | \(cmds.#FormatCommand.Help) 62 | \(cmds.#ImportCommand.Help) 63 | \(cmds.#TrimCommand.Help) 64 | \(cmds.#VetCommand.Help) 65 | \(cmds.#StCommand.Help) 66 | 67 | Manage logins, config, secrets, and context: 68 | \(cmds.#AuthCommand.Help) 69 | \(cmds.#ConfigCommand.Help) 70 | \(cmds.#SecretCommand.Help) 71 | \(cmds.#ContextCommand.Help) 72 | 73 | Examine workpsace history and state: 74 | \(cmds.#StatusCommand.Help) 75 | \(cmds.#LogCommand.Help) 76 | \(cmds.#DiffCommand.Help) 77 | \(cmds.#BisectCommand.Help) 78 | 79 | Grow, mark, and tweak your shared history (see also 'hof topic changesets'): 80 | \(cmds.#IncludeCommand.Help) 81 | \(cmds.#BranchCommand.Help) 82 | \(cmds.#CheckoutCommand.Help) 83 | \(cmds.#CommitCommand.Help) 84 | \(cmds.#MergeCommand.Help) 85 | \(cmds.#RebaseCommand.Help) 86 | \(cmds.#ResetCommand.Help) 87 | \(cmds.#TagCommand.Help) 88 | 89 | Collaborate (see also 'hof topic collaborate'): 90 | \(cmds.#FetchCommand.Help) 91 | \(cmds.#PullCommand.Help) 92 | \(cmds.#PushCommand.Help) 93 | \(cmds.#ProposeCommand.Help) 94 | \(cmds.#PublishCommand.Help) 95 | \(cmds.#RemotesCommand.Help) 96 | 97 | Local development commands: 98 | \(cmds.#ReproCommand.Help) 99 | \(cmds.#JumpCommand.Help) 100 | \(cmds.#UiCommand.Help) 101 | \(cmds.#TuiCommand.Help) 102 | \(cmds.#ReplCommand.Help) 103 | pprof go pprof by setting HOF_CPU_PROFILE="hof-cpu.prof" hof 104 | 105 | 106 | Send us feedback or say hello: 107 | \(cmds.#FeedbackCommand.Help) 108 | you can also chat with us on https://gitter.im/hofstadter-io 109 | 110 | Additional commands: 111 | help help about any command 112 | update check for new versions and run self-updates 113 | version print detailed version information 114 | completion generate completion helpers for your terminal 115 | 116 | (✓) command is generally available 117 | (β) command is beta and ready for testing 118 | (α) command is alpha and under developmenr 119 | (Ø) command is null and yet to be implemented 120 | 121 | Flags: 122 | <> 123 | Use "hof [command] --help / -h" for more information about a command. 124 | Use "hof topic [subject]" for more information about a subject. 125 | 126 | """ 127 | -------------------------------------------------------------------------------- /examples/hof/design/cli/main.cue: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "github.com/hofstadter-io/hofmod-cli/schema" 5 | 6 | "github.com/hofstadter-io/hof/design/cli/cmds" 7 | ) 8 | 9 | #Outdir: "./cmd/hof" 10 | 11 | #CLI: schema.#Cli & { 12 | Name: "hof" 13 | Package: "github.com/hofstadter-io/hof/cmd/hof" 14 | 15 | Usage: "hof" 16 | Short: "Polyglot Code Gereration Framework" 17 | Long: Short 18 | CustomHelp: #RootCustomHelp 19 | Topics: #RootTopics 20 | Examples: #RootExamples 21 | 22 | OmitRun: true 23 | 24 | Imports: [ 25 | {Path: "github.com/hofstadter-io/hof/lib/config"}, 26 | ] 27 | 28 | PersistentPrerun: true 29 | PersistentPrerunBody: "config.Init()" 30 | 31 | PersistentPostrun: true 32 | 33 | Pflags: #CliPflags 34 | 35 | //Commands: [...schema.#Command] 36 | Commands: [ 37 | 38 | // start 39 | cmds.#InitCommand, 40 | cmds.#CloneCommand, 41 | 42 | // hof 43 | cmds.#DatamodelCommand, 44 | cmds.#GenCommand, 45 | cmds.#RunCommand, // imperatively oriented commands from cue 46 | cmds.#RuntimesCommand, // (docker, node, go, cue, python) 47 | cmds.#TestCommand, 48 | 49 | // labels 50 | cmds.#LabelCommand, 51 | cmds.#LabelsetCommand, 52 | 53 | // hof + cue 54 | cmds.#ModCommand, 55 | cmds.#AddCommand, 56 | cmds.#CmdCommand, // Cue's cmd, but processed by hof 57 | 58 | // resources 59 | cmds.#InfoCommand, 60 | cmds.#CreateCommand, 61 | cmds.#GetCommand, 62 | cmds.#SetCommand, 63 | cmds.#EditCommand, 64 | cmds.#DeleteCommand, 65 | 66 | // cue 67 | cmds.#DefCommand, 68 | cmds.#EvalCommand, 69 | cmds.#ExportCommand, 70 | cmds.#FormatCommand, 71 | cmds.#ImportCommand, 72 | cmds.#TrimCommand, 73 | cmds.#VetCommand, 74 | cmds.#StCommand, 75 | 76 | // base 77 | cmds.#AuthCommand, 78 | cmds.#ConfigCommand, 79 | cmds.#SecretCommand, 80 | cmds.#ContextCommand, 81 | 82 | // workspace / workflow / git commands 83 | cmds.#StatusCommand, 84 | cmds.#LogCommand, 85 | cmds.#DiffCommand, 86 | cmds.#BisectCommand, 87 | 88 | // changeset related 89 | cmds.#IncludeCommand, 90 | cmds.#BranchCommand, 91 | cmds.#CheckoutCommand, 92 | cmds.#CommitCommand, 93 | cmds.#MergeCommand, 94 | cmds.#RebaseCommand, 95 | cmds.#ResetCommand, 96 | cmds.#TagCommand, 97 | 98 | // collab 99 | cmds.#FetchCommand, 100 | cmds.#PullCommand, 101 | cmds.#PushCommand, 102 | cmds.#ProposeCommand, 103 | cmds.#PublishCommand, 104 | cmds.#RemotesCommand, 105 | 106 | // dev & more st commands 107 | cmds.#ReproCommand, 108 | cmds.#JumpCommand, 109 | cmds.#UiCommand, 110 | cmds.#TuiCommand, 111 | cmds.#ReplCommand, 112 | // lint 113 | // fmt 114 | // fix 115 | // simplify 116 | // test 117 | // bench 118 | // scan 119 | // note / knowledge graph 120 | // todo / scrum 121 | // TOOLS (same as runtime?) 122 | // what is docker based 123 | 124 | // TODO: SECURITY 125 | // - report 126 | // - scan 127 | // - fix 128 | 129 | // additional help topics 130 | cmds.#FeedbackCommand, 131 | // bugreport 132 | // crashreport 133 | // changelog --version 134 | 135 | // hacks down this way 136 | { 137 | Hidden: true 138 | Name: "hack" 139 | Usage: "hack ..." 140 | Aliases: ["h", "x"] 141 | Short: "development command" 142 | Long: Short 143 | }, 144 | cmds.#GebCommand, 145 | cmds.#LogoCommand, 146 | ] 147 | 148 | // 149 | // Addons 150 | // 151 | Releases: #CliReleases 152 | Updates: true 153 | 154 | Telemetry: "UA-103579574-5" 155 | TelemetryIdDir: "hof" 156 | 157 | EnablePProf: true 158 | } 159 | 160 | #RootTopics: { 161 | "test-topic": ##""" 162 | hello, this is a test topic. 163 | please check out the others! 164 | 165 | """## 166 | 167 | "main-topics": ##""" 168 | There are several main topics: 169 | 170 | hof gen --topic list 171 | hof mod --topic list 172 | hof test --topic list 173 | hof run --topic list 174 | hof --topic script 175 | 176 | """## 177 | } 178 | 179 | #RootExamples: { 180 | "test-example": ##""" 181 | Thit is a test example, check out the subcommands, repo, and website for more! 182 | 183 | """## 184 | } 185 | -------------------------------------------------------------------------------- /examples/hof/design/cli/pflags.cue: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "github.com/hofstadter-io/hofmod-cli/schema" 5 | ) 6 | 7 | // TODO add: --non-intreactive (-y) ; --no-color 8 | 9 | #CliPflags: [...schema.#Flag] & [ 10 | // Labels will be core 11 | { 12 | Name: "labels" 13 | Long: "label" 14 | Short: "l" 15 | Type: "[]string" 16 | Default: "nil" 17 | Help: "Labels for use across all commands" 18 | }, 19 | { 20 | Name: "config" 21 | Long: "config" 22 | Short: "" 23 | Type: "string" 24 | Default: "" 25 | Help: "Path to a hof configuration file" 26 | }, 27 | { 28 | Name: "secret" 29 | Long: "secret" 30 | Short: "" 31 | Type: "string" 32 | Default: "" 33 | Help: "The path to a hof secret file" 34 | }, 35 | { 36 | Name: "contextFile" 37 | Long: "context-file" 38 | Short: "" 39 | Type: "string" 40 | Default: "" 41 | Help: "The path to a hof context file" 42 | }, 43 | { 44 | Name: "context" 45 | Long: "context" 46 | Short: "" 47 | Type: "string" 48 | Default: "" 49 | Help: "The of an entry in the context file" 50 | }, 51 | { 52 | Name: "global" 53 | Long: "global" 54 | Short: "" 55 | Type: "bool" 56 | Default: "false" 57 | Help: "Operate using only the global config/secret context" 58 | }, 59 | { 60 | Name: "local" 61 | Long: "local" 62 | Short: "" 63 | Type: "bool" 64 | Default: "false" 65 | Help: "Operate using only the local config/secret context" 66 | }, 67 | 68 | // i/o formats and streams 69 | { 70 | Name: "input" 71 | Long: "input" 72 | Short: "i" 73 | Type: "[]string" 74 | Default: "nil" 75 | Help: "input streams, depending on the command context" 76 | }, 77 | { 78 | Name: "inputFormat" 79 | Long: "input-format" 80 | Short: "I" 81 | Type: "string" 82 | Default: "" 83 | Help: "input format, defaults to infered" 84 | }, 85 | 86 | { 87 | Name: "output" 88 | Long: "output" 89 | Short: "o" 90 | Type: "[]string" 91 | Default: "nil" 92 | Help: "output streams, depending on the command context" 93 | }, 94 | { 95 | Name: "outputFormat" 96 | Long: "output-format" 97 | Short: "O" 98 | Type: "string" 99 | Default: "" 100 | Help: "output format, defaults to cue" 101 | }, 102 | 103 | { 104 | Name: "error" 105 | Long: "error" 106 | Short: "" 107 | Type: "[]string" 108 | Default: "nil" 109 | Help: "error streams, depending on the command context" 110 | }, 111 | { 112 | Name: "errorFormat" 113 | Long: "error-format" 114 | Short: "" 115 | Type: "string" 116 | Default: "" 117 | Help: "error format, defaults to cue" 118 | }, 119 | 120 | // context should encapsulate the next three 121 | { 122 | Name: "account" 123 | Long: "account" 124 | Short: "" 125 | Type: "string" 126 | Default: "" 127 | Help: "the account context to use during this hof execution" 128 | }, 129 | { 130 | Name: "billing" 131 | Long: "billing" 132 | Short: "" 133 | Type: "string" 134 | Default: "" 135 | Help: "the billing context to use during this hof execution" 136 | }, 137 | { 138 | Name: "project" 139 | Long: "project" 140 | Short: "" 141 | Type: "string" 142 | Default: "" 143 | Help: "the project context to use during this hof execution" 144 | }, 145 | { 146 | Name: "workspace" 147 | Long: "workspace" 148 | Short: "" 149 | Type: "string" 150 | Default: "" 151 | Help: "the workspace context to use during this hof execution" 152 | }, 153 | { 154 | Name: "datamodelDir" 155 | Long: "datamodel-dir" 156 | Short: "" 157 | Type: "string" 158 | Default: "" 159 | Help: "directory for discovering resources" 160 | }, 161 | { 162 | Name: "resourcesDir" 163 | Long: "resources-dir" 164 | Short: "" 165 | Type: "string" 166 | Default: "" 167 | Help: "directory for discovering resources" 168 | }, 169 | { 170 | Name: "runtimesDir" 171 | Long: "runtimes-dir" 172 | Short: "" 173 | Type: "string" 174 | Default: "" 175 | Help: "directory for discovering runtimes" 176 | }, 177 | 178 | // these are more cue specific with a dash of hof 179 | { 180 | Name: "package" 181 | Long: "package" 182 | Short: "p" 183 | Type: "string" 184 | Default: "" 185 | Help: "the package context to use during this hof execution" 186 | }, 187 | { 188 | Name: "errors" 189 | Long: "all-errors" 190 | Short: "E" 191 | Type: "bool" 192 | Default: "false" 193 | Help: "print all available errors" 194 | }, 195 | { 196 | Name: "ignore" 197 | Long: "ignore" 198 | Short: "" 199 | Type: "bool" 200 | Default: "false" 201 | Help: "proceed in the presence of errors" 202 | }, 203 | { 204 | Name: "simplify" 205 | Long: "simplify" 206 | Short: "S" 207 | Type: "bool" 208 | Default: "false" 209 | Help: "simplify output" 210 | }, 211 | { 212 | Name: "trace" 213 | Long: "trace" 214 | Short: "" 215 | Type: "bool" 216 | Default: "false" 217 | Help: "trace cue computation" 218 | }, 219 | { 220 | Name: "strict" 221 | Long: "strict" 222 | Short: "" 223 | Type: "bool" 224 | Default: "false" 225 | Help: "report errors for lossy mappings" 226 | }, 227 | { 228 | Name: "verbose" 229 | Long: "verbose" 230 | Short: "v" 231 | Type: "string" 232 | Default: "" 233 | Help: "set the verbosity of output" 234 | }, 235 | { 236 | Name: "quiet" 237 | Long: "quiet" 238 | Short: "q" 239 | Type: "bool" 240 | Default: "" 241 | Help: "turn off output and assume defaults at prompts" 242 | }, 243 | { 244 | Name: "ImpersonateAccount" 245 | Long: "impersonate-account" 246 | Short: "" 247 | Type: "string" 248 | Default: "" 249 | Help: "account to impersonate for this hof execution" 250 | }, 251 | { 252 | Name: "traceToken" 253 | Long: "trace-token" 254 | Short: "T" 255 | Type: "string" 256 | Default: "" 257 | Help: "used to help debug issues" 258 | }, 259 | { 260 | Name: "LogHTTP" 261 | Long: "log-http" 262 | Short: "" 263 | Type: "string" 264 | Default: "" 265 | Help: "used to help debug issues" 266 | }, 267 | { 268 | Name: "RunWeb" 269 | Long: "web" 270 | Short: "" 271 | Type: "bool" 272 | Default: "false" 273 | Help: "run the command from the web ui" 274 | }, 275 | { 276 | Name: "RunTUI" 277 | Long: "tui" 278 | Short: "" 279 | Type: "bool" 280 | Default: "false" 281 | Help: "run the command from the terminal ui" 282 | }, 283 | { 284 | Name: "RunREPL" 285 | Long: "repl" 286 | Short: "" 287 | Type: "bool" 288 | Default: "false" 289 | Help: "run the command from the hof repl" 290 | }, 291 | { 292 | Name: "Topic" 293 | Long: "topic" 294 | Short: "" 295 | Type: "string" 296 | Default: "" 297 | Help: "help topics for this command, 'list' will print available topics" 298 | }, 299 | { 300 | Name: "Example" 301 | Long: "example" 302 | Short: "" 303 | Type: "string" 304 | Default: "" 305 | Help: "examples for this command, 'list' will print available examples" 306 | }, 307 | { 308 | Name: "Tutorial" 309 | Long: "tutorial" 310 | Short: "" 311 | Type: "string" 312 | Default: "" 313 | Help: "tutorials for this command, 'list' will print available tutorials" 314 | }, 315 | ] 316 | -------------------------------------------------------------------------------- /examples/hof/design/cli/releases.cue: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "github.com/hofstadter-io/hofmod-cli/schema" 5 | ) 6 | 7 | #CliReleases: schema.#GoReleaser & { 8 | Disabled: false 9 | Draft: false 10 | Author: "Hofstadter, Inc" 11 | Homepage: "https://hofstadter.io" 12 | 13 | GitHub: { 14 | Owner: "hofstadter-io" 15 | Repo: "hof" 16 | } 17 | 18 | Docker: { 19 | Maintainer: "Hofstadter, Inc " 20 | Repo: "hofstadter" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /examples/hof/design/config/main.cue: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | hof "github.com/hofstadter-io/hof/schema" 5 | 6 | "github.com/hofstadter-io/hofmod-cuefig/schema" 7 | ) 8 | 9 | // Local context 10 | #HofContext: schema.#Config & { 11 | Name: "context" 12 | Entrypoint: ".hofctx.cue" 13 | ConfigSchema: #ContextSchema 14 | } 15 | 16 | // Local config 17 | #HofConfig: schema.#Config & { 18 | Name: "config" 19 | Entrypoint: ".hofcfg.cue" 20 | ConfigSchema: #WorkspaceSchema 21 | } 22 | 23 | // Local secret 24 | #HofSecret: schema.#Config & { 25 | Sensative: true 26 | Name: "secret" 27 | Entrypoint: ".hofshh.cue" 28 | ConfigSchema: #SecretSchema 29 | } 30 | 31 | // (user/app config dir) context 32 | #HofUserContext: schema.#Config & { 33 | Name: "hofctx" 34 | Entrypoint: ".hofctx.cue" 35 | Workpath: "hof" 36 | Location: "user" 37 | ConfigSchema: #ContextSchema 38 | } 39 | 40 | // (user/app config dir) config 41 | #HofUserConfig: schema.#Config & { 42 | Name: "hofcfg" 43 | Entrypoint: ".hofcfg.cue" 44 | Workpath: "hof" 45 | Location: "user" 46 | ConfigSchema: #ConfigSchema 47 | } 48 | 49 | // (user/app config dir) secret 50 | #HofUserSecret: schema.#Config & { 51 | Sensative: true 52 | Name: "hofshh" 53 | Entrypoint: ".hofshh.cue" 54 | Workpath: "hof" 55 | Location: "user" 56 | ConfigSchema: #SecretSchema 57 | } 58 | 59 | #ContextSchema: { 60 | Current?: #ContextItemSchema 61 | Contexts?: [ContextName=string]: #ContextItemSchema & {name: ContextName} 62 | } 63 | 64 | #ContextItemSchema: { 65 | Name: string 66 | Credentials?: string 67 | Environment?: string 68 | Account?: string 69 | Billing?: string 70 | Project?: string 71 | Package?: string 72 | ... 73 | } 74 | 75 | // Secrets at both local / global level 76 | #SecretSchema: { 77 | [Group=string]: { 78 | [Cred=string]: { 79 | [Key=string]: string 80 | } 81 | } 82 | } 83 | 84 | // Hof tool configuration 85 | #ConfigSchema: { 86 | // This should only be used from the global context, local ought to be determined from walking up to find a .hofcfg.cue file 87 | // Unless... we want to subdivide workspaces, monorepo style (probably do want ot do this) 88 | // We can also associate developer setups with this 89 | // ... rethinking having multiple workspaces per repo, doesn't fit with the latest UX (in particular workspace/workflow integration) 90 | Workspaces?: [WorkspaceName=string]: #WorkspaceSchema & {name: WorkspaceName} 91 | 92 | ... 93 | } 94 | 95 | // Workspace specfic config 96 | #WorkspaceSchema: { 97 | Name: string | *"" 98 | Dir: string | *"" 99 | 100 | ModelsDir: string | *"models" 101 | ResourcesDir: string | *"resources" 102 | } 103 | -------------------------------------------------------------------------------- /examples/hofmod-cli/.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # Dependency directories (remove the comment below to include it) 15 | # vendor/ 16 | /cue.mod/pkg/ 17 | -------------------------------------------------------------------------------- /examples/hofmod-cli/LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2020, Hofstadter, Inc 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /examples/hofmod-cli/README.md: -------------------------------------------------------------------------------- 1 | # hofmod-cli 2 | 3 | A [hof](https://github.com/hofstadter-io/hof) generator for creating advanced Golang CLIs. 4 | 5 | Design your CLI structure, arguments, flags, and a whole host of addons 6 | and then generate the implementation. Changed your mind about what your 7 | CLI should look like? Redesign, regenerate, and keep adding you custom code. 8 | 9 | ### Features: 10 | 11 | - Quickly architect your CLI commands, arguments, flags, configuration 12 | - Built on the fantastic [spf13/cobra](https://github.com/ andspf13/cobra)library for Golang CLIs 13 | - Cross-platform builds and releases using GoReleaser, GitHub, and Docker 14 | - Supports config files in local project falling back to OS specific application dir 15 | - Your CLI will self check for updates and can self install with a user command 16 | - Shell auto completion for bash, fish, zsh, and power shell 17 | - Advanced help system with support for custom overviews, extra topics, and examples 18 | - Telemetry systems which can hook up to Google Analytics 19 | - Golang pprof and many other ENV VARs to control inner behavior 20 | 21 | ### Sites to see: 22 | 23 | - [Schema](./schema) - the design spec your write a CLI in 24 | - [Generator](./gen) - [hof](https://github.com/hofstadter-io/hof) generator definition you invoke 25 | - [Templates](./templates) and [partials](./partials) - files which implement the code 26 | - [Example](https://github.com/hofstadter-io/hof) - the [hof](https://github.com/hofstadter-io/hof) tool leverages and powers this, see the `hof.cue` and `design` directory for relevant files 27 | 28 | ### Usage 29 | 30 | You'll need the [hof](https://github.com/hofstadter-io/hof) tool installed. 31 | You can download `hof` from [the releases page](https://github.com/hofstadter-io/hof/releases). 32 | 33 | Let's start a new project: 34 | 35 | ``` 36 | # Start a project 37 | hof init github.com/verdverm/my-cli 38 | cd my-cli 39 | ``` 40 | 41 | Add the following to the `cue.mods` file (same format as `go.mod`) 42 | 43 | ``` 44 | module github.com/verdverm/my-cli 45 | 46 | cue v0.2.0 47 | 48 | require ( 49 | github.com/hofstadter-io/hofmod-cli v0.5.8 50 | ) 51 | ``` 52 | 53 | To fetch the module, run: 54 | 55 | ``` 56 | hof mod vendor cue 57 | 58 | # and after the next file, run 59 | hof gen 60 | ``` 61 | 62 | Create a file named `cli.cue` and add the following content: 63 | 64 | ``` 65 | package cli 66 | 67 | import ( 68 | "github.com/hofstadter-io/hofmod-cli/schema" 69 | 70 | "github.com/hofstadter-io/hof/design/cli/cmds" 71 | ) 72 | 73 | # Typically we put the cli under a nested directory 74 | #Outdir: "./cmd/hof" 75 | 76 | #CLI: schema.#Cli & { 77 | # Name and package path (matches outdir) 78 | Name: "hof" 79 | Package: "github.com/hofstadter-io/hof/cmd/hof" 80 | 81 | # Usage and help 82 | Usage: "hof" 83 | Short: "Polyglot Development Tool and Framework" 84 | Long: Short 85 | CustomHelp: #RootCustomHelp 86 | 87 | # Print the help when no subcommands are supplied 88 | OmitRun: true 89 | 90 | # Command stage hooks 91 | PersistentPrerun: true 92 | # You can write code here or... 93 | PersistentPrerunBody: "runtime.Init()" 94 | 95 | PersistentPostrun: true 96 | # ...or add custom code right in the output 97 | 98 | # Persistent flags work for all subcommands too 99 | Pflags: [{ 100 | Name: "labels" 101 | Long: "label" 102 | Short: "l" 103 | Type: "[]string" 104 | Default: "nil" 105 | Help: "Labels for use across all commands" 106 | }, { 107 | Name: "config" 108 | Long: "config" 109 | Short: "" 110 | Type: "string" 111 | Default: "" 112 | Help: "Path to a hof configuration file" 113 | }, ...] 114 | 115 | # Subcommands and nested down as far as you need 116 | Commands: [ 117 | 118 | ] 119 | 120 | // 121 | // Addons 122 | // 123 | Releases: #CliReleases 124 | Updates: true 125 | 126 | ... 127 | } 128 | ``` 129 | 130 | (this was adapted from the [hof](https://github.com/hofstadter-io/hof t) tool) 131 | 132 | Now run `hof gen` to generate your code. 133 | Try adding implementation, and then build: 134 | 135 | ``` 136 | go build -o my-cli cmd/my-cli/main.go 137 | 138 | ./my-cli 139 | ``` 140 | 141 | Update your designs, rerun `hof gen`, rebuild 142 | and keep iterating away! 143 | 144 | -------------------------------------------------------------------------------- /examples/hofmod-cli/cue.mod/module.cue: -------------------------------------------------------------------------------- 1 | module: "github.com/hofstadter-io/hofmod-cli" 2 | -------------------------------------------------------------------------------- /examples/hofmod-cli/cue.mods: -------------------------------------------------------------------------------- 1 | module github.com/hofstadter-io/hofmod-cli 2 | 3 | cue master 4 | 5 | require ( 6 | github.com/hofstadter-io/hof v0.3.8 7 | ) 8 | -------------------------------------------------------------------------------- /examples/hofmod-cli/cue.sums: -------------------------------------------------------------------------------- 1 | github.com/hofstadter-io/hof v0.0.0 h1:azcPmXo6xFLdhBrPImIKMRsGsy42N8I/CCCh5PvUdNw= 2 | github.com/hofstadter-io/hof v0.0.0/cue.mods h1:0oZRhMRdCe9UmE5ZbAfhUB3TG02AAw115goi2Wj5/Tc= 3 | -------------------------------------------------------------------------------- /examples/hofmod-cli/partials/args-parse.go: -------------------------------------------------------------------------------- 1 | {{ define "args-parse" }} 2 | {{ $ARGS := . }} 3 | // Argument Parsing 4 | {{ range $i, $A := $ARGS }} 5 | {{ if $A.Required }} 6 | if {{ $i }} >= len(args) { 7 | fmt.Println("missing required argument: '{{$A.argName}}'") 8 | cmd.Usage() 9 | os.Exit(1) 10 | } 11 | {{ end }} 12 | var {{ $A.argName }} {{$A.Type}} 13 | {{ if $A.Default }}{{ $A.argName }} = {{ $A.Default }}{{end}} 14 | 15 | if {{ $i }} < len(args) { 16 | {{ if $A.Rest }} 17 | {{ $A.argName }} = args[{{ $i }}:] 18 | 19 | {{ else if eq $A.Type "string" }} 20 | {{ $A.argName }} = args[{{ $i }}] 21 | 22 | {{ else if eq $A.Type "int" }} 23 | {{ $A.argName}}Str := args[{{ $i }}] 24 | var {{ $A.argName }}Err error 25 | {{ $A.argName }}Type, {{ $A.argName }}Err := strconv.ParseInt({{ $A.argName }}Str, 10, 64) 26 | if {{ $A.argName }}Err != nil { 27 | fmt.Printf("argument of wrong type. expected: '{{ $A.Type}}' got error: %v", {{ $A.argName }}Err ) 28 | cmd.Usage() 29 | os.Exit(1) 30 | } 31 | {{ $A.argName }} = int({{ $A.argName }}Type) 32 | 33 | {{ end }} 34 | } 35 | {{ end }} 36 | {{ end }} 37 | -------------------------------------------------------------------------------- /examples/hofmod-cli/partials/flag-init.go: -------------------------------------------------------------------------------- 1 | {{ define "flag-init" }} 2 | {{ if $.Flags}} 3 | 4 | {{ $Prefix := "Root" }} 5 | {{ if $.Parent.Parent.Parent.Parent }} 6 | {{ $Prefix = (print $.CMD.Parent.Parent.Parent.Parent.Name "__" $.CMD.Parent.Parent.Parent.Name "__" $.CMD.Parent.Parent.Name "__" $.CMD.Parent.Name "__" $.CMD.CmdName) }} 7 | {{ else if $.Parent.Parent.Parent }} 8 | {{ $Prefix = (print $.CMD.Parent.Parent.Parent.Name "__" $.CMD.Parent.Parent.Name "__" $.CMD.Parent.Name "__" $.CMD.CmdName) }} 9 | {{ else if $.Parent.Parent }} 10 | {{ $Prefix = (print $.CMD.Parent.Parent.Name "__" $.CMD.Parent.Name "__" $.CMD.CmdName) }} 11 | {{ else if $.Parent }} 12 | {{ $Prefix = (print $.CMD.Parent.Name "__" $.CMD.CmdName) }} 13 | {{ else if $.CmdName }} 14 | {{ $Prefix = $.CmdName }} 15 | {{ end }} 16 | 17 | func init () { 18 | {{ range $i, $F := $.Flags }} 19 | {{ $Prefix }}Cmd.Flags().{{- template "cobra-type" $F.Type -}}VarP(&(flags.{{ $Prefix }}Flags.{{ $F.FlagName }}), "{{ $F.Long }}", "{{ $F.Short }}", {{ if $F.Default}}{{$F.Default}}{{else}}{{template "go-default" $F.Type }}{{end}}, "{{ $F.Help }}") 20 | {{- end }} 21 | } 22 | {{ end }} 23 | {{ end }} 24 | -------------------------------------------------------------------------------- /examples/hofmod-cli/partials/flag-var.go: -------------------------------------------------------------------------------- 1 | {{ define "flag-vars" }} 2 | {{ if $.Flags}} 3 | 4 | {{ $Prefix := "Root" }} 5 | {{ if $.Parent.Parent.Parent.Parent }} 6 | {{ $Prefix = (print $.CMD.Parent.Parent.Parent.Parent.Name "__" $.CMD.Parent.Parent.Parent.Name "__" $.CMD.Parent.Parent.Name "__" $.CMD.Parent.Name "__" $.CMD.CmdName) }} 7 | {{ else if $.Parent.Parent.Parent }} 8 | {{ $Prefix = (print $.CMD.Parent.Parent.Parent.Name "__" $.CMD.Parent.Parent.Name "__" $.CMD.Parent.Name "__" $.CMD.CmdName) }} 9 | {{ else if $.Parent.Parent }} 10 | {{ $Prefix = (print $.CMD.Parent.Parent.Name "__" $.CMD.Parent.Name "__" $.CMD.CmdName) }} 11 | {{ else if $.Parent }} 12 | {{ $Prefix = (print $.CMD.Parent.Name "__" $.CMD.CmdName) }} 13 | {{ else if $.CmdName }} 14 | {{ $Prefix = $.CmdName }} 15 | {{ end }} 16 | 17 | type {{ $Prefix }}Flagpole struct { 18 | {{ range $i, $F := $.Flags }} 19 | {{ $F.FlagName }} {{ $F.Type }} 20 | {{- end }} 21 | } 22 | 23 | var {{ $Prefix }}Flags {{ $Prefix }}Flagpole 24 | 25 | {{ end }} 26 | {{ end }} 27 | -------------------------------------------------------------------------------- /examples/hofmod-cli/partials/go-helpers.go: -------------------------------------------------------------------------------- 1 | {{- define "cobra-type" -}} 2 | {{- if eq . "string"}}String 3 | {{- else if eq . "[]string" }}StringSlice 4 | {{- else if eq . "int" }}Int 5 | {{- else if eq . "[]int" }}IntSlice 6 | {{- else if eq . "float64" }}Float64 7 | {{- else if eq . "[]float64" }}Float64Slice 8 | {{- else if eq . "bool" }}Bool 9 | {{- else }} 10 | {{- end -}} 11 | {{- end -}} 12 | 13 | {{- define "go-default" -}} 14 | {{- if eq . "string"}}"" 15 | {{- else if eq . "[]string" }}[]string{} 16 | {{- else if eq . "int" }}0 17 | {{- else if eq . "[]int" }}[]int{} 18 | {{- else if eq . "float64" }}0.0 19 | {{- else if eq . "[]float64" }}[]float64P{} 20 | {{- else if eq . "bool" }}false 21 | {{- else }} 22 | {{- end -}} 23 | {{- end -}} 24 | -------------------------------------------------------------------------------- /examples/hofmod-cli/partials/lib-args.go: -------------------------------------------------------------------------------- 1 | {{ if .CMD.Args -}} 2 | {{ range $i, $A := .CMD.Args -}} 3 | {{ if gt $i 0 }}, {{end }}{{ $A.argName }} {{ $A.Type -}} 4 | {{ end -}} 5 | {{ else -}} 6 | args []string{{ end -}} 7 | -------------------------------------------------------------------------------- /examples/hofmod-cli/partials/lib-call.go: -------------------------------------------------------------------------------- 1 | {{ if .CMD.Args -}} 2 | {{ range $i, $A := .CMD.Args -}} 3 | {{ if gt $i 0 }}, {{end }}{{ $A.argName -}} 4 | {{ end -}} 5 | {{ else -}} 6 | args{{ end -}} 7 | -------------------------------------------------------------------------------- /examples/hofmod-cli/partials/pflag-init.go: -------------------------------------------------------------------------------- 1 | {{ define "pflag-init" }} 2 | {{ if $.Pflags}} 3 | 4 | {{ $Prefix := "Root" }} 5 | {{ if $.Parent.Parent.Parent.Parent }} 6 | {{ $Prefix = (print $.CMD.Parent.Parent.Parent.Parent.Name "__" $.CMD.Parent.Parent.Parent.Name "__" $.CMD.Parent.Parent.Name "__" $.CMD.Parent.Name "__" $.CMD.CmdName) }} 7 | {{ else if $.Parent.Parent.Parent }} 8 | {{ $Prefix = (print $.CMD.Parent.Parent.Parent.Name "__" $.CMD.Parent.Parent.Name "__" $.CMD.Parent.Name "__" $.CMD.CmdName) }} 9 | {{ else if $.Parent.Parent }} 10 | {{ $Prefix = (print $.CMD.Parent.Parent.Name "__" $.CMD.Parent.Name "__" $.CMD.CmdName) }} 11 | {{ else if $.Parent }} 12 | {{ $Prefix = (print $.CMD.Parent.Name "__" $.CMD.CmdName) }} 13 | {{ else if $.CmdName }} 14 | {{ $Prefix = $.CmdName }} 15 | {{ end }} 16 | 17 | func init () { 18 | {{ range $i, $F := $.Pflags }} 19 | {{ $Prefix }}Cmd.PersistentFlags().{{- template "cobra-type" $F.Type -}}VarP(&(flags.{{ $Prefix }}Pflags.{{ $F.FlagName }}), "{{ $F.Long }}", "{{ $F.Short }}", {{ if $F.Default}}{{$F.Default}}{{else}}{{template "go-default" $F.Type }}{{end}}, "{{ $F.Help }}") 20 | {{- end }} 21 | } 22 | {{ end }} 23 | {{ end }} 24 | -------------------------------------------------------------------------------- /examples/hofmod-cli/partials/pflag-var.go: -------------------------------------------------------------------------------- 1 | {{ define "pflag-vars" }} 2 | {{ if $.Pflags}} 3 | 4 | {{ $Prefix := "Root" }} 5 | {{ if $.Parent.Parent.Parent.Parent }} 6 | {{ $Prefix = (print $.CMD.Parent.Parent.Parent.Parent.Name "__" $.CMD.Parent.Parent.Parent.Name "__" $.CMD.Parent.Parent.Name "__" $.CMD.Parent.Name "__" $.CMD.CmdName) }} 7 | {{ else if $.Parent.Parent.Parent }} 8 | {{ $Prefix = (print $.CMD.Parent.Parent.Parent.Name "__" $.CMD.Parent.Parent.Name "__" $.CMD.Parent.Name "__" $.CMD.CmdName) }} 9 | {{ else if $.Parent.Parent }} 10 | {{ $Prefix = (print $.CMD.Parent.Parent.Name "__" $.CMD.Parent.Name "__" $.CMD.CmdName) }} 11 | {{ else if $.Parent }} 12 | {{ $Prefix = (print $.CMD.Parent.Name "__" $.CMD.CmdName) }} 13 | {{ else if $.CmdName }} 14 | {{ $Prefix = $.CmdName }} 15 | {{ end }} 16 | 17 | type {{ $Prefix }}Pflagpole struct { 18 | {{ range $i, $F := $.Pflags }} 19 | {{ $F.FlagName }} {{ $F.Type }} 20 | {{- end }} 21 | } 22 | 23 | var {{ $Prefix }}Pflags {{ $Prefix }}Pflagpole 24 | {{ end }} 25 | {{ end }} 26 | -------------------------------------------------------------------------------- /examples/hofmod-cli/partials/test-cli-args.txt: -------------------------------------------------------------------------------- 1 | {{- if .CMD.Commands -}} 2 | {{- if .CMD.Parent.Parent.Parent.Parent -}} 3 | {{- .CMD.Parent.Parent.Parent.Parent.Name }} {{ .CMD.Parent.Parent.Parent.Name }} {{ .CMD.Parent.Parent.Name }} {{ .CMD.Parent.Name }} {{ .CMD.cmdName -}} 4 | {{- else if .CMD.Parent.Parent.Parent -}} 5 | {{- .CMD.Parent.Parent.Parent.Name }} {{ .CMD.Parent.Parent.Name }} {{ .CMD.Parent.Name }} {{ .CMD.cmdName -}} 6 | {{- else if .CMD.Parent.Parent -}} 7 | {{- .CMD.Parent.Parent.Name }} {{ .CMD.Parent.Name }} {{ .CMD.cmdName -}} 8 | {{- else if .CMD.Parent -}} 9 | {{- .CMD.Parent.Name }} {{ .CMD.cmdName -}} 10 | {{- else -}} 11 | {{- .CMD.cmdName -}} 12 | {{- end -}} 13 | {{- else -}} 14 | {{- .CMD.cmdName -}} 15 | {{- end -}} 16 | 17 | -------------------------------------------------------------------------------- /examples/hofmod-cli/schema/arg.cue: -------------------------------------------------------------------------------- 1 | package schema 2 | 3 | import ( 4 | "strings" 5 | ) 6 | 7 | #ArgType: 8 | "[]string" | 9 | "string" | 10 | "int" 11 | 12 | #Arg: { 13 | Name: string 14 | argName: strings.ToCamel(Name) 15 | ArgName: strings.ToTitle(Name) 16 | 17 | Type: #ArgType 18 | Default?: _ 19 | Required?: bool 20 | Rest?: bool 21 | Help: string | *"" 22 | 23 | ... 24 | } 25 | 26 | -------------------------------------------------------------------------------- /examples/hofmod-cli/schema/cli.cue: -------------------------------------------------------------------------------- 1 | package schema 2 | 3 | import ( 4 | "strings" 5 | ) 6 | 7 | #Cli: { 8 | Name: string 9 | cliName: strings.ToCamel(Name) 10 | CliName: strings.ToTitle(Name) 11 | CLI_NAME: strings.ToUpper(Name) 12 | 13 | Package: string 14 | 15 | VersionCommand: bool | *true 16 | CompletionCommands: bool | *true 17 | 18 | Releases?: #GoReleaser 19 | 20 | ConfigDir: string | *"\(cliName)" 21 | 22 | Updates: bool | *true 23 | 24 | Telemetry?: string 25 | TelemetryIdDir: string | *".\(cliName)" 26 | 27 | // Debugging 28 | EnablePProf: bool | *false 29 | 30 | #Common 31 | 32 | ... 33 | } 34 | -------------------------------------------------------------------------------- /examples/hofmod-cli/schema/cmd.cue: -------------------------------------------------------------------------------- 1 | package schema 2 | 3 | import ( 4 | "strings" 5 | ) 6 | 7 | #Command: { 8 | Name: string 9 | cmdName: strings.ToCamel(Name) 10 | CmdName: strings.ToTitle(Name) 11 | 12 | Hidden?: bool 13 | Aliases?: [...string] 14 | PackageName?: string 15 | 16 | #Common 17 | 18 | ... 19 | } 20 | 21 | -------------------------------------------------------------------------------- /examples/hofmod-cli/schema/common.cue: -------------------------------------------------------------------------------- 1 | package schema 2 | 3 | import "text/template" 4 | 5 | #Import: { 6 | As: string | *"" 7 | Path: string 8 | } 9 | 10 | #Common: { 11 | Name: string 12 | Usage: string | *Name 13 | Short: string 14 | Long: string | *Short 15 | TBD: string | *"" 16 | 17 | Help: template.Execute("{{ printf \"%-15s %-5s %s\" .name .tbd .short }}", { tbd: TBD, name: Name, short: Short }) 18 | CustomHelp?: string 19 | 20 | PersistentPrerun: bool | *false 21 | Prerun: bool | *false 22 | OmitRun: bool | *false 23 | Postrun: bool | *false 24 | PersistentPostrun: bool | *false 25 | 26 | PersistentPrerunBody?: string 27 | PrerunBody?: string 28 | Body?: string 29 | PostrunBody?: string 30 | PersistentPostrunBody?: string 31 | 32 | HasAnyRun: bool 33 | HasAnyRun: !OmitRun || PersistentPrerun || Prerun || Postrun || PersistentPostrun 34 | 35 | HasAnyFlags: bool 36 | HasAnyFlags: Pflags != _|_ || Flags != _|_ 37 | 38 | Imports?: [...#Import] 39 | Pflags?: [...#Flag] 40 | Flags?: [...#Flag] 41 | Args?: [...#Arg] 42 | Commands: [...#Command] | *[] 43 | 44 | Topics: [string]: string 45 | Examples: [string]: string 46 | Tutorials: [string]: string 47 | 48 | ... 49 | } 50 | 51 | -------------------------------------------------------------------------------- /examples/hofmod-cli/schema/flag.cue: -------------------------------------------------------------------------------- 1 | package schema 2 | 3 | import ( 4 | "strings" 5 | ) 6 | 7 | #FlagType: 8 | "string" | "[]string" | 9 | "int" | "[]int" | 10 | "float64" | "[]float64" | 11 | "bool" 12 | 13 | #Flag: { 14 | Name: string 15 | flagName: strings.ToCamel(Name) 16 | FlagName: strings.ToTitle(Name) 17 | 18 | Type: #FlagType 19 | Default: _ 20 | Help: string | *"" 21 | Long: string | *"" 22 | Short: string | *"" 23 | 24 | ... 25 | } 26 | 27 | -------------------------------------------------------------------------------- /examples/hofmod-cli/schema/release.cue: -------------------------------------------------------------------------------- 1 | package schema 2 | 3 | 4 | #GoReleaser: { 5 | Disable: bool | *true 6 | Draft: bool | *true 7 | Author: string 8 | Homepage: string 9 | 10 | GitHub: { 11 | Owner: string 12 | Repo: string 13 | URL: "https://github.com/\(Owner)/\(Repo)" 14 | Rel: "https://api.github.com/repos/\(Owner)/\(Repo)/releases" 15 | } 16 | 17 | Docker: { 18 | Maintainer: string 19 | Repo: string 20 | } 21 | 22 | ... 23 | } 24 | -------------------------------------------------------------------------------- /examples/hofmod-cli/templates/Dockerfile.cue: -------------------------------------------------------------------------------- 1 | package templates 2 | 3 | 4 | DockerfileMaintainer :: """ 5 | MAINTAINER {{ .CLI.Releases.Docker.Maintainer }} 6 | """ 7 | 8 | DockerfileWorkdir :: """ 9 | VOLUME ["/work"] 10 | WORKDIR /work 11 | """ 12 | 13 | 14 | DockerfileJessie :: """ 15 | FROM debian:jessie 16 | \(DockerfileMaintainer) 17 | 18 | COPY {{ .CLI.cliName }} /usr/bin/local 19 | ENTRYPOINT ["{{ .CLI.cliName }}"] 20 | 21 | \(DockerfileWorkdir) 22 | 23 | """ 24 | 25 | 26 | DockerfileScratch :: """ 27 | FROM scratch 28 | \(DockerfileMaintainer) 29 | 30 | COPY {{ .CLI.cliName }} / 31 | ENTRYPOINT ["/{{ .CLI.cliName }}"] 32 | 33 | \(DockerfileWorkdir) 34 | 35 | """ 36 | 37 | -------------------------------------------------------------------------------- /examples/hofmod-cli/templates/cmd_test.go: -------------------------------------------------------------------------------- 1 | {{ if .CMD.Parent }} 2 | package cmd{{ .CMD.Parent.Name }}_test 3 | {{ else }} 4 | package cmd_test 5 | {{ end }} 6 | 7 | import ( 8 | "testing" 9 | 10 | "github.com/hofstadter-io/hof/script/runtime" 11 | "github.com/hofstadter-io/hof/lib/yagu" 12 | 13 | {{ if .CMD.Commands }} 14 | 15 | {{ if .CMD.Parent.Parent.Parent.Parent }} 16 | "{{ .CLI.Package }}/cmd/{{ .CMD.Parent.Parent.Parent.Parent.Name }}/{{ .CMD.Parent.Parent.Parent.Name }}/{{ .CMD.Parent.Parent.Name }}/{{ .CMD.Parent.Name }}" 17 | {{ else if .CMD.Parent.Parent.Parent }} 18 | "{{ .CLI.Package }}/cmd/{{ .CMD.Parent.Parent.Parent.Name }}/{{ .CMD.Parent.Parent.Name }}/{{ .CMD.Parent.Name }}" 19 | {{ else if .CMD.Parent.Parent }} 20 | "{{ .CLI.Package }}/cmd/{{ .CMD.Parent.Parent.Name }}/{{ .CMD.Parent.Name }}" 21 | {{ else if .CMD.Parent }} 22 | "{{ .CLI.Package }}/cmd/{{ .CMD.Parent.Name }}" 23 | {{ else }} 24 | "{{ .CLI.Package }}/cmd" 25 | {{ end }} 26 | 27 | {{ else }} 28 | "{{ .CLI.Package }}/cmd" 29 | {{ end }} 30 | ) 31 | 32 | func TestScript{{ .CMD.CmdName }}CliTests(t *testing.T) { 33 | // setup some directories 34 | {{ if .CMD.Commands }} 35 | {{ if .CMD.Parent.Parent.Parent.Parent }} 36 | dir := "{{ .CMD.Parent.Parent.Parent.Parent.Name }}/{{ .CMD.Parent.Parent.Parent.Name }}/{{ .CMD.Parent.Parent.Name }}/{{ .CMD.Parent.Name }}/{{ .CMD.cmdName }}" 37 | {{ else if .CMD.Parent.Parent.Parent }} 38 | dir := "{{ .CMD.Parent.Parent.Parent.Name }}/{{ .CMD.Parent.Parent.Name }}/{{ .CMD.Parent.Name }}/{{ .CMD.cmdName }}" 39 | {{ else if .CMD.Parent.Parent }} 40 | dir := "{{ .CMD.Parent.Parent.Name }}/{{ .CMD.Parent.Name }}/{{ .CMD.cmdName }}" 41 | {{ else if .CMD.Parent }} 42 | dir := "{{ .CMD.Parent.Name }}/{{ .CMD.cmdName }}" 43 | {{ else }} 44 | dir := "{{ .CMD.cmdName }}" 45 | {{ end }} 46 | {{ else }} 47 | dir := "{{ .CMD.cmdName }}" 48 | {{ end }} 49 | workdir := ".workdir/cli/" + dir 50 | yagu.Mkdir(workdir) 51 | 52 | runtime.Run(t, runtime.Params{ 53 | Setup: func (env *runtime.Env) error { 54 | // add any environment variables for your tests here 55 | {{ if .CLI.Telemetry }} 56 | env.Vars = append(env.Vars, "{{ .CLI.CLI_NAME }}_TELEMETRY_DISABLED=1") 57 | {{ end }} 58 | return nil 59 | }, 60 | Funcs: map[string] func (ts* runtime.Script, args[]string) error { 61 | "__{{ .CLI.cliName }}": cmd.CallTS, 62 | }, 63 | Dir: "hls/cli/{{.CMD.cmdName}}", 64 | WorkdirRoot: workdir, 65 | }) 66 | } 67 | 68 | -------------------------------------------------------------------------------- /examples/hofmod-cli/templates/completions.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/spf13/cobra" 7 | 8 | "{{ .CLI.Package }}/ga" 9 | ) 10 | 11 | var ( 12 | CompletionVanillaFlag bool 13 | ) 14 | 15 | func init() { 16 | CompletionCmd.Flags().BoolVarP(&CompletionVanillaFlag, "vanilla", "8", false, "set to only check for an update") 17 | } 18 | 19 | 20 | var CompletionCmd = &cobra.Command{ 21 | Use: "completion", 22 | Aliases: []string{ "completions" }, 23 | Short: "Generate completion helpers for popular terminals", 24 | Long: "Generate completion helpers for popular terminals", 25 | } 26 | 27 | var BashCompletionLong = `Generate Bash completions 28 | 29 | To load completion run 30 | 31 | . <({{ .CLI.cliName }} completion bash) 32 | 33 | To configure your bash shell to load completions for each session add to your bashrc 34 | 35 | # ~/.bashrc or ~/.profile 36 | . <({{ .CLI.cliName }} completion bash) 37 | ` 38 | 39 | var BashCompletionCmd = &cobra.Command{ 40 | Use: "bash", 41 | Short: "Generate Bash completions", 42 | Long: BashCompletionLong, 43 | Run: func(cmd *cobra.Command, args []string) { 44 | RootCmd.GenBashCompletion(os.Stdout) 45 | }, 46 | } 47 | 48 | var ZshCompletionCmd = &cobra.Command{ 49 | Use: "zsh", 50 | Short: "Generate Zsh completions", 51 | Long: "Generate Zsh completions", 52 | Run: func(cmd *cobra.Command, args []string) { 53 | RootCmd.GenZshCompletion(os.Stdout) 54 | }, 55 | } 56 | 57 | var FishCompletionCmd = &cobra.Command{ 58 | Use: "fish", 59 | Short: "Generate Fish completions", 60 | Long: "Generate Fish completions", 61 | 62 | Run: func(cmd *cobra.Command, args []string) { 63 | RootCmd.GenFishCompletion(os.Stdout, true) 64 | }, 65 | } 66 | 67 | var PowerShellCompletionCmd = &cobra.Command{ 68 | Use: "power-shell", 69 | Aliases: []string{ "windows", "win", "power", "ps" }, 70 | Short: "Generate PowerShell completions", 71 | Long: "Generate PowerShell completions", 72 | 73 | Run: func(cmd *cobra.Command, args []string) { 74 | RootCmd.GenPowerShellCompletion(os.Stdout) 75 | }, 76 | } 77 | 78 | func init() { 79 | CompletionCmd.AddCommand(BashCompletionCmd) 80 | CompletionCmd.AddCommand(ZshCompletionCmd) 81 | CompletionCmd.AddCommand(FishCompletionCmd) 82 | CompletionCmd.AddCommand(PowerShellCompletionCmd) 83 | 84 | help := CompletionCmd.HelpFunc() 85 | usage := CompletionCmd.UsageFunc() 86 | 87 | {{ if .CLI.Telemetry }} 88 | thelp := func (cmd *cobra.Command, args []string) { 89 | if CompletionCmd.Name() == cmd.Name() { 90 | ga.SendCommandPath("completion help") 91 | } 92 | help(cmd, args) 93 | } 94 | tusage := func (cmd *cobra.Command) error { 95 | if CompletionCmd.Name() == cmd.Name() { 96 | ga.SendCommandPath("completion usage") 97 | } 98 | return usage(cmd) 99 | } 100 | CompletionCmd.SetHelpFunc(thelp) 101 | CompletionCmd.SetUsageFunc(tusage) 102 | {{ else }} 103 | CompletionCmd.SetHelpFunc(help) 104 | CompletionCmd.SetUsageFunc(usage) 105 | {{ end }} 106 | } 107 | -------------------------------------------------------------------------------- /examples/hofmod-cli/templates/flags.go: -------------------------------------------------------------------------------- 1 | package flags 2 | 3 | {{ if .CMD }} 4 | {{ template "pflag-vars" .CMD }} 5 | {{ template "flag-vars" .CMD }} 6 | {{ else }} 7 | import ( 8 | "bytes" 9 | "fmt" 10 | "strings" 11 | ) 12 | 13 | func PrintSubject(title, prefix, subject string, subjects map[string]string) bool { 14 | // skip if null or empty 15 | if subjects == nil || len(subjects) == 0 { 16 | return false 17 | } 18 | 19 | // print keys for list, so don't have a subject that name 20 | if subject == "list" { 21 | var S []string 22 | for k, _ := range subjects { 23 | S = append(S,k) 24 | } 25 | var b bytes.Buffer 26 | fmt.Fprintln(&b, title) 27 | for _, s := range S { 28 | fmt.Fprintln(&b, prefix + s) 29 | } 30 | 31 | fmt.Println(b.String()) 32 | return true 33 | } 34 | 35 | // print pubject, indenting all lines 36 | S, ok := subjects[subject] 37 | if !ok { 38 | return false 39 | } 40 | S = strings.Replace(S, "¡", "`", -1) 41 | 42 | var b bytes.Buffer 43 | fmt.Fprintln(&b, title) 44 | for _, s := range strings.Split(S, "\n") { 45 | fmt.Fprintln(&b, prefix + s) 46 | } 47 | 48 | fmt.Println(b.String()) 49 | return true 50 | } 51 | 52 | {{ template "pflag-vars" .CLI }} 53 | {{ template "flag-vars" .CLI }} 54 | {{ end }} 55 | -------------------------------------------------------------------------------- /examples/hofmod-cli/templates/ga.go: -------------------------------------------------------------------------------- 1 | package ga 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "os" 7 | "path/filepath" 8 | "strings" 9 | 10 | "github.com/google/uuid" 11 | "github.com/hofstadter-io/yagu" 12 | 13 | "{{ .CLI.Package }}/verinfo" 14 | ) 15 | 16 | func SendCommandPath(cmd string) { 17 | cs := strings.Fields(cmd) 18 | c := strings.Join(cs[1:], "/") 19 | SendGaEvent(c, "", 0) 20 | } 21 | 22 | func SendGaEvent(action, label string, value int) { 23 | if os.Getenv("{{ .CLI.CLI_NAME }}_TELEMETRY_DISABLED") != "" { 24 | return 25 | } 26 | 27 | cid, err := readGaId() 28 | if err != nil { 29 | cid = "unknown" 30 | } 31 | 32 | ua := fmt.Sprintf( 33 | "%s/%s %s/%s", 34 | "{{ .CLI.cliName }}", verinfo.Version, 35 | verinfo.BuildOS, verinfo.BuildArch, 36 | ) 37 | 38 | cfg := yagu.GaConfig{ 39 | TID: "{{ .CLI.Telemetry }}", 40 | CID: cid, 41 | UA: ua, 42 | CN: "{{ .CLI.cliName }}", 43 | CS: "{{ .CLI.cliName }}/" + verinfo.Version, 44 | CM: verinfo.Version, 45 | } 46 | 47 | evt := yagu.GaEvent{ 48 | Source: cfg.UA, 49 | Category: "{{ .CLI.cliName }}", 50 | Action: action, 51 | Label: label, 52 | } 53 | 54 | if value >= 0 { 55 | evt.Value = value 56 | } 57 | 58 | yagu.SendGaEvent(cfg, evt) 59 | } 60 | 61 | func readGaId() (string, error) { 62 | // ucd := yagu.UserHomeDir() 63 | ucd, err := os.UserConfigDir() 64 | if err != nil { 65 | return "", err 66 | } 67 | dir := filepath.Join(ucd, "{{ .CLI.TelemetryIdDir }}") 68 | fn := filepath.Join(dir, ".uuid") 69 | 70 | _, err = os.Lstat(fn) 71 | if err != nil { 72 | // file does not exist, probably... 73 | return writeGaId() 74 | } 75 | 76 | content, err := ioutil.ReadFile(fn) 77 | if err != nil { 78 | return writeGaId() 79 | } 80 | 81 | return string(content), nil 82 | } 83 | 84 | func writeGaId() (string, error) { 85 | 86 | ucd, err := os.UserConfigDir() 87 | if err != nil { 88 | return "", err 89 | } 90 | 91 | dir := filepath.Join(ucd, "{{ .CLI.TelemetryIdDir }}") 92 | err = yagu.Mkdir(dir) 93 | if err != nil { 94 | return "", err 95 | } 96 | 97 | fn := filepath.Join(dir, ".uuid") 98 | 99 | id, err := uuid.NewUUID() 100 | if err != nil { 101 | return id.String(), err 102 | } 103 | 104 | err = ioutil.WriteFile(fn, []byte(id.String()), 0644) 105 | if err != nil { 106 | return id.String(), err 107 | } 108 | 109 | return id.String(), nil 110 | } 111 | -------------------------------------------------------------------------------- /examples/hofmod-cli/templates/goreleaser.yml: -------------------------------------------------------------------------------- 1 | project_name: "{% .CLI.cliName %}" 2 | 3 | before: 4 | hooks: 5 | - go mod vendor 6 | 7 | builds: 8 | - binary: "{% .CLI.cliName %}" 9 | main: main.go 10 | 11 | ldflags: 12 | - -s -w 13 | - -X {% .CLI.Package %}/verinfo.Version={{.Version}} 14 | - -X {% .CLI.Package %}/verinfo.Commit={{.FullCommit}} 15 | - -X {% .CLI.Package %}/verinfo.BuildDate={{.Date}} 16 | - -X {% .CLI.Package %}/verinfo.GoVersion=go1.14 17 | - -X {% .CLI.Package %}/verinfo.BuildOS={{.Os}} 18 | - -X {% .CLI.Package %}/verinfo.BuildArch={{.Arch}} 19 | - -X {% .CLI.Package %}/verinfo.BuildArm={{.Arm}} 20 | 21 | env: 22 | - CGO_ENABLED=0 23 | 24 | goos: 25 | - darwin 26 | - linux 27 | - windows 28 | goarch: 29 | - amd64 30 | - arm64 31 | - arm 32 | 33 | ignore: 34 | - goos: linux 35 | goarch: arm 36 | 37 | 38 | snapshot: 39 | name_template: "{{ .Tag }}-SNAPSHOT-{{.ShortCommit}}" 40 | 41 | archives: 42 | - format: binary 43 | replacements: 44 | darwin: Darwin 45 | linux: Linux 46 | windows: Windows 47 | amd64: x86_64 48 | # Needed hack for binary only uploads 49 | # For more information, check #602 50 | files: 51 | - "thisfiledoesnotexist*" 52 | 53 | 54 | checksum: 55 | name_template: '{{ .ProjectName }}_{{ .Version }}_checksums.txt' 56 | 57 | changelog: 58 | sort: asc 59 | filters: 60 | exclude: 61 | - '^docs:' 62 | - '^test:' 63 | 64 | 65 | release: 66 | disable: {% .CLI.Releases.Disabled %} 67 | draft: {% .CLI.Releases.Draft %} 68 | github: 69 | owner: {% .CLI.Releases.GitHub.Owner %} 70 | name: {% .CLI.Releases.GitHub.Repo %} 71 | 72 | dockers: 73 | - binaries: 74 | - {% .CLI.cliName %} 75 | skip_push: {% .CLI.Releases.Disabled %} 76 | dockerfile: ../../ci/{% .CLI.cliName %}/docker/Dockerfile.jessie 77 | image_templates: 78 | - "{% .CLI.Releases.Docker.Repo %}/{{.ProjectName}}:{{.Tag}}" 79 | - "{% .CLI.Releases.Docker.Repo %}/{{.ProjectName}}:v{{ .Major }}.{{ .Minor }}" 80 | - "{% .CLI.Releases.Docker.Repo %}/{{.ProjectName}}:v{{ .Major }}" 81 | - "{% .CLI.Releases.Docker.Repo %}/{{.ProjectName}}:latest" 82 | 83 | - "{% .CLI.Releases.Docker.Repo %}/{{.ProjectName}}:{{.Tag}}-debian" 84 | - "{% .CLI.Releases.Docker.Repo %}/{{.ProjectName}}:v{{ .Major }}.{{ .Minor }}-debian" 85 | - "{% .CLI.Releases.Docker.Repo %}/{{.ProjectName}}:v{{ .Major }}-debian" 86 | - "{% .CLI.Releases.Docker.Repo %}/{{.ProjectName}}:latest-debian" 87 | 88 | 89 | - binaries: 90 | - {% .CLI.cliName %} 91 | skip_push: {% .CLI.Releases.Disabled %} 92 | dockerfile: ../../ci/{% .CLI.cliName %}/docker/Dockerfile.scratch 93 | image_templates: 94 | - "{% .CLI.Releases.Docker.Repo %}/{{.ProjectName}}:{{.Tag}}-scratch" 95 | - "{% .CLI.Releases.Docker.Repo %}/{{.ProjectName}}:v{{ .Major }}.{{ .Minor }}-scratch" 96 | - "{% .CLI.Releases.Docker.Repo %}/{{.ProjectName}}:v{{ .Major }}-scratch" 97 | - "{% .CLI.Releases.Docker.Repo %}/{{.ProjectName}}:latest-scratch" 98 | -------------------------------------------------------------------------------- /examples/hofmod-cli/templates/hls/cli/cmd_help.hls: -------------------------------------------------------------------------------- 1 | ### Test "{{ .CMD.cmdName }} --help" prints help 2 | call __{{ .CLI.cliName }} {{ template "test-cli-args.txt" . }} --help 3 | 4 | ### Test "{{ .CMD.cmdName }} -h" prints help 5 | call __{{ .CLI.cliName }} {{ template "test-cli-args.txt" . }} -h 6 | 7 | {{ if .CMD.OmitRun -}} 8 | ### Test "{{ .CMD.cmdName }}" (without any args) prints help 9 | call __{{ .CLI.cliName }} {{ template "test-cli-args.txt" . }} 10 | {{end}} 11 | -------------------------------------------------------------------------------- /examples/hofmod-cli/templates/hls/cli/root_help.hls: -------------------------------------------------------------------------------- 1 | ### Test "{{ .CLI.cliName }} --help" prints help 2 | call __{{ .CLI.cliName }} --help 3 | 4 | ### Test "{{ .CLI.cliName }} -h" prints help 5 | call __{{ .CLI.cliName }} -h 6 | 7 | ### Test "{{ .CLI.cliName }} help" prints help 8 | call __{{ .CLI.cliName }} help 9 | 10 | {{ if .CLI.OmitRun }} 11 | ### Test "{{ .CLI.cliName }}" (without any args) prints help 12 | call __{{ .CLI.cliName }} 13 | {{end}} 14 | -------------------------------------------------------------------------------- /examples/hofmod-cli/templates/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "{{ .CLI.Package }}/cmd" 5 | ) 6 | 7 | func main() { 8 | cmd.RunExit() 9 | } 10 | -------------------------------------------------------------------------------- /examples/hofmod-cli/templates/root_test.go: -------------------------------------------------------------------------------- 1 | package cmd_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/hofstadter-io/hof/script/runtime" 7 | "github.com/hofstadter-io/hof/lib/yagu" 8 | 9 | "{{ .CLI.Package }}/cmd" 10 | ) 11 | 12 | func init() { 13 | // ensure our root command is setup 14 | cmd.RootInit() 15 | } 16 | 17 | func TestScriptRootCliTests(t *testing.T) { 18 | // setup some directories 19 | workdir := ".workdir/cli/root" 20 | yagu.Mkdir(workdir) 21 | 22 | runtime.Run(t, runtime.Params{ 23 | Setup: func (env *runtime.Env) error { 24 | // add any environment variables for your tests here 25 | {{ if .CLI.Telemetry }} 26 | env.Vars = append(env.Vars, "{{ .CLI.CLI_NAME }}_TELEMETRY_DISABLED=1") 27 | {{ end }} 28 | return nil 29 | }, 30 | Funcs: map[string] func (ts* runtime.Script, args[]string) error { 31 | "__{{ .CLI.cliName }}": cmd.CallTS, 32 | }, 33 | Dir: "hls/cli/root", 34 | WorkdirRoot: workdir, 35 | }) 36 | } 37 | 38 | -------------------------------------------------------------------------------- /examples/hofmod-cli/templates/verinfo.go: -------------------------------------------------------------------------------- 1 | package verinfo 2 | 3 | import ( 4 | "runtime" 5 | "time" 6 | ) 7 | 8 | var ( 9 | Version = "Local" 10 | Commit = "Dirty" 11 | 12 | BuildDate = "Unknown" 13 | GoVersion = "Unknown" 14 | BuildOS = "Unknown" 15 | BuildArch = "Unknown" 16 | 17 | ) 18 | 19 | func init() { 20 | 21 | if BuildDate == "Unknown" { 22 | BuildDate = time.Now().String() 23 | GoVersion = "run 'go version', you should have been the one who built this" 24 | BuildOS = runtime.GOOS 25 | BuildArch = runtime.GOARCH 26 | } 27 | } 28 | 29 | 30 | -------------------------------------------------------------------------------- /examples/hofmod-cli/templates/version.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "path/filepath" 7 | 8 | "github.com/spf13/cobra" 9 | 10 | "{{ .CLI.Package }}/ga" 11 | "{{ .CLI.Package }}/verinfo" 12 | ) 13 | 14 | const versionMessage = ` 15 | Version: v%s 16 | Commit: %s 17 | 18 | BuildDate: %s 19 | GoVersion: %s 20 | OS / Arch: %s %s 21 | 22 | {{ with .CLI.Releases }} 23 | Author: {{ .Author }} 24 | Homepage: {{ .Homepage }} 25 | GitHub: {{ .GitHub.URL }} 26 | {{ end }} 27 | ` 28 | 29 | var VersionLong = `Print the build version for {{ .CLI.cliName }}` 30 | 31 | var VersionCmd = &cobra.Command{ 32 | 33 | Use: "version", 34 | 35 | Aliases: []string{ 36 | "ver", 37 | }, 38 | 39 | Short: "print the version", 40 | 41 | Long: VersionLong, 42 | 43 | Run: func(cmd *cobra.Command, args []string) { 44 | {{ if .CLI.ConfigDir }} 45 | s, e := os.UserConfigDir() 46 | fmt.Printf("{{ .CLI.Name }} ConfigDir %q %v\n", filepath.Join(s, "{{ .CLI.ConfigDir }}"), e) 47 | {{ end }} 48 | 49 | fmt.Printf( 50 | versionMessage, 51 | verinfo.Version, 52 | verinfo.Commit, 53 | verinfo.BuildDate, 54 | verinfo.GoVersion, 55 | verinfo.BuildOS, 56 | verinfo.BuildArch, 57 | ) 58 | }, 59 | } 60 | 61 | func init() { 62 | help := VersionCmd.HelpFunc() 63 | usage := VersionCmd.UsageFunc() 64 | 65 | {{ if .CLI.Telemetry }} 66 | thelp := func (cmd *cobra.Command, args []string) { 67 | if VersionCmd.Name() == cmd.Name() { 68 | ga.SendCommandPath("version help") 69 | } 70 | help(cmd, args) 71 | } 72 | tusage := func (cmd *cobra.Command) error { 73 | if VersionCmd.Name() == cmd.Name() { 74 | ga.SendCommandPath("version usage") 75 | } 76 | return usage(cmd) 77 | } 78 | VersionCmd.SetHelpFunc(thelp) 79 | VersionCmd.SetUsageFunc(tusage) 80 | {{ else }} 81 | VersionCmd.SetHelpFunc(help) 82 | VersionCmd.SetUsageFunc(usage) 83 | {{ end }} 84 | } 85 | -------------------------------------------------------------------------------- /misc/cel/policy-engine-for-osdu-entitlements.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/misc/cel/policy-engine-for-osdu-entitlements.pdf -------------------------------------------------------------------------------- /misc/cue-slack-files/A Generic Approach to Parallel Chart Parsing with an Application to LinGO.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/misc/cue-slack-files/A Generic Approach to Parallel Chart Parsing with an Application to LinGO.pdf -------------------------------------------------------------------------------- /misc/cue-slack-files/A Library of Anti-Unification Algorithms.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/misc/cue-slack-files/A Library of Anti-Unification Algorithms.pdf -------------------------------------------------------------------------------- /misc/cue-slack-files/A Variant of Higher-Order Anti-Unification.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/misc/cue-slack-files/A Variant of Higher-Order Anti-Unification.pdf -------------------------------------------------------------------------------- /misc/cue-slack-files/Anti-Unification Based Learning of T-Wrappers for Information Extraction.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/misc/cue-slack-files/Anti-Unification Based Learning of T-Wrappers for Information Extraction.pdf -------------------------------------------------------------------------------- /misc/cue-slack-files/Anti-Unification and Natural Language ProcessingAnti-Unification and Natural Language Processing.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/misc/cue-slack-files/Anti-Unification and Natural Language ProcessingAnti-Unification and Natural Language Processing.pdf -------------------------------------------------------------------------------- /misc/cue-slack-files/Anti-Unification for Unranked Terms and Hedges.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/misc/cue-slack-files/Anti-Unification for Unranked Terms and Hedges.pdf -------------------------------------------------------------------------------- /misc/cue-slack-files/Anti-Unification with Type Classes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/misc/cue-slack-files/Anti-Unification with Type Classes.pdf -------------------------------------------------------------------------------- /misc/cue-slack-files/Anti-unification algorithms and their applications in program analysis.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/misc/cue-slack-files/Anti-unification algorithms and their applications in program analysis.pdf -------------------------------------------------------------------------------- /misc/cue-slack-files/Applying Anti-Unication Strategies to Matching and Generalization of Recursive Functions.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/misc/cue-slack-files/Applying Anti-Unication Strategies to Matching and Generalization of Recursive Functions.pdf -------------------------------------------------------------------------------- /misc/cue-slack-files/Compiling Typed Attribute-Value Logic Grammars.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/misc/cue-slack-files/Compiling Typed Attribute-Value Logic Grammars.pdf -------------------------------------------------------------------------------- /misc/cue-slack-files/Duplicate code detection using anti-unification.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/misc/cue-slack-files/Duplicate code detection using anti-unification.pdf -------------------------------------------------------------------------------- /misc/cue-slack-files/EXPLOITING PARALLELISM INUNIFICATION-BASED PARSING.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/misc/cue-slack-files/EXPLOITING PARALLELISM INUNIFICATION-BASED PARSING.pdf -------------------------------------------------------------------------------- /misc/cue-slack-files/Effective Exploitation of Parallelism in NLP.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/misc/cue-slack-files/Effective Exploitation of Parallelism in NLP.pdf -------------------------------------------------------------------------------- /misc/cue-slack-files/EfficientParsingwithLarge-ScaleUnificationGrammars.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/misc/cue-slack-files/EfficientParsingwithLarge-ScaleUnificationGrammars.pdf -------------------------------------------------------------------------------- /misc/cue-slack-files/Feature Structures and How toRepresent Multiple Phenomena Simultaneously.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/misc/cue-slack-files/Feature Structures and How toRepresent Multiple Phenomena Simultaneously.pdf -------------------------------------------------------------------------------- /misc/cue-slack-files/Graph Unification and Matching.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/misc/cue-slack-files/Graph Unification and Matching.pdf -------------------------------------------------------------------------------- /misc/cue-slack-files/Higher-Order Pattern Anti-Unification in Linear Time.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/misc/cue-slack-files/Higher-Order Pattern Anti-Unification in Linear Time.pdf -------------------------------------------------------------------------------- /misc/cue-slack-files/Memory-Efficient and Thread-Safe Quasi-Destructive Graph Unification.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/misc/cue-slack-files/Memory-Efficient and Thread-Safe Quasi-Destructive Graph Unification.pdf -------------------------------------------------------------------------------- /misc/cue-slack-files/Memory-Efficient and Thread-Safe Quasi-Destructive GraphUnification.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/misc/cue-slack-files/Memory-Efficient and Thread-Safe Quasi-Destructive GraphUnification.pdf -------------------------------------------------------------------------------- /misc/cue-slack-files/Parallel Natural Language Parsing-From Analysis to Speedup.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/misc/cue-slack-files/Parallel Natural Language Parsing-From Analysis to Speedup.pdf -------------------------------------------------------------------------------- /misc/cue-slack-files/Quasi-Destructive Graph Unification.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/misc/cue-slack-files/Quasi-Destructive Graph Unification.pdf -------------------------------------------------------------------------------- /misc/cue-slack-files/Squibs and Discussions A Note on Typing Feature Structures.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/misc/cue-slack-files/Squibs and Discussions A Note on Typing Feature Structures.pdf -------------------------------------------------------------------------------- /misc/cue-slack-files/TYPED FEATU19E STRUCTURES AS DESCRIPTIONS.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/misc/cue-slack-files/TYPED FEATU19E STRUCTURES AS DESCRIPTIONS.pdf -------------------------------------------------------------------------------- /misc/cue-slack-files/The Logic of Typed Feature Structures.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/misc/cue-slack-files/The Logic of Typed Feature Structures.pdf -------------------------------------------------------------------------------- /misc/cue-slack-files/Unification ParsingTyped Feature Structures.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/misc/cue-slack-files/Unification ParsingTyped Feature Structures.pdf -------------------------------------------------------------------------------- /misc/oopsla90.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/misc/oopsla90.pdf -------------------------------------------------------------------------------- /talks/Deliver-Your-Cloud-Native-Application-with-Design-Pattern-as-Code.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/talks/Deliver-Your-Cloud-Native-Application-with-Design-Pattern-as-Code.pdf -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/.gitignore: -------------------------------------------------------------------------------- 1 | _talk_html_ 2 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # present: 3 | # 4 | # go get golang.org/x/tools/cmd/present 5 | # 6 | # https://pkg.go.dev/golang.org/x/tools/cmd/present 7 | # https://pkg.go.dev/golang.org/x/tools/present 8 | # 9 | 10 | run: 11 | present -base=./present -play 12 | 13 | html: 14 | -rm -rf ./_talk_html_ 15 | 16 | # present 17 | mkdir -p _talk_html_/static 18 | curl -s http://127.0.0.1:3999/static/notes.js > _talk_html_/static/notes.js 19 | curl -s http://127.0.0.1:3999/static/slides.js | sed -E 's/(\/static\/)/.\1/' > _talk_html_/static/slides.js 20 | curl -s http://127.0.0.1:3999/static/styles.css > _talk_html_/static/styles.css 21 | curl -s http://127.0.0.1:3999/static/notes.css > _talk_html_/static/notes.css 22 | 23 | # cue-intro.slide 24 | cp cue-intro.slide _talk_html_/ 25 | mkdir -p _talk_html_/images 26 | mkdir -p _talk_html_/code 27 | cp -R images/ _talk_html_/images/ 28 | cp -R code/ _talk_html_/code/ 29 | curl -s http://127.0.0.1:3999/cue-intro.slide | sed -E 's/(\/static\/)/.\1/' | sed -E '/play\.js/d' > _talk_html_/index.html 30 | 31 | clean: 32 | -rm -rf ./_talk_html_ 33 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/README.md: -------------------------------------------------------------------------------- 1 | # CUE配置语言简介(幻灯片) 2 | 3 | CUE是一种Go语言实现的开源数据约束语言,它是JSON的超集,是一种功能强大的配置语言。 4 | 5 | **在线浏览幻灯片:** 6 | 7 | - https://talks.godoc.org/github.com/chai2010/awesome-cue-zh/talks/chai2010-cue-intro-talk/cue-intro.slide 8 | 9 | **本地启动幻灯片方式:** 10 | 11 | 1. 安装 present 工具: `go get golang.org/x/tools/cmd/present` 12 | 2. `make` 启动服务, 浏览器打开 http://127.0.0.1:3999 13 | 3. `make html`导出html静态文件到 `_talk_html_` 目录 14 | 15 | ## CUE语言简单入门 16 | 17 | 安装CUE命令(Go语言项目安装方式): 18 | 19 | ``` 20 | $ go get cuelang.org/go/cmd/cue 21 | ``` 22 | 23 | 创建`hello.cue`文件: 24 | 25 | ```yaml 26 | one: 1 27 | two: 2 28 | 29 | // A field using quotes. 30 | "two-and-a-half": 2.5 31 | 32 | list: [ 33 | 1, 34 | 2, 35 | 3, 36 | ] 37 | ``` 38 | 39 | 转化为JOSN格式: 40 | 41 | ```json 42 | $ go run main.go export --out=json hello.cue 43 | { 44 | "list": [ 45 | 1, 46 | 2, 47 | 3 48 | ], 49 | "one": 1, 50 | "two": 2, 51 | "two-and-a-half": 2.5 52 | } 53 | ``` 54 | 55 | 转化为YAML格式: 56 | 57 | ```yaml 58 | $ go run main.go export --out=yaml hello.cue 59 | list: 60 | - 1 61 | - 2 62 | - 3 63 | one: 1 64 | two: 2 65 | two-and-a-half: 2.5 66 | ``` 67 | 68 | 执行脚本(以下的格式化对齐是否有问题?): 69 | 70 | ``` 71 | $ go run main.go eval hello.cue 72 | list: [1, 2, 3] 73 | one: 1 74 | two: 2 75 | "two-and-a-half": 2.5 76 | ``` 77 | 78 | 79 | ## 参考资料 80 | 81 | - https://cuelang.org/ 82 | 83 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/00-cue-is-json-01/Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | 3 | clean: 4 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/00-cue-is-json-01/hello.json.cue: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cue", 3 | "url": "https://cuelang.org" 4 | } -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/00/Makefile: -------------------------------------------------------------------------------- 1 | default: hello.cue 2 | cue export --out=json hello.cue > hello.json 3 | cue export --out=yaml hello.cue > hello.yml 4 | 5 | cue eval hello.cue 6 | 7 | clean: 8 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/00/hello.cue: -------------------------------------------------------------------------------- 1 | one: 1 2 | two: 2 3 | 4 | // A field using quotes. 5 | "two-and-a-half": 2.5 6 | 7 | list: [ 8 | 1, 9 | 2, 10 | 3, 11 | ] 12 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/00/hello.json: -------------------------------------------------------------------------------- 1 | { 2 | "list": [ 3 | 1, 4 | 2, 5 | 3 6 | ], 7 | "one": 1, 8 | "two": 2, 9 | "two-and-a-half": 2.5 10 | } 11 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/00/hello.yml: -------------------------------------------------------------------------------- 1 | list: 2 | - 1 3 | - 2 4 | - 3 5 | one: 1 6 | two: 2 7 | two-and-a-half: 2.5 8 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/00/readme.md: -------------------------------------------------------------------------------- 1 | 最简单的例子,一个文件 2 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/01-hello/Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | cue export --out=json hello.cue > hello.json 3 | cue export --out=yaml hello.cue > hello.yml 4 | 5 | cue eval hello.cue 6 | 7 | clean: 8 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/01-hello/hello.cue: -------------------------------------------------------------------------------- 1 | import "sub" 2 | 3 | one: 1 4 | two: 2 5 | 6 | // A field using quotes. 7 | "two-and-a-half": 2.5 8 | 9 | list: [ 10 | 1, 11 | 2, 12 | 3, 13 | ] 14 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/01-hello/hello.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/talks/chai2010-cue-intro-talk/code/01-hello/hello.json -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/01-hello/hello.yml: -------------------------------------------------------------------------------- 1 | list: 2 | - 1 3 | - 2 4 | - 3 5 | one: 1 6 | two: 2 7 | two-and-a-half: 2.5 8 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/01-hello/module.mod: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/talks/chai2010-cue-intro-talk/code/01-hello/module.mod -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/01-hello/sub/bar.cue: -------------------------------------------------------------------------------- 1 | package sub 2 | 3 | ONE = 1 4 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/01/Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | cue eval a.cue b.cue 3 | 4 | clean: 5 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/01/a.cue: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | foo: 100 4 | bar: int 5 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/01/b.cue: -------------------------------------------------------------------------------- 1 | 2 | bar: 200 3 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/01/readme.md: -------------------------------------------------------------------------------- 1 | 2个文件,都没有声明 pkg 名字,可以混合使用 2 | 3 | 如果2个都有pkg name,必须一样 4 | 5 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/02/Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | cue eval a.cue b.cue 3 | 4 | clean: 5 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/02/a.cue: -------------------------------------------------------------------------------- 1 | import ( 2 | "encoding/json" 3 | "math" 4 | ) 5 | 6 | data: json.Marshal({ a: math.Sqrt(7) }) 7 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/02/b.cue: -------------------------------------------------------------------------------- 1 | bar: 200 2 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/02/readme.md: -------------------------------------------------------------------------------- 1 | 导入标准库 2 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/03/Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | cue eval a.cue 3 | 4 | clean: 5 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/03/a.cue: -------------------------------------------------------------------------------- 1 | import ( 2 | "chai2010/sub" 3 | v2 "chai2010/sub:sub_v2" 4 | v3 "chai2010/sub:sub_v3" 5 | 6 | "abcd.com/vv:vv" 7 | ) 8 | 9 | aaa: sub.Version 10 | bbb: v2.Version 11 | ccc: v3.Version 12 | 13 | qq: vv.Method 14 | 15 | vv_a: vv.vv_a 16 | vv_b: vv.vv_b 17 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/03/cue.mod/module.cue: -------------------------------------------------------------------------------- 1 | module: "chai2010" 2 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/03/cue.mod/pkg/abcd.com/vv/1234.com/vv/b.cue: -------------------------------------------------------------------------------- 1 | package vv 2 | 3 | 4 | vv_b : "vv-b" 5 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/03/cue.mod/pkg/abcd.com/vv/a.cue: -------------------------------------------------------------------------------- 1 | package vv 2 | 3 | Method: "tnt" | "catapult" | "net" 4 | 5 | vv_a : "vv-a" 6 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/03/readme.md: -------------------------------------------------------------------------------- 1 | 构建一个pkg,用于import 2 | 3 | cue.mod/module.cue 文件表示当前目录是一个模块 4 | 5 | module.cue 文件指定了当前目录对应的模块路径,当前的子包都是相对于这个路径 6 | 7 | 每个目录下,package必须指定名字才能被其他文件import,默认选择的是和目录同名的。 8 | 9 | 第三方的模块 在 cue.mod/pkg 目录下 10 | 11 | cue.mod/gen 第三方模块生成的文件 12 | 13 | cue.mod/usr 用户定义的约束(?) 14 | 15 | ---- 16 | 17 | 和Go的差别 18 | 19 | 1. package 语句是可选的,如果缺少则不能被其他包导入 20 | 2. 被导入包通过路径和名字唯一定位,比如 "hello.com/abc:abc",冒号之后的是包名字,如果包名和目录名一样可以省略。 21 | 3. 一个目录下可以有多个不同名字的包 22 | 4. 同一个模块下,同一个名字的文件属于同一个包(不区分目录路径吗?) 23 | 5. 当前目录对应包包包含目录下的全部文件,和到模块根目录下所有的cue文件???? 24 | 25 | 包的实例是包的子集,是不是当前目录到模块跟木块? 26 | 27 | 当导入的路径匹配搭配多个目录时,cue.mod/pkg, cue.mod/gen, and cue.mod/usr 会合并到一个路径。 28 | 29 | 需要从网上cue get 一个模块测试 30 | 31 | 32 | The package clause is optional: such files do not belong to a package and cannot be imported. 33 | 34 | A package is identified by its import path and its package name, separated by a :. If its name is equal to the base of this path it may be omitted. 35 | 36 | There can be more than one package per directory. 37 | 38 | All files within a module with the same package name belong to the same package; an instance of such a package for a given directory contains all its files from that directory up till the module root. -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/03/sub/v1.cue: -------------------------------------------------------------------------------- 1 | package sub 2 | 3 | Version: "v1" 4 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/03/sub/v2.cue: -------------------------------------------------------------------------------- 1 | package sub_v2 2 | 3 | Version: "v2" 4 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/03/sub/v3.cue: -------------------------------------------------------------------------------- 1 | package sub_v3 2 | 3 | 4 | Version: "v3"// + vv.AAA 5 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/04/Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | cue eval cfg.cue 3 | 4 | clean: 5 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/04/cfg.cue: -------------------------------------------------------------------------------- 1 | #Spec: { 2 | kind: string 3 | 4 | name: { 5 | first: !="" // must be specified and non-empty 6 | middle?: !="" // optional, but must be non-empty when specified 7 | last: !="" 8 | } 9 | 10 | // The minimum must be strictly smaller than the maximum and vice versa. 11 | minimum?: int & minimum 13 | } 14 | 15 | #SpecChecker: { 16 | minimum: >10 17 | ... 18 | } 19 | 20 | // 支持多个模式组合 21 | 22 | spec: #Spec & #SpecChecker & { 23 | kind: "Homo Sapiens" // error, misspelled field 24 | 25 | name: first: "Jane" 26 | name: last: "Doe" 27 | 28 | minimum: 15 29 | } 30 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/05/Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | cue eval a.cue 3 | 4 | clean: 5 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/05/a.cue: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // The following struct is unified with all elements in job. 4 | // The name of each element is bound to Name and visible in the struct. 5 | job: [Name=_]: { 6 | name: "Name" 7 | replicas: uint | *1 8 | command: string 9 | // Name: "aaa" // cannot have both alias and field with name "Name" in same scope: 10 | "\(Name)": Name 11 | } 12 | 13 | job: list: command: "ls" 14 | 15 | job: nginx: { 16 | command: "nginx" 17 | replicas: 2 18 | } -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/05/readme.md: -------------------------------------------------------------------------------- 1 | 2个文件,都没有声明 pkg 名字,可以混合使用 2 | 3 | 如果2个都有pkg name,必须一样 4 | 5 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/builtin-01/Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | cue eval hello.cue 3 | 4 | clean: 5 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/builtin-01/builtin.txt: -------------------------------------------------------------------------------- 1 | len("abc") 3 2 | len("中文") 6 3 | 4 | len([1, 2, 3]) 3 5 | len([1, 2, ...]) >=2 6 | 7 | and([a, b]) a & b 8 | and([a]) a 9 | and([]) _ 10 | 11 | or([a, b]) a | b 12 | or([a]) a 13 | or([]) _|_ 14 | 15 | close // 闭合类型 -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/builtin-01/hello.cue: -------------------------------------------------------------------------------- 1 | a: len("abc") // 3 2 | b: len("世界") // 6 3 | 4 | c: len([1, 2, 3]) // 3 5 | d: len([1, 2, ...]) // 2, >=2 6 | 7 | e: and([true, true]) // true 8 | g: and([]) // _, top 集合, 类似无穷大集合 9 | 10 | h: or([true, false]) // a | b 11 | h: or(true) // or([true, false]) & or(true) 12 | 13 | i: or([int, "abc"]) // a | b 14 | j: or([]) // _|_, bottom 集合, 类似空集 15 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/cmd-00/Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | @cue cmd hello 3 | 4 | clean: 5 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/cmd-00/hello_tool.cue: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "tool/cli" // HL 4 | 5 | command: hello: { // HL 6 | print: cli.Print & { 7 | text: "Hello CUE." // HL 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/cmd-01/Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | @cue cmd hello 3 | @cue cmd --inject who=cuelang hello 4 | 5 | clean: 6 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/cmd-01/hello_tool.cue: -------------------------------------------------------------------------------- 1 | package foo 2 | 3 | import "tool/exec" // HL 4 | 5 | city: "杭州" 6 | who: *"World" | string @tag(who,type=string) 7 | 8 | // Say hello! 9 | command: hello: { // HL 10 | print: exec.Run & { // HL 11 | cmd: "echo Hello \(who)! Welcome to \(city)." // HL 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/cmd-02/Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | @cue cmd --inject file=a.out.txt hello 3 | 4 | clean: 5 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/cmd-02/a.out.txt: -------------------------------------------------------------------------------- 1 | Hello 111! 2 | Hello 222! 3 | Hello qq! 4 | Hello 11! 5 | Hello aaa! 6 | Hello aaa! 7 | Hello 111! 8 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/cmd-02/hello_tool.cue: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "tool/cli" 4 | import "tool/exec" 5 | import "tool/file" 6 | 7 | command: hello: { 8 | var: file: *"out.txt" | string @tag(file) 9 | 10 | ask: cli.Ask & { // HL 11 | prompt: "What is your name?" 12 | response: string 13 | } 14 | echo: exec.Run & { // HL 15 | cmd: ["echo", "Hello", ask.response + "!"] 16 | stdout: string // capture stdout 17 | } 18 | append: file.Append & { // HL 19 | filename: var.file 20 | contents: echo.stdout 21 | } 22 | print: cli.Print & { // HL 23 | text: echo.stdout 24 | } 25 | } -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/cmd-03/Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | cue cmd hello 3 | 4 | clean: 5 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/cmd-03/hello_tool.cue: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "tool/exec" 4 | 5 | command: hello: { 6 | task:c: exec.Run & { 7 | $after: [task.a,task.b] 8 | cmd: "echo done" 9 | } 10 | 11 | task:a: exec.Run & { 12 | cmd: ["go", "version"] 13 | z: task.b.z 14 | } 15 | task:b: exec.Run & { 16 | cmd: "go env GOROOT" 17 | z: int 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/install-01/help.txt: -------------------------------------------------------------------------------- 1 | $ cue 2 | cue evaluates CUE files, an extension of JSON, and sends them 3 | to user-defined commands for processing. 4 | 5 | Usage: 6 | cue [command] 7 | 8 | Available Commands: 9 | cmd run a user-defined shell command 10 | completion Generate completion script 11 | def print consolidated definitions 12 | eval evaluate and print a configuration 13 | ... 14 | 15 | Use "cue [command] --help" for more information about a command. 16 | $ cue version 17 | cue version (devel) darwin/amd64 18 | $ 19 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/install-01/install.txt: -------------------------------------------------------------------------------- 1 | $ go get -u cuelang.org/go/cmd/cue 2 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/json-01/Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | cue eval hello.cue 3 | 4 | clean: 5 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/json-01/hello.cue: -------------------------------------------------------------------------------- 1 | { 2 | "name": "CUE", 3 | "url": "https://cuelang.org" 4 | } 5 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/json-01/hello.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "CUE", 3 | "url": "https://cuelang.org" 4 | } 5 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/json-02/Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | cue export hello.cue 3 | 4 | clean: 5 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/json-02/cmd.txt: -------------------------------------------------------------------------------- 1 | $ cue export hello.cue 2 | { 3 | "name": "CUE", 4 | "desc": "Configure Unify Execute\nhttps://cuelang.org" 5 | } -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/json-02/hello.cue: -------------------------------------------------------------------------------- 1 | { 2 | name: "CUE", // 这是行注释 // HL 3 | desc: """ 4 | Configure Unify Execute 5 | https://cuelang.org 6 | """, // 多行字符串 // HL 7 | } 8 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/json-03/Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | cue export hello.cue 3 | 4 | clean: 5 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/json-03/hello1.cue: -------------------------------------------------------------------------------- 1 | { 2 | name: "CUE", // 这是行注释 // HL 3 | desc: """ 4 | Configure Unify Execute 5 | https://cuelang.org 6 | """, // 多行字符串 // HL 7 | } 8 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/json-03/hello2.cue: -------------------------------------------------------------------------------- 1 | name: "CUE" // 省略花括弧和逗号 // HL 2 | 3 | desc: """ 4 | Configure Unify Execute 5 | https://cuelang.org 6 | """ 7 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/json-04/Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | cue export hello.cue 3 | 4 | clean: 5 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/json-04/hello.check.cue: -------------------------------------------------------------------------------- 1 | name: string 2 | age: int & >1 3 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/json-04/hello.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"CUE", 3 | "age": 2 4 | } -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/pkg/01-import/main.cue: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/talks/chai2010-cue-intro-talk/code/pkg/01-import/main.cue -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/play/Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | cue cmd hello 3 | 4 | clean: 5 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/play/hello_tool.cue: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "tool/exec" 4 | 5 | command: hello: { 6 | task:a: exec.Run & { 7 | cmd: ["go", "version"] 8 | z: task.c.z 9 | } 10 | task:b: exec.Run & { 11 | cmd: "go env GOROOT" 12 | z: task.a.z 13 | } 14 | task:c: exec.Run & { 15 | cmd: "go env GOPATH" 16 | z: int 17 | } 18 | task:d: exec.Run & { 19 | cmd: "echo done" 20 | $after: [task.a,task.b,task.c] 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/prime-01/Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | cue eval hello.cue 3 | 4 | clean: 5 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/prime-01/cmd.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/talks/chai2010-cue-intro-talk/code/prime-01/cmd.txt -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/prime-01/hello.cue: -------------------------------------------------------------------------------- 1 | a: 10*[0] // 定义数组 // HL 2 | b: [for i, _ in a { i+1 }] // for迭代数组的下标 // HL 3 | c: [for x in b if x mod 2 == 0 { x }] 4 | 5 | // 合并 6 | x: [ 7 | for x in [for i, _ in 10*[0] { i+1 }] if x mod 2 == 0 { x } 8 | 9 | ] 10 | 11 | // 尝试生成阶乘和素数 12 | // 生成 fib 数列 13 | // 挖掘 for 和 if 的表达力 14 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/tmpl-01/Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | cue eval hello.cue 3 | 4 | clean: 5 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/tmpl-01/cmd.txt: -------------------------------------------------------------------------------- 1 | $ cue eval hello.cue 2 | a: { 3 | b: { 4 | name: "cue:b" 5 | age: 111 6 | } 7 | c: { 8 | name: "cue:c" 9 | age: 222 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/tmpl-01/hello.cue: -------------------------------------------------------------------------------- 1 | a: [_x=_]: { // HL 2 | name: "cue:\(_x)" 3 | age: int 4 | } 5 | 6 | a: b: age: 111 7 | a: c: age: 222 8 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/tmpl-02/Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | cue eval hello.cue 3 | 4 | clean: 5 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/tmpl-02/cmd.txt: -------------------------------------------------------------------------------- 1 | $ cue eval hello.cue 2 | a: { 3 | xx0: { 4 | yy0: { 5 | name: "cue:xx0:yy0" 6 | age: 111 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/tmpl-02/hello.cue: -------------------------------------------------------------------------------- 1 | 2 | a: [_x=string]: [_y=string]: { // HL 3 | name: "cue:\(_x):\(_y)" 4 | age: int 5 | } 6 | 7 | a: xx0: yy0: age: 111 8 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/tmpl-03/Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | cue eval hello.cue 3 | 4 | clean: 5 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/tmpl-03/cmd.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/talks/chai2010-cue-intro-talk/code/tmpl-03/cmd.txt -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/tmpl-03/hello.cue: -------------------------------------------------------------------------------- 1 | 2 | acmeMonitoring: { 3 | name: string 4 | age: int 5 | } 6 | 7 | jobs: [a=string]: acmeMonitoring & { 8 | name: a 9 | } 10 | 11 | jobs: { 12 | foo: { } 13 | bar: { } 14 | baz: { } 15 | } 16 | 17 | // 遍历字段的名字 18 | for k, _ in jobs { 19 | jobs: "\(k)": age: 1 20 | } -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/type-01/Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | cue eval hello.cue 3 | 4 | clean: 5 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/type-01/hello.cue: -------------------------------------------------------------------------------- 1 | a: <=3 2 | a: >0 3 | a: 1 | 2 | 3 4 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/var-00/Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | cue export hello.cue 3 | 4 | clean: 5 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/var-00/cmd.txt: -------------------------------------------------------------------------------- 1 | $ cue export hello.cue 2 | cue export hello.cue 3 | { 4 | "a": { 5 | "b": { 6 | "c": "foo" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/var-00/hello.cue: -------------------------------------------------------------------------------- 1 | a: b: c: "foo" -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/var-01/Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | cue eval hello.cue 3 | 4 | clean: 5 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/var-01/hello.cue: -------------------------------------------------------------------------------- 1 | let _name1 = "cue1" // HL 2 | 3 | _name2: "cue2" // HL 4 | _name2: string // HL 5 | 6 | config: { 7 | name1: _name1 + ":aaa" 8 | name2: _name2 + ":bbb" 9 | } 10 | 11 | x: config.name1 // 嵌套路径的访问 // HL 12 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/var-02/Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | cue eval hello.cue 3 | 4 | clean: 5 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/var-02/cmd.txt: -------------------------------------------------------------------------------- 1 | $ cue export hello.cue 2 | { 3 | "arg1": 1, 4 | "arg2": "my string", 5 | "arg3": "arg3", 6 | "a": 1, 7 | "b": "abc:arg3" 8 | } 9 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/var-02/hello.cue: -------------------------------------------------------------------------------- 1 | 2 | arg1: 1 3 | arg2: "abc" 4 | arg3: string 5 | _arg4: "hidden" // 输出时隐藏 // HL 6 | 7 | { 8 | a: arg1 // 引用上下文的字段 9 | b: "\(arg2):" + "arg3" 10 | arg3: "arg3" // string + "arg3" => "arg3" // HL 11 | } 12 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/var-03/Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | cue eval hello.cue 3 | 4 | clean: 5 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/var-03/cmd.txt: -------------------------------------------------------------------------------- 1 | $ cue eval hello.cue 2 | a: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 3 | b: [10, 20, 30, 40, 50, 60, 70, 80, 90, 100] 4 | c: [2, 4, 6, 8, 10] 5 | d: "1~5" 6 | e: 10 -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/var-03/hello.cue: -------------------------------------------------------------------------------- 1 | a: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 2 | 3 | b: [ for x in a {x * 10}] // HL 4 | c: [ for x in a if x mod 2 == 0 {x}] // HL 5 | 6 | if len(b) > 5 {d: "1~5"} // HL 7 | e: len(b) 8 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/var-04/Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | cue eval hello.cue 3 | 4 | clean: 5 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/var-04/cmd.txt: -------------------------------------------------------------------------------- 1 | $ cue eval hello.cue 2 | a: [0, 0, 0] 3 | b: [1, 2, 3] 4 | c: { 5 | "1": 1 6 | "2": 2 7 | "3": 3 8 | } -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/var-04/hello.cue: -------------------------------------------------------------------------------- 1 | a: 3*[0] // 定义数组 [3]int{...} // HL 2 | b: [for i, _ in a { i+1 }] // for迭代数组的下标 // HL 3 | c: { 4 | for i, _ in 3*[0] { "\(i+1)": i+1 } // HL 5 | } 6 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/code/zz_dev/cue.mod/module.cue: -------------------------------------------------------------------------------- 1 | module: "hello.cn/abc" 2 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/cue-intro.slide: -------------------------------------------------------------------------------- 1 | # CUE语言简介 2 | 3 | CUE语言简介 4 | Tags: cue, k8s 5 | 6 | chai2010 7 | chaishushan@gmail.com 8 | https://github.com/chai2010/awesome-cue-zh 9 | 10 | # ----------------------------------------------------------------------------- 11 | * 认识CUE语言 12 | # ----------------------------------------------------------------------------- 13 | 14 | * CUE语言是什么? 15 | 16 | - CUE 是 JSON++ 17 | - CUE 是 CUE Configure Unify Execute 的缩写 18 | - 用于给类似JSON结构的数据增加类型和数据验证功能, 简化和复用 19 | - 提供了和 Go/JSON/YAML/Protobuf 集成的支持 20 | - CUE 命令行工具 21 | 22 | .image ./images/cue-logo.svg 280 _ 23 | 24 | * CUE官网: https://cuelang.org 25 | 26 | .image ./images/cuelang-01.png 480 _ 27 | 28 | .caption [[https://cuelang.org][https://cuelang.org]] 29 | 30 | 31 | * CUE项目Star趋势 32 | 33 | .image ./images/cue-star.png 450 _ 34 | 35 | .caption [[https://starcharts.herokuapp.com/cuelang/cue.svg][https://starcharts.herokuapp.com/cuelang/cue.svg]] 36 | 37 | 38 | * CUE作者 - Marcel van Lohuizen(马塞尔·范·罗威岑) 39 | 40 | .image ./images/mpvl-01.png 550 _ 41 | 42 | * CUE作者 - Marcel van Lohuizen(马塞尔·范·罗威岑) 43 | 44 | - *GopherChina2018讲师-Go2中的错误处理* 45 | - 在Go语言官方博客有3篇Go语言相关的技术博文 46 | - *Borg(以及它的前身)和搜索引擎* 47 | - 2011年初加入了Go团队 48 | - *2018年底开始CUE项目* 49 | - 瑞士·苏黎世 50 | 51 | .image ./images/cue-logo.svg 280 _ 52 | 53 | 54 | * 安装CUE语言环境 55 | 56 | .code ./code/install-01/install.txt 57 | 58 | .code ./code/install-01/help.txt 59 | 60 | - VSCode 语法高亮插件 61 | 62 | # ----------------------------------------------------------------------------- 63 | * 快速入门 64 | # ----------------------------------------------------------------------------- 65 | 66 | * CUE 是 JSON++ 67 | 68 | 新建 hello.json 文件: 69 | 70 | .code ./code/json-01/hello.json 71 | 72 | 重新保存为 hello.cue 文件: 73 | 74 | .code ./code/json-01/hello.cue 75 | 76 | 77 | 78 | - 类似 C++和C语言的关系, CUE 也是 JSON 的超集 79 | - 因此可以先把CUE当作JSON使用, 快速上手 80 | 81 | 82 | * CUE 增强了那些JSON特性 83 | 84 | .code ./code/json-02/hello.cue 85 | 86 | .code ./code/json-02/cmd.txt 87 | 88 | 89 | 90 | - 对象的键名可以是标识符, 不用加引号 91 | - 对象和数组可以以一个逗号结尾 92 | - 增加了多行字符串支持 93 | - 增加了注释支持 94 | 95 | * 先做加法到 JSON++, 再做减法到一个新语言 96 | 97 | .code ./code/json-03/hello1.cue 98 | 99 | .code ./code/json-03/hello2.cue 100 | 101 | 102 | 103 | - 省略JSON最外层花括弧, 省略末尾的逗号 104 | - 量变到质变, CUE 现在是一个新语言了 105 | - 不支持多行注释 106 | 107 | * JSON的非侵入验证 108 | 109 | hello.json 110 | 111 | .code ./code/json-04/hello.json 112 | 113 | hello.check.cue 114 | 115 | .code ./code/json-04/hello.check.cue 116 | 117 | 118 | 119 | - cue vet hello.json hello.check.cue 120 | - 验证 name 是字符串类型 121 | - 验证 age 类型和值范围 122 | 123 | # ----------------------------------------------------------------------------- 124 | * CUE新手上路 125 | # ----------------------------------------------------------------------------- 126 | 127 | * 嵌套路径简化 128 | 129 | .code ./code/var-00/hello.cue 130 | 131 | .code ./code/var-00/cmd.txt 132 | 133 | 134 | 135 | - a:b:c 定义c成员 136 | - a.b.c 访问c成员 137 | 138 | * 常量和表达式 139 | 140 | .code ./code/var-01/hello.cue 141 | 142 | 143 | 144 | - let可以定义临时常量 145 | - _xxx字段不能修改, 也不会输出, 类似 let 效果 146 | - _xxx作为字段可以添加集合约束, 比如加类型 147 | 148 | * 引用上下文其他字段 149 | 150 | .code ./code/var-02/hello.cue 151 | .code ./code/var-02/cmd.txt 152 | 153 | 154 | 155 | - arg3 是一种集合交集的关系 156 | 157 | * for和if 158 | 159 | .code ./code/var-03/hello.cue 160 | .code ./code/var-03/cmd.txt 161 | 162 | 163 | 164 | - for和if可以生成多个常量值, **但是故意设计得极其难用** 165 | - 但是因为没有变量, 使得for的使用受到严格限制 166 | - if目前还没有else 167 | 168 | * for配合数组 169 | 170 | .code ./code/var-04/hello.cue 171 | .code ./code/var-04/cmd.txt 172 | 173 | 174 | 175 | - 3*[0] 生成一个指定长度的数组 176 | - 可否生成一个素数表/阶乘表? 177 | 178 | * 模板变量 179 | 180 | 181 | .code ./code/tmpl-01/hello.cue 182 | .code ./code/tmpl-01/cmd.txt 183 | 184 | 185 | 186 | - [_x=_] 定义一个模板变量(要避免和成员变量冲突)(_是什么含义?) 187 | 188 | * 模板变量的类型 189 | 190 | .code ./code/tmpl-02/hello.cue 191 | .code ./code/tmpl-02/cmd.txt 192 | 193 | 194 | 195 | - a: b: c: 冒号是定义新的字段, 因此不是变量, 而是字符串类型常量 196 | - 字段路径中可以有多个参数 197 | 198 | * 模板和for 199 | 200 | .code ./code/tmpl-03/hello.cue 201 | 202 | 203 | 204 | - 模板和for工作在2个纬度: 模板参数类似目录路径, for则是目录下的文件名列表 205 | 206 | * Builtin 函数 207 | 208 | .code ./code/builtin-01/hello.cue 209 | 210 | 211 | 212 | - and([]) 和 or([]) 的结果有什么区别, 如何参与运算? 213 | 214 | 215 | # ----------------------------------------------------------------------------- 216 | * 脚本命令 217 | # ----------------------------------------------------------------------------- 218 | 219 | * 脚本命令 - 打印字符串 220 | 221 | hello_tool.cue: 222 | 223 | .code ./code/cmd-00/hello_tool.cue 224 | 225 | 226 | 227 | - hello_tool.cue 中的 hello 表示命令 228 | - command: hello: 中的 hello 表示命令, 和文件名保持一致 229 | - cli.Print 打印的参数是 text 内容 230 | - cue cmd hello 231 | 232 | * 脚本命令 - 执行Shell命令 233 | 234 | .code ./code/cmd-01/hello_tool.cue 235 | 236 | 237 | 238 | - tool/exec.Run 可以执行Shell命令 239 | - @tag(who,type=string)可以通过命令行传人参数 240 | - cue cmd --inject who=cuelang hello 241 | 242 | * 脚本命令 - 顺序执行多个命令 243 | 244 | .code ./code/cmd-02/hello_tool.cue /^command/, 245 | 246 | 247 | 248 | - 定义多个子命令, 串联执行 249 | 250 | * 脚本命令 - 补充说明 251 | 252 | .code ./code/cmd-03/hello_tool.cue /^command/, 253 | 254 | 255 | 256 | - 可以通过 $after 定义依赖顺序 257 | - 通过命令的输出依赖关系解析执行的顺序, 而不是定义的先后顺序 258 | - 比 Makefile 之类工具的优势, 将命令的结果结合 encoding 双向转化和赋值 259 | 260 | # ----------------------------------------------------------------------------- 261 | * 参考资料 262 | # ----------------------------------------------------------------------------- 263 | 264 | * 参考资料 265 | 266 | - 官网: [[https://cuelang.org][https://cuelang.org]] 267 | - 最新: [[https://tip.cuelang.org][https://tip.cuelang.org]] 268 | - 代码: [[https://github.com/cuelang/cue][https://github.com/cuelang/cue]] 269 | 270 | # ----------------------------------------------------------------------------- 271 | # END 272 | # ----------------------------------------------------------------------------- 273 | 274 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/images/cue-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Produced by OmniGraffle 7.10.1 6 | 2019-08-10 23:02:54 +0000 7 | 8 | 9 | Canvas 1 10 | 11 | Layer 1 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/images/cue-star.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/talks/chai2010-cue-intro-talk/images/cue-star.png -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/images/cuelang-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/talks/chai2010-cue-intro-talk/images/cuelang-01.png -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/images/mpvl-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/talks/chai2010-cue-intro-talk/images/mpvl-01.png -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/present/static/article.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: Helvetica, Arial, sans-serif; 4 | font-size: 16px; 5 | } 6 | pre, 7 | code { 8 | font-family: Menlo, monospace; 9 | font-size: 14px; 10 | } 11 | pre { 12 | line-height: 18px; 13 | margin: 0; 14 | padding: 0; 15 | } 16 | a { 17 | color: #375eab; 18 | text-decoration: none; 19 | } 20 | a:hover { 21 | text-decoration: underline; 22 | } 23 | p, 24 | ul, 25 | ol { 26 | margin: 20px; 27 | } 28 | 29 | h1, 30 | h2, 31 | h3, 32 | h4 { 33 | margin: 20px 0; 34 | padding: 0; 35 | color: #375eab; 36 | font-weight: bold; 37 | } 38 | h1 { 39 | font-size: 18px; 40 | padding: 2px 5px; 41 | } 42 | h2 { 43 | font-size: 16px; 44 | } 45 | h3 { 46 | font-size: 16px; 47 | } 48 | h3, 49 | h4 { 50 | margin: 20px 5px; 51 | } 52 | h4 { 53 | font-size: 16px; 54 | } 55 | 56 | div#heading { 57 | margin: 0 0 10px 0; 58 | padding: 21px 0; 59 | font-size: 20px; 60 | font-weight: bold; 61 | } 62 | 63 | div#heading .author { 64 | padding-top: 10px; 65 | font-size: 14px; 66 | font-weight: normal; 67 | } 68 | 69 | div#topbar { 70 | } 71 | 72 | body { 73 | text-align: center; 74 | } 75 | div#page { 76 | width: 100%; 77 | } 78 | div#page > .container, 79 | div#topbar > .container { 80 | text-align: left; 81 | margin-left: auto; 82 | margin-right: auto; 83 | padding: 0 20px; 84 | width: 900px; 85 | } 86 | div#page.wide > .container, 87 | div#topbar.wide > .container { 88 | width: auto; 89 | } 90 | 91 | div#footer { 92 | text-align: center; 93 | color: #666; 94 | font-size: 14px; 95 | margin: 40px 0; 96 | } 97 | 98 | .author p { 99 | margin: 0; 100 | padding: 0 20px; 101 | } 102 | 103 | div.code, 104 | div.output { 105 | margin: 20px 20px 20px 40px; 106 | -webkit-border-radius: 5px; 107 | -moz-border-radius: 5px; 108 | border-radius: 5px; 109 | } 110 | 111 | div.output { 112 | padding: 10px; 113 | } 114 | 115 | div.code { 116 | background: white; 117 | } 118 | div.output { 119 | background: black; 120 | } 121 | div.output .stdout { 122 | color: #e6e6e6; 123 | } 124 | div.output .stderr { 125 | color: rgb(244, 74, 63); 126 | } 127 | div.output .system { 128 | color: rgb(255, 209, 77); 129 | } 130 | 131 | .buttons { 132 | margin-left: 20px; 133 | } 134 | div.output .buttons { 135 | margin-left: 0; 136 | margin-bottom: 10px; 137 | } 138 | 139 | #toc { 140 | float: right; 141 | margin: 0px 10px; 142 | padding: 10px; 143 | border: 1px solid #e5ecf9; 144 | background-color: #eee; 145 | box-shadow: 3px 3px 2px #888888; 146 | 147 | max-width: 33%; 148 | 149 | -webkit-border-radius: 5px; 150 | -moz-border-radius: 5px; 151 | border-radius: 5px; 152 | } 153 | 154 | #tochead { 155 | font-weight: bold; 156 | font-variant: small-caps; 157 | font-size: 100%; 158 | text-align: center; 159 | padding-bottom: 5px; 160 | } 161 | 162 | #toc ul, 163 | #toc a { 164 | list-style-type: none; 165 | padding-left: 0px; 166 | color: black; 167 | margin: 0px; 168 | } 169 | 170 | ul.toc-inner a { 171 | padding-left: 10px !important; 172 | } 173 | 174 | @media print { 175 | .no-print, 176 | .no-print * { 177 | display: none !important; 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/present/static/dir.css: -------------------------------------------------------------------------------- 1 | /* copied from $GOROOT/doc/style.css */ 2 | 3 | body { 4 | margin: 0; 5 | font-family: Helvetica, Arial, sans-serif; 6 | font-size: 16px; 7 | } 8 | pre, 9 | code { 10 | font-family: Menlo, monospace; 11 | font-size: 14px; 12 | } 13 | pre { 14 | line-height: 18px; 15 | } 16 | pre .comment { 17 | color: #375eab; 18 | } 19 | pre .highlight, 20 | pre .highlight-comment, 21 | pre .selection-highlight, 22 | pre .selection-highlight-comment { 23 | background: #ffff00; 24 | } 25 | pre .selection, 26 | pre .selection-comment { 27 | background: #ff9632; 28 | } 29 | pre .ln { 30 | color: #999; 31 | } 32 | body { 33 | color: #222; 34 | } 35 | a, 36 | .exampleHeading .text { 37 | color: #375eab; 38 | text-decoration: none; 39 | } 40 | a:hover, 41 | .exampleHeading .text:hover { 42 | text-decoration: underline; 43 | } 44 | p, 45 | pre, 46 | ul, 47 | ol { 48 | margin: 20px; 49 | } 50 | pre { 51 | background: #e9e9e9; 52 | padding: 10px; 53 | 54 | -webkit-border-radius: 5px; 55 | -moz-border-radius: 5px; 56 | border-radius: 5px; 57 | } 58 | 59 | h1, 60 | h2, 61 | h3, 62 | h4, 63 | .rootHeading { 64 | margin: 20px 0; 65 | padding: 0; 66 | color: #375eab; 67 | font-weight: bold; 68 | } 69 | h1 { 70 | font-size: 24px; 71 | } 72 | h2 { 73 | font-size: 20px; 74 | background: #e0ebf5; 75 | padding: 2px 5px; 76 | } 77 | h3 { 78 | font-size: 20px; 79 | } 80 | h3, 81 | h4 { 82 | margin: 20px 5px; 83 | } 84 | h4 { 85 | font-size: 16px; 86 | } 87 | 88 | dl { 89 | margin: 20px; 90 | } 91 | dd { 92 | margin: 2px 20px; 93 | } 94 | dl, 95 | dd { 96 | font-size: 14px; 97 | } 98 | div#nav table td { 99 | vertical-align: top; 100 | } 101 | 102 | div#heading { 103 | float: left; 104 | margin: 0 0 10px 0; 105 | padding: 21px 0; 106 | font-size: 20px; 107 | font-weight: normal; 108 | } 109 | div#heading a { 110 | color: #222; 111 | text-decoration: none; 112 | } 113 | 114 | div#topbar { 115 | background: #e0ebf5; 116 | height: 64px; 117 | } 118 | 119 | body { 120 | text-align: center; 121 | } 122 | div#page, 123 | div#topbar > .container { 124 | clear: both; 125 | text-align: left; 126 | margin-left: auto; 127 | margin-right: auto; 128 | padding: 0 20px; 129 | width: 900px; 130 | } 131 | div#page.wide, 132 | div#topbar > .wide { 133 | width: auto; 134 | } 135 | div#plusone { 136 | float: right; 137 | } 138 | 139 | div#footer { 140 | color: #666; 141 | font-size: 14px; 142 | margin: 40px 0; 143 | } 144 | 145 | div#menu > a, 146 | div#menu > input { 147 | padding: 10px; 148 | 149 | text-decoration: none; 150 | font-size: 16px; 151 | 152 | -webkit-border-radius: 5px; 153 | -moz-border-radius: 5px; 154 | border-radius: 5px; 155 | } 156 | div#menu > a, 157 | div#menu > input { 158 | border: 1px solid #375eab; 159 | } 160 | div#menu > a { 161 | color: white; 162 | background: #375eab; 163 | } 164 | 165 | div#menu { 166 | float: right; 167 | min-width: 590px; 168 | padding: 10px 0; 169 | text-align: right; 170 | } 171 | div#menu > a { 172 | margin-right: 5px; 173 | margin-bottom: 10px; 174 | 175 | padding: 10px; 176 | } 177 | div#menu > input { 178 | position: relative; 179 | top: 1px; 180 | width: 60px; 181 | background: white; 182 | color: #222; 183 | } 184 | div#menu > input.inactive { 185 | color: #999; 186 | } 187 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/present/static/dir.js: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // copied from $GOROOT/doc/godocs.js 6 | 7 | function bindEvent(el, e, fn) { 8 | if (el.addEventListener) { 9 | el.addEventListener(e, fn, false); 10 | } else if (el.attachEvent) { 11 | el.attachEvent('on' + e, fn); 12 | } 13 | } 14 | 15 | function godocs_bindSearchEvents() { 16 | var search = document.getElementById('search'); 17 | if (!search) { 18 | // no search box (index disabled) 19 | return; 20 | } 21 | function clearInactive() { 22 | if (search.className == 'inactive') { 23 | search.value = ''; 24 | search.className = ''; 25 | } 26 | } 27 | function restoreInactive() { 28 | if (search.value !== '') { 29 | return; 30 | } 31 | if (search.type != 'search') { 32 | search.value = search.getAttribute('placeholder'); 33 | } 34 | search.className = 'inactive'; 35 | } 36 | restoreInactive(); 37 | bindEvent(search, 'focus', clearInactive); 38 | bindEvent(search, 'blur', restoreInactive); 39 | } 40 | 41 | bindEvent(window, 'load', godocs_bindSearchEvents); 42 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/present/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/talks/chai2010-cue-intro-talk/present/static/favicon.ico -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/present/static/notes.css: -------------------------------------------------------------------------------- 1 | p { 2 | margin: 10px; 3 | } 4 | 5 | #presenter-slides { 6 | display: block; 7 | margin-top: -10px; 8 | margin-left: -17px; 9 | position: fixed; 10 | border: 0; 11 | width: 146%; 12 | height: 750px; 13 | 14 | transform: scale(0.7, 0.7); 15 | transform-origin: top left; 16 | -moz-transform: scale(0.7); 17 | -moz-transform-origin: top left; 18 | -o-transform: scale(0.7); 19 | -o-transform-origin: top left; 20 | -webkit-transform: scale(0.7); 21 | -webkit-transform-origin: top left; 22 | } 23 | 24 | #presenter-notes { 25 | margin-top: -180px; 26 | font-family: 'Open Sans', Arial, sans-serif; 27 | height: 30%; 28 | width: 100%; 29 | overflow: scroll; 30 | position: fixed; 31 | top: 706px; 32 | } 33 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/present/static/notes.js: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Store child window object which will display slides with notes 6 | var notesWindow = null; 7 | 8 | var isParentWindow = window.parent == window; 9 | 10 | // When parent window closes, clear storage and close child window 11 | if (isParentWindow) { 12 | window.onbeforeunload = function() { 13 | localStorage.clear(); 14 | if (notesWindow) notesWindow.close(); 15 | }; 16 | } 17 | 18 | function toggleNotesWindow() { 19 | if (!isParentWindow) return; 20 | if (notesWindow) { 21 | notesWindow.close(); 22 | notesWindow = null; 23 | return; 24 | } 25 | 26 | initNotes(); 27 | } 28 | 29 | // Create an unique key for the local storage so we don't mix the 30 | // destSlide of different presentations. For golang.org/issue/24688. 31 | function destSlideKey() { 32 | var key = ''; 33 | if (notesWindow) { 34 | var slides = notesWindow.document.getElementById('presenter-slides'); 35 | key = slides.src.split('#')[0]; 36 | } else { 37 | key = window.location.href.split('#')[0]; 38 | } 39 | return 'destSlide:' + key; 40 | } 41 | 42 | function initNotes() { 43 | notesWindow = window.open('', '', 'width=1000,height=700'); 44 | var w = notesWindow; 45 | var slidesUrl = window.location.href; 46 | 47 | // Hack to apply css. Requires existing html on notesWindow. 48 | w.document.write("
"); 49 | 50 | w.document.title = window.document.title; 51 | 52 | var slides = w.document.createElement('iframe'); 53 | slides.id = 'presenter-slides'; 54 | slides.src = slidesUrl; 55 | w.document.body.appendChild(slides); 56 | 57 | var curSlide = parseInt(localStorage.getItem(destSlideKey()), 10); 58 | var formattedNotes = ''; 59 | var section = sections[curSlide - 1]; 60 | // curSlide is 0 when initialized from the first page of slides. 61 | // Check if section is valid before retrieving Notes. 62 | if (section) { 63 | formattedNotes = formatNotes(section.Notes); 64 | } else if (curSlide == 0) { 65 | formattedNotes = formatNotes(titleNotes); 66 | } 67 | 68 | // setTimeout needed for Firefox 69 | setTimeout(function() { 70 | slides.focus(); 71 | }, 100); 72 | 73 | var notes = w.document.createElement('div'); 74 | notes.id = 'presenter-notes'; 75 | notes.innerHTML = formattedNotes; 76 | w.document.body.appendChild(notes); 77 | 78 | w.document.close(); 79 | 80 | function addPresenterNotesStyle() { 81 | var el = w.document.createElement('link'); 82 | el.rel = 'stylesheet'; 83 | el.type = 'text/css'; 84 | el.href = PERMANENT_URL_PREFIX + 'notes.css'; 85 | w.document.body.appendChild(el); 86 | w.document.querySelector('head').appendChild(el); 87 | } 88 | 89 | addPresenterNotesStyle(); 90 | 91 | // Add listener on notesWindow to update notes when triggered from 92 | // parent window 93 | w.addEventListener('storage', updateNotes, false); 94 | } 95 | 96 | function formatNotes(notes) { 97 | var formattedNotes = ''; 98 | if (notes) { 99 | for (var i = 0; i < notes.length; i++) { 100 | formattedNotes = formattedNotes + '

' + notes[i] + '

'; 101 | } 102 | } 103 | return formattedNotes; 104 | } 105 | 106 | function updateNotes() { 107 | // When triggered from parent window, notesWindow is null 108 | // The storage event listener on notesWindow will update notes 109 | if (!notesWindow) return; 110 | var destSlide = parseInt(localStorage.getItem(destSlideKey()), 10); 111 | var section = sections[destSlide - 1]; 112 | var el = notesWindow.document.getElementById('presenter-notes'); 113 | 114 | if (!el) return; 115 | 116 | if (section && section.Notes) { 117 | el.innerHTML = formatNotes(section.Notes); 118 | } else if (destSlide == 0) { 119 | el.innerHTML = formatNotes(titleNotes); 120 | } else { 121 | el.innerHTML = ''; 122 | } 123 | } 124 | 125 | /* Playground syncing */ 126 | 127 | // When presenter notes are enabled, playground click handlers are 128 | // stored here to sync click events on the correct playground 129 | var playgroundHandlers = { onRun: [], onKill: [], onClose: [] }; 130 | 131 | function updatePlay(e) { 132 | var i = localStorage.getItem('play-index'); 133 | 134 | switch (e.key) { 135 | case 'play-index': 136 | return; 137 | case 'play-action': 138 | // Sync 'run', 'kill', 'close' actions 139 | var action = localStorage.getItem('play-action'); 140 | playgroundHandlers[action][i](e); 141 | return; 142 | case 'play-code': 143 | // Sync code editing 144 | var play = document.querySelectorAll('div.playground')[i]; 145 | play.innerHTML = localStorage.getItem('play-code'); 146 | return; 147 | case 'output-style': 148 | // Sync resizing of playground output 149 | var out = document.querySelectorAll('.output')[i]; 150 | out.style = localStorage.getItem('output-style'); 151 | return; 152 | } 153 | } 154 | 155 | // Reset 'run', 'kill', 'close' storage items when synced 156 | // so that successive actions can be synced correctly 157 | function updatePlayStorage(action, index, e) { 158 | localStorage.setItem('play-index', index); 159 | 160 | if (localStorage.getItem('play-action') === action) { 161 | // We're the receiving window, and the message has been received 162 | localStorage.removeItem('play-action'); 163 | } else { 164 | // We're the triggering window, send the message 165 | localStorage.setItem('play-action', action); 166 | } 167 | 168 | if (action === 'onRun') { 169 | if (localStorage.getItem('play-shiftKey') === 'true') { 170 | localStorage.removeItem('play-shiftKey'); 171 | } else if (e.shiftKey) { 172 | localStorage.setItem('play-shiftKey', e.shiftKey); 173 | } 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/present/templates/action.tmpl: -------------------------------------------------------------------------------- 1 | {/* 2 | This is the action template. 3 | It determines how the formatting actions are rendered. 4 | */} 5 | 6 | {{define "section"}} 7 | {{.FormattedNumber}} {{.Title}} 8 | {{range .Elem}}{{elem $.Template .}}{{end}} 9 | {{end}} 10 | 11 | {{define "list"}} 12 |
    13 | {{range .Bullet}} 14 |
  • {{style .}}
  • 15 | {{end}} 16 |
17 | {{end}} 18 | 19 | {{define "text"}} 20 | {{if .Pre}} 21 |
{{range .Lines}}{{.}}{{end}}
22 | {{else}} 23 |

24 | {{range $i, $l := .Lines}}{{if $i}}{{template "newline"}} 25 | {{end}}{{style $l}}{{end}} 26 |

27 | {{end}} 28 | {{end}} 29 | 30 | {{define "code"}} 31 |
{{.Text}}
32 | {{end}} 33 | 34 | {{define "image"}} 35 |
36 | 37 |
38 | {{end}} 39 | 40 | {{define "video"}} 41 |
42 | 45 |
46 | {{end}} 47 | 48 | {{define "background"}} 49 |
50 | 51 |
52 | {{end}} 53 | 54 | {{define "iframe"}} 55 | 56 | {{end}} 57 | 58 | {{define "link"}}{{end}} 59 | 60 | {{define "html"}}{{.HTML}}{{end}} 61 | 62 | {{define "caption"}}
{{style .Text}}
{{end}} 63 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/present/templates/article.tmpl: -------------------------------------------------------------------------------- 1 | {/* This is the article template. It defines how articles are formatted. */} 2 | 3 | {{define "root"}} 4 | 5 | 6 | 7 | {{.Title}} 8 | 9 | 10 | 27 | 28 | 29 | 30 |
31 |
32 |
{{.Title}} 33 | {{with .Subtitle}}{{.}}{{end}} 34 | {{if .Authors}} 35 | {{range .Authors}} 36 |
37 | {{range .Elem}}{{elem $.Template .}}{{end}} 38 |
39 | {{end}} 40 | {{end}} 41 |
42 |
43 |
44 |
45 |
46 | {{with .Sections}} 47 |
48 |
Contents
49 | {{template "TOC" .}} 50 |
51 | {{end}} 52 | 53 | {{range .Sections}} 54 | {{elem $.Template .}} 55 | {{end}}{{/* of Section block */}} 56 | 57 |
58 |
59 | 60 | {{if .PlayEnabled}} 61 | 62 | {{end}} 63 | 64 | 74 | 75 | 76 | {{end}} 77 | 78 | {{define "TOC"}} 79 |
    80 | {{range .}} 81 |
  • {{.Title}}
  • 82 | {{with .Sections}}{{template "TOC-Inner" .}}{{end}} 83 | {{end}} 84 |
85 | {{end}} 86 | 87 | {{define "TOC-Inner"}} 88 |
    89 | {{range .}} 90 |
  • {{.Title}}
  • 91 | {{with .Sections}}{{template "TOC-Inner" .}}{{end}} 92 | {{end}} 93 |
94 | {{end}} 95 | 96 | {{define "newline"}} 97 | {{/* No automatic line break. Paragraphs are free-form. */}} 98 | {{end}} 99 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/present/templates/dir.tmpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Talks - The Go Programming Language 6 | 7 | 8 | 25 | 26 | 27 | 28 |
29 | 30 |
31 | 39 | 40 |
41 | 42 |
43 | 44 |
45 | 46 |

Go talks

47 | 48 | {{with .Path}}

{{.}}

{{end}} 49 | 50 | {{with .Articles}} 51 |

Articles:

52 |
53 | {{range .}} 54 |
{{.Name}}: {{.Title}}
55 | {{end}} 56 |
57 | {{end}} 58 | 59 | {{with .Slides}} 60 |

Slide decks:

61 |
62 | {{range .}} 63 |
{{.Name}}: {{.Title}}
64 | {{end}} 65 |
66 | {{end}} 67 | 68 | {{with .Other}} 69 |

Files:

70 |
71 | {{range .}} 72 |
{{.Name}}
73 | {{end}} 74 |
75 | {{end}} 76 | 77 | {{with .Dirs}} 78 |

Sub-directories:

79 |
80 | {{range .}} 81 |
{{.Name}}
82 | {{end}} 83 |
84 | {{end}} 85 | 86 |
87 | 88 | 96 | 97 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /talks/chai2010-cue-intro-talk/present/templates/slides.tmpl: -------------------------------------------------------------------------------- 1 | {/* This is the slide template. It defines how presentations are formatted. */} 2 | 3 | {{define "root"}} 4 | 5 | 6 | 7 | {{.Title}} 8 | 9 | 12 | 13 | 14 | {{if .NotesEnabled}} 15 | 19 | 20 | {{end}} 21 | 22 | 39 | 40 | 41 | 42 | 43 |
44 | 45 |
46 |

{{.Title}}

47 | {{with .Subtitle}}

{{.}}

{{end}} 48 | {{if not .Time.IsZero}}

{{.Time.Format "2 January 2006"}}

{{end}} 49 | {{range .Authors}} 50 |
51 | {{range .TextElem}}{{elem $.Template .}}{{end}} 52 |
53 | {{end}} 54 |
55 | 56 | {{range $i, $s := .Sections}} 57 | 58 |
59 | {{if $s.Elem}} 60 |

{{$s.Title}}

61 | {{range $s.Elem}}{{elem $.Template .}}{{end}} 62 | {{else}} 63 |

{{$s.Title}}

64 | {{end}} 65 | {{pagenum $s 1}} 66 |
67 | 68 | {{end}}{{/* of Slide block */}} 69 | 70 |
71 |

Thank you

72 | {{range .Authors}} 73 |
74 | {{range .Elem}}{{elem $.Template .}}{{end}} 75 |
76 | {{end}} 77 |
78 | 79 |
80 | 81 |
82 | Use the left and right arrow keys or click the left and right 83 | edges of the page to navigate between slides.
84 | (Press 'H' or navigate to hide this message.) 85 |
86 | 87 | {{if .PlayEnabled}} 88 | 89 | {{end}} 90 | 91 | 101 | 102 | 103 | {{end}} 104 | 105 | {{define "newline"}} 106 |
107 | {{end}} 108 | -------------------------------------------------------------------------------- /talks/k8sjp_29_002.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chai2010/awesome-cue-zh/317c3da3f917a0f627666bf65010d887c62fa6e6/talks/k8sjp_29_002.pdf --------------------------------------------------------------------------------