mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-02 19:50:15 +08:00
feat: new template generator
This commit is contained in:
parent
1ac16d1933
commit
7015b80888
15
cmd/cli.go
15
cmd/cli.go
@ -96,6 +96,7 @@ type Command struct {
|
|||||||
flagCount int
|
flagCount int
|
||||||
log *Logger
|
log *Logger
|
||||||
helpFlag bool
|
helpFlag bool
|
||||||
|
hidden bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCommand creates a new Command
|
// NewCommand creates a new Command
|
||||||
@ -106,6 +107,7 @@ func NewCommand(name string, description string, app *Cli, parentCommandPath str
|
|||||||
SubCommandsMap: make(map[string]*Command),
|
SubCommandsMap: make(map[string]*Command),
|
||||||
App: app,
|
App: app,
|
||||||
log: NewLogger(),
|
log: NewLogger(),
|
||||||
|
hidden: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up command path
|
// Set up command path
|
||||||
@ -212,6 +214,9 @@ func (c *Command) PrintHelp() {
|
|||||||
c.log.White("Available commands:")
|
c.log.White("Available commands:")
|
||||||
fmt.Println("")
|
fmt.Println("")
|
||||||
for _, subcommand := range c.SubCommands {
|
for _, subcommand := range c.SubCommands {
|
||||||
|
if subcommand.isHidden() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
spacer := strings.Repeat(" ", 3+c.longestSubcommand-len(subcommand.Name))
|
spacer := strings.Repeat(" ", 3+c.longestSubcommand-len(subcommand.Name))
|
||||||
isDefault := ""
|
isDefault := ""
|
||||||
if subcommand.isDefaultCommand() {
|
if subcommand.isDefaultCommand() {
|
||||||
@ -237,6 +242,16 @@ func (c *Command) isDefaultCommand() bool {
|
|||||||
return c.App.defaultCommand == c
|
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
|
// Command - Defines a subcommand
|
||||||
func (c *Command) Command(name, description string) *Command {
|
func (c *Command) Command(name, description string) *Command {
|
||||||
result := NewCommand(name, description, c.App, c.CommandPath)
|
result := NewCommand(name, description, c.App, c.CommandPath)
|
||||||
|
18
cmd/fs.go
18
cmd/fs.go
@ -1,7 +1,9 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@ -174,6 +176,22 @@ func (fs *FSHelper) MkDir(dir string) error {
|
|||||||
return os.Mkdir(dir, 0700)
|
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
|
// LoadAsString will attempt to load the given file and return
|
||||||
// its contents as a string
|
// its contents as a string
|
||||||
func (fs *FSHelper) LoadAsString(filename string) (string, error) {
|
func (fs *FSHelper) LoadAsString(filename string) (string, error) {
|
||||||
|
@ -68,6 +68,17 @@ func (s *SystemHelper) ConfigFileIsValid() bool {
|
|||||||
return err == nil
|
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
|
// BackupConfig attempts to backup the system config file
|
||||||
func (s *SystemHelper) BackupConfig() (string, error) {
|
func (s *SystemHelper) BackupConfig() (string, error) {
|
||||||
now := strconv.FormatInt(time.Now().UTC().UnixNano(), 10)
|
now := strconv.FormatInt(time.Now().UTC().UnixNano(), 10)
|
||||||
|
@ -3,12 +3,14 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
|
"github.com/kennygrant/sanitize"
|
||||||
"github.com/leaanthony/slicer"
|
"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
|
// LoadMetadata loads the template's 'metadata.json' file
|
||||||
func (t *TemplateHelper) LoadMetadata(dir string) (*TemplateMetadata, error) {
|
func (t *TemplateHelper) LoadMetadata(dir string) (*TemplateMetadata, error) {
|
||||||
templateFile := filepath.Join(dir, t.metadataFilename)
|
templateFile := filepath.Join(dir, t.metadataFilename)
|
||||||
|
21
cmd/templates/vuebasic/frontend/.gitignore
vendored
Normal file
21
cmd/templates/vuebasic/frontend/.gitignore
vendored
Normal 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*
|
121
cmd/wails/10.1_dev_newtemplate.go
Normal file
121
cmd/wails/10.1_dev_newtemplate.go
Normal 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
18
cmd/wails/10_dev.go
Normal 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
|
||||||
|
})
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user