Parcourir la source

feat: 添加 make cmd 命令 \r\n例如: gohub make cmd testCommand

runningwater il y a 7 mois
Parent
commit
53724c8c57
7 fichiers modifiés avec 228 ajouts et 0 suppressions
  1. 1 0
      CHANGELOG.md
  2. 132 0
      app/cmd/make/make.go
  3. 33 0
      app/cmd/make/make_cmd.go
  4. 24 0
      app/cmd/make/stubs/cmd.stub
  5. 4 0
      main.go
  6. 28 0
      pkg/file/file.go
  7. 6 0
      pkg/str/str.go

+ 1 - 0
CHANGELOG.md

@@ -6,6 +6,7 @@
 
 ### ⚙️ 辅助工具的变动
 
+- 参数格式化(str 包)
 - Changelog file
 - Git-cliff generator changelog files
 - Console 包

+ 132 - 0
app/cmd/make/make.go

@@ -0,0 +1,132 @@
+package make
+
+import (
+	"embed"
+	"fmt"
+
+	"github.com/runningwater/gohub/pkg/console"
+	"github.com/runningwater/gohub/pkg/file"
+	"github.com/runningwater/gohub/pkg/str"
+	"github.com/spf13/cobra"
+)
+
+// Model 参数解释
+// 单个词,用户命令传参,以 User 模型为例:
+//   - user
+//   - User
+//   - users
+//   - Users
+//
+// 整理好的数据:
+//
+//	{
+//	    "TableName": "users",
+//	    "StructName": "User",
+//	    "StructNamePlural": "Users"
+//	    "VariableName": "user",
+//	    "VariableNamePlural": "users",
+//	    "PackageName": "user"
+//	}
+//
+// -
+// 两个词或者以上,用户命令传参,以 TopicComment 模型为例:
+//   - topic_comment
+//   - topic_comments
+//   - TopicComment
+//   - TopicComments
+//
+// 整理好的数据:
+//
+//	{
+//	    "TableName": "topic_comments",
+//	    "StructName": "TopicComment",
+//	    "StructNamePlural": "TopicComments"
+//	    "VariableName": "topicComment",
+//	    "VariableNamePlural": "topicComments",
+//	    "PackageName": "topic_comment"
+//	}
+type Model struct {
+	TableName          string
+	StructName         string
+	StructNamePlural   string
+	VariableName       string
+	VariableNamePlural string
+	PackageName        string
+}
+
+// stubsFS 方便我们后面打包的 .stub 为后缀的文件
+//
+//go:embed stubs
+var stubsFS embed.FS
+
+var CmdMake = &cobra.Command{
+	Use:   "make",
+	Short: "Generate code and file",
+}
+
+func init() {
+	// 注册 make 子命令
+	CmdMake.AddCommand(
+		CmdMakeCMD,
+	)
+}
+
+// makeModelFromString 通过用户传入的字符串,生成模型数据
+func makeModelFromString(name string) Model {
+	model := Model{}
+	model.StructName = str.Singular(str.Camel(name))
+	model.StructNamePlural = str.Plural(model.StructName)
+	model.TableName = str.Snake(model.StructNamePlural)
+	model.VariableName = str.LowerCamel(model.StructName)
+	model.PackageName = str.Snake(model.StructName)
+	model.VariableNamePlural = str.LowerCamel(model.StructNamePlural)
+
+	return model
+
+}
+
+// createFileFromStub 读取 stub 文件并进行变量替换
+// 最后个选项可选参数,允许用户传递变量替换
+func createFileFromStub(filePath, stubName string, model Model, vars ...map[string]string) {
+
+	replaces := make(map[string]string)
+	if len(vars) > 0 {
+		for _, _var := range vars {
+			for k, v := range _var {
+				replaces[k] = v
+			}
+		}
+	}
+
+	// 文件已经存在
+	if file.Exists(filePath) {
+		console.Exit(filePath + " already exists")
+	}
+
+	// 读取 stub 文件内容
+	stub, err := stubsFS.ReadFile("stubs/" + stubName + ".stub")
+	if err != nil {
+		console.Exit(err.Error())
+	}
+	modelStub := string(stub)
+
+	// 替换变量,默认的变量
+	replaces["{{TableName}}"] = model.TableName
+	replaces["{{StructName}}"] = model.StructName
+	replaces["{{StructNamePlural}}"] = model.StructNamePlural
+	replaces["{{VariableName}}"] = model.VariableName
+	replaces["{{VariableNamePlural}}"] = model.VariableNamePlural
+	replaces["{{PackageName}}"] = model.PackageName
+	// 替换变量
+	for search, replace := range replaces {
+		modelStub = str.ReplaceAll(modelStub, search, replace)
+	}
+
+	// 存储到目标文件中
+	err = file.Put([]byte(modelStub), filePath)
+	if err != nil {
+		console.Exit(err.Error())
+	}
+
+	console.Success(fmt.Sprintf("[%s] created.", filePath))
+}

