From fc35a578e085b10313d513745a1c1638cdec3092 Mon Sep 17 00:00:00 2001 From: Kaxi <1042864399@qq.com> Date: Fri, 10 Oct 2025 00:43:43 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=BC=93=E5=AD=98=E6=9C=BA?= =?UTF-8?q?=E5=88=B6=20=E8=A1=A5=E5=85=85=E9=94=99=E8=AF=AF=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/mod.go | 43 ++++++++++ config/mod_config.go | 24 ++++++ worker/mod_worker.go | 200 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 267 insertions(+) create mode 100644 cmd/mod.go create mode 100644 config/mod_config.go create mode 100644 worker/mod_worker.go diff --git a/cmd/mod.go b/cmd/mod.go new file mode 100644 index 0000000..6e8664b --- /dev/null +++ b/cmd/mod.go @@ -0,0 +1,43 @@ +package cmd + +import ( + "complie-erlang/worker" + "fmt" + "github.com/spf13/cobra" + "log" +) + +type modSet struct{} + +func (m *modSet) run(cmd *cobra.Command, args []string) { + if len(args) == 0 { + _ = cmd.Help() + return + } + modName := args[0] + modArgs := args[1:] + + if err := worker.ModWorkerRun(modName, modArgs); err != nil { + log.Printf("[error] mod worker run error: %v", err) + } + + fmt.Printf("ok \n") +} + +func init() { + var singleSet = new(modSet) + var singleCmd = &cobra.Command{ + Use: "mod", + Short: "根据约定模板生成 多个文件构建 功能模版", + Long: ` +- 根据约定模板生成 + +mod activity activity_test.proto +mod func test1.proto + +`, + Run: singleSet.run, + } + + rootCmd.AddCommand(singleCmd) +} diff --git a/config/mod_config.go b/config/mod_config.go new file mode 100644 index 0000000..08bea65 --- /dev/null +++ b/config/mod_config.go @@ -0,0 +1,24 @@ +package config + +type ModConfigs struct { + TemplateDir string `yaml:"template_dir"` + Plugin string `yaml:"plugin"` + ModConfigs []ModConfig `yaml:"mod_configs"` +} +type ModConfig struct { + Name string `yaml:"name"` // 模板关键词 + Worker string `yaml:"worker"` // 输入参数 + ProtoName string `yaml:"proto_name"` + MakeDir []ModDir `yaml:"make_dir"` + OutFiles []ModFile `yaml:"out_files"` +} + +type ModDir struct { + Name string `yaml:"name"` + Path string `yaml:"path"` +} +type ModFile struct { + BaseDir string `yaml:"base_dir"` // + FileName string `yaml:"file_name"` + ContentTemplate string `yaml:"content_template"` // 文件内容模板 +} diff --git a/worker/mod_worker.go b/worker/mod_worker.go new file mode 100644 index 0000000..565f11e --- /dev/null +++ b/worker/mod_worker.go @@ -0,0 +1,200 @@ +package worker + +import ( + "complie-erlang/config" + "complie-erlang/parser/zm_lib" + "complie-erlang/parser/zm_proto" + tm "complie-erlang/template" + "errors" + "fmt" + "gopkg.in/yaml.v2" + "log" + "os" + "path/filepath" + "time" +) + +type ModWorker interface { + Name() string + LoadCfg(BaseSet, []string) error + OutPutFiles() ([]string, error) +} + +type BaseSet struct { + ModConfigs *config.ModConfigs + Conf config.ModConfig +} + +func ModWorkerRun(name string, args []string) error { + + xmlPath, err := zm_lib.FindPathByExecutable("./mod_config.yaml") + if err != nil { + return fmt.Errorf("find xml path error: %v", err) + } + + bytes, err := os.ReadFile(xmlPath) + if err != nil { + return fmt.Errorf("读取配置文件失败: %v", err) + } + + var conf = config.ModConfigs{} + + if err = yaml.Unmarshal(bytes, &conf); err != nil { + return fmt.Errorf("解析配置文件 %s 失败: %v", xmlPath, err) + } + + var modWorkerName string + var baseSet BaseSet + + baseSet.ModConfigs = &conf + + for _, modconfig := range conf.ModConfigs { + if modconfig.Name == name { + modWorkerName = modconfig.Worker + baseSet.Conf = modconfig + break + } + } + if modWorkerName == "" { + return fmt.Errorf("无效的 %s", name) + } + + for _, worker := range AllWorkers() { + if worker.Name() == modWorkerName { + log.Printf("[info] 初始化开始。。。") + if err := worker.LoadCfg(baseSet, args); err != nil { + return fmt.Errorf("初始化 Err:%v", err) + } + log.Printf("[info] 初始化完成 开始生成输出。。。") + + outFiles, err := worker.OutPutFiles() + if err != nil { + return fmt.Errorf("生成输出 Err:%v", err) + } + log.Printf("[info] 生成完成: \n") + for _, outFile := range outFiles { + log.Printf(" - %s:0\n", outFile) + } + return nil + } + } + return errors.New("worker not found") +} + +func AllWorkers() []ModWorker { + return []ModWorker{&ProtoModWorker{}} +} + +type ProtoModWorker struct { + set BaseSet + Args []string + DefaultArgs []config.DefaultArg + + templates *tm.Template // 模板 + pluginPath string + parsePort []zm_proto.Port + proto *zm_proto.Proto +} + +func (mod *ProtoModWorker) Name() string { + return "proto" +} + +func (mod *ProtoModWorker) LoadCfg(set BaseSet, Args []string) error { + mod.set = set + mod.Args = Args + log.Println("[info] 加载配置 set:", set.Conf, "args:", Args) + + pluginPathByWd, err := zm_lib.GetPluginPathByWd(set.ModConfigs.Plugin) + if err != nil { + return err + } + log.Println("[info] 项目根目录:", pluginPathByWd) + mod.pluginPath = pluginPathByWd + + // 加载模版 + findPathByExecutable, err := zm_lib.FindPathByExecutable(set.ModConfigs.TemplateDir) + if err != nil { + return err + } + log.Println("[info] 加载模板:", findPathByExecutable) + + mod.templates = tm.NewTemplate() + if err = mod.templates.ParseGlob(findPathByExecutable); err != nil { + return err + } + + protoFile := filepath.Join(mod.pluginPath, fmt.Sprintf(mod.set.Conf.ProtoName, mod.Args[0])) + log.Printf("[info] 加载proto文件: %s:1\n", protoFile) + + proto := zm_proto.NewProto() + proto.Include(filepath.Dir(protoFile)) + if err = proto.ParseImport(filepath.Base(protoFile)); err != nil { + return err + } + parsePort, err := zm_proto.ParsePort(proto, protoFile) + if err != nil { + return err + } + mod.proto = proto + mod.parsePort = parsePort + + for _, p := range mod.parsePort { + log.Printf("[info] 解析接口: %s 是否推送: %v \n", p.Cmd, p.IsPush) + } + + return nil +} + +func (mod *ProtoModWorker) OutPutFiles() ([]string, error) { + for _, dir := range mod.set.Conf.MakeDir { + dir.Path = filepath.Join(mod.pluginPath, fmt.Sprintf(dir.Path, mod.Args[0])) + log.Println("[info] make outDir:", dir.Path) + //if err := os.MkdirAll(dir.Path, os.ModePerm); err != nil { + // return nil, err + //} + } + + for _, outFs := range mod.set.Conf.OutFiles { + log.Println("[info] make file:", fmt.Sprintf(outFs.FileName, mod.Args[0])) + template, err := mod.templates.ExecuteTemplate(outFs.ContentTemplate, mod.FormatArgs()) + if err != nil { + return nil, err + } + fmt.Printf("\n\n >:\n%s \n\n", template) + } + + return nil, nil +} + +func (mod *ProtoModWorker) FormatArgs() map[string]any { + var templatesArgs = make(map[string]any) + var defaultArgs = make(map[string]any) + + for _, defaultArg := range mod.DefaultArgs { + defaultArgs[defaultArg.Key] = defaultArg.Value + } + templatesArgs["default"] = defaultArgs + + var ports []any + for _, port := range mod.parsePort { + if port.IsPush { + continue + } + var portMap = map[string]any{ + "Cmd": port.Cmd, + "PortDesc": port.PortDesc, + "ClientPB": port.ClientPB, + "ServerPB": port.ServerPB, + "ClientProto": mod.proto.MessageToErlMod(port.ClientPB), + "ServerProto": mod.proto.MessageToErlMod(port.ServerPB), + } + ports = append(ports, portMap) + } + templatesArgs["ports"] = ports + + // 其他默认值 + templatesArgs["CreateAt"] = time.Now().Format(time.DateTime) + + return templatesArgs +}