Git Product home page Git Product logo

gomodifytags's Introduction

gomodifytags

Go tool to modify/update field tags in structs. gomodifytags makes it easy to update, add or delete the tags in a struct field. You can easily add new tags, update existing tags (such as appending a new key, i.e: db, xml, etc..) or remove existing tags. It also allows you to add and remove tag options. It's intended to be used by an editor, but also has modes to run it from the terminal. Read the usage section below for more information.

gomodifytags

Install

go install github.com/fatih/gomodifytags@latest

Supported editors

Usage

gomodifytags has multiple ways to modify a tag. Let's start with an example package:

package main

type Server struct {
	Name        string
	Port        int
	EnableLogs  bool
	BaseDomain  string
	Credentials struct {
		Username string
		Password string
	}
}

We have to first pass a file. For that we can use the -file flag:

$ gomodifytags -file demo.go
-line, -offset, -struct or -all is not passed

What are these? There are four different ways of defining which field tags to change:

  • -struct: This accepts the struct name. i.e: -struct Server. The name should be a valid type name. The -struct flag selects the whole struct, and thus it will operate on all fields.
  • -field: This accepts a field name. i.e: -field Address. Useful to select a certain field. The name should be a valid field name. The -struct flag is required.
  • -offset: This accepts a byte offset of the file. Useful for editors to pass the position under the cursor. i.e: -offset 548. The offset has to be inside a valid struct. The -offset selects the whole struct. If you need more granular option see -line
  • -line: This accepts a string that defines the line or lines of which fields should be changed. I.e: -line 4 or -line 5,8
  • -all: This is a boolean. The -all flag selects all structs of the given file.

Let's continue by using the -struct tag:

$ gomodifytags -file demo.go -struct Server
one of [-add-tags, -add-options, -remove-tags, -remove-options, -clear-tags, -clear-options] should be defined

Adding tags & options

There are many options on how you can change the struct. Let us start by adding tags. The following will add the json key to all fields. The value will be automatically inherited from the field name and transformed to snake_case:

$ gomodifytags -file demo.go -struct Server -add-tags json
package main

type Server struct {
	Name        string `json:"name"`
	Port        int    `json:"port"`
	EnableLogs  bool   `json:"enable_logs"`
	BaseDomain  string `json:"base_domain"`
	Credentials struct {
		Username string `json:"username"`
		Password string `json:"password"`
	} `json:"credentials"`
}

By default changes will be printed to stdout and can be used for dry-run your changes before making destructive changes. If you want to change it permanently, pass the -w (write) flag.

$ gomodifytags -file demo.go -struct Server -add-tags json -w

You can disable printing the results to stdout with the --quiet flag:

$ gomodifytags -file demo.go -struct Server -add-tags json -w --quiet

You can pass multiple keys to add tags. The following will add json and xml keys:

$ gomodifytags -file demo.go -struct Server -add-tags json,xml
package main

type Server struct {
	Name        string `json:"name" xml:"name"`
	Port        int    `json:"port" xml:"port"`
	EnableLogs  bool   `json:"enable_logs" xml:"enable_logs"`
	BaseDomain  string `json:"base_domain" xml:"base_domain"`
	Credentials struct {
		Username string `json:"username" xml:"username"`
		Password string `json:"password" xml:"password"`
	} `json:"credentials" xml:"credentials"`
}

If you prefer to use camelCase instead of snake_case for the values, you can use the -transform flag to define a different transformation rule. The following example uses the camelcase transformation rule:

$ gomodifytags -file demo.go -struct Server -add-tags json,xml -transform camelcase
package main

type Server struct {
	Name        string `json:"name" xml:"name"`
	Port        int    `json:"port" xml:"port"`
	EnableLogs  bool   `json:"enableLogs" xml:"enableLogs"`
	BaseDomain  string `json:"baseDomain" xml:"baseDomain"`
	Credentials struct {
		Username string `json:"username" xml:"username"`
		Password string `json:"password" xml:"password"`
	} `json:"credentials" xml:"credentials"`
}

Formatting tag values

By default a struct tag's value is transformed from a struct's field and used directly. As an example for the field Server string, we generate a tag in the form: json:"server" (assuming -add-tags=json is used).

However, some third party libraries use tags in a different way and might require to them to have a particular formatting, such as is the case of prefixing them (field_name=<your_value>). The --template flag allows you to specify a custom format for the tag value to be applied.

$ gomodifytags -file demo.go -struct Server -add-tags gaum -template "field_name={field}" 
package main

type Server struct {
	Name        string `gaum:"field_name=name"`
	Port        int    `gaum:"field_name=port"`
	EnableLogs  bool   `gaum:"field_name=enableLogs"`
	BaseDomain  string `gaum:"field_name=baseDomain"`
}

The {field} word is a special keyword that is replaced by the struct tag's value after the transformation.

Transformations

We currently support the following transformations:

  • snakecase: "BaseDomain" -> "base_domain"
  • camelcase: "BaseDomain" -> "baseDomain"
  • lispcase: "BaseDomain" -> "base-domain"
  • pascalcase: "BaseDomain" -> "BaseDomain"
  • titlecase: "BaseDomain" -> "Base Domain"
  • keep: keeps the original field name

You can also pass a static value for each fields. This is useful if you use Go packages that validates the struct fields or extract values for certain operations. The following example adds the json key, a validate key with the value set to gt=1 and the scope key with the value read-only:

$ gomodifytags -file demo.go -struct Server -add-tags json,validate:gt=1,scope:read-only
package main

type Server struct {
	Name        string `json:"name" validate:"gt=1" scope:"read-only"`
	Port        int    `json:"port" validate:"gt=1" scope:"read-only"`
	EnableLogs  bool   `json:"enable_logs" validate:"gt=1" scope:"read-only"`
	BaseDomain  string `json:"base_domain" validate:"gt=1" scope:"read-only"`
	Credentials struct {
		Username string `json:"username" validate:"gt=1" scope:"read-only"`
		Password string `json:"password" validate:"gt=1" scope:"read-only"`
	} `json:"credentials" validate:"gt=1" scope:"read-only"`
}

