feature: file namestyle (#223)
* add api filename style * new feature: config.yaml * optimize * optimize logic generation * check hanlder valid * optimize * reactor naming style * optimize * optimize test * optimize gen middleware * format Co-authored-by: anqiansong <anqiansong@xiaoheiban.cn> Co-authored-by: kim <xutao@xiaoheiban.cn>
This commit is contained in:
155
tools/goctl/util/format/format.go
Normal file
155
tools/goctl/util/format/format.go
Normal file
@@ -0,0 +1,155 @@
|
||||
package format
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
flagGo = "GO"
|
||||
flagZero = "ZERO"
|
||||
|
||||
unknown style = iota
|
||||
title
|
||||
lower
|
||||
upper
|
||||
)
|
||||
|
||||
var ErrNamingFormat = errors.New("unsupported format")
|
||||
|
||||
type (
|
||||
styleFormat struct {
|
||||
before string
|
||||
through string
|
||||
after string
|
||||
goStyle style
|
||||
zeroStyle style
|
||||
}
|
||||
|
||||
style int
|
||||
)
|
||||
|
||||
// FileNamingFormat is used to format the file name. You can define the format style
|
||||
// through the go and zero formatting characters. For example, you can define the snake
|
||||
// format as go_zero, and the camel case format as goZero. You can even specify the split
|
||||
// character, such as go#Zero, theoretically any combination can be used, but the prerequisite
|
||||
// must meet the naming conventions of each operating system file name.
|
||||
// Note: Formatting is based on snake or camel string
|
||||
func FileNamingFormat(format, content string) (string, error) {
|
||||
upperFormat := strings.ToUpper(format)
|
||||
indexGo := strings.Index(upperFormat, flagGo)
|
||||
indexZero := strings.Index(upperFormat, flagZero)
|
||||
if indexGo < 0 || indexZero < 0 || indexGo > indexZero {
|
||||
return "", ErrNamingFormat
|
||||
}
|
||||
var (
|
||||
before, through, after string
|
||||
flagGo, flagZero string
|
||||
goStyle, zeroStyle style
|
||||
err error
|
||||
)
|
||||
before = format[:indexGo]
|
||||
flagGo = format[indexGo : indexGo+2]
|
||||
through = format[indexGo+2 : indexZero]
|
||||
flagZero = format[indexZero : indexZero+4]
|
||||
after = format[indexZero+4:]
|
||||
|
||||
goStyle, err = getStyle(flagGo)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
zeroStyle, err = getStyle(flagZero)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var formatStyle styleFormat
|
||||
formatStyle.goStyle = goStyle
|
||||
formatStyle.zeroStyle = zeroStyle
|
||||
formatStyle.before = before
|
||||
formatStyle.through = through
|
||||
formatStyle.after = after
|
||||
return doFormat(formatStyle, content)
|
||||
}
|
||||
|
||||
func doFormat(f styleFormat, content string) (string, error) {
|
||||
splits, err := split(content)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var join []string
|
||||
for index, split := range splits {
|
||||
if index == 0 {
|
||||
join = append(join, transferTo(split, f.goStyle))
|
||||
continue
|
||||
}
|
||||
join = append(join, transferTo(split, f.zeroStyle))
|
||||
}
|
||||
joined := strings.Join(join, f.through)
|
||||
return f.before + joined + f.after, nil
|
||||
}
|
||||
|
||||
func transferTo(in string, style style) string {
|
||||
switch style {
|
||||
case upper:
|
||||
return strings.ToUpper(in)
|
||||
case lower:
|
||||
return strings.ToLower(in)
|
||||
case title:
|
||||
return strings.Title(in)
|
||||
default:
|
||||
return in
|
||||
}
|
||||
}
|
||||
|
||||
func split(content string) ([]string, error) {
|
||||
var (
|
||||
list []string
|
||||
reader = strings.NewReader(content)
|
||||
buffer = bytes.NewBuffer(nil)
|
||||
)
|
||||
for {
|
||||
r, _, err := reader.ReadRune()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
if buffer.Len() > 0 {
|
||||
list = append(list, buffer.String())
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
if r == '_' {
|
||||
if buffer.Len() > 0 {
|
||||
list = append(list, buffer.String())
|
||||
}
|
||||
buffer.Reset()
|
||||
continue
|
||||
}
|
||||
|
||||
if r >= 'A' && r <= 'Z' {
|
||||
if buffer.Len() > 0 {
|
||||
list = append(list, buffer.String())
|
||||
}
|
||||
buffer.Reset()
|
||||
}
|
||||
buffer.WriteRune(r)
|
||||
}
|
||||
}
|
||||
|
||||
func getStyle(flag string) (style, error) {
|
||||
compare := strings.ToLower(flag)
|
||||
switch flag {
|
||||
case strings.ToLower(compare):
|
||||
return lower, nil
|
||||
case strings.ToUpper(compare):
|
||||
return upper, nil
|
||||
case strings.Title(compare):
|
||||
return title, nil
|
||||
default:
|
||||
return unknown, fmt.Errorf("unexpected format: %s", flag)
|
||||
}
|
||||
}
|
||||
112
tools/goctl/util/format/format_test.go
Normal file
112
tools/goctl/util/format/format_test.go
Normal file
@@ -0,0 +1,112 @@
|
||||
package format
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestSplit(t *testing.T) {
|
||||
list, err := split("A")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, []string{"A"}, list)
|
||||
|
||||
list, err = split("goZero")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, []string{"go", "Zero"}, list)
|
||||
|
||||
list, err = split("Gozero")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, []string{"Gozero"}, list)
|
||||
|
||||
list, err = split("go_zero")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, []string{"go", "zero"}, list)
|
||||
|
||||
list, err = split("talGo_zero")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, []string{"tal", "Go", "zero"}, list)
|
||||
|
||||
list, err = split("GOZERO")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, []string{"G", "O", "Z", "E", "R", "O"}, list)
|
||||
|
||||
list, err = split("gozero")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, []string{"gozero"}, list)
|
||||
|
||||
list, err = split("")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 0, len(list))
|
||||
|
||||
list, err = split("a_b_CD_EF")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, []string{"a", "b", "C", "D", "E", "F"}, list)
|
||||
|
||||
list, err = split("_")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 0, len(list))
|
||||
|
||||
list, err = split("__")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 0, len(list))
|
||||
|
||||
list, err = split("_A")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, []string{"A"}, list)
|
||||
|
||||
list, err = split("_A_")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, []string{"A"}, list)
|
||||
|
||||
list, err = split("A_")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, []string{"A"}, list)
|
||||
|
||||
list, err = split("welcome_to_go_zero")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, []string{"welcome", "to", "go", "zero"}, list)
|
||||
}
|
||||
|
||||
func TestFileNamingFormat(t *testing.T) {
|
||||
testFileNamingFormat(t, "gozero", "welcome_to_go_zero", "welcometogozero")
|
||||
testFileNamingFormat(t, "_go#zero_", "welcome_to_go_zero", "_welcome#to#go#zero_")
|
||||
testFileNamingFormat(t, "Go#zero", "welcome_to_go_zero", "Welcome#to#go#zero")
|
||||
testFileNamingFormat(t, "Go#Zero", "welcome_to_go_zero", "Welcome#To#Go#Zero")
|
||||
testFileNamingFormat(t, "Go_Zero", "welcome_to_go_zero", "Welcome_To_Go_Zero")
|
||||
testFileNamingFormat(t, "go_Zero", "welcome_to_go_zero", "welcome_To_Go_Zero")
|
||||
testFileNamingFormat(t, "goZero", "welcome_to_go_zero", "welcomeToGoZero")
|
||||
testFileNamingFormat(t, "GoZero", "welcome_to_go_zero", "WelcomeToGoZero")
|
||||
testFileNamingFormat(t, "GOZero", "welcome_to_go_zero", "WELCOMEToGoZero")
|
||||
testFileNamingFormat(t, "GoZERO", "welcome_to_go_zero", "WelcomeTOGOZERO")
|
||||
testFileNamingFormat(t, "GOZERO", "welcome_to_go_zero", "WELCOMETOGOZERO")
|
||||
testFileNamingFormat(t, "GO*ZERO", "welcome_to_go_zero", "WELCOME*TO*GO*ZERO")
|
||||
testFileNamingFormat(t, "[GO#ZERO]", "welcome_to_go_zero", "[WELCOME#TO#GO#ZERO]")
|
||||
testFileNamingFormat(t, "{go###zero}", "welcome_to_go_zero", "{welcome###to###go###zero}")
|
||||
testFileNamingFormat(t, "{go###zerogo_zero}", "welcome_to_go_zero", "{welcome###to###go###zerogo_zero}")
|
||||
testFileNamingFormat(t, "GogoZerozero", "welcome_to_go_zero", "WelcomegoTogoGogoZerozero")
|
||||
testFileNamingFormat(t, "前缀GoZero后缀", "welcome_to_go_zero", "前缀WelcomeToGoZero后缀")
|
||||
testFileNamingFormat(t, "GoZero", "welcometogozero", "Welcometogozero")
|
||||
testFileNamingFormat(t, "GoZero", "WelcomeToGoZero", "WelcomeToGoZero")
|
||||
testFileNamingFormat(t, "gozero", "WelcomeToGoZero", "welcometogozero")
|
||||
testFileNamingFormat(t, "go_zero", "WelcomeToGoZero", "welcome_to_go_zero")
|
||||
testFileNamingFormat(t, "Go_Zero", "WelcomeToGoZero", "Welcome_To_Go_Zero")
|
||||
testFileNamingFormat(t, "Go_Zero", "", "")
|
||||
testFileNamingFormatErr(t, "go", "")
|
||||
testFileNamingFormatErr(t, "gOZero", "")
|
||||
testFileNamingFormatErr(t, "zero", "")
|
||||
testFileNamingFormatErr(t, "goZEro", "welcome_to_go_zero")
|
||||
testFileNamingFormatErr(t, "goZERo", "welcome_to_go_zero")
|
||||
testFileNamingFormatErr(t, "zerogo", "welcome_to_go_zero")
|
||||
}
|
||||
|
||||
func testFileNamingFormat(t *testing.T, format, in, expected string) {
|
||||
format, err := FileNamingFormat(format, in)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, expected, format)
|
||||
}
|
||||
|
||||
func testFileNamingFormatErr(t *testing.T, format, in string) {
|
||||
_, err := FileNamingFormat(format, in)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
Reference in New Issue
Block a user