package main import ( "os" "path/filepath" "strings" "unicode" "unicode/utf8" ) type style string const ( kebabCase style = "kebab" // 全小写中划线 underscoreCase style = "underscore" // 小写下划线 camelCase style = "camel" // 小写字母开头驼峰 pascalCase style = "pascal" // 大写字母开头驼峰 lowerCase style = "lower" // 全小写 ) // convert to underscore style, example: UserProfile > user_profile func toUnderscoreCase(s string) string { return toLowerCase(s, 95) } // convert to kebab style, example: UserProfile > user-profile func toKebabCase(s string) string { return toLowerCase(s, 45) } // convert to camel style, example: user-profile > userProfile func toCamelCase(s string) string { chars := make([]rune, 0, len(s)) upper := false first := true for i := 0; i < len(s); i++ { switch { case s[i] >= 65 && s[i] <= 90: if first { chars = append(chars, rune(s[i]+32)) } else { chars = append(chars, rune(s[i])) } first = false upper = false case s[i] >= 97 && s[i] <= 122: if upper && !first { chars = append(chars, rune(s[i]-32)) } else { chars = append(chars, rune(s[i])) } first = false upper = false case s[i] == 45: upper = true case s[i] == 95: upper = true } } return string(chars) } // convert to pascal style, example: user-profile > UserProfile func toPascalCase(s string) string { s = toCamelCase(s) return strings.ToUpper(string(s[0])) + s[1:] } func toLowerCase(s string, c rune) string { chars := make([]rune, 0) for i := 0; i < len(s); i++ { if s[i] >= 65 && s[i] <= 90 { if i == 0 { chars = append(chars, rune(s[i]+32)) } else { chars = append(chars, c, rune(s[i]+32)) } } else { chars = append(chars, rune(s[i])) } } return string(chars) } func toPackageName(s string) string { chars := make([]rune, 0, len(s)) for i := 0; i < len(s); i++ { switch { case s[i] >= 65 && s[i] <= 90: chars = append(chars, rune(s[i]+32)) case s[i] >= 97 && s[i] <= 122: chars = append(chars, rune(s[i])) } } return string(chars) } func toPackagePath(s string, style style) string { switch style { case kebabCase: return toKebabCase(s) case underscoreCase: return toUnderscoreCase(s) case camelCase: return toCamelCase(s) case pascalCase: return toPascalCase(s) case lowerCase: return toPackageName(s) default: return toKebabCase(s) } } func toFileName(s string, style style) string { switch style { case kebabCase: return toKebabCase(s) case underscoreCase: return toUnderscoreCase(s) case camelCase: return toCamelCase(s) case pascalCase: return toPascalCase(s) case lowerCase: return toPackageName(s) default: return toUnderscoreCase(s) } } func doWrite(file string, tpl string, replaces map[string]string) error { s := os.Expand(tpl, func(s string) string { switch { case len(s) >= 3 && s[:3] == "Var": return replaces[s] case len(s) >= 6 && s[:6] == "Symbol": return replaces[s] default: return "$" + s } }) if err := os.MkdirAll(filepath.Dir(file), os.ModePerm); err != nil { return err } return os.WriteFile(file, []byte(strings.TrimPrefix(s, "\n")), os.ModePerm) } // 大写字母开头的字段才是导出的 func isExportable(s string) bool { r, _ := utf8.DecodeRuneInString(s) return unicode.IsUpper(r) }