To add options to for a given key, we use the -add-options flag. In the example below we're going to add the json key and the omitempty option to all json keys:

$ gomodifytags -file demo.go -struct Server -add-tags json -add-options json=omitempty
package main

type Server struct {
	Name        string `json:"name,omitempty"`
	Port        int    `json:"port,omitempty"`
	EnableLogs  bool   `json:"enable_logs,omitempty"`
	BaseDomain  string `json:"base_domain,omitempty"`
	Credentials struct {
		Username string `json:"username,omitempty"`
		Password string `json:"password,omitempty"`
	} `json:"credentials,omitempty"`
}

If the key already exists you don't have to use -add-tags

Skipping unexported fields

By default all fields are processed. This main reason for this is to allow structs to evolve with time and be ready in case a field is exported in the future. However if you don't like this behavior, you can skip it by passing the --skip-unexported flag:

$ gomodifytags -file demo.go -struct Server -add-tags json --skip-unexported
package main

type Server struct {
        Name       string `json:"name"`
        Port       int    `json:"port"`
        enableLogs bool
        baseDomain string
}

Removing tags & options

Let's continue with removing tags. We're going to use the following simple package:

package main

type Server struct {
	Name        string `json:"name,omitempty" xml:"name,attr,cdata"`
	Port        int    `json:"port,omitempty" xml:"port,attr,cdata"`
	EnableLogs  bool   `json:"enable_logs,omitempty" xml:"enable_logs,attr,cdata"`
	BaseDomain  string `json:"base_domain,omitempty" xml:"base_domain,attr,cdata"`
	Credentials struct {
		Username string `json:"username,omitempty" xml:"username,attr,cdata"`
		Password string `json:"password,omitempty" xml:"password,attr,cdata"`
	} `json:"credentials,omitempty" xml:"credentials,attr,cdata"`
}

To remove the xml tags, we're going to use the -remove-tags flag:

$ gomodifytags -file demo.go -struct Server -remove-tags xml
package main

type Server struct {
	Name        string `json:"name"`
	Port        int    `json:"port"`
	EnableLogs  bool   `json:"enable_logs"`
	BaseDomain  string `json:"base_domain"`
	Credentials struct {
		Username string `json:"username"`
		Password string `json:"password"`
	} `json:"credentials"`
}

You can also remove multiple tags. The example below removs json and xml:

$ gomodifytags -file demo.go -struct Server -remove-tags json,xml
package main

type Server struct {
	Name        string
	Port        int
	EnableLogs  bool
	BaseDomain  string
	Credentials struct {
		Username string
		Password string
	}
}

If you want to remove all keys, we can also use the -clear-tags flag. This flag removes all tags and doesn't require to explicitly pass the key names:

$ gomodifytags -file demo.go -struct Server -clear-tags
package main

type Server struct {
	Name        string
	Port        int
	EnableLogs  bool
	BaseDomain  string
	Credentials struct {
		Username string
		Password string
	}
}

To remove any option, we can use the -remove-options flag. The following will remove all omitempty flags from the json key:

$ gomodifytags -file demo.go -struct Server -remove-options json=omitempty
package main

type Server struct {
	Name        string `json:"name" xml:"name,attr,cdata"`
	Port        int    `json:"port" xml:"port,attr,cdata"`
	EnableLogs  bool   `json:"enable_logs" xml:"enable_logs,attr,cdata"`
	BaseDomain  string `json:"base_domain" xml:"base_domain,attr,cdata"`
	Credentials struct {
		Username string `json:"username" xml:"username,attr,cdata"`
		Password string `json:"password" xml:"password,attr,cdata"`
	} `json:"credentials" xml:"credentials,attr,cdata"`
}

To remove multiple options from multiple tags just add another options:

$ gomodifytags -file demo.go -struct Server -remove-options json=omitempty,xml=cdata
package main

type Server struct {
	Name        string `json:"name" xml:"name,attr"`
	Port        int    `json:"port" xml:"port,attr"`
	EnableLogs  bool   `json:"enable_logs" xml:"enable_logs,attr"`
	BaseDomain  string `json:"base_domain" xml:"base_domain,attr"`
	Credentials struct {
		Username string `json:"username" xml:"username,attr"`
		Password string `json:"password" xml:"password,attr"`
	} `json:"credentials" xml:"credentials,attr"`
}

Lastly, to remove all options without explicitly defining the keys and names, we can use the -clear-options flag. The following example will remove all options for the given struct:

$ gomodifytags -file demo.go -struct Server -clear-options
package main

type Server struct {
	Name        string `json:"name" xml:"name"`
	Port        int    `json:"port" xml:"port"`
	EnableLogs  bool   `json:"enable_logs" xml:"enable_logs"`
	BaseDomain  string `json:"base_domain" xml:"base_domain"`
	Credentials struct {
		Username string `json:"username" xml:"username"`
		Password string `json:"password" xml:"password"`
	} `json:"credentials" xml:"credentials"`
}

Line based modification

So far all examples used the -struct flag. However we also can pass the line numbers to only change certain files. Suppose we only want to remove the tags for the Credentials struct (including the fields) for the following code (lines are included):

01  package main
02  
03  type Server struct {
04  	Name        string `json:"name" xml:"name"`
05  	Port        int    `json:"port" xml:"port"`
06  	EnableLogs  bool   `json:"enable_logs" xml:"enable_logs"`
07  	BaseDomain  string `json:"base_domain" xml:"base_domain"`
08  	Credentials struct {
09  		Username string `json:"username" xml:"username"`
10  		Password string `json:"password" xml:"password"`
11  	} `json:"credentials" xml:"credentials"`
12  }