+ 33 - 0
app/cmd/make/make_cmd.go

@@ -0,0 +1,33 @@
+package make
+
+import (
+	"fmt"
+
+	"github.com/runningwater/gohub/pkg/console"
+	"github.com/spf13/cobra"
+)
+
+var CmdMakeCMD = &cobra.Command{
+	Use:   "cmd",
+	Short: "Create a command, should be snake case, like: make cmd test_cmd",
+	Run:   runMakeCMD,
+	Args:  cobra.ExactArgs(1), // 只允许且必须传 1 个参数
+}
+
+// runMakeCMD 运行命令行
+// 该函数会被 cobra 自动调用
+func runMakeCMD(cmd *cobra.Command, args []string) {
+	// 格式化模型名称,返回一个 Model 实例
+	model := makeModelFromString(args[0])
+
+	filePath := fmt.Sprintf("app/cmd/%s.go", model.PackageName)
+
+	// 从模板中创建文件
+	createFileFromStub(filePath, "cmd", model)
+
+	// 输出成功信息
+	console.Success(fmt.Sprintf("Create %s success", filePath))
+	console.Info(fmt.Sprintf("command name: %s", model.PackageName))
+	console.Info(fmt.Sprintf("command variable name: cmd.Cmd %s", model.StructName))
+	console.Warning("Please edit main.go's app.Commands slice to register this command")
+}

+ 24 - 0
app/cmd/make/stubs/cmd.stub

@@ -0,0 +1,24 @@
+package cmd
+
+import (
+	"errors"
+
+	"github.com/runningwater/gohub/pkg/console"
+	"github.com/spf13/cobra"
+)
+
+var Cmd{{StructName}} = &cobra.Command{
+	Use:   "{{PackageName}}",
+	Short: "Here puts the command description",
+	Run:   runCmd{{StructName}},
+	Args:  cobra.ExactArgs(1), // 只允许且必须传 1 个参数
+}
+
+func runCmd{{StructName}}(cmd *cobra.Command, args []string) {
+	console.Success("这是一条成功的提示")
+	console.Warning("这是一条提示")
+	console.Error("这是一条错误信息")
+	console.Warning("终端输出最好使用英文,这样兼容性会更好~")
+	console.Exit("exit 方法可以用来打印消息并中断程序!")
+	console.ExitIf(errors.New("在 err != nil 的时候打印并退出"))
+}

+ 4 - 0
main.go

@@ -7,6 +7,7 @@ import (
 	"github.com/spf13/cobra"
 
 	"github.com/runningwater/gohub/app/cmd"
+	"github.com/runningwater/gohub/app/cmd/make"
 	"github.com/runningwater/gohub/bootstrap"
 	appConfig "github.com/runningwater/gohub/config"
 	"github.com/runningwater/gohub/pkg/config"
@@ -48,6 +49,9 @@ func main() {
 		cmd.CmdServe,
 		cmd.CmdKey,
 		cmd.CmdPlay,
+		cmd.CmdTestCommand,
+
+		make.CmdMake,
 	)
 
 	// 配置默认运行 Web 服务

+ 28 - 0
pkg/file/file.go

@@ -0,0 +1,28 @@
+package file
+
+import "os"
+
+// Put 将数据写入文件
+// 如果文件不存在,则创建文件
+// 如果文件存在,则覆盖文件
+// data: 要写入的数据
+// to: 要写入的文件路径
+// return:
+// 如果成功,则返回 nil
+// 如果失败,则返回错误信息
+func Put(data []byte, to string) error {
+	return os.WriteFile(to, data, 0644)
+}
+
+// Exists 判断文件是否存在
+// path: 文件路径
+// return:
+// 如果文件存在,则返回 true
+// 如果文件不存在,则返回 false
+func Exists(path string) bool {
+	_, err := os.Stat(path)
+	if os.IsNotExist(err) {
+		return false
+	}
+	return true
+}

+ 6 - 0
pkg/str/str.go

@@ -2,6 +2,8 @@
 package str
 
 import (
+	"strings"
+
 	"github.com/gertd/go-pluralize"
 	"github.com/iancoleman/strcase"
 )
@@ -30,3 +32,7 @@ func Camel(word string) string {
 func LowerCamel(word string) string {
 	return strcase.ToLowerCamel(word)
 }
+
+func ReplaceAll(s, old, new string) string {
+	return strings.ReplaceAll(s, old, new)
+}