Skip to content

Commit

Permalink
adding initial support to generate content type from more descriptive…
Browse files Browse the repository at this point in the history
… cli args
  • Loading branch information
nilslice committed Nov 24, 2016
1 parent 6f58938 commit 04344fd
Show file tree
Hide file tree
Showing 4 changed files with 262 additions and 153 deletions.
65 changes: 65 additions & 0 deletions cmd/ponzu/cli_test.go
@@ -0,0 +1,65 @@
package main

import "testing"

func TestParseType(t *testing.T) {
// blog title:string Author:string PostCategory:string content:string some_thing:int
args := []string{
"blog", "title:string", "Author:string",
"PostCategory:string", "content:string",
"some_thing:int", "Some_otherThing:float64",
}

gt, err := parseType(args)
if err != nil {
t.Errorf("Failed: %s", err.Error())
}

if gt.Name != "Blog" {
t.Errorf("Expected %s, got: %s", "Blog", gt.Name)
}
}

func TestFieldJSONName(t *testing.T) {
cases := map[string]string{
"_T": "t",
"T": "t",
"_tT_": "t_t_",
"TestCapsNoSym": "test_caps_no_sym",
"test_Some_caps_Sym": "test_some_caps_sym",
"testnocaps": "testnocaps",
"_Test_Caps_Sym_odd": "test_caps_sym_odd",
"test-hyphen": "test-hyphen",
"Test-hyphen-Caps": "test-hyphen-caps",
"Test-Hyphen_Sym-Caps": "test-hyphen_sym-caps",
}

for input, expected := range cases {
output := fieldJSONName(input)
if output != expected {
t.Errorf("Expected: %s, got: %s", expected, output)
}
}
}

func TestFieldName(t *testing.T) {
cases := map[string]string{
"_T": "T",
"T": "T",
"_tT_": "TT",
"TestCapsNoSym": "TestCapsNoSym",
"test_Some_caps_Sym": "TestSomeCapsSym",
"testnocaps": "Testnocaps",
"_Test_Caps_Sym_odd": "TestCapsSymOdd",
"test-hyphen": "TestHyphen",
"Test-hyphen-Caps": "TestHyphenCaps",
"Test-Hyphen_Sym-Caps": "TestHyphenSymCaps",
}

for input, expected := range cases {
output := fieldName(input)
if output != expected {
t.Errorf("Expected: %s, got: %s", expected, output)
}
}
}
192 changes: 192 additions & 0 deletions 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
}
5 changes: 4 additions & 1 deletion cmd/ponzu/main.go
Expand Up @@ -120,11 +120,12 @@ func main() {
os.Exit(0)
}

err := generateContentType(args[1], "")
err := generateContentType(args[1:], "")
if err != nil {
fmt.Println(err)
os.Exit(1)
}

case "build":
err := buildPonzuServer(args)
if err != nil {
Expand Down Expand Up @@ -197,8 +198,10 @@ func main() {
}

log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", port), nil))

case "":
flag.PrintDefaults()

default:
flag.PrintDefaults()
}
Expand Down

0 comments on commit 04344fd

Please sign in to comment.