To remove the tags for the credentials we're going to pass the -line flag:

$ gomodifytags -file demo.go -line 8,11 -clear-tags xml
package main

type Server struct {
	Name        string `json:"name" xml:"name"`
	Port        int    `json:"port" xml:"port"`
	EnableLogs  bool   `json:"enable_logs" xml:"enable_logs"`
	BaseDomain  string `json:"base_domain" xml:"base_domain"`
	Credentials struct {
		Username string
		Password string
	}
}

For removing the xml tags for certain lines, we can use the -remove-tags field. The following example will remove the xml tags for the lines 6 and 7 (fields with names of EnableLogs and BaseDomain):

$ gomodifytags -file demo.go -line 6,7 -remove-tags xml
package main

type Server struct {
	Name        string `json:"name" xml:"name"`
	Port        int    `json:"port" xml:"port"`
	EnableLogs  bool   `json:"enable_logs"`
	BaseDomain  string `json:"base_domain"`
	Credentials struct {
		Username string `json:"username" xml:"username"`
		Password string `json:"password" xml:"password"`
	} `json:"credentials" xml:"credentials"`
}

The same logic applies to adding tags or any other option as well. To add the bson tag to the lines between 5 and 7, we can use the following example:

$ gomodifytags -file demo.go -line 5,7 -add-tags bson
package main

type Server struct {
	Name        string `json:"name" xml:"name"`
	Port        int    `json:"port" xml:"port" bson:"port"`
	EnableLogs  bool   `json:"enable_logs" xml:"enable_logs" bson:"enable_logs"`
	BaseDomain  string `json:"base_domain" xml:"base_domain" bson:"base_domain"`
	Credentials struct {
		Username string `json:"username" xml:"username"`
		Password string `json:"password" xml:"password"`
	} `json:"credentials" xml:"credentials"`
}

Editor integration

Editors can use the tool by calling the tool and then either replace the buffer with the stdout or use the -w flag.

Also -line and -offset flags should be preferred to be used with editors. An editor can select a range of lines and then pass it to -line flag. The editor also can pass the offset under the cursor if it's inside the struct to -offset

Editors also can use the -format flag to output a json output with the changed lines. This is useful if you want to explicitly replace the buffer with the given lines. For the file below:

package main

type Server struct {
	Name        string
	Port        int
	EnableLogs  bool
	BaseDomain  string
	Credentials struct {
		Username string
		Password string
	}
}

If we add the xml tag and tell to output the format in json with the -format flag, the following will be printed:

$ gomodifytags -file demo.go -struct Server -add-tags xml -format json
{
  "start": 3,
  "end": 12,
  "lines": [
    "type Server struct {",
    "\tName        string `xml:\"name\"`",
    "\tPort        int    `xml:\"port\"`",
    "\tEnableLogs  bool   `xml:\"enable_logs\"`",
    "\tBaseDomain  string `xml:\"base_domain\"`",
    "\tCredentials struct {",
    "\t\tUsername string `xml:\"username\"`",
    "\t\tPassword string `xml:\"password\"`",
    "\t} `xml:\"credentials\"`",
    "}"
  ]
}

The output is defined with the following Go struct:

type output struct {
	Start int      `json:"start"`
	End   int      `json:"end"`
	Lines []string `json:"lines"`
}

The start and end specifies the positions in the file the lines will apply. With this information, you can replace the editor buffer by iterating over the lines and set it for the given range. An example how it's done in vim-go in Vimscript is:

let index = 0
for line_number in range(start, end)
  call setline(line_number, lines[index])
  let index += 1
endfor

Unsaved files

Editors can supply gomodifytags with the contents of unsaved buffers by using the -modified flag and writing an archive to stdin. Files in the archive will be preferred over those on disk.

Each archive entry consists of:

  • the file name, followed by a newline
  • the (decimal) file size, followed by a newline
  • the contents of the file

Development

At least Go v1.11.x is required. Older versions might work, but it's not recommended.

gomodifytags uses Go modules for dependency management. This means that you don't have to go get it into a GOPATH anymore. Checkout the repository:

git clone https://github.com/fatih/gomodifytags.git

Start developing the code. To build a binary, execute:

GO111MODULE=on go build -mod=vendor

This will create a gomodifytags binary in the current directory. To test the package, run the following:

GO111MODULE=on go test -v -mod=vendor

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

gomodifytags's People

Contributors

allenpetersen avatar bhcleek avatar brantou avatar coffeepac avatar davidrjenni avatar dependabot[bot] avatar fatih avatar igrmk avatar laurixyz avatar legec avatar perrito666 avatar ramya-rao-a avatar siruela avatar testwill avatar unicod3 avatar vigo avatar zmb3 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gomodifytags's Issues

add option to add tags to all structs in file

as of now you have to specify the name of each struct or know the position of each struct individually.

would be great to be able to bulk process a large file with multiple structs.

Formatting tag values $field not generated

I'm trying to generate with formatting tag values with -template. And I got null $field.

script executed:

gomodifytags -file purchase.go -all -add-tags gorm --template "column:$field" -w

result:

type PurchaseModel struct {
        BaseField         `json:",inline" gorm:"column:"`
        Code              string `json:"code,omitempty" gorm:"column:"`
        RefOrderId        string `json:"ref_order_id,omitempty" gorm:"column:"`
        Date              string `json:"date,omitempty" gorm:"column:"`
        Status            string `json:"status,omitempty" gorm:"column:"`
        PaymentStatus     string `json:"payment_status,omitempty" gorm:"column:"`
        InvoiceNumber     string `json:"invoice_number,omitempty" gorm:"column:"`
        InvoiceDate       string `json:"invoice_date,omitempty" gorm:"column:"`
        InvoiceDueDate    string `json:"invoice_due_date,omitempty" gorm:"column:"`
        InvoiceTotalPrice string `json:"invoice_total_price,omitempty" gorm:"column:"`
}

