summaryrefslogtreecommitdiff
path: root/cmd/ponzu/generate.go
diff options
context:
space:
mode:
authorSteve Manuel <nilslice@gmail.com>2016-11-24 10:37:54 -0800
committerSteve Manuel <nilslice@gmail.com>2016-11-24 10:37:54 -0800
commit04344fd03a609af37ec95a6c8279a45c17d5de70 (patch)
tree0129828f4a6eb5c1cfb2a02124fc4a14a22f4006 /cmd/ponzu/generate.go
parent6f5893828077eb0034dca01344f3742eb5cd5fa6 (diff)
adding initial support to generate content type from more descriptive cli args
Diffstat (limited to 'cmd/ponzu/generate.go')
-rw-r--r--cmd/ponzu/generate.go192
1 files changed, 192 insertions, 0 deletions
diff --git a/cmd/ponzu/generate.go b/cmd/ponzu/generate.go
new file mode 100644
index 0000000..9325d1d
--- /dev/null
+++ b/cmd/ponzu/generate.go
@@ -0,0 +1,192 @@
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "go/format"
+ "html/template"
+ "os"
+ "path/filepath"
+ "strings"
+)
+
+type generateType struct {
+ Name string
+ Initial string
+ Fields []generateField
+}
+
+type generateField struct {
+ Name string
+ TypeName string
+ JSONName string
+}
+
+// blog title:string Author:string PostCategory:string content:string some_thing:int
+func parseType(args []string) (generateType, error) {
+ t := generateType{
+ Name: fieldName(args[0]),
+ }
+ t.Initial = strings.ToLower(string(t.Name[0]))
+
+ fields := args[1:]
+ for _, field := range fields {
+ f, err := parseField(field)
+ if err != nil {
+ return generateType{}, err
+ }
+
+ t.Fields = append(t.Fields, f)
+ }
+
+ return t, nil
+}
+
+func parseField(raw string) (generateField, error) {
+ // title:string
+ if !strings.Contains(raw, ":") {
+ return generateField{}, fmt.Errorf("Invalid generate argument. [%s]", raw)
+ }
+
+ pair := strings.Split(raw, ":")
+ field := generateField{
+ Name: fieldName(pair[0]),
+ TypeName: strings.ToLower(pair[1]),
+ JSONName: fieldJSONName(pair[0]),
+ }
+
+ return field, nil
+}
+
+// get the initial field name passed and check it for all possible cases
+// MyTitle:string myTitle:string my_title:string -> MyTitle
+// error-message:string -> ErrorMessage
+func fieldName(name string) string {
+ // remove _ or - if first character
+ if name[0] == '-' || name[0] == '_' {
+ name = name[1:]
+ }
+
+ // remove _ or - if last character
+ if name[len(name)-1] == '-' || name[len(name)-1] == '_' {
+ name = name[:len(name)-1]
+ }
+
+ // upcase the first character
+ name = strings.ToUpper(string(name[0])) + name[1:]
+
+ // remove _ or - character, and upcase the character immediately following
+ for i := 0; i < len(name); i++ {
+ r := rune(name[i])
+ if isUnderscore(r) || isHyphen(r) {
+ up := strings.ToUpper(string(name[i+1]))
+ name = name[:i] + up + name[i+2:]
+ }
+ }
+
+ return name
+}
+
+// get the initial field name passed and convert to json-like name
+// MyTitle:string myTitle:string my_title:string -> my_title
+// error-message:string -> error-message
+func fieldJSONName(name string) string {
+ // remove _ or - if first character
+ if name[0] == '-' || name[0] == '_' {
+ name = name[1:]
+ }
+
+ // downcase the first character
+ name = strings.ToLower(string(name[0])) + name[1:]
+
+ // check for uppercase character, downcase and insert _ before it if i-1
+ // isn't already _ or -
+ for i := 0; i < len(name); i++ {
+ r := rune(name[i])
+ if isUpper(r) {
+ low := strings.ToLower(string(r))
+ if name[i-1] == '_' || name[i-1] == '-' {
+ name = name[:i] + low + name[i+1:]
+ } else {
+ name = name[:i] + "_" + low + name[i+1:]
+ }
+ }
+ }
+
+ return name
+}
+
+func isUpper(char rune) bool {
+ if char >= 'A' && char <= 'Z' {
+ return true
+ }
+
+ return false
+}
+
+func isUnderscore(char rune) bool {
+ return char == '_'
+}
+
+func isHyphen(char rune) bool {
+ return char == '-'
+}
+
+func generateContentType(args []string, path string) error {
+ name := args[0]
+ fileName := strings.ToLower(name) + ".go"
+
+ // open file in ./content/ dir
+ // if exists, alert user of conflict
+ pwd, err := os.Getwd()
+ if err != nil {
+ return err
+ }
+
+ if path != "" {
+ pwd = path
+ }
+
+ contentDir := filepath.Join(pwd, "content")
+ filePath := filepath.Join(contentDir, fileName)
+
+ if _, err := os.Stat(filePath); !os.IsNotExist(err) {
+ return fmt.Errorf("Please remove '%s' before executing this command.", fileName)
+ }
+
+ // no file exists.. ok to write new one
+ file, err := os.Create(filePath)
+ defer file.Close()
+ if err != nil {
+ return err
+ }
+
+ // parse type info from args
+ gt, err := parseType(args)
+ if err != nil {
+ return fmt.Errorf("Failed to parse type args: %s", err.Error())
+ }
+
+ tmpl, err := template.ParseFiles("contentType.tmpl")
+ if err != nil {
+ return fmt.Errorf("Failed to parse template: %s", err.Error())
+ }
+
+ buf := &bytes.Buffer{}
+ err = tmpl.Execute(buf, gt)
+ if err != nil {
+ return fmt.Errorf("Failed to execute template: %s", err.Error())
+ }
+
+ fmtBuf, err := format.Source(buf.Bytes())
+ if err != nil {
+ return fmt.Errorf("Failed to format template: %s", err.Error())
+ }
+
+ _, err = file.Write(fmtBuf)
+ if err != nil {
+ return fmt.Errorf("Failed to write generated file buffer: %s", err.Error())
+ }
+
+ return nil
+}