From feddadaeee1824701a198ea26c776909259976c5 Mon Sep 17 00:00:00 2001 From: Unknown Date: Thu, 16 May 2013 05:48:11 -0400 Subject: [PATCH] initialize --- LICENSE | 2 +- gpm.go | 277 +++++++++++++++++++++++++++++++++++++++++++ i18n/gpm.toml | 5 + i18n/usage_en-US.tpl | 18 +++ 4 files changed, 301 insertions(+), 1 deletion(-) create mode 100644 gpm.go create mode 100644 i18n/gpm.toml create mode 100644 i18n/usage_en-US.tpl diff --git a/LICENSE b/LICENSE index ab7628fba..87feceb7f 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2013 GPMGo members. +Copyright (c) 2013 GPMGo Members. All rights reserved. MIT +no-false-attribs License diff --git a/gpm.go b/gpm.go new file mode 100644 index 000000000..2c0a1ab3f --- /dev/null +++ b/gpm.go @@ -0,0 +1,277 @@ +// Copyright (c) 2013 GPMGo Members. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +// gpm(Go Package Manager) is a Go package manage tool for search, install, update and share packages in Go. + +package main + +import ( + "bytes" + "flag" + "fmt" + "go/build" + "io" + "log" + "os" + "path/filepath" + "runtime" + "strings" + "sync" + "text/template" + "unicode" + "unicode/utf8" + + "github.com/BurntSushi/toml" +) + +var ( + config tomlConfig +) + +type tomlConfig struct { + Title, Version string + Lang string `toml:"user_language"` +} + +// 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 ' output. + Long string + + // Flag is a set of flags specific to this command. + Flag flag.FlagSet + + // CustomFlags indicates that the command will do its own + // flag parsing. + CustomFlags 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 +} + +// Commands lists the available commands and help topics. +// The order here is the order in which they are printed by 'go help'. +var commands = []*Command{} + +var exitStatus = 0 +var exitMu sync.Mutex + +func setExitStatus(n int) { + exitMu.Lock() + if exitStatus < n { + exitStatus = n + } + exitMu.Unlock() +} + +func main() { + // Load configuration. + if _, err := toml.DecodeFile("i18n/gpm.toml", &config); err != nil { + fmt.Println(err) + return + } + + // Load usage template by language. + f, err := os.Open("i18n/usage_" + config.Lang + ".tpl") + if err != nil { + fmt.Println(err) + return + } + defer f.Close() + // Read usage. + fi, _ := f.Stat() + usageBytes := make([]byte, fi.Size()) + f.Read(usageBytes) + usageTemplate = string(usageBytes) + + // Initialization. + flag.Usage = usage + flag.Parse() + log.SetFlags(0) + + args := flag.Args() + if len(args) < 1 { + usage() + } + + if args[0] == "help" { + help(args[1:]) + return + } + + // Diagnose common mistake: GOPATH==GOROOT. + // This setting is equivalent to not setting GOPATH at all, + // which is not what most people want when they do it. + if gopath := os.Getenv("GOPATH"); gopath == runtime.GOROOT() { + fmt.Fprintf(os.Stderr, "warning: GOPATH set to GOROOT (%s) has no effect\n", gopath) + } else { + for _, p := range filepath.SplitList(gopath) { + // Note: using HasPrefix instead of Contains because a ~ can appear + // in the middle of directory elements, such as /tmp/git-1.8.2~rc3 + // or C:\PROGRA~1. Only ~ as a path prefix has meaning to the shell. + if strings.HasPrefix(p, "~") { + fmt.Fprintf(os.Stderr, "go: GOPATH entry cannot start with shell metacharacter '~': %q\n", p) + os.Exit(2) + } + if build.IsLocalImport(p) { + fmt.Fprintf(os.Stderr, "go: GOPATH entry is relative; must be absolute path: %q.\nRun 'go help gopath' for usage.\n", p) + os.Exit(2) + } + } + } + + for _, cmd := range commands { + if cmd.Name() == args[0] && cmd.Run != nil { + cmd.Flag.Usage = func() { cmd.Usage() } + if cmd.CustomFlags { + args = args[1:] + } else { + cmd.Flag.Parse(args[1:]) + args = cmd.Flag.Args() + } + cmd.Run(cmd, args) + exit() + return + } + } + + fmt.Fprintf(os.Stderr, "go: unknown subcommand %q\nRun 'go help' for usage.\n", args[0]) + setExitStatus(2) + exit() +} + +var usageTemplate string +var helpTemplate = `{{if .Runnable}}usage: go {{.UsageLine}} + +{{end}}{{.Long | trim}} +` + +var documentationTemplate = `// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// DO NOT EDIT THIS FILE. GENERATED BY mkdoc.sh. +// Edit the documentation in other files and rerun mkdoc.sh to generate this one. + +/* +{{range .}}{{if .Short}}{{.Short | capitalize}} + +{{end}}{{if .Runnable}}Usage: + + go {{.UsageLine}} + +{{end}}{{.Long | trim}} + + +{{end}}*/ +package main + +// NOTE: cmdDoc is in fmt.go. +` + +// 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 'gpm help'. + return + } + if len(args) != 1 { + fmt.Fprintf(os.Stderr, "usage: gpm help command\n\nToo many arguments given.\n") + os.Exit(2) // failed at 'gpm help' + } + + arg := args[0] + + // 'go help documentation' generates doc.go. + if arg == "documentation" { + buf := new(bytes.Buffer) + printUsage(buf) + usage := &Command{Long: buf.String()} + tmpl(os.Stdout, documentationTemplate, append([]*Command{usage}, commands...)) + return + } + + for _, cmd := range commands { + if cmd.Name() == arg { + tmpl(os.Stdout, helpTemplate, cmd) + // not exit 2: succeeded at 'go help cmd'. + return + } + } + + fmt.Fprintf(os.Stderr, "Unknown help topic %#q. Run 'gpm help'.\n", arg) + os.Exit(2) // failed at 'go help cmd' +} + +var atexitFuncs []func() + +func atexit(f func()) { + atexitFuncs = append(atexitFuncs, f) +} + +func exit() { + for _, f := range atexitFuncs { + f() + } + os.Exit(exitStatus) +} diff --git a/i18n/gpm.toml b/i18n/gpm.toml new file mode 100644 index 000000000..d4e9ea066 --- /dev/null +++ b/i18n/gpm.toml @@ -0,0 +1,5 @@ +# This is a configuration file for gpm with toml format. + +title = "gpm(Go Package Manager)" +version = "v0.0.0 Build 0516" +user_language = "en-US" \ No newline at end of file diff --git a/i18n/usage_en-US.tpl b/i18n/usage_en-US.tpl new file mode 100644 index 000000000..a1bb4a1c9 --- /dev/null +++ b/i18n/usage_en-US.tpl @@ -0,0 +1,18 @@ +gpm is a Go package manage tool for search, install, update and share packages. + +Usage: + + gpm command [arguments] + +The commands are: +{{range .}}{{if .Runnable}} + {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}} + +Use "gpm help [command]" for more information about a command. + +Additional help topics: +{{range .}}{{if not .Runnable}} + {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}} + +Use "gpm help [topic]" for more information about that topic. +