result gorm:"column:"
should be gorm:"column:code"

please help,
Thanks

Extra line returned when -format json is used

In the below example, lines from 61(start) to 66(end): 6 lines in total are expected to be in the output.

image

But the 7th line: line 67 (with just the })makes it to the output as well.

You can see this in the example in the README as well

{
  "start": 4,
  "end": 11,
  "lines": [
    "\tName        string `xml:\"name\"`",
    "\tPort        int    `xml:\"port\"`",
    "\tEnableLogs  bool   `xml:\"enable_logs\"`",
    "\tBaseDomain  string `xml:\"base_domain\"`",
    "\tCredentials struct {",
    "\t\tUsername string `xml:\"username\"`",
    "\t\tPassword string `xml:\"password\"`",
    "\t} `xml:\"credentials\"`",
    "}"
  ]
}

anonymous structs?

Is there support for anonymous structs? gomodifytags doesn't seem to work on anonymous structs.

Here's an example:

Running gomodifytags -file main.go -line 7,9 -add-tags json returns selection is not inside a struct

package main

import "fmt"

func main() {
	anon := []struct {
		ID int
		A  string
		B  string
	}{}

	fmt.Println(anon)
}

Support modified files

It would be nice if this tool could accept modified files on stdin instead of requiring editors to save them off as temp files.

I would recommend using the same archive format as guru and gogetdoc, which has a parser in the go/buildutil package.

The changes should be pretty straightforward:

  • document the archive format in the readme
  • add a -modified flag, and if present, use buildutil.ParseOverlayArchive to read the archive from stdin
  • if the file is present in the archive, populate the src argument of parser.ParseFile

With these updates, you'll be able to remove the temp files from vim-go and reuse the same code you already use for guru and gogetdoc.

I'm happy to take a stab at implementing these changes if you agree with the idea.

Unable to build with GCC go v7.1.1

As a result of this go-plus Atom package doesn't install properly.

Google go distribution, builds fine

$ go version
go version go1.8.3 linux/amd64
$ go get -u -x github.com/fatih/gomodifytags
cd .
git clone https://github.com/fatih/gomodifytags /home/lukas/dev/go/src/github.com/fatih/gomodifytags
cd /home/lukas/dev/go/src/github.com/fatih/gomodifytags
git submodule update --init --recursive
cd /home/lukas/dev/go/src/github.com/fatih/gomodifytags
git show-ref
cd /home/lukas/dev/go/src/github.com/fatih/gomodifytags
git submodule update --init --recursive
cd /home/lukas/dev/go/src/github.com/fatih/gomodifytags
git config remote.origin.url
cd /home/lukas/dev/go/src/github.com/fatih/gomodifytags
git config remote.origin.url
cd /home/lukas/dev/go/src/github.com/fatih/gomodifytags
git config remote.origin.url
WORK=/tmp/go-build216595188
mkdir -p $WORK/github.com/fatih/gomodifytags/vendor/github.com/fatih/structtag/_obj/
mkdir -p $WORK/github.com/fatih/gomodifytags/vendor/github.com/fatih/
cd /home/lukas/dev/go/src/github.com/fatih/gomodifytags/vendor/github.com/fatih/structtag
/usr/lib/go/pkg/tool/linux_amd64/compile -o $WORK/github.com/fatih/gomodifytags/vendor/github.com/fatih/structtag.a -trimpath $WORK -p github.com/fatih/gomodifytags/vendor/github.com/fatih/structtag -complete -buildid 72cb72096acf71b6d7bca0347aae7ff2bde3d9c3 -D _/home/lukas/dev/go/src/github.com/fatih/gomodifytags/vendor/github.com/fatih/structtag -I $WORK -pack ./tags.go
mkdir -p $WORK/github.com/fatih/gomodifytags/vendor/github.com/fatih/camelcase/_obj/
mkdir -p $WORK/github.com/fatih/gomodifytags/vendor/golang.org/x/tools/go/buildutil/_obj/
cd /home/lukas/dev/go/src/github.com/fatih/gomodifytags/vendor/github.com/fatih/camelcase
/usr/lib/go/pkg/tool/linux_amd64/compile -o $WORK/github.com/fatih/gomodifytags/vendor/github.com/fatih/camelcase.a -trimpath $WORK -p github.com/fatih/gomodifytags/vendor/github.com/fatih/camelcase -complete -buildid c4d679f88a92a34fb977a677836b8e41a5e27396 -D _/home/lukas/dev/go/src/github.com/fatih/gomodifytags/vendor/github.com/fatih/camelcase -I $WORK -pack ./camelcase.go
mkdir -p $WORK/github.com/fatih/gomodifytags/vendor/golang.org/x/tools/go/
cd /home/lukas/dev/go/src/github.com/fatih/gomodifytags/vendor/golang.org/x/tools/go/buildutil
/usr/lib/go/pkg/tool/linux_amd64/compile -o $WORK/github.com/fatih/gomodifytags/vendor/golang.org/x/tools/go/buildutil.a -trimpath $WORK -p github.com/fatih/gomodifytags/vendor/golang.org/x/tools/go/buildutil -complete -buildid 02625f824d9f8b09a97009c9953709ebbb8d7293 -D _/home/lukas/dev/go/src/github.com/fatih/gomodifytags/vendor/golang.org/x/tools/go/buildutil -I $WORK -pack ./allpackages.go ./fakecontext.go ./overlay.go ./tags.go ./util.go
mkdir -p /home/lukas/dev/go/pkg/linux_amd64/github.com/fatih/gomodifytags/vendor/github.com/fatih/
cp $WORK/github.com/fatih/gomodifytags/vendor/github.com/fatih/camelcase.a /home/lukas/dev/go/pkg/linux_amd64/github.com/fatih/gomodifytags/vendor/github.com/fatih/camelcase.a
cp $WORK/github.com/fatih/gomodifytags/vendor/github.com/fatih/structtag.a /home/lukas/dev/go/pkg/linux_amd64/github.com/fatih/gomodifytags/vendor/github.com/fatih/structtag.a
mkdir -p /home/lukas/dev/go/pkg/linux_amd64/github.com/fatih/gomodifytags/vendor/golang.org/x/tools/go/
cp $WORK/github.com/fatih/gomodifytags/vendor/golang.org/x/tools/go/buildutil.a /home/lukas/dev/go/pkg/linux_amd64/github.com/fatih/gomodifytags/vendor/golang.org/x/tools/go/buildutil.a
mkdir -p $WORK/github.com/fatih/gomodifytags/_obj/
mkdir -p $WORK/github.com/fatih/gomodifytags/_obj/exe/
cd /home/lukas/dev/go/src/github.com/fatih/gomodifytags
/usr/lib/go/pkg/tool/linux_amd64/compile -o $WORK/github.com/fatih/gomodifytags.a -trimpath $WORK -p main -complete -buildid 4183ffe72db4ba7f3b7cc40f68d677722530a383 -importmap github.com/fatih/camelcase=github.com/fatih/gomodifytags/vendor/github.com/fatih/camelcase -importmap github.com/fatih/structtag=github.com/fatih/gomodifytags/vendor/github.com/fatih/structtag -importmap golang.org/x/tools/go/buildutil=github.com/fatih/gomodifytags/vendor/golang.org/x/tools/go/buildutil -D _/home/lukas/dev/go/src/github.com/fatih/gomodifytags -I $WORK -I /home/lukas/dev/go/pkg/linux_amd64 -pack ./main.go
cd .
/usr/lib/go/pkg/tool/linux_amd64/link -o $WORK/github.com/fatih/gomodifytags/_obj/exe/a.out -L $WORK -L /home/lukas/dev/go/pkg/linux_amd64 -extld=gcc -buildmode=exe -buildid=4183ffe72db4ba7f3b7cc40f68d677722530a383 $WORK/github.com/fatih/gomodifytags.a
mkdir -p /home/lukas/dev/go/bin/
cp $WORK/github.com/fatih/gomodifytags/_obj/exe/a.out /home/lukas/dev/go/bin/gomodifytags

