Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@
# vendor/
pyrotic
.vscode
# examples
.idea
# examples
8 changes: 0 additions & 8 deletions .idea/.gitignore

This file was deleted.

7 changes: 0 additions & 7 deletions .idea/golinter.xml

This file was deleted.

8 changes: 0 additions & 8 deletions .idea/modules.xml

This file was deleted.

7 changes: 1 addition & 6 deletions .idea/pyrotic.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

59 changes: 34 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# pyrotic
code generator inspired by https://www.hygen.io/ for golang.
code generator inspired by https://plopjs.com/ & https://github.com/jondot/hygen for golang.


## Motivation
Why not use hygen? great question! I would recommend [hygen](https://www.hygen.io/) over this, however [hygen](https://www.hygen.io/) is written in js.
Why not use hygen? great question! I would recommend [plop](https://plopjs.com/) over this, however [plop](https://plopjs.com/) is written in js.
This project is for people who want to use a code generator and not have to install node. Pyrotic also is specifically written to generate go code, all templates are parsed using go's builtin template parser and output is formatted using go's built in code formatter.


Expand Down Expand Up @@ -75,38 +75,47 @@ pyrotic -s foo/bar generate cmd --name setup

Formatter will pick up any of these variables within the `---` block and hydrate the metadata for the template. Any properties matching the signature will be added to the Meta property, for example `foo: bar` will be accessible by `{{ Meta.foo }}`. View more [examples](example/_templates).

| Property | Type | Default | Example |
| -------- | ---- | ------- | ------- |
| to: | string (path) | "" | src/lib/utils/readme.md |
| append: | bool | false | false |
| inject: | bool | false | false |
| before: | string | "" | type config struct |
| after: | string | "" | // commands |
| Property | Type | Default | Example |
|----------|---------------|---------|-------------------------|
| to: | string (path) | "" | src/lib/utils/readme.md |
| append: | bool | false | false |
| inject: | bool | false | false |
| before: | string | "" | type config struct |
| after: | string | "" | // commands |


### Variables within formater properties

Tool's two-stage parser hydrates the data within the `---` blocks before parsing the template.

| Property | Type | Default | Example |
|----------|---------------|---------|----------------------------------------------|
| to: | string (path) | "" | src/lib/{{ .Name }}/{{ Meta.readmeName }}.md |


### Using shared templates

In some instances you will want to reuse some templates across multiple generators. This can be done by having a `shared` directory within the `_templates` directory.
Any templates that are declared in the [shared](example/_templates/shared/config.tmpl) directory will be loading along with the generator. [Reference](example/_templates/fakr/shared_config.tmpl) the shared template within your generator directory in order to inject / append / create file.
Any templates that are declared in the [shared](example/_templates/shared/config.tmpl) directory will be loading along with the generator. [Reference](example/_templates/fakr/shared_config.tmpl) the shared template within your generator directory to inject / append / create file.


## Built in template functions

ships with some already built in template funcs, some [examples](example/_templates/fakr/farkr_case.tmpl)

| func name | description | code example | result |
| --------- | ----------- | ------------ | ------ |
| caseSnake | convert to snake case | {{ MetaData \| caseSnake }} | meta_data |
| caseKebab | convert to kebab case | {{ MetaData \| caseKebab }} | meta-data |
| casePascal | convert to pascal case | {{ meta_data \| casePascal }} | MetaData |
| caseLower | convert to lower case | {{ MetaData \| caseLower }} | metadata |
| caseTitle | convert to title case | {{ MetaData \| caseTitle }} | METADATA |
| caseCamel | convert to camel case | {{ MetaData \| caseCamel }} | metaData |
| splitByDelimiter | splits string by delimiter | {{ splitByDelimiter "long,list" "," }} | []string{"long" "list"} |
| splitAfterDelimiter | splits string after delimiter | {{ splitAfterDelimiter "a,long,list" "," }} | []string{"a," "long," "list"} |
| contains | checks if string contains substring | {{ contains "foobarbin" "bar" }} | true |
| hasPrefix | checks if string has the prefix | {{ contains "foobarbin" "foo" }} | true |
| hasSuffix | checks if string has the suffix | {{ contains "foobarbin" "bin" }} | true |
ships with some already built in template funcs, some [examples](example/_templates/fakr/fakr_case.tmpl)

| func name | description | code example | result |
|---------------------|-------------------------------------|---------------------------------------------|-------------------------------|
| caseSnake | convert to snake case | {{ MetaData \| caseSnake }} | meta_data |
| caseKebab | convert to kebab case | {{ MetaData \| caseKebab }} | meta-data |
| casePascal | convert to pascal case | {{ meta_data \| casePascal }} | MetaData |
| caseLower | convert to lower case | {{ MetaData \| caseLower }} | metadata |
| caseTitle | convert to title case | {{ MetaData \| caseTitle }} | METADATA |
| caseCamel | convert to camel case | {{ MetaData \| caseCamel }} | metaData |
| splitByDelimiter | splits string by delimiter | {{ splitByDelimiter "long,list" "," }} | []string{"long" "list"} |
| splitAfterDelimiter | splits string after delimiter | {{ splitAfterDelimiter "a,long,list" "," }} | []string{"a," "long," "list"} |
| contains | checks if string contains substring | {{ contains "foobarbin" "bar" }} | true |
| hasPrefix | checks if string has the prefix | {{ contains "foobarbin" "foo" }} | true |
| hasSuffix | checks if string has the suffix | {{ contains "foobarbin" "bin" }} | true |


we also provide some Inflections using [flect](https://github.com/gobuffalo/flect)
Expand Down
8 changes: 4 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
module github.com/code-gorilla-au/pyrotic

go 1.24.4
go 1.25.3

require (
github.com/code-gorilla-au/odize v1.3.4
github.com/gobuffalo/flect v1.0.3
github.com/mattn/go-isatty v0.0.20
github.com/spf13/cobra v1.10.1
golang.org/x/text v0.30.0
golang.org/x/text v0.31.0
)

require (
github.com/code-gorilla-au/env v1.1.1 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/joho/godotenv v1.5.1 // indirect
github.com/spf13/pflag v1.0.9 // indirect
github.com/spf13/pflag v1.0.10 // indirect
github.com/stretchr/testify v1.8.4 // indirect
golang.org/x/sys v0.32.0 // indirect
golang.org/x/sys v0.38.0 // indirect
)
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s=
github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0=
github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY=
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
Expand All @@ -32,8 +34,12 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
Expand Down
2 changes: 1 addition & 1 deletion internal/commands/cmd_generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ func generateCmd() *cobra.Command {
return &cobra.Command{
Use: "generate <generator-name> --name <file-name>",
Short: "Generate template",
Long: `Generate tempate by generator name. `,
Long: `Generate template by generator name. `,
Run: generateFunc(),
}
}
Expand Down
6 changes: 3 additions & 3 deletions internal/engine/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,19 @@ func (c *Core) Generate(data Data) error {
for _, item := range parsedOutput {
switch item.Action {
case parser.ActionAppend:
if err := c.fwr.AppendFile(item.To, item.Output); err != nil {
if err = c.fwr.AppendFile(item.To, item.Output); err != nil {
log.Println("error appending file ", err)
return err
}
case parser.ActionInject:
if err := c.fwr.InjectIntoFile(item.To, item.Output, writer.Inject{
if err = c.fwr.InjectIntoFile(item.To, item.Output, writer.Inject{
Matcher: item.InjectMatcher,
Clause: writer.InjectClause(item.InjectClause),
}); err != nil {
return err
}
default:
if err := c.fwr.WriteFile(item.To, item.Output, 0750); err != nil {
if err = c.fwr.WriteFile(item.To, item.Output, 0750); err != nil {
log.Println("error writing to file ", err)
return err
}
Expand Down
12 changes: 6 additions & 6 deletions internal/parser/lexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func parse(tmplName, tmpl string, data TemplateData, funcs template.FuncMap, sha
log.Println(chalk.Red("error parsing metadata"), err)
return hydratedData, err
}
output, err := generateTemplate(tmplName, string(stringOutput), hydratedData, funcs, sharedTmpl)
output, err := generateTemplate(tmplName, stringOutput, hydratedData, funcs, sharedTmpl)
if err != nil {
log.Println(chalk.Red("error generating template"), err)
return hydratedData, err
Expand All @@ -49,7 +49,7 @@ func parse(tmplName, tmpl string, data TemplateData, funcs template.FuncMap, sha
}

func generateParseData(tmplName string, meta []string, data TemplateData, funcs template.FuncMap) (TemplateData, error) {
parsedMeta := []string{}
var parsedMeta []string

for _, item := range meta {
var buf bytes.Buffer
Expand All @@ -59,11 +59,11 @@ func generateParseData(tmplName string, meta []string, data TemplateData, funcs
return data, err
}

if err := t.Execute(wr, data); err != nil {
if err = t.Execute(wr, data); err != nil {
return data, fmt.Errorf("%w \n %s", err, item)
}

if err := wr.Flush(); err != nil {
if err = wr.Flush(); err != nil {
return data, err
}

Expand All @@ -88,10 +88,10 @@ func generateTemplate(tmplName, tmplOutput string, data TemplateData, funcs temp

var buf bytes.Buffer
wr := bufio.NewWriter(&buf)
if err := tmpl.Execute(wr, data); err != nil {
if err = tmpl.Execute(wr, data); err != nil {
return nil, fmt.Errorf("%w \n %s", err, tmplOutput)
}
if err := wr.Flush(); err != nil {
if err = wr.Flush(); err != nil {
log.Printf(chalk.Red("error flushing writer: %s"), err)
return buf.Bytes(), err
}
Expand Down
10 changes: 5 additions & 5 deletions internal/parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func New(dirPath string, sharedPath string, fileSuffix string) (TemplateEngine,
}

func (te *TemplateEngine) Parse(data TemplateData) ([]TemplateData, error) {
result := []TemplateData{}
var result []TemplateData

for name, tmpl := range te.templates {

Expand Down Expand Up @@ -121,9 +121,9 @@ func withTemplates(dirPath string, fileSuffix string) (map[string]string, error)
}

func orderTemplateData(data []TemplateData) []TemplateData {
create := []TemplateData{}
inject := []TemplateData{}
app := []TemplateData{}
var create []TemplateData
var inject []TemplateData
var app []TemplateData

for _, tmp := range data {
switch tmp.Action {
Expand All @@ -135,7 +135,7 @@ func orderTemplateData(data []TemplateData) []TemplateData {
app = append(app, tmp)
}
}
result := []TemplateData{}
var result []TemplateData
result = append(result, create...)
result = append(result, inject...)
result = append(result, app...)
Expand Down
Loading