Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add external config file support to make editors configurable #80

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,28 @@ Each archive entry consists of:
- the (decimal) file size, followed by a newline
- the contents of the file

## Use external config file

when we use editors like vscode to add tags, the vscode can only add json tags for us, there is no way to change the config, so I add a toml config support.
we just need add a `gomodifytags.toml` in the same directory of gomodifytags. in linux we can use `whereis gomodifytags` to get the directory.
```toml
Add = ["form", "gorm","binding"]
Transform = "camelcase"
[TemplateMap]
gorm = "column:$field"
binding = "required"
[TransformMap]
gorm = "snakecase"

```

- the `Add` will add external tags to flag tag.
- the `Transform` will config transform for all tag.
- the `TemplateMap` will config template for each tag,overwrite the flag template.
- the `TransformMap` will config transform for each tag,overwrite the flag transform and Transform.

![gomodifytags](https://user-images.githubusercontent.com/5291739/123039779-53382900-d425-11eb-9ae9-daa84f00bb23.gif)

# Development

At least Go `v1.11.x` is required. Older versions might work, but it's not
Expand Down Expand Up @@ -607,3 +629,5 @@ GO111MODULE=on go test -v -mod=vendor
```

If everything works fine, feel free to open a pull request with your changes.


1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module github.com/fatih/gomodifytags

require (
github.com/BurntSushi/toml v0.3.1 // indirect
github.com/fatih/camelcase v1.0.0
github.com/fatih/structtag v1.2.0
golang.org/x/tools v0.0.0-20180824175216-6c1c5e93cdc1
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8=
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4=
Expand Down
113 changes: 90 additions & 23 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@ import (
"io"
"io/ioutil"
"os"
"path/filepath"
"sort"
"strconv"
"strings"
"unicode"

"github.com/BurntSushi/toml"
"github.com/fatih/camelcase"
"github.com/fatih/structtag"
"golang.org/x/tools/go/buildutil"
Expand Down Expand Up @@ -65,11 +67,21 @@ type config struct {
override bool
skipUnexportedFields bool

transform string
sort bool
valueFormat string
clear bool
clearOption bool
transform string
sort bool
valueFormat string
clear bool
clearOption bool
templateMap map[string]string // give different template for each tag
transformMap map[string]string // give different transform for each tag
}

// use toml to config the gomodifytags
type tomlConfig struct {
Add []string // add external tags
Transform string
TemplateMap map[string]string // give different template for each tag
TransformMap map[string]string // give different transform for each tag
}

func main() {
Expand Down Expand Up @@ -122,6 +134,14 @@ func realMain() error {
}

func parseConfig(args []string) (*config, error) {
var tomlCfg tomlConfig

ex, err := os.Executable()
if err == nil {
exPath := filepath.Dir(ex)
toml.DecodeFile(filepath.Join(exPath, "gomodifytags.toml"), &tomlCfg)
}

var (
// file flags
flagFile = flag.String("file", "", "Filename to be parsed")
Expand Down Expand Up @@ -202,12 +222,37 @@ func parseConfig(args []string) (*config, error) {
skipUnexportedFields: *flagSkipUnexportedFields,
}

cfg.templateMap = tomlCfg.TemplateMap
if cfg.templateMap == nil {
cfg.templateMap = make(map[string]string)
}
if tomlCfg.Transform != "" {
cfg.transform = tomlCfg.Transform
}
cfg.transformMap = tomlCfg.TransformMap
if cfg.transformMap == nil {
cfg.transformMap = make(map[string]string)
}

if *flagModified {
cfg.modified = os.Stdin
}

// add extenal tags config
if *flagAddTags != "" {
cfg.add = strings.Split(*flagAddTags, ",")

// remove duplicate tag
addMap := make(map[string]struct{})
for _, add := range cfg.add {
addMap[add] = struct{}{}
}
for _, add := range tomlCfg.Add {
if _, ok := addMap[add]; !ok {
cfg.add = append(cfg.add, add)
}
}

}

if *flagAddOptions != "" {
Expand Down Expand Up @@ -378,16 +423,12 @@ func (c *config) addTagOptions(tags *structtag.Tags) (*structtag.Tags, error) {
return tags, nil
}

func (c *config) addTags(fieldName string, tags *structtag.Tags) (*structtag.Tags, error) {
if c.add == nil || len(c.add) == 0 {
return tags, nil
}
func convertFieldName(transform, fieldName string) (name string, unknown bool) {
name = ""
unknown = false

splitted := camelcase.Split(fieldName)
name := ""

unknown := false
switch c.transform {
switch transform {
case "snakecase":
var lowerSplitted []string
for _, s := range splitted {
Expand Down Expand Up @@ -430,18 +471,28 @@ func (c *config) addTags(fieldName string, tags *structtag.Tags) (*structtag.Tag
default:
unknown = true
}
return
}

if c.valueFormat != "" {
prevName := name
name = strings.ReplaceAll(c.valueFormat, "{field}", name)
if name == c.valueFormat {
// support old style for backward compatibility
name = strings.ReplaceAll(c.valueFormat, "$field", prevName)
}

func (c *config) addTags(fieldName string, tags *structtag.Tags) (*structtag.Tags, error) {
if c.add == nil || len(c.add) == 0 {
return tags, nil
}

name := fieldName
tagName := name
unknown := false

for _, key := range c.add {
splitted = strings.SplitN(key, ":", 2)

if transform, ok := c.transformMap[key]; ok {
name, unknown = convertFieldName(transform, fieldName)
} else {
name, unknown = convertFieldName(c.transform, fieldName)
}

splitted := strings.SplitN(key, ":", 2)
if len(splitted) >= 2 {
key = splitted[0]
name = strings.Join(splitted[1:], "")
Expand All @@ -451,16 +502,32 @@ func (c *config) addTags(fieldName string, tags *structtag.Tags) (*structtag.Tag
// might pass a value
return nil, fmt.Errorf("unknown transform option %q", c.transform)
}
// toml template config ,overwrite the flag template
if valueFormat, ok := c.templateMap[key]; ok {
tagName = strings.ReplaceAll(valueFormat, "{field}", name)
if tagName == valueFormat {
// support old style for backward compatibility
tagName = strings.ReplaceAll(valueFormat, "$field", name)
}
} else if c.valueFormat != "" {
tagName = strings.ReplaceAll(c.valueFormat, "{field}", name)
if tagName == c.valueFormat {
// support old style for backward compatibility
tagName = strings.ReplaceAll(c.valueFormat, "$field", name)
}
} else {
tagName = name
}

tag, err := tags.Get(key)
if err != nil {
// tag doesn't exist, create a new one
tag = &structtag.Tag{
Key: key,
Name: name,
Name: tagName,
}
} else if c.override {
tag.Name = name
tag.Name = tagName
}

if err := tags.Set(tag); err != nil {
Expand Down