diff --git a/hatmill.go b/hatmill.go index 36bd6d8..baf2bc2 100644 --- a/hatmill.go +++ b/hatmill.go @@ -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 { diff --git a/internal/attribgen/README.md b/internal/attribgen/README.md deleted file mode 100644 index d4f8737..0000000 --- a/internal/attribgen/README.md +++ /dev/null @@ -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`). diff --git a/internal/attribgen/main.go b/internal/attribgen/main.go deleted file mode 100644 index df8ca98..0000000 --- a/internal/attribgen/main.go +++ /dev/null @@ -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) - } -} diff --git a/internal/codegen/README.md b/internal/codegen/README.md new file mode 100644 index 0000000..7832603 --- /dev/null +++ b/internal/codegen/README.md @@ -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'). diff --git a/internal/codegen/codegen.go b/internal/codegen/codegen.go new file mode 100644 index 0000000..ee0a882 --- /dev/null +++ b/internal/codegen/codegen.go @@ -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() +} diff --git a/internal/elementgen/README.md b/internal/elementgen/README.md deleted file mode 100644 index 60b204e..0000000 --- a/internal/elementgen/README.md +++ /dev/null @@ -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'). diff --git a/internal/elementgen/main.go b/internal/elementgen/main.go deleted file mode 100644 index 1ebf4bb..0000000 --- a/internal/elementgen/main.go +++ /dev/null @@ -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) - } -}