5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-02 20:03:01 +08:00

feat: new template generator

This commit is contained in:
Lea Anthony 2019-05-20 18:44:14 +10:00
parent 1ac16d1933
commit 7015b80888
No known key found for this signature in database
GPG Key ID: 33DAF7BB90A58405
7 changed files with 236 additions and 0 deletions

View File

@ -96,6 +96,7 @@ type Command struct {
flagCount int
log *Logger
helpFlag bool
hidden bool
}
// NewCommand creates a new Command
@ -106,6 +107,7 @@ func NewCommand(name string, description string, app *Cli, parentCommandPath str
SubCommandsMap: make(map[string]*Command),
App: app,
log: NewLogger(),
hidden: false,
}
// Set up command path
@ -212,6 +214,9 @@ func (c *Command) PrintHelp() {
c.log.White("Available commands:")
fmt.Println("")
for _, subcommand := range c.SubCommands {
if subcommand.isHidden() {
continue
}
spacer := strings.Repeat(" ", 3+c.longestSubcommand-len(subcommand.Name))
isDefault := ""
if subcommand.isDefaultCommand() {
@ -237,6 +242,16 @@ func (c *Command) isDefaultCommand() bool {
return c.App.defaultCommand == c
}
// isHidden returns true if the command is a hidden command
func (c *Command) isHidden() bool {
return c.hidden
}
// Hidden hides the command from the Help system
func (c *Command) Hidden() {
c.hidden = true
}
// Command - Defines a subcommand
func (c *Command) Command(name, description string) *Command {
result := NewCommand(name, description, c.App, c.CommandPath)

View File

@ -1,7 +1,9 @@
package cmd
import (
"bytes"
"crypto/md5"
"encoding/json"
"fmt"
"io"
"io/ioutil"
@ -174,6 +176,22 @@ func (fs *FSHelper) MkDir(dir string) error {
return os.Mkdir(dir, 0700)
}
// SaveAsJSON saves the JSON representation of the given data to the given filename
func (fs *FSHelper) SaveAsJSON(data interface{}, filename string) error {
var buf bytes.Buffer
e := json.NewEncoder(&buf)
e.SetEscapeHTML(false)
e.SetIndent("", " ")
e.Encode(data)
err := ioutil.WriteFile(filename, buf.Bytes(), 0755)
if err != nil {
return err
}
return nil
}
// LoadAsString will attempt to load the given file and return
// its contents as a string
func (fs *FSHelper) LoadAsString(filename string) (string, error) {

View File

@ -68,6 +68,17 @@ func (s *SystemHelper) ConfigFileIsValid() bool {
return err == nil
}
// GetAuthor returns a formatted string of the user's name and email
func (s *SystemHelper) GetAuthor() (string, error) {
var config *SystemConfig
config, err := s.LoadConfig()
if err != nil {
return "", err
}
return fmt.Sprintf("%s <%s>", config.Name, config.Email), nil
}
// BackupConfig attempts to backup the system config file
func (s *SystemHelper) BackupConfig() (string, error) {
now := strconv.FormatInt(time.Now().UTC().UnixNano(), 10)

View File

@ -3,12 +3,14 @@ package cmd
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"path/filepath"
"strings"
"text/template"
"github.com/kennygrant/sanitize"
"github.com/leaanthony/slicer"
)
@ -57,6 +59,36 @@ func NewTemplateHelper() *TemplateHelper {
}
}
// IsValidTemplate returns true if the given tempalte name resides on disk
func (t *TemplateHelper) IsValidTemplate(templateName string) bool {
pathToTemplate := filepath.Join(t.templateDir.fullPath, templateName)
return t.fs.DirExists(pathToTemplate)
}
// SanitizeFilename sanitizes the given string to make a valid filename
func (t *TemplateHelper) SanitizeFilename(name string) string {
return sanitize.Name(name)
}
// CreateNewTemplate creates a new template based on the given directory name and string
func (t *TemplateHelper) CreateNewTemplate(dirname string, details *TemplateMetadata) (string, error) {
// Check if this template has already been created
if t.IsValidTemplate(dirname) {
return "", fmt.Errorf("cannot create template in directory '%s' - already exists", dirname)
}
targetDir := filepath.Join(t.templateDir.fullPath, dirname)
err := t.fs.MkDir(targetDir)
if err != nil {
return "", err
}
targetMetadata := filepath.Join(targetDir, t.metadataFilename)
err = t.fs.SaveAsJSON(details, targetMetadata)
return targetDir, err
}
// LoadMetadata loads the template's 'metadata.json' file
func (t *TemplateHelper) LoadMetadata(dir string) (*TemplateMetadata, error) {
templateFile := filepath.Join(dir, t.metadataFilename)

View File

@ -0,0 +1,21 @@
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw*

View File

@ -0,0 +1,121 @@
// +build dev
package main
import (
"fmt"
"time"
"github.com/wailsapp/wails/cmd"
"gopkg.in/AlecAivazis/survey.v1"
)
var templateHelper = cmd.NewTemplateHelper()
var qs = []*survey.Question{
{
Name: "Name",
Prompt: &survey.Input{Message: "Please enter the name of your template (eg: React/Webpack Basic):"},
Validate: survey.Required,
},
{
Name: "ShortDescription",
Prompt: &survey.Input{Message: "Please enter a short description for the template (eg: React with Webpack 4):"},
Validate: survey.Required,
},
{
Name: "Description",
Prompt: &survey.Input{Message: "Please enter a long description:"},
Validate: survey.Required,
},
{
Name: "FrontendDir",
Prompt: &survey.Input{Message: "Please enter the name of the directory the frontend code resides (eg: frontend):"},
Validate: survey.Required,
},
{
Name: "Install",
Prompt: &survey.Input{Message: "Please enter the install command (eg: npm install):"},
Validate: survey.Required,
},
{
Name: "Build",
Prompt: &survey.Input{Message: "Please enter the build command (eg: npm run build):"},
Validate: survey.Required,
},
{
Name: "Serve",
Prompt: &survey.Input{Message: "Please enter the serve command (eg: npm run serve):"},
Validate: survey.Required,
},
{
Name: "Bridge",
Prompt: &survey.Input{Message: "Please enter the name of the directory to copy the wails bridge runtime (eg: src):"},
Validate: survey.Required,
},
}
func newTemplate(devCommand *cmd.Command) {
commandDescription := `This command scaffolds everything needed to develop a new template.`
newTemplate := devCommand.Command("newtemplate", "Generate a new template").
LongDescription(commandDescription)
newTemplate.Action(func() error {
logger.PrintSmallBanner("Generating new project template")
fmt.Println()
var answers cmd.TemplateMetadata
// perform the questions
err := survey.Ask(qs, &answers)
if err != nil {
fmt.Println(err.Error())
return err
}
dirname := templateHelper.SanitizeFilename(answers.Name)
prompt := []*survey.Question{{
Prompt: &survey.Input{
Message: "Please enter a directory name for the template:",
Default: dirname,
},
Validate: func(val interface{}) error {
err := survey.Required(val)
if err != nil {
return err
}
if templateHelper.IsValidTemplate(val.(string)) {
return fmt.Errorf("template directory already exists")
}
if templateHelper.SanitizeFilename(val.(string)) != val.(string) {
return fmt.Errorf("invalid directory name '%s'", val.(string))
}
return nil
},
}}
err = survey.Ask(prompt, &dirname)
if err != nil {
return err
}
answers.Version = "1.0.0"
answers.Created = time.Now().String()
// Get Author info from system info
system := cmd.NewSystemHelper()
author, err := system.GetAuthor()
if err == nil {
answers.Author = author
}
templateDirectory, err := templateHelper.CreateNewTemplate(dirname, &answers)
if err != nil {
return err
}
logger.Green("Created new template '%s' in directory '%s'", answers.Name, templateDirectory)
return nil
})
}

18
cmd/wails/10_dev.go Normal file
View File

@ -0,0 +1,18 @@
// +build dev
package main
func init() {
commandDescription := `This command provides access to developer tooling.`
devCommand := app.Command("dev", "A selection of developer tools").
LongDescription(commandDescription)
// Add subcommands
newTemplate(devCommand)
devCommand.Action(func() error {
devCommand.PrintHelp()
return nil
})
}