diff --git a/g.go b/g.go index e0eb265..a7d9ae1 100644 --- a/g.go +++ b/g.go @@ -31,6 +31,10 @@ bee generate model [modelname] [-fields=""] generate RESTFul model based on fields -fields: a list of table fields. Format: field:type, ... +bee generate structure [structurefile] [-fields=""] + generate struct based + -fields: a list of table fields. Format: field:type, ... + bee generate controller [controllerfile] generate RESTFul controllers @@ -179,6 +183,27 @@ func generateCode(cmd *Command, args []string) int { ColorLog("[HINT] Usage: bee generate controller [controllername]\n") os.Exit(2) } + case "structure": + sname := args[1] + switch len(args) { + case 2: + generateStructure(sname, "", curpath) + case 3: + cmd.Flag.Parse(args[2:]) + if fields == "" { + ColorLog("[ERRO] Wrong number of arguments\n") + ColorLog("[HINT] Usage: bee generate structure [structurename] [-fields=\"title:string,body:text\"]\n") + os.Exit(2) + } + sname := args[1] + ColorLog("[INFO] Using '%s' as structure name\n", sname) + generateStructure(sname, fields.String(), curpath) + default: + ColorLog("[ERRO] Wrong number of arguments\n") + ColorLog("[HINT] Usage: bee generate structure [structurename] [-fields=\"title:string,body:text\"]\n") + os.Exit(2) + + } case "model": if len(args) < 2 { ColorLog("[ERRO] Wrong number of arguments\n") diff --git a/g_controller.go b/g_controller.go index 87b11dc..ff36e80 100644 --- a/g_controller.go +++ b/g_controller.go @@ -25,14 +25,13 @@ import ( // func generateController(cname, crupath string) { p, f := path.Split(cname) - fileName := strings.Title(f) + "_controllers" controllerName := strings.Title(f) packageName := "controllers" if p != "" { i := strings.LastIndex(p[:len(p)-1], "/") packageName = p[i+1 : len(p)-1] } - ColorLog("[INFO] Using '%s' as controller name\n", fileName) + ColorLog("[INFO] Using '%s' as controller name\n", controllerName) ColorLog("[INFO] Using '%s' as package name\n", packageName) fp := path.Join(crupath, "controllers", p) if _, err := os.Stat(fp); os.IsNotExist(err) { @@ -42,7 +41,7 @@ func generateController(cname, crupath string) { os.Exit(2) } } - fpath := path.Join(fp, strings.ToLower(fileName)+".go") + fpath := path.Join(fp, strings.ToLower(controllerName)+"_controller.go") if f, err := os.OpenFile(fpath, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err == nil { defer f.Close() modelPath := path.Join(crupath, "models", strings.ToLower(controllerName)+".go") diff --git a/g_model.go b/g_model.go index 859164f..476e25c 100644 --- a/g_model.go +++ b/g_model.go @@ -1,7 +1,6 @@ package main import ( - "errors" "os" "path" "strings" @@ -15,11 +14,7 @@ func generateModel(mname, fields, crupath string) { i := strings.LastIndex(p[:len(p)-1], "/") packageName = p[i+1 : len(p)-1] } - modelStruct, err, hastime := getStruct(modelName, fields) - if err != nil { - ColorLog("[ERRO] Could not genrate models struct: %s\n", err) - os.Exit(2) - } + ColorLog("[INFO] Using '%s' as model name\n", modelName) ColorLog("[INFO] Using '%s' as package name\n", packageName) fp := path.Join(crupath, "models", p) @@ -35,12 +30,7 @@ func generateModel(mname, fields, crupath string) { defer f.Close() content := strings.Replace(modelTpl, "{{packageName}}", packageName, -1) content = strings.Replace(content, "{{modelName}}", modelName, -1) - content = strings.Replace(content, "{{modelStruct}}", modelStruct, -1) - if hastime { - content = strings.Replace(content, "{{timePkg}}", `"time"`, -1) - } else { - content = strings.Replace(content, "{{timePkg}}", "", -1) - } + f.WriteString(content) // gofmt generated source code formatSourceCode(fpath) @@ -52,67 +42,6 @@ func generateModel(mname, fields, crupath string) { } } -func getStruct(structname, fields string) (string, error, bool) { - if fields == "" { - return "", errors.New("fields can't empty"), false - } - hastime := false - structStr := "type " + structname + " struct{\n" - fds := strings.Split(fields, ",") - for i, v := range fds { - kv := strings.SplitN(v, ":", 2) - if len(kv) != 2 { - return "", errors.New("the filds format is wrong. should key:type,key:type " + v), false - } - typ, tag, hastimeinner := getType(kv[1]) - if typ == "" { - return "", errors.New("the filds format is wrong. should key:type,key:type " + v), false - } - if i == 0 && strings.ToLower(kv[0]) != "id" { - structStr = structStr + "Id int64 `orm:\"auto\"`\n" - } - if hastimeinner { - hastime = true - } - structStr = structStr + camelString(kv[0]) + " " + typ + " " + tag + "\n" - } - structStr += "}\n" - return structStr, nil, hastime -} - -// fields support type -// http://beego.me/docs/mvc/model/models.md#mysql -func getType(ktype string) (kt, tag string, hasTime bool) { - kv := strings.SplitN(ktype, ":", 2) - switch kv[0] { - case "string": - if len(kv) == 2 { - return "string", "`orm:\"size(" + kv[1] + ")\"`", false - } else { - return "string", "`orm:\"size(128)\"`", false - } - case "text": - return "string", "`orm:\"type(longtext)\"`", false - case "auto": - return "int64", "`orm:\"auto\"`", false - case "pk": - return "int64", "`orm:\"pk\"`", false - case "datetime": - return "time.Time", "`orm:\"type(datetime)\"`", true - case "int", "int8", "int16", "int32", "int64": - fallthrough - case "uint", "uint8", "uint16", "uint32", "uint64": - fallthrough - case "bool": - fallthrough - case "float32", "float64": - return kv[0], "", false - case "float": - return "float64", "", false - } - return "", "", false -} - var modelTpl = `package {{packageName}} import ( diff --git a/g_structure.go b/g_structure.go index 06ab7d0..f8a4111 100644 --- a/g_structure.go +++ b/g_structure.go @@ -1 +1,154 @@ +// Copyright 2013 Dylan LYU (mingzong.lyu@gmail.com) +// +// Licensed under the Apache License, Version 2.0 (the "License"): you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. + package main + +import ( + "errors" + "os" + "path" + "strings" +) + +func generateStructure(cname, fields, crupath string) { + p, f := path.Split(cname) + structureName := strings.Title(f) + packageName := "structures" + if p != "" { + i := strings.LastIndex(p[:len(p)-1], "/") + packageName = p[i+1 : len(p)-1] + } + ColorLog("[INFO] Using '%s' as structure name\n", structureName) + ColorLog("[INFO] Using '%s' as package name\n", packageName) + fp := path.Join(crupath, packageName, p) + if _, err := os.Stat(fp); os.IsNotExist(err) { + // create controller directory + if err := os.MkdirAll(fp, 0777); err != nil { + ColorLog("[ERRO] Could not create structures directory: %s\n", err) + os.Exit(2) + } + } + fpath := path.Join(fp, strings.ToLower(structureName)+"_structure.go") + if f, err := os.OpenFile(fpath, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err == nil { + defer f.Close() + var content string + + if fields != "" { + structStruct, err, hastime := getStruct(structureName, fields) + if err != nil { + ColorLog("[ERRO] Could not genrate struct: %s\n", err) + os.Exit(2) + } + content = strings.Replace(INIT_STRUCTURE_TPL, "{{packageName}}", packageName, -1) + content = strings.Replace(content, "{{structStruct}}", structStruct, -1) + if hastime { + content = strings.Replace(content, "{{timePkg}}", `"time"`, -1) + } else { + content = strings.Replace(content, "{{timePkg}}", "", -1) + } + + } else { + content = strings.Replace(STRUCTURE_TPL, "{{packageName}}", packageName, -1) + } + content = strings.Replace(content, "{{structureName}}", structureName, -1) + f.WriteString(content) + // gofmt generated source code + formatSourceCode(fpath) + ColorLog("[INFO] structure file generated: %s\n", fpath) + } else { + // error creating file + ColorLog("[ERRO] Could not create structure file: %s\n", err) + os.Exit(2) + } + +} + +func getStruct(structname, fields string) (string, error, bool) { + if fields == "" { + return "", errors.New("fields can't empty"), false + } + hastime := false + structStr := "type " + structname + " struct{\n" + fds := strings.Split(fields, ",") + for i, v := range fds { + kv := strings.SplitN(v, ":", 2) + if len(kv) != 2 { + return "", errors.New("the filds format is wrong. should key:type,key:type " + v), false + } + typ, tag, hastimeinner := getType(kv[1]) + if typ == "" { + return "", errors.New("the filds format is wrong. should key:type,key:type " + v), false + } + if i == 0 && strings.ToLower(kv[0]) != "id" { + structStr = structStr + "Id int64 `orm:\"auto\"`\n" + } + if hastimeinner { + hastime = true + } + structStr = structStr + camelString(kv[0]) + " " + typ + " " + tag + "\n" + } + structStr += "}\n" + return structStr, nil, hastime +} + +// fields support type +// http://beego.me/docs/mvc/model/models.md#mysql +func getType(ktype string) (kt, tag string, hasTime bool) { + kv := strings.SplitN(ktype, ":", 2) + switch kv[0] { + case "string": + if len(kv) == 2 { + return "string", "`orm:\"size(" + kv[1] + ")\"`", false + } else { + return "string", "`orm:\"size(128)\"`", false + } + case "text": + return "string", "`orm:\"type(longtext)\"`", false + case "auto": + return "int64", "`orm:\"auto\"`", false + case "pk": + return "int64", "`orm:\"pk\"`", false + case "datetime": + return "time.Time", "`orm:\"type(datetime)\"`", true + case "int", "int8", "int16", "int32", "int64": + fallthrough + case "uint", "uint8", "uint16", "uint32", "uint64": + fallthrough + case "bool": + fallthrough + case "float32", "float64": + return kv[0], "", false + case "float": + return "float64", "", false + } + return "", "", false +} + +const ( + STRUCTURE_TPL = `package {{packageName}} + + type {{structureName}}Struct struct { + + } + ` + + INIT_STRUCTURE_TPL = `package {{packageName}} + + {{structStruct}} + + func init() { + orm.RegisterModel(new({{structureName}})) + } + ` +)