andrey1s
2 years ago
8 changed files with 364 additions and 0 deletions
@ -0,0 +1,60 @@ |
|||
package command |
|||
|
|||
import ( |
|||
"context" |
|||
"fmt" |
|||
|
|||
"gitoa.ru/go-4devs/console" |
|||
"gitoa.ru/go-4devs/console/input" |
|||
"gitoa.ru/go-4devs/console/input/argument" |
|||
"gitoa.ru/go-4devs/console/input/option" |
|||
"gitoa.ru/go-4devs/console/output" |
|||
"gitoa.ru/go-4devs/mime/scripts/mime" |
|||
) |
|||
|
|||
const ( |
|||
ArgFile = "file" |
|||
OptExtTpl = "ext-tpl" |
|||
OptExtPackage = "ext-package" |
|||
OptExtResult = "ext-result" |
|||
OptMimeTpl = "mime-tpl" |
|||
OptMimePackage = "mime-package" |
|||
OptMimeResult = "mime-result" |
|||
) |
|||
|
|||
func Mime() *console.Command { |
|||
return &console.Command{ |
|||
Name: "mime", |
|||
Description: "generate mime from file", |
|||
Configure: func(ctx context.Context, cfg *input.Definition) error { |
|||
cfg.SetArgument(ArgFile, "file", argument.Required) |
|||
cfg.SetOptions( |
|||
option.String(OptExtTpl, "extension template", option.Default("mime/tpl/extension.text.tmpl")), |
|||
option.String(OptExtPackage, "extension package", option.Default("mime")), |
|||
option.String(OptExtResult, "extension result", option.Default("../extension.go")), |
|||
option.String(OptMimeTpl, "mime template", option.Default("mime/tpl/mime.text.tmpl")), |
|||
option.String(OptMimePackage, "mime package", option.Default("mime")), |
|||
option.String(OptMimeResult, "mime result", option.Default("../mime.go")), |
|||
) |
|||
|
|||
return nil |
|||
}, |
|||
Execute: func(ctx context.Context, input input.Input, output output.Output) error { |
|||
file := input.Argument(ctx, ArgFile).String() |
|||
opts := []mime.Option{ |
|||
mime.WithExtTpl(input.Option(ctx, OptExtTpl).String()), |
|||
mime.WithExtPacakge(input.Option(ctx, OptExtPackage).String()), |
|||
mime.WithExtResult(input.Option(ctx, OptExtResult).String()), |
|||
mime.WithMimeTpl(input.Option(ctx, OptMimeTpl).String()), |
|||
mime.WithMimePackage(input.Option(ctx, OptMimePackage).String()), |
|||
mime.WithMimeResult(input.Option(ctx, OptMimeResult).String()), |
|||
} |
|||
|
|||
if err := mime.Generate(file, opts...); err != nil { |
|||
return fmt.Errorf("generate:%w", err) |
|||
} |
|||
|
|||
return nil |
|||
}, |
|||
} |
|||
} |
@ -0,0 +1,9 @@ |
|||
module gitoa.ru/go-4devs/mime/scripts |
|||
|
|||
go 1.19 |
|||
|
|||
require ( |
|||
github.com/achiku/varfmt v0.0.0-20160708124000-f820e1efecee |
|||
gitoa.ru/go-4devs/closer v0.1.1 |
|||
gitoa.ru/go-4devs/console v0.1.2 |
|||
) |
@ -0,0 +1,24 @@ |
|||
github.com/achiku/varfmt v0.0.0-20160708124000-f820e1efecee h1:IfTwtLm+DUeY8kZ8NKSxGRr2kaCe8qqIpJz4Uwh1efU= |
|||
github.com/achiku/varfmt v0.0.0-20160708124000-f820e1efecee/go.mod h1:RKS7P4TSY/jV2QjH/ZxoAE2l4EEXZRPwQ/tIzXiFrk0= |
|||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= |
|||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= |
|||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= |
|||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= |
|||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= |
|||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= |
|||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= |
|||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= |
|||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= |
|||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= |
|||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= |
|||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= |
|||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= |
|||
gitoa.ru/go-4devs/closer v0.1.1 h1:3mTzBBmAVZB9Im5FcRzk6QUak3Ko+tWiNyFkTuKzIx4= |
|||
gitoa.ru/go-4devs/closer v0.1.1/go.mod h1:S+QAdgSt4CVLH3v3YZK1Mukl7SVn2Z0CYj0oJQMTZG4= |
|||
gitoa.ru/go-4devs/console v0.1.2 h1:SsQWLSClXFwWFseH6CGKQfmCtG84aHOiaFHG3oZlJ8s= |
|||
gitoa.ru/go-4devs/console v0.1.2/go.mod h1:ddqmjQ0yr9v+oa5E3Bu3X/SUcws/ENR5f5cz1g5fHbk= |
|||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= |
|||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= |
|||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
|||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= |
|||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
@ -0,0 +1,24 @@ |
|||
package main |
|||
|
|||
import ( |
|||
"context" |
|||
"syscall" |
|||
|
|||
"gitoa.ru/go-4devs/closer" |
|||
"gitoa.ru/go-4devs/console" |
|||
"gitoa.ru/go-4devs/mime/scripts/command" |
|||
) |
|||
|
|||
func main() { |
|||
ctx, cancel := context.WithCancel(context.Background()) |
|||
closer.AddLast(func() error { |
|||
cancel() |
|||
return nil |
|||
}) |
|||
|
|||
go func() { |
|||
closer.Wait(ctx, syscall.SIGTERM, syscall.SIGINT) |
|||
}() |
|||
|
|||
console.Execute(ctx, command.Mime()) |
|||
} |
@ -0,0 +1,177 @@ |
|||
package mime |
|||
|
|||
import ( |
|||
"encoding/json" |
|||
"fmt" |
|||
"go/format" |
|||
"io/ioutil" |
|||
"os" |
|||
"path" |
|||
"text/template" |
|||
) |
|||
|
|||
type Config struct { |
|||
Source string |
|||
|
|||
Mimes map[string][]string |
|||
MimePrefix string |
|||
MimeTpl string |
|||
MimeResult string |
|||
MimePackage string |
|||
|
|||
Extensions map[string][]string |
|||
ExtPrefix string |
|||
ExtTpl string |
|||
ExtResult string |
|||
ExtPackage string |
|||
} |
|||
|
|||
func WithExtTpl(name string) Option { |
|||
return func(c *Config) { |
|||
c.ExtTpl = name |
|||
} |
|||
} |
|||
|
|||
func WithExtPacakge(name string) Option { |
|||
return func(c *Config) { |
|||
c.ExtPackage = name |
|||
} |
|||
} |
|||
|
|||
func WithExtResult(name string) Option { |
|||
return func(c *Config) { |
|||
c.ExtResult = name |
|||
} |
|||
} |
|||
|
|||
func WithMimeTpl(name string) Option { |
|||
return func(c *Config) { |
|||
c.MimeTpl = name |
|||
} |
|||
} |
|||
|
|||
func WithMimePackage(name string) Option { |
|||
return func(c *Config) { |
|||
c.MimePackage = name |
|||
} |
|||
} |
|||
|
|||
func WithMimeResult(name string) Option { |
|||
return func(c *Config) { |
|||
c.MimeResult = name |
|||
} |
|||
} |
|||
|
|||
type Option func(*Config) |
|||
|
|||
func funcMap() template.FuncMap { |
|||
return template.FuncMap{ |
|||
"name": VarName, |
|||
"value": Value, |
|||
} |
|||
} |
|||
|
|||
func Generate(fileName string, opts ...Option) error { |
|||
cfg := Config{ |
|||
Source: fileName, |
|||
|
|||
ExtPrefix: "Ext", |
|||
ExtTpl: "mime/tpl/extension.text.tmpl", |
|||
ExtResult: "extension.go", |
|||
Extensions: make(map[string][]string), |
|||
ExtPackage: "mime", |
|||
|
|||
MimeTpl: "mime/tpl/mime.text.tmpl", |
|||
Mimes: make(map[string][]string), |
|||
MimePrefix: "", |
|||
MimeResult: "mime.go", |
|||
MimePackage: "mime", |
|||
} |
|||
|
|||
for _, opt := range opts { |
|||
opt(&cfg) |
|||
} |
|||
|
|||
data, err := os.ReadFile(fileName) |
|||
if err != nil { |
|||
return fmt.Errorf("read file:%w", err) |
|||
} |
|||
|
|||
if err := json.Unmarshal(data, &cfg.Mimes); err != nil { |
|||
return fmt.Errorf("unmarshal:%w", err) |
|||
} |
|||
|
|||
cfg.Extensions = extensions(cfg.Mimes) |
|||
|
|||
template, err := template.New("mimes").Funcs(funcMap()).ParseFiles(cfg.ExtTpl, cfg.MimeTpl) |
|||
if err != nil { |
|||
return fmt.Errorf("ext template:%w", err) |
|||
} |
|||
|
|||
extFile, err := os.Create(cfg.ExtResult) |
|||
if err != nil { |
|||
return fmt.Errorf("ext file:%w", err) |
|||
} |
|||
|
|||
if err := template.ExecuteTemplate(extFile, path.Base(cfg.ExtTpl), cfg); err != nil { |
|||
return fmt.Errorf("ext execute:%w", err) |
|||
} |
|||
|
|||
if err := Format(extFile.Name()); err != nil { |
|||
return fmt.Errorf("format ext:%w", err) |
|||
} |
|||
|
|||
mimeFile, err := os.Create(cfg.MimeResult) |
|||
if err != nil { |
|||
return fmt.Errorf("mime file:%w", err) |
|||
} |
|||
|
|||
if err := template.ExecuteTemplate(mimeFile, path.Base(cfg.MimeTpl), cfg); err != nil { |
|||
return fmt.Errorf("mime execute:%w", err) |
|||
} |
|||
|
|||
if err := Format(mimeFile.Name()); err != nil { |
|||
return fmt.Errorf("format mime:%w", err) |
|||
} |
|||
|
|||
return nil |
|||
} |
|||
|
|||
// Format file and write it.
|
|||
func Format(name string) error { |
|||
in, err := ioutil.ReadFile(name) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
out, err := format.Source(in) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
|
|||
file, err := os.Create(name) |
|||
if err != nil { |
|||
return fmt.Errorf("ext file:%w", err) |
|||
} |
|||
|
|||
if _, err := file.Write(out); err != nil { |
|||
return fmt.Errorf("write:%w", err) |
|||
} |
|||
|
|||
return nil |
|||
} |
|||
|
|||
func extensions(mimes map[string][]string) map[string][]string { |
|||
out := make(map[string][]string) |
|||
|
|||
for mime, exts := range mimes { |
|||
for _, ext := range exts { |
|||
if _, ok := out[ext]; ok { |
|||
out[ext] = append(out[ext], mime) |
|||
continue |
|||
} |
|||
out[ext] = []string{ext} |
|||
} |
|||
} |
|||
|
|||
return out |
|||
} |
@ -0,0 +1,19 @@ |
|||
// Code generated by gitoa.ru/go-4devs/mime and sourse {{.Source}} |
|||
package {{.ExtPackage}} |
|||
|
|||
const ( |
|||
{{- range $key, $value := .Extensions }} |
|||
{{ name $.ExtPrefix $key }} = "{{ $key }}" |
|||
{{- end}} |
|||
) |
|||
|
|||
func Mime(name string) []string { |
|||
switch name { |
|||
{{- range $key, $value := .Extensions }} |
|||
case {{ name $.ExtPrefix $key }}: |
|||
return {{ value $value }} |
|||
{{- end}} |
|||
} |
|||
|
|||
return nil |
|||
} |
@ -0,0 +1,19 @@ |
|||
// Code generated by gitoa.ru/go-4devs/mime and sourse {{.Source}} |
|||
package {{.MimePackage}} |
|||
|
|||
const ( |
|||
{{- range $key, $value := .Mimes }} |
|||
{{ name $.MimePrefix $key }} = "{{ $key }}" |
|||
{{- end}} |
|||
) |
|||
|
|||
func Extension(name string) []string { |
|||
switch name { |
|||
{{- range $key, $value := .Mimes }} |
|||
case {{ name $.MimePrefix $key }}: |
|||
return {{ value $value }} |
|||
{{- end}} |
|||
} |
|||
|
|||
return nil |
|||
} |
@ -0,0 +1,32 @@ |
|||
package mime |
|||
|
|||
import ( |
|||
"fmt" |
|||
"strings" |
|||
"unicode" |
|||
|
|||
"github.com/achiku/varfmt" |
|||
) |
|||
|
|||
func VarName(prefix, name string) string { |
|||
rules := map[string]string{ |
|||
"+": "_plus", |
|||
"-": "_dash_", |
|||
"/": "_", |
|||
".": "_dot_", |
|||
} |
|||
|
|||
for old, new := range rules { |
|||
name = strings.ReplaceAll(name, old, new) |
|||
} |
|||
|
|||
if unicode.IsUpper(rune(name[0])) { |
|||
name = " " + name |
|||
} |
|||
|
|||
return varfmt.PublicVarName(prefix + "_" + name) |
|||
} |
|||
|
|||
func Value(val []string) string { |
|||
return fmt.Sprintf("%#v", val) |
|||
} |
Loading…
Reference in new issue