cmd: Add more docs

This commit is contained in:
Albert Nigmatzianov 2017-04-29 14:53:52 +02:00
parent 32756eb440
commit 0dd1c429a3
6 changed files with 90 additions and 67 deletions

View file

@ -107,7 +107,7 @@ func init() {
data["parentName"] = parentName
data["cmdName"] = cmdName
filePath := filepath.Join(project.AbsPath(), project.CmdDir(), cmdName+".go")
filePath := filepath.Join(project.CmdPath(), cmdName+".go")
cmdScript, err := executeTemplate(template, data)
if err != nil {

View file

@ -99,38 +99,36 @@ func executeTemplate(tmplStr string, data interface{}) (string, error) {
}
func writeStringToFile(path string, s string) error {
return safeWriteToDisk(path, strings.NewReader(s))
return writeToFile(path, strings.NewReader(s))
}
// safeWriteToDisk as WriteToDisk but checks to see if file/directory already exists.
func safeWriteToDisk(inpath string, r io.Reader) (err error) {
dir := filepath.Dir(inpath)
ospath := filepath.FromSlash(dir)
if ospath != "" {
err = os.MkdirAll(ospath, 0777)
if err != nil {
return
}
// writeToFile writes r to file with path only
// if file/directory on given path doesn't exist.
// If file/directory exists on given path, then
// it terminates app and prints an appropriate error.
func writeToFile(path string, r io.Reader) error {
if exists(path) {
return fmt.Errorf("%v already exists", path)
}
if exists(inpath) {
return fmt.Errorf("%v already exists", inpath)
}
if _, err := os.Stat(inpath); err != nil && !os.IsNotExist(err) {
dir := filepath.Dir(path)
if dir != "" {
if err := os.MkdirAll(dir, 0777); err != nil {
return err
}
}
file, err := os.Create(inpath)
file, err := os.Create(path)
if err != nil {
return
return err
}
defer file.Close()
_, err = io.Copy(file, r)
return
return err
}
// commentfyString comments every line of in.
func commentifyString(in string) string {
var newlines []string
lines := strings.Split(in, "\n")

View file

@ -27,7 +27,6 @@ func init() {
RootCmd.AddCommand(initCmd)
}
// initialize Command
var initCmd = &cobra.Command{
Use: "init [name]",
Aliases: []string{"initialize", "initialise", "create"},
@ -69,27 +68,27 @@ func initializePath(project *Project) {
er(err)
}
} else if !isEmpty(project.AbsPath()) { // If path exists and is not empty don't use it
er("Cobra will not create a new project in a non empty directory")
er("Cobra will not create a new project in a non empty directory: " + project.AbsPath())
}
// We have a directory and it's empty.. Time to initialize it.
createLicenseFile(project)
// We have a directory and it's empty. Time to initialize it.
createLicenseFile(project.License(), project.AbsPath())
createMainFile(project)
createRootCmdFile(project)
}
func createLicenseFile(project *Project) {
func createLicenseFile(license License, path string) {
data := make(map[string]interface{})
data["copyright"] = copyrightLine()
// Generate license template from text and data.
text, err := executeTemplate(project.License().Text, data)
text, err := executeTemplate(license.Text, data)
if err != nil {
er(err)
}
// Write license text to LICENSE file.
err = writeStringToFile(filepath.Join(project.AbsPath(), "LICENSE"), text)
err = writeStringToFile(filepath.Join(path, "LICENSE"), text)
if err != nil {
er(err)
}
@ -110,7 +109,7 @@ func main() {
data := make(map[string]interface{})
data["copyright"] = copyrightLine()
data["license"] = project.License().Header
data["importpath"] = path.Join(project.Name(), project.CmdDir())
data["importpath"] = path.Join(project.Name(), filepath.Base(project.CmdPath()))
mainScript, err := executeTemplate(mainTemplate, data)
if err != nil {
@ -199,19 +198,21 @@ func initConfig() {
data["copyright"] = copyrightLine()
data["viper"] = viper.GetBool("useViper")
data["license"] = project.License().Header
data["appName"] = path.Base(project.Name())
rootCmdScript, err := executeTemplate(template, data)
if err != nil {
er(err)
}
err = writeStringToFile(filepath.Join(project.AbsPath(), project.CmdDir(), "root.go"), rootCmdScript)
err = writeStringToFile(filepath.Join(project.CmdPath(), "root.go"), rootCmdScript)
if err != nil {
er(err)
}
fmt.Println("Your Cobra application is ready at")
fmt.Println(project.AbsPath() + "\n")
fmt.Println("Give it a try by going there and running `go run main.go`.")
fmt.Println("Add commands to it by running `cobra add [cmdname]`")
fmt.Println(`Your Cobra application is ready at
` + project.AbsPath() + `.
Give it a try by going there and running ` + "`go run main.go`." + `
Add commands to it by running ` + "`cobra add [cmdname]`.")
}

View file

@ -16,18 +16,17 @@
package cmd
import (
"fmt"
"strings"
"time"
"github.com/spf13/viper"
)
//Licenses contains all possible licenses a user can chose from
var Licenses map[string]License
// Licenses contains all possible licenses a user can choose from.
var Licenses = make(map[string]License)
// License represents a software license agreement, containing the Name of
// the license, its possible matches (on the command line as given to cobra)
// the license, its possible matches (on the command line as given to cobra),
// the header to be used with each file on the file's creating, and the text
// of the license
type License struct {
@ -38,8 +37,6 @@ type License struct {
}
func init() {
Licenses = make(map[string]License)
// Allows a user to not use a license.
Licenses["none"] = License{"None", []string{"none", "false"}, "", ""}
@ -53,6 +50,9 @@ func init() {
initAgpl()
}
// getLicense returns license specified by user in flag or in config.
// If user didn't specify the license, it returns Apache License 2.0.
//
// TODO: Inspect project for existing license
func getLicense() License {
// If explicitly flagged, use that.
@ -72,7 +72,6 @@ func getLicense() License {
}
// If user didn't set any license, use Apache 2.0 by default.
fmt.Println("apache")
return Licenses["apache"]
}
@ -83,15 +82,21 @@ func copyrightLine() string {
return "Copyright © " + year + " " + author
}
// findLicense looks for License object of built-in licenses.
// If it didn't find license, then the app will be terminated and
// error will be printed.
func findLicense(name string) License {
found := matchLicense(name)
if found == "" {
er(fmt.Errorf("unknown license %q", name))
er("unknown license: " + name)
}
return Licenses[found]
}
// given a license name, try to match the license indicated
// matchLicense compares the given a license name
// to PossibleMatches of all built-in licenses.
// It returns blank string, if name is blank string or it didn't find
// then appropriate match to name.
func matchLicense(name string) string {
if name == "" {
return ""

View file

@ -6,14 +6,17 @@ import (
"strings"
)
// Project contains name, license and paths to projects.
type Project struct {
absPath string
cmdDir string
cmdPath string
srcPath string
license License
name string
}
// NewProject returns Project with specified project name.
// If projectName is blank string, it returns nil.
func NewProject(projectName string) *Project {
if projectName == "" {
return nil
@ -25,8 +28,8 @@ func NewProject(projectName string) *Project {
// 1. Find already created protect.
p.absPath = findPackage(projectName)
// 2. If there are no created project with this path and user in GOPATH,
// then use GOPATH+projectName.
// 2. If there are no created project with this path, and user is in GOPATH,
// then use GOPATH/src+projectName.
if p.absPath == "" {
wd, err := os.Getwd()
if err != nil {
@ -34,7 +37,7 @@ func NewProject(projectName string) *Project {
}
for _, goPath := range goPaths {
if filepath.HasPrefix(wd, goPath) {
p.absPath = filepath.Join(goPath, projectName)
p.absPath = filepath.Join(goPath, "src", projectName)
break
}
}
@ -48,14 +51,9 @@ func NewProject(projectName string) *Project {
return p
}
// findPackage returns full path to go package. It supports multiple GOPATHs.
// findPackage returns full path to existing go package in GOPATHs.
// findPackage returns "", if it can't find path.
// If packageName is "", findPackage returns "" too.
//
// For example, package "github.com/spf13/hugo"
// is located in /home/user/go/src/github.com/spf13/hugo,
// then `findPackage("github.com/spf13/hugo")`
// will return "/home/user/go/src/github.com/spf13/hugo"
// If packageName is "", findPackage returns "".
func findPackage(packageName string) string {
if packageName == "" {
return ""
@ -71,6 +69,10 @@ func findPackage(packageName string) string {
return ""
}
// NewProjectFromPath returns Project with specified absolute path to
// package.
// If absPath is blank string or if absPath is not actually absolute,
// it returns nil.
func NewProjectFromPath(absPath string) *Project {
if absPath == "" || !filepath.IsAbs(absPath) {
return nil
@ -78,51 +80,68 @@ func NewProjectFromPath(absPath string) *Project {
p := new(Project)
p.absPath = absPath
p.absPath = strings.TrimSuffix(p.absPath, p.CmdDir())
p.absPath = strings.TrimSuffix(p.absPath, findCmdDir(p.absPath))
p.name = filepath.ToSlash(trimSrcPath(p.absPath, p.SrcPath()))
return p
}
// trimSrcPath trims at the end of absPaththe srcPath.
func trimSrcPath(absPath, srcPath string) string {
relPath, err := filepath.Rel(srcPath, absPath)
if err != nil {
er("Cobra only supports project within $GOPATH")
er("Cobra supports project only within $GOPATH")
}
return relPath
}
// License returns the License object of project.
func (p *Project) License() License {
if p.license.Text == "" { // check if license is not blank
if p.license.Text == "" && p.license.Name != "None" {
p.license = getLicense()
}
return p.license
}
// Name returns the name of project, e.g. "github.com/spf13/cobra"
func (p Project) Name() string {
return p.name
}
func (p *Project) CmdDir() string {
// CmdPath returns absolute path to directory, where all commands are located.
//
// CmdPath returns blank string, only if p.AbsPath() is a blank string.
func (p *Project) CmdPath() string {
if p.absPath == "" {
return ""
}
if p.cmdDir == "" {
p.cmdDir = findCmdDir(p.absPath)
if p.cmdPath == "" {
p.cmdPath = filepath.Join(p.absPath, findCmdDir(p.absPath))
}
return p.cmdDir
return p.cmdPath
}
// findCmdDir checks if base of absPath is cmd dir and returns it or
// looks for existing cmd dir in absPath.
// If the cmd dir doesn't exist, empty, or cannot be found,
// it returns "cmd".
func findCmdDir(absPath string) string {
if !exists(absPath) || isEmpty(absPath) {
return "cmd"
}
base := filepath.Base(absPath)
for _, cmdDir := range cmdDirs {
if base == cmdDir {
return cmdDir
}
}
files, _ := filepath.Glob(filepath.Join(absPath, "c*"))
for _, f := range files {
for _, c := range cmdDirs {
if f == c {
return c
for _, file := range files {
for _, cmdDir := range cmdDirs {
if file == cmdDir {
return cmdDir
}
}
}
@ -130,10 +149,12 @@ func findCmdDir(absPath string) string {
return "cmd"
}
// AbsPath returns absolute path of project.
func (p Project) AbsPath() string {
return p.absPath
}
// SrcPath returns absolute path to $GOPATH/src where project is located.
func (p *Project) SrcPath() string {
if p.srcPath != "" {
return p.srcPath

View file

@ -23,7 +23,6 @@ import (
var cfgFile, projectBase, userLicense string // are used for flags
// RootCmd represents the base command when called without any subcommands
var RootCmd = &cobra.Command{
Use: "cobra",
Short: "A generator for Cobra based Applications",
@ -32,7 +31,6 @@ This application is a tool to generate the needed files
to quickly create a Cobra application.`,
}
//Execute adds all child commands to the root command sets flags appropriately.
func Execute() {
if err := RootCmd.Execute(); err != nil {
fmt.Println(err)