GCC go, won't build

$ go version
go version go1.8.1 gccgo (GCC) 7.1.1 20170528 linux/amd64
$ go get -u -x github.com/fatih/gomodifytags
cd .
git clone https://github.com/fatih/gomodifytags /home/lukas/dev/go/src/github.com/fatih/gomodifytags
cd /home/lukas/dev/go/src/github.com/fatih/gomodifytags
git submodule update --init --recursive
cd /home/lukas/dev/go/src/github.com/fatih/gomodifytags
git show-ref
cd /home/lukas/dev/go/src/github.com/fatih/gomodifytags
git submodule update --init --recursive
cd /home/lukas/dev/go/src/github.com/fatih/gomodifytags
git config remote.origin.url
cd /home/lukas/dev/go/src/github.com/fatih/gomodifytags
git config remote.origin.url
cd /home/lukas/dev/go/src/github.com/fatih/gomodifytags
git config remote.origin.url
WORK=/tmp/go-build286964385
mkdir -p $WORK/github.com/fatih/gomodifytags/vendor/github.com/fatih/camelcase/_obj/
mkdir -p $WORK/github.com/fatih/gomodifytags/vendor/github.com/fatih/
cd /home/lukas/dev/go/src/github.com/fatih/gomodifytags/vendor/github.com/fatih/camelcase
/usr/bin/gccgo -I $WORK -c -g -m64 -fgo-pkgpath=github.com/fatih/gomodifytags/vendor/github.com/fatih/camelcase -fgo-relative-import-path=_/home/lukas/dev/go/src/github.com/fatih/gomodifytags/vendor/github.com/fatih/camelcase -o $WORK/github.com/fatih/gomodifytags/vendor/github.com/fatih/camelcase/_obj/_go_.o ./camelcase.go
mkdir -p $WORK/github.com/fatih/gomodifytags/vendor/github.com/fatih/structtag/_obj/
cd /home/lukas/dev/go/src/github.com/fatih/gomodifytags/vendor/github.com/fatih/structtag
/usr/bin/gccgo -I $WORK -c -g -m64 -fgo-pkgpath=github.com/fatih/gomodifytags/vendor/github.com/fatih/structtag -fgo-relative-import-path=_/home/lukas/dev/go/src/github.com/fatih/gomodifytags/vendor/github.com/fatih/structtag -o $WORK/github.com/fatih/gomodifytags/vendor/github.com/fatih/structtag/_obj/_go_.o ./tags.go
mkdir -p $WORK/github.com/fatih/gomodifytags/vendor/golang.org/x/tools/go/buildutil/_obj/
mkdir -p $WORK/github.com/fatih/gomodifytags/vendor/golang.org/x/tools/go/
cd /home/lukas/dev/go/src/github.com/fatih/gomodifytags/vendor/golang.org/x/tools/go/buildutil
/usr/bin/gccgo -I $WORK -c -g -m64 -fgo-pkgpath=github.com/fatih/gomodifytags/vendor/golang.org/x/tools/go/buildutil -fgo-relative-import-path=_/home/lukas/dev/go/src/github.com/fatih/gomodifytags/vendor/golang.org/x/tools/go/buildutil -o $WORK/github.com/fatih/gomodifytags/vendor/golang.org/x/tools/go/buildutil/_obj/_go_.o ./allpackages.go ./fakecontext.go ./overlay.go ./tags.go ./util.go
cd /home/lukas/dev/go/src/github.com/fatih/gomodifytags/vendor/github.com/fatih/camelcase
ar rc $WORK/github.com/fatih/gomodifytags/vendor/github.com/fatih/libcamelcase.a $WORK/github.com/fatih/gomodifytags/vendor/github.com/fatih/camelcase/_obj/_go_.o
mkdir -p /home/lukas/dev/go/pkg/gccgo_linux_amd64/github.com/fatih/gomodifytags/vendor/github.com/fatih/
cp $WORK/github.com/fatih/gomodifytags/vendor/github.com/fatih/libcamelcase.a /home/lukas/dev/go/pkg/gccgo_linux_amd64/github.com/fatih/gomodifytags/vendor/github.com/fatih/libcamelcase.a
cd /home/lukas/dev/go/src/github.com/fatih/gomodifytags/vendor/github.com/fatih/structtag
ar rc $WORK/github.com/fatih/gomodifytags/vendor/github.com/fatih/libstructtag.a $WORK/github.com/fatih/gomodifytags/vendor/github.com/fatih/structtag/_obj/_go_.o
cp $WORK/github.com/fatih/gomodifytags/vendor/github.com/fatih/libstructtag.a /home/lukas/dev/go/pkg/gccgo_linux_amd64/github.com/fatih/gomodifytags/vendor/github.com/fatih/libstructtag.a
cd /home/lukas/dev/go/src/github.com/fatih/gomodifytags/vendor/golang.org/x/tools/go/buildutil
ar rc $WORK/github.com/fatih/gomodifytags/vendor/golang.org/x/tools/go/libbuildutil.a $WORK/github.com/fatih/gomodifytags/vendor/golang.org/x/tools/go/buildutil/_obj/_go_.o
mkdir -p /home/lukas/dev/go/pkg/gccgo_linux_amd64/github.com/fatih/gomodifytags/vendor/golang.org/x/tools/go/
cp $WORK/github.com/fatih/gomodifytags/vendor/golang.org/x/tools/go/libbuildutil.a /home/lukas/dev/go/pkg/gccgo_linux_amd64/github.com/fatih/gomodifytags/vendor/golang.org/x/tools/go/libbuildutil.a
mkdir -p $WORK/github.com/fatih/gomodifytags/_obj/
mkdir -p $WORK/github.com/fatih/gomodifytags/_obj/exe/
cd /home/lukas/dev/go/src/github.com/fatih/gomodifytags
/usr/bin/gccgo -I $WORK -I /home/lukas/dev/go/pkg/gccgo_linux_amd64 -I $WORK/github.com/fatih/gomodifytags/vendor -I /home/lukas/dev/go/pkg/gccgo_linux_amd64/github.com/fatih/gomodifytags/vendor -c -g -m64 -fgo-relative-import-path=_/home/lukas/dev/go/src/github.com/fatih/gomodifytags -o $WORK/github.com/fatih/gomodifytags/_obj/_go_.o ./main.go
ar rc $WORK/github.com/fatih/libgomodifytags.a $WORK/github.com/fatih/gomodifytags/_obj/_go_.o
cd .
/usr/bin/gccgo -o $WORK/github.com/fatih/gomodifytags/_obj/exe/a.out $WORK/github.com/fatih/gomodifytags/_obj/_go_.o -Wl,-( -m64 -Wl,--whole-archive /home/lukas/dev/go/pkg/gccgo_linux_amd64/github.com/fatih/gomodifytags/vendor/github.com/fatih/libcamelcase.a /home/lukas/dev/go/pkg/gccgo_linux_amd64/github.com/fatih/gomodifytags/vendor/github.com/fatih/libstructtag.a /home/lukas/dev/go/pkg/gccgo_linux_amd64/github.com/fatih/gomodifytags/vendor/golang.org/x/tools/go/libbuildutil.a -Wl,--no-whole-archive -Wl,-)
# github.com/fatih/gomodifytags
/tmp/go-build286964385/github.com/fatih/gomodifytags/_obj/_go_.o: In function `main.rewrite.pN11_main.config':
/home/lukas/dev/go/src/github.com/fatih/gomodifytags/main.go:184: undefined reference to `golang_org_x_tools_go_buildutil.ParseOverlayArchive'
/tmp/go-build286964385/github.com/fatih/gomodifytags/_obj/_go_.o: In function `__go_init_main':
/home/lukas/dev/go/src/github.com/fatih/gomodifytags/main.go:1: undefined reference to `golang_org_x_tools_go_buildutil..import'
collect2: error: ld returned 1 exit status

