remove xorm dir as it's relocated to github.com/go-xorm/cmd

This commit is contained in:
Nash Tsai 2014-04-11 17:29:00 +08:00
parent e7277992ad
commit a0919b5371
15 changed files with 0 additions and 1175 deletions

View File

@ -1,2 +0,0 @@
[deps]
github.com/go-xorm/xorm=../

View File

@ -1,62 +0,0 @@
# xorm tools
xorm tools is a set of tools for database operation.
## Install
`go get github.com/go-xorm/xorm/xorm`
and you should install the depends below:
* github.com/go-xorm/xorm
* Mysql: [github.com/go-sql-driver/mysql](https://github.com/go-sql-driver/mysql)
* MyMysql: [github.com/ziutek/mymysql/godrv](https://github.com/ziutek/mymysql/godrv)
* SQLite: [github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3)
* Postgres: [github.com/bylevel/pq](https://github.com/bylevel/pq)
## Reverse
After you installed the tool, you can type
`xorm help reverse`
to get help
example:
sqlite:
`xorm reverse sqite3 test.db templates/goxorm`
mysql:
`xorm reverse mysql root:@/xorm_test?charset=utf8 templates/goxorm`
mymysql:
`xorm reverse mymysql xorm_test2/root/ templates/goxorm`
postgres:
`xorm reverse postgres "dbname=xorm_test sslmode=disable" templates/goxorm`
will generated go files in `./model` directory
## Template and Config
Now, xorm tool supports go and c++ two languages and have go, goxorm, c++ three of default templates. In template directory, we can put a config file to control how to generating.
````
lang=go
genJson=1
```
lang must be go or c++ now.
genJson can be 1 or 0, if 1 then the struct will have json tag.
## LICENSE
BSD License
[http://creativecommons.org/licenses/BSD/](http://creativecommons.org/licenses/BSD/)

View File

@ -1,66 +0,0 @@
package main
import (
//"fmt"
"strings"
"text/template"
"github.com/go-xorm/core"
)
var (
CPlusTmpl LangTmpl = LangTmpl{
template.FuncMap{"Mapper": mapper.Table2Obj,
"Type": cPlusTypeStr,
"UnTitle": unTitle,
},
nil,
genCPlusImports,
}
)
func cPlusTypeStr(col *core.Column) string {
tp := col.SQLType
name := strings.ToUpper(tp.Name)
switch name {
case core.Bit, core.TinyInt, core.SmallInt, core.MediumInt, core.Int, core.Integer, core.Serial:
return "int"
case core.BigInt, core.BigSerial:
return "__int64"
case core.Char, core.Varchar, core.TinyText, core.Text, core.MediumText, core.LongText:
return "tstring"
case core.Date, core.DateTime, core.Time, core.TimeStamp:
return "time_t"
case core.Decimal, core.Numeric:
return "tstring"
case core.Real, core.Float:
return "float"
case core.Double:
return "double"
case core.TinyBlob, core.Blob, core.MediumBlob, core.LongBlob, core.Bytea:
return "tstring"
case core.Bool:
return "bool"
default:
return "tstring"
}
return ""
}
func genCPlusImports(tables []*core.Table) map[string]string {
imports := make(map[string]string)
for _, table := range tables {
for _, col := range table.Columns() {
switch cPlusTypeStr(col) {
case "time_t":
imports[`<time.h>`] = `<time.h>`
case "tstring":
imports["<string>"] = "<string>"
//case "__int64":
// imports[""] = ""
}
}
}
return imports
}

View File

@ -1,78 +0,0 @@
package main
import (
"fmt"
"os"
"strings"
)
// A Command is an implementation of a go command
// like go build or go fix.
type Command struct {
// Run runs the command.
// The args are the arguments after the command name.
Run func(cmd *Command, args []string)
// UsageLine is the one-line usage message.
// The first word in the line is taken to be the command name.
UsageLine string
// Short is the short description shown in the 'go help' output.
Short string
// Long is the long message shown in the 'go help <this-command>' output.
Long string
// Flag is a set of flags specific to this command.
Flags map[string]bool
}
// Name returns the command's name: the first word in the usage line.
func (c *Command) Name() string {
name := c.UsageLine
i := strings.Index(name, " ")
if i >= 0 {
name = name[:i]
}
return name
}
func (c *Command) Usage() {
fmt.Fprintf(os.Stderr, "usage: %s\n\n", c.UsageLine)
fmt.Fprintf(os.Stderr, "%s\n", strings.TrimSpace(c.Long))
os.Exit(2)
}
// Runnable reports whether the command can be run; otherwise
// it is a documentation pseudo-command such as importpath.
func (c *Command) Runnable() bool {
return c.Run != nil
}
// checkFlags checks if the flag exists with correct format.
func checkFlags(flags map[string]bool, args []string, print func(string)) int {
num := 0 // Number of valid flags, use to cut out.
for i, f := range args {
// Check flag prefix '-'.
if !strings.HasPrefix(f, "-") {
// Not a flag, finish check process.
break
}
// Check if it a valid flag.
if v, ok := flags[f]; ok {
flags[f] = !v
if !v {
print(f)
} else {
fmt.Println("DISABLE: " + f)
}
} else {
fmt.Printf("[ERRO] Unknown flag: %s.\n", f)
return -1
}
num = i + 1
}
return num
}

View File

@ -1,261 +0,0 @@
package main
import (
"errors"
"fmt"
"go/format"
"reflect"
"strings"
"text/template"
"github.com/go-xorm/core"
)
var (
GoLangTmpl LangTmpl = LangTmpl{
template.FuncMap{"Mapper": mapper.Table2Obj,
"Type": typestring,
"Tag": tag,
"UnTitle": unTitle,
"gt": gt,
"getCol": getCol,
},
formatGo,
genGoImports,
}
)
var (
errBadComparisonType = errors.New("invalid type for comparison")
errBadComparison = errors.New("incompatible types for comparison")
errNoComparison = errors.New("missing argument for comparison")
)
type kind int
const (
invalidKind kind = iota
boolKind
complexKind
intKind
floatKind
integerKind
stringKind
uintKind
)
func basicKind(v reflect.Value) (kind, error) {
switch v.Kind() {
case reflect.Bool:
return boolKind, nil
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return intKind, nil
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return uintKind, nil
case reflect.Float32, reflect.Float64:
return floatKind, nil
case reflect.Complex64, reflect.Complex128:
return complexKind, nil
case reflect.String:
return stringKind, nil
}
return invalidKind, errBadComparisonType
}
// eq evaluates the comparison a == b || a == c || ...
func eq(arg1 interface{}, arg2 ...interface{}) (bool, error) {
v1 := reflect.ValueOf(arg1)
k1, err := basicKind(v1)
if err != nil {
return false, err
}
if len(arg2) == 0 {
return false, errNoComparison
}
for _, arg := range arg2 {
v2 := reflect.ValueOf(arg)
k2, err := basicKind(v2)
if err != nil {
return false, err
}
if k1 != k2 {
return false, errBadComparison
}
truth := false
switch k1 {
case boolKind:
truth = v1.Bool() == v2.Bool()
case complexKind:
truth = v1.Complex() == v2.Complex()
case floatKind:
truth = v1.Float() == v2.Float()
case intKind:
truth = v1.Int() == v2.Int()
case stringKind:
truth = v1.String() == v2.String()
case uintKind:
truth = v1.Uint() == v2.Uint()
default:
panic("invalid kind")
}
if truth {
return true, nil
}
}
return false, nil
}
// lt evaluates the comparison a < b.
func lt(arg1, arg2 interface{}) (bool, error) {
v1 := reflect.ValueOf(arg1)
k1, err := basicKind(v1)
if err != nil {
return false, err
}
v2 := reflect.ValueOf(arg2)
k2, err := basicKind(v2)
if err != nil {
return false, err
}
if k1 != k2 {
return false, errBadComparison
}
truth := false
switch k1 {
case boolKind, complexKind:
return false, errBadComparisonType
case floatKind:
truth = v1.Float() < v2.Float()
case intKind:
truth = v1.Int() < v2.Int()
case stringKind:
truth = v1.String() < v2.String()
case uintKind:
truth = v1.Uint() < v2.Uint()
default:
panic("invalid kind")
}
return truth, nil
}
// le evaluates the comparison <= b.
func le(arg1, arg2 interface{}) (bool, error) {
// <= is < or ==.
lessThan, err := lt(arg1, arg2)
if lessThan || err != nil {
return lessThan, err
}
return eq(arg1, arg2)
}
// gt evaluates the comparison a > b.
func gt(arg1, arg2 interface{}) (bool, error) {
// > is the inverse of <=.
lessOrEqual, err := le(arg1, arg2)
if err != nil {
return false, err
}
return !lessOrEqual, nil
}
func getCol(cols map[string]*core.Column, name string) *core.Column {
return cols[name]
}
func formatGo(src string) (string, error) {
source, err := format.Source([]byte(src))
if err != nil {
return "", err
}
return string(source), nil
}
func genGoImports(tables []*core.Table) map[string]string {
imports := make(map[string]string)
for _, table := range tables {
for _, col := range table.Columns() {
if typestring(col) == "time.Time" {
imports["time"] = "time"
}
}
}
return imports
}
func typestring(col *core.Column) string {
st := col.SQLType
t := core.SQLType2Type(st)
s := t.String()
if s == "[]uint8" {
return "[]byte"
}
return s
}
func tag(table *core.Table, col *core.Column) string {
isNameId := (mapper.Table2Obj(col.Name) == "Id")
isIdPk := isNameId && typestring(col) == "int64"
res := make([]string, 0)
if !col.Nullable {
if !isIdPk {
res = append(res, "not null")
}
}
if col.IsPrimaryKey {
if !isIdPk {
res = append(res, "pk")
}
}
if col.Default != "" {
res = append(res, "default "+col.Default)
}
if col.IsAutoIncrement {
if !isIdPk {
res = append(res, "autoincr")
}
}
if col.IsCreated {
res = append(res, "created")
}
if col.IsUpdated {
res = append(res, "updated")
}
for name, _ := range col.Indexes {
index := table.Indexes[name]
var uistr string
if index.Type == core.UniqueType {
uistr = "unique"
} else if index.Type == core.IndexType {
uistr = "index"
}
if len(index.Cols) > 1 {
uistr += "(" + index.Name + ")"
}
res = append(res, uistr)
}
nstr := col.SQLType.Name
if col.Length != 0 {
if col.Length2 != 0 {
nstr += fmt.Sprintf("(%v,%v)", col.Length, col.Length2)
} else {
nstr += fmt.Sprintf("(%v)", col.Length)
}
}
res = append(res, nstr)
var tags []string
if genJson {
tags = append(tags, "json:\""+col.Name+"\"")
}
if len(res) > 0 {
tags = append(tags, "xorm:\""+strings.Join(res, " ")+"\"")
}
if len(tags) > 0 {
return "`" + strings.Join(tags, " ") + "`"
} else {
return ""
}
}

View File

@ -1,51 +0,0 @@
package main
import (
"github.com/go-xorm/core"
"io/ioutil"
"strings"
"text/template"
)
type LangTmpl struct {
Funcs template.FuncMap
Formater func(string) (string, error)
GenImports func([]*core.Table) map[string]string
}
var (
mapper = &core.SnakeMapper{}
langTmpls = map[string]LangTmpl{
"go": GoLangTmpl,
"c++": CPlusTmpl,
}
)
func loadConfig(f string) map[string]string {
bts, err := ioutil.ReadFile(f)
if err != nil {
return nil
}
configs := make(map[string]string)
lines := strings.Split(string(bts), "\n")
for _, line := range lines {
line = strings.TrimRight(line, "\r")
vs := strings.Split(line, "=")
if len(vs) == 2 {
configs[strings.TrimSpace(vs[0])] = strings.TrimSpace(vs[1])
}
}
return configs
}
func unTitle(src string) string {
if src == "" {
return ""
}
if len(src) == 1 {
return strings.ToLower(string(src[0]))
} else {
return strings.ToLower(string(src[0])) + src[1:]
}
}

View File

@ -1,288 +0,0 @@
package main
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"path"
"path/filepath"
"strconv"
"strings" //[SWH|+]
"text/template"
_ "github.com/bylevel/pq"
"github.com/dvirsky/go-pylog/logging"
_ "github.com/go-sql-driver/mysql"
"github.com/go-xorm/core"
"github.com/go-xorm/xorm"
_ "github.com/mattn/go-sqlite3"
_ "github.com/ziutek/mymysql/godrv"
)
var CmdReverse = &Command{
UsageLine: "reverse [-m] driverName datasourceName tmplPath [generatedPath]",
Short: "reverse a db to codes",
Long: `
according database's tables and columns to generate codes for Go, C++ and etc.
-m Generated one go file for every table
driverName Database driver name, now supported four: mysql mymysql sqlite3 postgres
datasourceName Database connection uri, for detail infomation please visit driver's project page
tmplPath Template dir for generated. the default templates dir has provide 1 template
generatedPath This parameter is optional, if blank, the default value is model, then will
generated all codes in model dir
`,
}
func init() {
CmdReverse.Run = runReverse
CmdReverse.Flags = map[string]bool{
"-s": false,
"-l": false,
}
}
var (
genJson bool = false
)
func printReversePrompt(flag string) {
}
type Tmpl struct {
Tables []*core.Table
Imports map[string]string
Model string
}
func dirExists(dir string) bool {
d, e := os.Stat(dir)
switch {
case e != nil:
return false
case !d.IsDir():
return false
}
return true
}
func runReverse(cmd *Command, args []string) {
num := checkFlags(cmd.Flags, args, printReversePrompt)
if num == -1 {
return
}
args = args[num:]
if len(args) < 3 {
fmt.Println("params error, please see xorm help reverse")
return
}
var isMultiFile bool = true
if use, ok := cmd.Flags["-s"]; ok {
isMultiFile = !use
}
curPath, err := os.Getwd()
if err != nil {
fmt.Println(curPath)
return
}
var genDir string
var model string
if len(args) == 4 {
genDir, err = filepath.Abs(args[3])
if err != nil {
fmt.Println(err)
return
}
//[SWH|+] 经测试path.Base不能解析windows下的“\”,需要替换为“/”
genDir = strings.Replace(genDir, "\\", "/", -1)
model = path.Base(genDir)
} else {
model = "model"
genDir = path.Join(curPath, model)
}
dir, err := filepath.Abs(args[2])
if err != nil {
logging.Error("%v", err)
return
}
if !dirExists(dir) {
logging.Error("Template %v path is not exist", dir)
return
}
var langTmpl LangTmpl
var ok bool
var lang string = "go"
var prefix string = "" //[SWH|+]
cfgPath := path.Join(dir, "config")
info, err := os.Stat(cfgPath)
var configs map[string]string
if err == nil && !info.IsDir() {
configs = loadConfig(cfgPath)
if l, ok := configs["lang"]; ok {
lang = l
}
if j, ok := configs["genJson"]; ok {
genJson, err = strconv.ParseBool(j)
}
//[SWH|+]
if j, ok := configs["prefix"]; ok {
prefix = j
}
}
if langTmpl, ok = langTmpls[lang]; !ok {
fmt.Println("Unsupported programing language", lang)
return
}
os.MkdirAll(genDir, os.ModePerm)
Orm, err := xorm.NewEngine(args[0], args[1])
if err != nil {
logging.Error("%v", err)
return
}
tables, err := Orm.DBMetas()
if err != nil {
logging.Error("%v", err)
return
}
filepath.Walk(dir, func(f string, info os.FileInfo, err error) error {
if info.IsDir() {
return nil
}
if info.Name() == "config" {
return nil
}
bs, err := ioutil.ReadFile(f)
if err != nil {
logging.Error("%v", err)
return err
}
t := template.New(f)
t.Funcs(langTmpl.Funcs)
tmpl, err := t.Parse(string(bs))
if err != nil {
logging.Error("%v", err)
return err
}
var w *os.File
fileName := info.Name()
newFileName := fileName[:len(fileName)-4]
ext := path.Ext(newFileName)
if !isMultiFile {
w, err = os.OpenFile(path.Join(genDir, newFileName), os.O_RDWR|os.O_CREATE, 0600)
if err != nil {
logging.Error("%v", err)
return err
}
imports := langTmpl.GenImports(tables)
tbls := make([]*core.Table, 0)
for _, table := range tables {
//[SWH|+]
if prefix != "" {
table.Name = strings.TrimPrefix(table.Name, prefix)
}
tbls = append(tbls, table)
}
newbytes := bytes.NewBufferString("")
t := &Tmpl{Tables: tbls, Imports: imports, Model: model}
err = tmpl.Execute(newbytes, t)
if err != nil {
logging.Error("%v", err)
return err
}
tplcontent, err := ioutil.ReadAll(newbytes)
if err != nil {
logging.Error("%v", err)
return err
}
var source string
if langTmpl.Formater != nil {
source, err = langTmpl.Formater(string(tplcontent))
if err != nil {
logging.Error("%v", err)
return err
}
} else {
source = string(tplcontent)
}
w.WriteString(source)
w.Close()
} else {
for _, table := range tables {
//[SWH|+]
if prefix != "" {
table.Name = strings.TrimPrefix(table.Name, prefix)
}
// imports
tbs := []*core.Table{table}
imports := langTmpl.GenImports(tbs)
w, err := os.OpenFile(path.Join(genDir, unTitle(mapper.Table2Obj(table.Name))+ext), os.O_RDWR|os.O_CREATE, 0600)
if err != nil {
logging.Error("%v", err)
return err
}
newbytes := bytes.NewBufferString("")
t := &Tmpl{Tables: tbs, Imports: imports, Model: model}
err = tmpl.Execute(newbytes, t)
if err != nil {
logging.Error("%v", err)
return err
}
tplcontent, err := ioutil.ReadAll(newbytes)
if err != nil {
logging.Error("%v", err)
return err
}
var source string
if langTmpl.Formater != nil {
source, err = langTmpl.Formater(string(tplcontent))
if err != nil {
logging.Error("%v-%v", err, string(tplcontent))
return err
}
} else {
source = string(tplcontent)
}
w.WriteString(source)
w.Close()
}
}
return nil
})
}

View File

@ -1,147 +0,0 @@
package main
import (
"fmt"
"github.com/go-xorm/xorm"
"strings"
)
var CmdShell = &Command{
UsageLine: "shell driverName datasourceName",
Short: "a general shell to operate all kinds of database",
Long: `
general database's shell for sqlite3, mysql, postgres.
driverName Database driver name, now supported four: mysql mymysql sqlite3 postgres
datasourceName Database connection uri, for detail infomation please visit driver's project page
`,
}
func init() {
CmdShell.Run = runShell
CmdShell.Flags = map[string]bool{}
}
var engine *xorm.Engine
func shellHelp() {
fmt.Println(`
show tables show all tables
columns <table_name> show table's column info
indexes <table_name> show table's index info
exit exit shell
source <sql_file> exec sql file to current database
dump [-nodata] <sql_file> dump structs or records to sql file
help show this document
<statement> SQL statement
`)
}
func runShell(cmd *Command, args []string) {
if len(args) != 2 {
fmt.Println("params error, please see xorm help shell")
return
}
var err error
engine, err = xorm.NewEngine(args[0], args[1])
if err != nil {
fmt.Println(err)
return
}
err = engine.Ping()
if err != nil {
fmt.Println(err)
return
}
var scmd string
fmt.Print("xorm$ ")
for {
var input string
_, err := fmt.Scan(&input)
if err != nil {
fmt.Println(err)
continue
}
if strings.ToLower(input) == "exit" {
fmt.Println("bye")
return
}
if !strings.HasSuffix(input, ";") {
scmd = scmd + " " + input
continue
}
scmd = scmd + " " + input
lcmd := strings.TrimSpace(strings.ToLower(scmd))
if strings.HasPrefix(lcmd, "select") {
res, err := engine.Query(scmd + "\n")
if err != nil {
fmt.Println(err)
} else {
if len(res) <= 0 {
fmt.Println("no records")
} else {
columns := make(map[string]int)
for k, _ := range res[0] {
columns[k] = len(k)
}
for _, m := range res {
for k, s := range m {
l := len(string(s))
if l > columns[k] {
columns[k] = l
}
}
}
var maxlen = 0
for _, l := range columns {
maxlen = maxlen + l + 3
}
maxlen = maxlen + 1
fmt.Println(strings.Repeat("-", maxlen))
fmt.Print("|")
slice := make([]string, 0)
for k, l := range columns {
fmt.Print(" " + k + " ")
fmt.Print(strings.Repeat(" ", l-len(k)))
fmt.Print("|")
slice = append(slice, k)
}
fmt.Print("\n")
for _, r := range res {
fmt.Print("|")
for _, k := range slice {
fmt.Print(" " + string(r[k]) + " ")
fmt.Print(strings.Repeat(" ", columns[k]-len(string(r[k]))))
fmt.Print("|")
}
fmt.Print("\n")
}
fmt.Println(strings.Repeat("-", maxlen))
//fmt.Println(res)
}
}
} else if lcmd == "show tables;" {
/*tables, err := engine.DBMetas()
if err != nil {
fmt.Println(err)
} else {
}*/
} else {
cnt, err := engine.Exec(scmd)
if err != nil {
fmt.Println(err)
} else {
fmt.Printf("%d records changed.\n", cnt)
}
}
scmd = ""
fmt.Print("xorm$ ")
}
}

View File

@ -1,21 +0,0 @@
{{ range .Imports}}
#include {{.}}
{{ end }}
{{range .Tables}}class {{Mapper .Name}} {
{{$table := .}}
public:
{{range .Columns}}{{$name := Mapper .Name}} {{Type .}} Get{{Mapper .Name}}() {
return this->m_{{UnTitle $name}};
}
void Set{{$name}}({{Type .}} {{UnTitle $name}}) {
this->m_{{UnTitle $name}} = {{UnTitle $name}};
}
{{end}}private:
{{range .Columns}}{{$name := Mapper .Name}} {{Type .}} m_{{UnTitle $name}};
{{end}}
}
{{end}}

View File

@ -1 +0,0 @@
lang=c++

View File

@ -1 +0,0 @@
lang=go

View File

@ -1,14 +0,0 @@
package {{.Model}}
import (
{{range .Imports}}"{{.}}"{{end}}
)
{{range .Tables}}
type {{Mapper .Name}} struct {
{{$table := .}}
{{range .Columns}} {{Mapper .Name}} {{Type .}}
{{end}}
}
{{end}}

View File

@ -1,3 +0,0 @@
lang=go
genJson=0
prefix=cos_

View File

@ -1,18 +0,0 @@
package {{.Model}}
{{$ilen := len .Imports}}
{{if gt $ilen 0}}
import (
{{range .Imports}}"{{.}}"{{end}}
)
{{end}}
{{range .Tables}}
type {{Mapper .Name}} struct {
{{$table := .}}
{{$columns := .Columns}}
{{range .ColumnsSeq}}{{$col := getCol $columns .}} {{Mapper $col.Name}} {{Type $col}} {{Tag $table $col}}
{{end}}
}
{{end}}

View File

@ -1,162 +0,0 @@
package main
import (
"fmt"
"github.com/dvirsky/go-pylog/logging"
"io"
"os"
"runtime"
"strings"
"sync"
"text/template"
"unicode"
"unicode/utf8"
)
// +build go1.1
// Test that go1.1 tag above is included in builds. main.go refers to this definition.
const go11tag = true
const version = "0.1"
// Commands lists the available commands and help topics.
// The order here is the order in which they are printed by 'gopm help'.
var commands = []*Command{
CmdReverse,
CmdShell,
}
func init() {
runtime.GOMAXPROCS(runtime.NumCPU())
}
func main() {
logging.SetLevel(logging.ALL)
// Check length of arguments.
args := os.Args[1:]
if len(args) < 1 {
usage()
return
}
// Show help documentation.
if args[0] == "help" {
help(args[1:])
return
}
// Check commands and run.
for _, comm := range commands {
if comm.Name() == args[0] && comm.Run != nil {
comm.Run(comm, args[1:])
exit()
return
}
}
fmt.Fprintf(os.Stderr, "xorm: unknown subcommand %q\nRun 'xorm help' for usage.\n", args[0])
setExitStatus(2)
exit()
}
var exitStatus = 0
var exitMu sync.Mutex
func setExitStatus(n int) {
exitMu.Lock()
if exitStatus < n {
exitStatus = n
}
exitMu.Unlock()
}
var usageTemplate = `xorm is a database tool based xorm package.
Usage:
xorm command [arguments]
The commands are:
{{range .}}{{if .Runnable}}
{{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}
Use "xorm help [command]" for more information about a command.
Additional help topics:
{{range .}}{{if not .Runnable}}
{{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}
Use "xorm help [topic]" for more information about that topic.
`
var helpTemplate = `{{if .Runnable}}usage: xorm {{.UsageLine}}
{{end}}{{.Long | trim}}
`
// tmpl executes the given template text on data, writing the result to w.
func tmpl(w io.Writer, text string, data interface{}) {
t := template.New("top")
t.Funcs(template.FuncMap{"trim": strings.TrimSpace, "capitalize": capitalize})
template.Must(t.Parse(text))
if err := t.Execute(w, data); err != nil {
panic(err)
}
}
func capitalize(s string) string {
if s == "" {
return s
}
r, n := utf8.DecodeRuneInString(s)
return string(unicode.ToTitle(r)) + s[n:]
}
func printUsage(w io.Writer) {
tmpl(w, usageTemplate, commands)
}
func usage() {
printUsage(os.Stderr)
os.Exit(2)
}
// help implements the 'help' command.
func help(args []string) {
if len(args) == 0 {
printUsage(os.Stdout)
// not exit 2: succeeded at 'gopm help'.
return
}
if len(args) != 1 {
fmt.Fprintf(os.Stderr, "usage: xorm help command\n\nToo many arguments given.\n")
os.Exit(2) // failed at 'gopm help'
}
arg := args[0]
for _, cmd := range commands {
if cmd.Name() == arg {
tmpl(os.Stdout, helpTemplate, cmd)
// not exit 2: succeeded at 'gopm help cmd'.
return
}
}
fmt.Fprintf(os.Stderr, "Unknown help topic %#q. Run 'xorm help'.\n", arg)
os.Exit(2) // failed at 'gopm help cmd'
}
var atexitFuncs []func()
func atexit(f func()) {
atexitFuncs = append(atexitFuncs, f)
}
func exit() {
for _, f := range atexitFuncs {
f()
}
os.Exit(exitStatus)
}