Files
config/definition/generate/generate.go
andrey f9a0411192
All checks were successful
Go Action / goaction (push) Successful in 29s
def (#12)
Reviewed-on: #12
2025-12-26 14:55:42 +03:00

234 lines
3.9 KiB
Go

package generate
import (
"bytes"
"context"
"embed"
"fmt"
"io"
"strings"
"text/template"
"unicode"
"gitoa.ru/go-4devs/config"
"gitoa.ru/go-4devs/config/definition/generate/pkg"
"gitoa.ru/go-4devs/config/definition/generate/render"
"gitoa.ru/go-4devs/config/definition/generate/view"
"gitoa.ru/go-4devs/config/param"
)
type Option func(*Config)
func WithSkipContext(c *Config) {
view.WithSkipContext(c.Params)
}
func WithPrefix(name string) Option {
return func(c *Config) {
c.prefix = name
}
}
func WithSuffix(name string) Option {
return func(c *Config) {
c.suffix = name
}
}
// WithMethods set methosd.
//
// generate.WithMethods(runtime.FuncForPC(reflect.ValueOf(configure).Pointer()).Name()).
func WithMethods(in ...string) Option {
return func(c *Config) {
c.methods = in
}
}
func WithOutName(in string) Option {
return func(c *Config) {
c.outName = in
}
}
func WithFile(in string) Option {
return func(c *Config) {
c.file = in
}
}
func WithFullPkg(in string) Option {
return func(c *Config) {
c.fullPkg = in
}
}
func NewConfig(opts ...Option) Config {
var cfg Config
cfg.Params = param.New()
cfg.prefix = "Input"
for _, opt := range opts {
opt(&cfg)
}
return cfg
}
type Config struct {
param.Params
methods []string
prefix string
suffix string
fullPkg string
pkg string
file string
buildTags string
outName string
}
func (c Config) BuildTags() string {
return c.buildTags
}
func (c Config) Pkg() string {
if c.pkg == "" {
if idx := strings.LastIndex(c.fullPkg, "/"); idx != -1 {
c.pkg = c.fullPkg[idx+1:]
}
}
return c.pkg
}
func (c Config) FullPkg() string {
return c.fullPkg
}
func (c Config) SkipContext() bool {
return view.IsSkipContext(c.Params)
}
func (c Config) Methods() []string {
return c.methods
}
func (c Config) Prefix() string {
return c.prefix
}
func (c Config) Suffix() string {
return c.suffix
}
func (c Config) File() string {
return c.file
}
func (c Config) OutName() string {
return c.outName
}
//go:embed tpl/*
var tpls embed.FS
var initTpl = template.Must(template.New("tpls").ParseFS(tpls, "tpl/*.tpl")).Lookup("init.go.tpl")
func Run(_ context.Context, cfg Config, w io.Writer, inputs ...Input) error {
data := Data{
Config: cfg,
imp: pkg.NewImports(cfg.FullPkg()).Adds("fmt", "context", "gitoa.ru/go-4devs/config"),
}
var buff bytes.Buffer
for _, in := range inputs {
vi := view.NewViews(in.Method(), data.Params, in.Options(), view.WithKeys())
if err := render.Render(&buff, vi, data); err != nil {
return fmt.Errorf("render:%w", err)
}
}
if err := initTpl.Execute(w, data); err != nil {
return fmt.Errorf("render base:%w", err)
}
if _, err := io.Copy(w, &buff); err != nil {
return fmt.Errorf("copy:%w", err)
}
return nil
}
type Data struct {
Config
imp *pkg.Imports
}
func (f Data) Imports() []pkg.Import {
return f.imp.Imports()
}
func (f Data) StructName(name string) string {
return f.Prefix() + FuncName(name) + f.Suffix()
}
func (f Data) FuncName(in string) string {
return FuncName(in)
}
func (f Data) AddType(pkg string) (string, error) {
short, err := f.imp.AddType(pkg)
if err != nil {
return "", fmt.Errorf("data: %w", err)
}
return short, nil
}
func FuncName(name string) string {
data := strings.Builder{}
toUp := true
for _, char := range name {
isLeter := unicode.IsLetter(char)
isAllowed := isLeter || unicode.IsDigit(char)
switch {
case isAllowed && !toUp:
data.WriteRune(char)
case !isAllowed:
toUp = true
case toUp:
data.WriteString(strings.ToUpper(string(char)))
toUp = false
}
}
return data.String()
}
func NewInput(method string, options config.Options) Input {
return Input{
method: method,
options: options,
}
}
type Input struct {
options config.Options
method string
}
func (i Input) Method() string {
return i.method
}
func (i Input) Options() config.Options {
return i.options
}