How 2 add tag name before element name?

I've struct name as below

type Server struct {
Name string json:"name"
Port int json:"port"
}

I want to add the element before name (Person:name) as like below

type Server struct {
Name string json:"Person:name"
Port int json:"port"
}

Is it possible to add this option in this lib?

Feature Request: skip already ignored fields

When using structs in combination with various ORM's like GORM you'll end up having fields like: Customer and CustomerID. We ignore the Customer or the CustomerID based on what we would like to output. It would be nice to skip the fields that are explicitly set to be ignored like json:"-".

Implementing a regex would also be a fine solution: #83

MP3 is converted to mp_3

Hey,

I just ran this tool on a struct with field name MP3 and the added tag was json:"xmp_3,omitempty".

This is wrong, but I wonder if it's worth fixing at all.

Add option to support custom formats

I would like to be able to customize the format of the outputted tag, like so:
Input:

type Foo struct {
  FooID int
}

What I want:

type Foo struct {
  FooID int `json:"fooId"`
}

If I use the camelcase option, the FooID, becomes, as expected, fooID, would there be any way to convert it to fooId?

Unexported embedded struct with skip-unexported option is still tagged

Input:

type stationEvent struct{}

type StationConnectorUnplugged struct {
	stationEvent
	ConnectorID    int
	MeterStop      int
	TransactionID  int32
	ChargingCardID identifier.ChargingCardID
	Timestamp      time.Time `json:"timestamp`
}

