Combine code generation commands

This commit is contained in:
Brandon Dyck 2019-03-24 13:28:36 -06:00
parent 2e5426d211
commit 6664713f32
7 changed files with 196 additions and 206 deletions

View File

@ -2,8 +2,7 @@ package hatmill
import "io"
//go:generate go run ./internal/elementgen/main.go
//go:generate go run ./internal/attribgen/main.go
//go:generate go run ./internal/codegen/codegen.go
// Term represents a fragment of HTML markup, and is one of EmptyElement, ParentElement, or Text.
type Term interface {

View File

@ -1,11 +0,0 @@
# attribgen
attribgen reads simple descriptions of HTML element attributes from
`attribs.txt` and generates Go functions to create them. The file contains
one description per line. Each description is in the form
```
attribute-name attribute-type
```
where `attribute-name` is the lowercase name of the attribute, and
`attribute-type` is either `string` for normal attributes (e.g. `id`, 'style')
or `bool` for boolean attributes (e.g. `disabled`).

View File

@ -1,87 +0,0 @@
package main
import (
"bufio"
"bytes"
"fmt"
"go/format"
"io/ioutil"
"log"
"os"
"strings"
)
const (
inputPath = "attribs.txt"
outputPath = "attribs.go"
packageName = "hatmill"
boolType = "bool"
stringType = "string"
stringTemplate = `func %s(value string) Attrib {
return Attrib{
Key: "%s",
Value: value,
}
}
`
boolTemplate = `func %s() Attrib {
return Attrib{
Key: "%s",
}
}
`
)
func main() {
inputFile, err := os.Open(inputPath)
if err != nil {
log.Fatal(err)
}
defer inputFile.Close()
var output bytes.Buffer
fmt.Fprintln(&output, "// GENERATED BY gitlab.codemonkeysoftware.net/b/hatmill/internal/attribgen")
fmt.Fprintln(&output, "// DO NOT EDIT!\n")
fmt.Fprintln(&output, "package ", packageName, "\n")
scanner := bufio.NewScanner(inputFile)
for scanner.Scan() {
line := scanner.Text()
if line == "" {
continue
}
var attribName, attribType string
_, err = fmt.Sscanf(line, "%s %s", &attribName, &attribType)
if err != nil {
log.Fatalf("error parsing input line: %s", err)
}
var template string
switch attribType {
case boolType:
template = boolTemplate
case stringType:
template = stringTemplate
default:
log.Fatal("unknown attribute type: ", attribType)
}
fmt.Fprintf(&output, template, strings.Title(attribName), attribName)
}
if err := scanner.Err(); err != nil {
log.Fatalf("error scanning input: %s", err)
}
formatted, err := format.Source(output.Bytes())
if err != nil {
log.Fatalf("error formatting output: %s", err)
}
err = ioutil.WriteFile(outputPath, formatted, 0644)
if err != nil {
log.Fatalf("error writing output: %s", err)
}
}

View File

@ -0,0 +1,21 @@
# codegen
codegen reads simple descriptions of HTML elements and attributes from
`elements.txt` and `attribs.txt`, respectively, and generates Go functions to
create them.
The files contains one description per line. Each attribute description is in
the form
```
attribute-name attribute-type
```
where `attribute-name` is the lowercase name of the attribute, and
`attribute-type` is either `string` for normal attributes (e.g. `id`, 'style')
or `bool` for boolean attributes (e.g. `disabled`). Each element description is
in the form
```
tag-name element-type
```
where `tag-name` is the lowercase name of the element, and `element-type` is
either `empty` for empty elements (e.g. `img`, 'br') or `parent` for elements
that can have child nodes (e.g. 'div', 'body').

174
internal/codegen/codegen.go Normal file
View File

@ -0,0 +1,174 @@
package main
import (
"bufio"
"bytes"
"fmt"
"go/format"
"io/ioutil"
"log"
"os"
"strings"
)
const packageName = "hatmill"
func genElements() {
const (
elementInputPath = "elements.txt"
elementOutputPath = "elements.go"
parentType = "parent"
emptyType = "empty"
parentTemplate = `// %[1]s creates a <%[2]s> element.
func %[1]s(attribs ...Attrib) func(children ...Term) *ParentElement {
return func(children ...Term) *ParentElement {
return &ParentElement{
EmptyElement: EmptyElement{
TagName: "%[2]s",
Attribs: attribs,
},
Children: children,
}
}
}
`
emptyTemplate = `// %[1]s creates a <%[2]s> element.
func %[1]s(attribs ...Attrib) EmptyElement {
return EmptyElement{
TagName: "%[2]s",
Attribs: attribs,
}
}
`
)
inputFile, err := os.Open(elementInputPath)
if err != nil {
log.Fatal(err)
}
defer inputFile.Close()
var output bytes.Buffer
fmt.Fprintln(&output, "// GENERATED BY gitlab.codemonkeysoftware.net/b/hatmill/internal/elementgen")
fmt.Fprintln(&output, "// DO NOT EDIT!\n")
fmt.Fprintln(&output, "package ", packageName, "\n")
scanner := bufio.NewScanner(inputFile)
for scanner.Scan() {
line := scanner.Text()
if line == "" {
continue
}
var tagName, elemType string
_, err = fmt.Sscanf(line, "%s %s", &tagName, &elemType)
if err != nil {
log.Fatalf("error parsing input line: %s", err)
}
var template string
switch elemType {
case parentType:
template = parentTemplate
case emptyType:
template = emptyTemplate
default:
log.Fatal("unknown element type: ", elemType)
}
fmt.Fprintf(&output, template, strings.Title(tagName), tagName)
}
if err := scanner.Err(); err != nil {
log.Fatalf("error scanning input: %s", err)
}
formatted, err := format.Source(output.Bytes())
if err != nil {
log.Fatalf("error formatting output: %s", err)
}
err = ioutil.WriteFile(elementOutputPath, formatted, 0644)
if err != nil {
log.Fatalf("error writing output: %s", err)
}
}
func genAttribs() {
const (
inputPath = "attribs.txt"
outputPath = "attribs.go"
boolType = "bool"
stringType = "string"
stringTemplate = `func %s(value string) Attrib {
return Attrib{
Key: "%s",
Value: value,
}
}
`
boolTemplate = `func %s() Attrib {
return Attrib{
Key: "%s",
}
}
`
)
inputFile, err := os.Open(inputPath)
if err != nil {
log.Fatal(err)
}
defer inputFile.Close()
var output bytes.Buffer
fmt.Fprintln(&output, "// GENERATED BY gitlab.codemonkeysoftware.net/b/hatmill/internal/attribgen")
fmt.Fprintln(&output, "// DO NOT EDIT!\n")
fmt.Fprintln(&output, "package ", packageName, "\n")
scanner := bufio.NewScanner(inputFile)
for scanner.Scan() {
line := scanner.Text()
if line == "" {
continue
}
var attribName, attribType string
_, err = fmt.Sscanf(line, "%s %s", &attribName, &attribType)
if err != nil {
log.Fatalf("error parsing input line: %s", err)
}
var template string
switch attribType {
case boolType:
template = boolTemplate
case stringType:
template = stringTemplate
default:
log.Fatal("unknown attribute type: ", attribType)
}
fmt.Fprintf(&output, template, strings.Title(attribName), attribName)
}
if err := scanner.Err(); err != nil {
log.Fatalf("error scanning input: %s", err)
}
formatted, err := format.Source(output.Bytes())
if err != nil {
log.Fatalf("error formatting output: %s", err)
}
err = ioutil.WriteFile(outputPath, formatted, 0644)
if err != nil {
log.Fatalf("error writing output: %s", err)
}
}
func main() {
genElements()
genAttribs()
}

View File

@ -1,11 +0,0 @@
# elementgen
elementgen reads simple descriptions of HTML elements from `elements.txt`
and generates Go functions to create them. The file contains one description
per line. Each description is in the form
```
tag-name element-type
```
where `tag-name` is the lowercase name of the element, and `element-type` is
either `empty` for empty elements (e.g. `img`, 'br') or `parent` for elements
that can have child nodes (e.g. 'div', 'body').

View File

@ -1,95 +0,0 @@
package main
import (
"bufio"
"bytes"
"fmt"
"go/format"
"io/ioutil"
"log"
"os"
"strings"
)
const (
inputPath = "elements.txt"
outputPath = "elements.go"
packageName = "hatmill"
parentType = "parent"
emptyType = "empty"
parentTemplate = `// %[1]s creates a <%[2]s> element.
func %[1]s(attribs ...Attrib) func(children ...Term) *ParentElement {
return func(children ...Term) *ParentElement {
return &ParentElement{
EmptyElement: EmptyElement{
TagName: "%[2]s",
Attribs: attribs,
},
Children: children,
}
}
}
`
emptyTemplate = `// %[1]s creates a <%[2]s> element.
func %[1]s(attribs ...Attrib) EmptyElement {
return EmptyElement{
TagName: "%[2]s",
Attribs: attribs,
}
}
`
)
func main() {
inputFile, err := os.Open(inputPath)
if err != nil {
log.Fatal(err)
}
defer inputFile.Close()
var output bytes.Buffer
fmt.Fprintln(&output, "// GENERATED BY gitlab.codemonkeysoftware.net/b/hatmill/internal/elementgen")
fmt.Fprintln(&output, "// DO NOT EDIT!\n")
fmt.Fprintln(&output, "package ", packageName, "\n")
scanner := bufio.NewScanner(inputFile)
for scanner.Scan() {
line := scanner.Text()
if line == "" {
continue
}
var tagName, elemType string
_, err = fmt.Sscanf(line, "%s %s", &tagName, &elemType)
if err != nil {
log.Fatalf("error parsing input line: %s", err)
}
var template string
switch elemType {
case parentType:
template = parentTemplate
case emptyType:
template = emptyTemplate
default:
log.Fatal("unknown element type: ", elemType)
}
fmt.Fprintf(&output, template, strings.Title(tagName), tagName)
}
if err := scanner.Err(); err != nil {
log.Fatalf("error scanning input: %s", err)
}
formatted, err := format.Source(output.Bytes())
if err != nil {
log.Fatalf("error formatting output: %s", err)
}
err = ioutil.WriteFile(outputPath, formatted, 0644)
if err != nil {
log.Fatalf("error writing output: %s", err)
}
}