Repository: googleapis/api-linter
Pull request #299 (2019-11-04 21:33:32)

Used pflag.
```
Usage of api-linter:
      --config string                 The linter config file.
      --disable-rule stringArray      Disable a rule with the given name.
                                      May be specified multiple times.
      --enable-rule stringArray       Enable a rule with the given name.
                                      May be specified multiple times.
      --output-format string          The format of the linting results.
                                      Supported formats include "yaml", "json" and "summary" table.
                                      YAML is the default.
  -o, --output-path string            The output file path.
                                      If not given, the linting results will be printed out to STDOUT.
      --proto-descriptor-set string   A delimited (':') list of files each containing a FileDescriptorSet for searching proto imports.
  -I, --proto-path stringArray        The folder for searching proto imports.
                                      May be specified multiple times; directories will be searched in order.
                                      The current working directory is always used.
pflag: help requested
```


Patch:
diff --git a/cmd/api-linter/cli.go b/cmd/api-linter/cli.go
index 9b31e7e..3ba926c 100644
--- a/cmd/api-linter/cli.go
+++ b/cmd/api-linter/cli.go
@@ -16,7 +16,6 @@ package main
 
 import (
 	"encoding/json"
-	"flag"
 	"fmt"
 	"io/ioutil"
 	"os"
@@ -27,6 +26,7 @@ import (
 	"github.com/googleapis/api-linter/lint"
 	"github.com/jhump/protoreflect/desc"
 	"github.com/jhump/protoreflect/desc/protoparse"
+	"github.com/spf13/pflag"
 	"gopkg.in/yaml.v2"
 )
 
@@ -46,20 +46,20 @@ func newCli(args []string) *cli {
 	var cfgFlag string
 	var fmtFlag string
 	var outFlag string
-	var protoImportFlag stringSlice
+	var protoImportFlag []string
 	var protoDescFlag string
-	var ruleEnableFlag stringSlice
-	var ruleDisableFlag stringSlice
+	var ruleEnableFlag []string
+	var ruleDisableFlag []string
 
 	// Register flag variables.
-	fs := flag.NewFlagSet("api-linter", flag.ExitOnError)
+	fs := pflag.NewFlagSet("api-linter", pflag.ExitOnError)
 	fs.StringVar(&cfgFlag, "config", "", "The linter config file.")
-	fs.StringVar(&fmtFlag, "output_format", "", "The format of the linting results.\nSupported formats include \"yaml\", \"json\" and \"summary\" table.\nYAML is the default.")
-	fs.StringVar(&outFlag, "output_path", "", "The output file path.\nIf not given, the linting results will be printed out to STDOUT.")
-	fs.Var(&protoImportFlag, "proto_path", "The folder for searching proto imports.\nMay be specified multiple times; directories will be searched in order.\nThe current working directory is always used.")
-	fs.StringVar(&protoDescFlag, "proto_descriptor_set", "", "A delimited (':') list of files each containing a FileDescriptorSet for searching proto imports.")
-	fs.Var(&ruleEnableFlag, "enable_rule", "Enable a rule with the given name.\nMay be specified multiple times.")
-	fs.Var(&ruleDisableFlag, "disable_rule", "Disable a rule with the given name.\nMay be specified multiple times.")
+	fs.StringVar(&fmtFlag, "output-format", "", "The format of the linting results.\nSupported formats include \"yaml\", \"json\" and \"summary\" table.\nYAML is the default.")
+	fs.StringVarP(&outFlag, "output-path", "o", "", "The output file path.\nIf not given, the linting results will be printed out to STDOUT.")
+	fs.StringArrayVarP(&protoImportFlag, "proto-path", "I", nil, "The folder for searching proto imports.\nMay be specified multiple times; directories will be searched in order.\nThe current working directory is always used.")
+	fs.StringVar(&protoDescFlag, "proto-descriptor-set", "", "A delimited (':') list of files each containing a FileDescriptorSet for searching proto imports.")
+	fs.StringArrayVar(&ruleEnableFlag, "enable-rule", nil, "Enable a rule with the given name.\nMay be specified multiple times.")
+	fs.StringArrayVar(&ruleDisableFlag, "disable-rule", nil, "Disable a rule with the given name.\nMay be specified multiple times.")
 
 	// Parse flags.
 	fs.Parse(args)
@@ -174,22 +174,6 @@ func (c *cli) lint(rules lint.RuleRegistry, configs lint.Configs) error {
 	return nil
 }
 
-type stringSlice []string
-
-// String is the method to format the flag's value, part of the flag.Value interface.
-// The String method's output will be used in diagnostics.
-func (p *stringSlice) String() string {
-	return fmt.Sprint(*p)
-}
-
-// Set is the method to set the flag value, part of the flag.Value interface.
-// Set's argument is a string to be parsed to set the flag.
-// It's a comma-separated list, so we split it.
-func (p *stringSlice) Set(value string) error {
-	*p = append(*p, strings.Split(value, ",")...)
-	return nil
-}
-
 func loadFileDescriptors(filePaths ...string) (map[string]*desc.FileDescriptor, error) {
 	fds := []*dpb.FileDescriptorProto{}
 	for _, filePath := range filePaths {
diff --git a/go.mod b/go.mod
index 639fce0..6c948e4 100644
--- a/go.mod
+++ b/go.mod
@@ -12,6 +12,7 @@ require (
 	github.com/lithammer/dedent v1.1.0
 	github.com/mattn/go-runewidth v0.0.5 // indirect
 	github.com/olekukonko/tablewriter v0.0.1
+	github.com/spf13/pflag v1.0.5
 	github.com/stoewer/go-strcase v1.0.2
 	google.golang.org/genproto v0.0.0-20191028173616-919d9bdd9fe6
 	gopkg.in/yaml.v2 v2.2.5
diff --git a/go.sum b/go.sum
index a7a651b..c24f61e 100644
--- a/go.sum
+++ b/go.sum
@@ -30,6 +30,8 @@ github.com/olekukonko/tablewriter v0.0.1 h1:b3iUnf1v+ppJiOfNX4yxxqfWKMQPZR5yoh8u
 github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
 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/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
+github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
 github.com/stoewer/go-strcase v1.0.2 h1:l3iQ2FPu8+36ars/7syO1dQAkjwMCb1IE3J+Th0ohfE=
 github.com/stoewer/go-strcase v1.0.2/go.mod h1:eLfe5bL3qbL7ep/KafHzthxejrOF5J3xmt03uL5tzek=
 github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=


Test patch:
diff --git a/cmd/api-linter/cli_test.go b/cmd/api-linter/cli_test.go
index cc70269..c78ae31 100644
--- a/cmd/api-linter/cli_test.go
+++ b/cmd/api-linter/cli_test.go
@@ -15,7 +15,7 @@ func TestNewCli(t *testing.T) {
 	}{
 		{
 			name:      "AllFlags",
-			inputArgs: strings.Split("-config=config -output_format=json -output_path=out -proto_descriptor_set=proto_desc -proto_path=proto_path_a -proto_path=proto_path_b a.proto b.proto", " "),
+			inputArgs: strings.Split("--config=config --output-format=json -o=out --proto-descriptor-set=proto_desc -I=proto_path_a -I=proto_path_b a.proto b.proto", " "),
 			wantCli: &cli{
 				ConfigPath:       "config",
 				OutputPath:       "out",
diff --git a/cmd/api-linter/integration_test.go b/cmd/api-linter/integration_test.go
index 5372927..70da604 100644
--- a/cmd/api-linter/integration_test.go
+++ b/cmd/api-linter/integration_test.go
@@ -176,15 +176,15 @@ func runLinter(t *testing.T, protoContent, configContent string) string {
 		if err := writeFile(configFilePath, configContent); err != nil {
 			t.Fatal(err)
 		}
-		args = append(args, fmt.Sprintf("-config=%s", configFilePath))
+		args = append(args, fmt.Sprintf("--config=%s", configFilePath))
 	}
 	// Add a flag for the output path.
 	outPath := filepath.Join(tempDir, "test.out")
-	args = append(args, fmt.Sprintf("-output_path=%s", outPath))
+	args = append(args, fmt.Sprintf("-o=%s", outPath))
 	// Add the temp dir to the proto paths.
-	args = append(args, fmt.Sprintf("-proto_path=%s", tempDir))
+	args = append(args, fmt.Sprintf("-I=%s", tempDir))
 	// Add a flag for the file descriptor set.
-	args = append(args, "-proto_descriptor_set=internal/testdata/dummy.protoset")
+	args = append(args, "--proto-descriptor-set=internal/testdata/dummy.protoset")
 	// Write the proto file.
 	protoFileName := "test.proto"
 	protoFilePath := filepath.Join(tempDir, protoFileName)