Output:

type stationEvent struct{}

type StationConnectorUnplugged struct {
        stationEvent   `json:"stationEvent"`
        ConnectorID    int                       `json:"connectorID"`
        MeterStop      int                       `json:"meterStop"`
        TransactionID  int32                     `json:"transactionID"`
        ChargingCardID identifier.ChargingCardID `json:"chargingCardID"`
        Timestamp      time.Time                 `json:"timestamp`
}

Expected:

type stationEvent struct{}

type StationConnectorUnplugged struct {
        stationEvent
        ConnectorID    int                       `json:"connectorID"`
        MeterStop      int                       `json:"meterStop"`
        TransactionID  int32                     `json:"transactionID"`
        ChargingCardID identifier.ChargingCardID `json:"chargingCardID"`
        Timestamp      time.Time                 `json:"timestamp`
}

Unable to add static tag value with comma.

Is it somehow possible to add tags with comma eg. with mapstructure:

type Friend struct {
    Person `mapstructure:",squash"`
}

I tried this but then squash is treated as the next tag token, maybe I'm missing something? :)

Feature Request: regex based modification

for example:

gomodifytags bla.go -w -field-regex '.*Id' -add-options json=string
gomodifytags bla.go -w -field-regex '.*At' -add-options json=string

those will modify only fields that ends with Id or At

Incomplete detection for anonymous structs in function signature

We have a code base where the following code appears :

func SomeHandler(args *struct{
    Arg1 int    `json:"arg1,omitempty"`
    Arg2 string `json:"arg2,omitempty"`
}) error {
    ...

When running gomodifytags with an offset falling within the range of this struct declaration, it returns an error : offset is not inside a struct.

Different tags use different transforms

A tag on a struct uses the same transforms, and I want to use separate transforms for each tag.

AppDeploymentServerModuleConfig struct {
		ID                    int    `json:"id" gorm:"id"`
		AppDeploymentConfigID int    `json:"appDeploymentConfigID" gorm:"app_deployment_config_id"`

}

json use camelcase transforms, gorm use snakecase transforms

Parsing fails for test files with -modified flag

While trying to run gomodifytags with -modified flag on a test file, we get the below error:

"failed to parse -modified archive: parsing size of archive file .: strconv.ParseUint: parsing "}": invalid syntax"

support anonymous structs

Behavior

package main

func main() {
    // I believe running :GoAddTags inside this anonymous struct should add its tags accordingly
	&struct {
		Hello string
	}{}
}

Steps to reproduce:

  • Open file .go file
  • Create anonymous struct
  • Run :GoAddTags in it
  • Message "offset is not inside a struct" will show up

Will gladly work on this one if you have no problems with it.

Support custom tag for selected field in struct

Hi, first thank you for this great library. So i have special case like this, i want to generate custom tag in my Struct, but not all the field will have it. Example

type Pokemon struct {
	Name     string
	Age        int    `validate:min=5,max=10`
}

so on the example above, i only want field Age have the custom tag with value validate:min=5,max=10

Can we have this feature? Thank you for your attention

camelcase does'nt work

gomodifytags -file audiovo.go -struct AudioSimpleVo -add-tags json -transform camelcase

generated content is below:

type AudioSimpleVo struct {
        //音频ID
        ID string `json:"id,omitempty"`
        //父ID 课程ID或书的ID
        ParentID string `json:"parent_id,omitempty"`
        //标题
        Titile string `json:"titile,omitempty"`
        //音频时长
        Length int64 `json:"length,omitempty"`
        //是否免费  0:收费 1:免费
        Free int `json:"free,omitempty"`
        //标签类型  2:加餐
        TadType int `json:"tadType"`
        //分组ID
        SectionID string `json:"section_id,omitempty"`
        //分组标题
        // example: 开篇词
        SectionTitle string `json:"section_title,omitempty"`
        //学习状态: 0:未学习 1:已学习
        LearnStatus int `json:"learn_status,omitempty"`
        //学习人数
        LearnCount int64 `json:"learn_count,omitempty"`
        //学习人数(带文案)
        LearnCountText string `json:"learn_count_text,omitempty"`
        //答题标志
        TopicTag int `json:"topic_tag,omitempty"`
        //答对几题
        TopicScore int `json:"topicScore"`
}

why???

Wrong output when the file isn't gofmt'd

With the following file:

$ cat tags.go
package a
type x struct {
    Foo int
    bar int
}

The tool gives the wrong results.

Should be start=2:

$ gomodifytags -format json -file tags.go -transform snakecase -line 3,4 -add-tags json -add-options json=
{
  "start": 3,
  "end": 4,
  "lines": [
    "type x struct {",
    "\tFoo int `json:\"foo\"`"
  ]
}

Should be start=2, and one line is missing from the output:

$ gomodifytags -format json -file tags.go -transform snakecase -line 3,3 -add-tags json -add-options json=
{
  "start": 3,
  "end": 3,
  "lines": [
    "type x struct {"
  ]
}

start is correct, but the last line (}) missing:

$ gomodifytags -format json -file tags.go -transform snakecase -offset 23 -add-tags json -add-options json=
{
  "start": 2,
  "end": 5,
  "lines": [
    "",
    "type x struct {",
    "\tFoo int `json:\"foo\"`",
    "\tbar int `json:\"bar\"`"
  ]
}

It seems that the tool operates on the file as if they're gofmt'd.

Case cannot be changed without removing tags first

For the input file main.go:

package main

type Foo struct {
	BarBash  string `json:"bar_bash"`
	BazBob   string `json:"baz_bob"`
	QuuxKing int    `json:"quux_king"`
}

The command gomodifytags -file main.go -struct Foo -add-tags json -transform camelcase returns the input unmodified, instead of changing the tags from snake_case to camelCase.

For reference, the same behavior does not occur with the -sort option. I can have an input file with xml and json tags (in that order), and invoke gomodifytags with -add-tags xml,json -sort and the order of the tags is updated as expected.

Cannot add more than one -add-options

tested both of this didn't work:

-add-options json=string,omitempty
-add-options json=string -add-options json=omitempty

but running the command twice works:

-add-options json=string 
-add-options json=omitempty

Add -transform lowercase

background: I got some error while doing scanny.pgxscan.Select because the column is not there

without the struct tag db:"createdat" (actually it was CreatedAt on the struct) it shows error scanning all: scanning: scanning: doing scan: scanFn: scany: column: createdat

and gomodifytags only allow PascalCase or snake_case (only these two that most similar), where what i need is lowercase.

Adding Title Case to the list of supported cases

Hi, I was wondering if we could add an additional option of 'Title Case'. I came across its usefulness while adding csv tags to my structs.

I've written a simple code fix for it, but I'm unable to push the branch to this repo. I would appreciate any feedback on this.

support -field option

gomodifytags -file test.go -struct PostReviewProcess -field Id --add-tags gorm -w

We can specify the field option to support modifying the tag of the specific field of the structure?
in structSelection function: add codes like below:

// struct selects all lines inside a struct

start := c.fset.Position(encStruct.Pos()).Line
end := c.fset.Position(encStruct.End()).Line

if c.fieldName!=""{
	for i:=0;i<len(encStruct.Fields.List);i++{
		f:=encStruct.Fields.List[i]
		if len(f.Names)>0{
			if f.Names[0].Name==c.fieldName{
				start=c.fset.Position(f.Pos()).Line
				end=start
				break
			}
		}
	}
}

GoModifyTags doesn't work if a tag contains malformed tags

$ cat demo.go
package main

type Example struct {
	StatusID int64 `json:"status_id`
	Foo      string
	Bar      bool

	Server struct {
		Address string
		TLS     bool
	}

	DiskSize int64
	Volumes  []string
}
$ gomodifytags --file demo.go -struct Example -add-tags json
bad syntax for struct tag value

Here the struct tag is missing a quote. Two things we need to improve:

  1. Error message should contain the struct name and the line position
  2. We should modify other fields expect the malformed, instead of failing direclty

copy tag value and options

I wonder if its possible and I'm missing something, or if it is something that you might want to accept as a PR.

tl;dr: I want to copy all yaml tag options and names to json

so, in:

package main

type Foo struct {
  Bar string `yaml:"bar,omitempty"`
}

out:

package main

type Foo struct {
  Bar string `yaml:"bar,omitempty" json:"bar,omitempty"`
}

is there a good way to do that with the current gomodifytags version?

Override flag defaults with a config file

I'd like to have the ability to change the defaults of the executable, e.g. to make the default transformation be camelCase instead of snake_case.

My proposal would be to introduce a config file (e.g. ~/.config/gomodifytags/config) where you could override default flag values.

Add new transformation where acronyms are in capital case

I use the camelcase transformation, but I have one issue with it.
In my API, we use the go linter conventions regarding acronyms in our JSONs:
we use keys like userID instead of userId.

I did not find a way to preserve this behavior.

I don't even mind writing the PR if that's OK with you

Embedded struct can not be used with -transform camelcase

type PDetail struct {
	PSummary //will cause problem
	Thumbnail             string `json:"thumbnail"`
}
 W
panic: runtime error: index out of range

goroutine 1 [running]:
main.(*config).addTags(0xc4200a4200, 0x0, 0x0, 0xc4200e74e0, 0x0, 0x100eda8, 0x20)
        /Users/ / /go/src/github.com/fatih/gomodifytags/main.go:351 +0x8a5

Document option to tag all structs

I had to search in the issues to see a way for all structs to be used in the file, almost not using this lib(which is great, by the way! only missing a few tiny things, that may hinder the usability). Which I've found the solution to be, to pass line 1,100000.

As for the behavior I expected when I used the gomodifytags command, it would be:

  • gomodifytags -file <file>.go: parses entire file, modify all structs, because no filter option passed
  • gomodifytags -file <file>.go -struct/-line/-offset: gets the entire file, apply the filter, only modify structs that were filtered

But, I don't know if that's everyone's expected behavior, so to at least cover this use case, we could at least document this hidden option, or implement it the proper way(without the line workaround, at least not to the end-user)

Unable to install gomodifytags tool on VS Code

I have been unable to download and install the gomodifytags package automatically via the install all option and when I attempt to do it manually via the go install github.com/fatih/gomodifytags@latest command, I get the following as feedback:

# github.com/fatih/gomodifytags
C:\Program Files\Go\pkg\tool\windows_amd64\link.exe: C:\Users\IAN\AppData\Local\go-build\7e\7ead9b6fbf2293b80b2d0531d108001d1e31a4fd463224b9b481fc70392a1baa-d: not package main

How can I resolve this challenge?

Feature Reqest: silent output

Currently even with -w flag the output still printed in stdout
it would be nice if there's a flag that print only when there's error

:GoAddTags cannot add tags to variable defined with struct literal

(originally opened in vim-go)

What did you do?

I tried to run :GoAddTags inside a variable defined with a struct literal:

var thing struct{
  id int
  value string
}

What did you expect to happen?

I expected struct tags to be added per usual.

What happened instead?

I got the error message:

vim-go: offset is not inside a struct

Configuration:

  • vim-go version: v1.17

  • vimrc you used to reproduce (use a minimal vimrc with other plugins disabled; do not link to a 2,000 line vimrc):
    My vimrc

  • Vim version (first three lines from :version):
    VIM - Vi IMproved 8.0 (2016 Sep 12, compiled Nov 29 2017 18:37:46)
    Included patches: 1-503, 505-608, 682-1283
    Compiled by [email protected]

  • Go version (go version): go1.10.1

  • Go environment (go env): darwin/amd64

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.