Browse Source

Migrated to github.com/pierrec/cmdflag

Pierre Curto 6 years ago
parent
commit
7d6ffbcb8e

+ 18 - 15
cmd/lz4c/main.go

@@ -4,27 +4,30 @@ import (
 	"flag"
 	"fmt"
 
-	"github.com/pierrec/lz4/internal/cmdflag"
+	"github.com/pierrec/cmdflag"
 	"github.com/pierrec/lz4/internal/cmds"
 )
 
-func init() {
-	const onError = flag.ExitOnError
-	cmdflag.New(
-		"compress", "[arguments] [<file name> ...]",
-		"Compress the given files or from stdin to stdout.",
-		onError, cmds.Compress)
-	cmdflag.New(
-		"uncompress", "[arguments] [<file name> ...]",
-		"Uncompress the given files or from stdin to stdout.",
-		onError, cmds.Uncompress)
-}
-
 func main() {
 	flag.CommandLine.Bool(cmdflag.VersionBoolFlag, false, "print the program version")
 
-	err := cmdflag.Parse()
-	if err != nil {
+	cli := cmdflag.New(nil)
+	cli.MustAdd(cmdflag.Application{
+		Name:  "compress",
+		Args:  "[arguments] [<file name> ...]",
+		Descr: "Compress the given files or from stdin to stdout.",
+		Err:   flag.ExitOnError,
+		Init:  cmds.Compress,
+	})
+	cli.MustAdd(cmdflag.Application{
+		Name:  "uncompress",
+		Args:  "[arguments] [<file name> ...]",
+		Descr: "Uncompress the given files or from stdin to stdout.",
+		Err:   flag.ExitOnError,
+		Init:  cmds.Uncompress,
+	})
+
+	if err := cli.Parse(); err != nil {
 		fmt.Println(err)
 		return
 	}

+ 1 - 0
go.mod

@@ -4,6 +4,7 @@ require (
 	code.cloudfoundry.org/bytefmt v0.0.0-20180906201452-2aa6f33b730c
 	github.com/onsi/ginkgo v1.8.0 // indirect
 	github.com/onsi/gomega v1.5.0 // indirect
+	github.com/pierrec/cmdflag v0.0.2
 	github.com/schollz/progressbar/v2 v2.12.1
 	golang.org/x/net v0.0.0-20190311183353-d8887717615a // indirect
 	golang.org/x/sync v0.0.0-20190423024810-112230192c58 // indirect

+ 2 - 0
go.sum

@@ -16,6 +16,8 @@ github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w=
 github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=
 github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
+github.com/pierrec/cmdflag v0.0.2 h1:ybjGJnPr/aURn2IKWjO49znx9N0DL6YfGsIxN0PYuVY=
+github.com/pierrec/cmdflag v0.0.2/go.mod h1:a3zKGZ3cdQUfxjd0RGMLZr8xI3nvpJOB+m6o/1X5BmU=
 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/schollz/progressbar/v2 v2.12.1 h1:0Ce7IBClG+s3lxXN1Noqwh7aToKGL5a3mnMfPJqDlv4=

+ 0 - 14
internal/cmdflag/buildinfo.go

@@ -1,14 +0,0 @@
-// +build go1.12
-
-package cmdflag
-
-import (
-	"runtime/debug"
-)
-
-func buildinfo() string {
-	if bi, ok := debug.ReadBuildInfo(); ok {
-		return bi.Main.Version
-	}
-	return "no version available (not built with module support)"
-}

+ 0 - 7
internal/cmdflag/buildinfo_lt_1_12.go

@@ -1,7 +0,0 @@
-// +build !go1.12
-
-package cmdflag
-
-func buildinfo() string {
-	return "no version available"
-}

+ 0 - 148
internal/cmdflag/cmdflag.go

@@ -1,148 +0,0 @@
-// Package cmdflag adds single level cmdflag support to the standard library flag package.
-package cmdflag
-
-import (
-	"flag"
-	"fmt"
-	"io"
-	"os"
-	"path/filepath"
-	"runtime"
-	"strings"
-	"sync"
-)
-
-//TODO add a -fullversion command to display module versions, compiler version
-//TODO add multi level command support
-
-// VersionBoolFlag is the flag name to be used as a boolean flag to display the program version.
-const VersionBoolFlag = "version"
-
-// Usage is the function used for help.
-var Usage = func() {
-	fset := flag.CommandLine
-	out := fsetOutput(fset)
-
-	program := programName(os.Args[0])
-	fmt.Fprintf(out, "Usage of %s:\n", program)
-	fset.PrintDefaults()
-
-	fmt.Fprintf(out, "\nSubcommands:")
-	for _, sub := range subs {
-		fmt.Fprintf(out, "\n%s\n%s %s\n", sub.desc, sub.name, sub.argsdesc)
-		fs, _ := sub.init(out)
-		fs.PrintDefaults()
-	}
-}
-
-// Handler is the function called when a matching cmdflag is found.
-type Handler func(...string) error
-
-type subcmd struct {
-	errh     flag.ErrorHandling
-	name     string
-	argsdesc string
-	desc     string
-	ini      func(*flag.FlagSet) Handler
-}
-
-func (sub *subcmd) init(out io.Writer) (*flag.FlagSet, Handler) {
-	fname := fmt.Sprintf("cmdflag `%s`", sub.name)
-	fs := flag.NewFlagSet(fname, sub.errh)
-	fs.SetOutput(out)
-	return fs, sub.ini(fs)
-}
-
-var (
-	mu   sync.Mutex
-	subs []*subcmd
-)
-
-// New instantiates a new cmdflag with its name and description.
-//
-// It is safe to be called from multiple go routines (typically in init functions).
-//
-// The cmdflag initializer is called only when the cmdflag is present on the command line.
-// The handler is called with the remaining arguments once the cmdflag flags have been parsed successfully.
-//
-// It will panic if the cmdflag already exists.
-func New(name, argsdesc, desc string, errh flag.ErrorHandling, initializer func(*flag.FlagSet) Handler) {
-	sub := &subcmd{
-		errh:     errh,
-		name:     name,
-		argsdesc: argsdesc,
-		desc:     desc,
-		ini:      initializer,
-	}
-
-	mu.Lock()
-	defer mu.Unlock()
-	for _, sub := range subs {
-		if sub.name == name {
-			panic(fmt.Errorf("cmdflag %s redeclared", name))
-		}
-	}
-	subs = append(subs, sub)
-}
-
-// Parse parses the command line arguments including the global flags and, if any, the cmdflag and its flags.
-//
-// If the VersionBoolFlag is defined as a global boolean flag, then the program version is displayed and the program stops.
-func Parse() error {
-	args := os.Args
-	if len(args) == 1 {
-		return nil
-	}
-
-	// Global flags.
-	fset := flag.CommandLine
-	fset.Usage = Usage
-	out := fsetOutput(fset)
-
-	if err := fset.Parse(args[1:]); err != nil {
-		return err
-	}
-
-	// Handle version request.
-	if f := fset.Lookup(VersionBoolFlag); f != nil {
-		if v, ok := f.Value.(flag.Getter); ok {
-			// All values implemented by the flag package implement the flag.Getter interface.
-			if b, ok := v.Get().(bool); ok && b {
-				// The flag was defined as a bool and is set.
-				program := programName(args[0])
-				fmt.Fprintf(out, "%s version %s %s/%s\n",
-					program, buildinfo(),
-					runtime.GOOS, runtime.GOARCH)
-				return nil
-			}
-		}
-	}
-
-	// No cmdflag.
-	if fset.NArg() == 0 {
-		return nil
-	}
-
-	// Subcommand.
-	idx := len(args) - fset.NArg()
-	s := args[idx]
-	args = args[idx+1:]
-	for _, sub := range subs {
-		if sub.name != s {
-			continue
-		}
-
-		fs, handler := sub.init(out)
-		if err := fs.Parse(args); err != nil {
-			return err
-		}
-		return handler(args[len(args)-fs.NArg():]...)
-	}
-
-	return fmt.Errorf("%s is not a valid cmdflag", s)
-}
-
-func programName(s string) string {
-	name := filepath.Base(s)
-	return strings.TrimSuffix(name, ".exe")
-}

+ 0 - 163
internal/cmdflag/cmdflag_test.go

@@ -1,163 +0,0 @@
-package cmdflag_test
-
-import (
-	"flag"
-	"os"
-	"testing"
-
-	"github.com/pierrec/lz4/internal/cmdflag"
-)
-
-func TestGlobalFlagOnly(t *testing.T) {
-	cmd, args := flag.CommandLine, os.Args
-	defer func() { flag.CommandLine, os.Args = cmd, args }()
-
-	flag.CommandLine = flag.NewFlagSet("", flag.ExitOnError)
-	var gv1 string
-	flag.StringVar(&gv1, "v1", "val1", "usage1")
-	os.Args = []string{"program", "-v1=gcli1"}
-
-	if err := cmdflag.Parse(); err != nil {
-		t.Fatal(err)
-	}
-
-	if got, want := gv1, "gcli1"; got != want {
-		t.Fatalf("got %s; want %s", got, want)
-	}
-}
-
-func TestInvalidcmdflag(t *testing.T) {
-	cmd, args := flag.CommandLine, os.Args
-	defer func() { flag.CommandLine, os.Args = cmd, args }()
-
-	flag.CommandLine = flag.NewFlagSet("", flag.ExitOnError)
-	os.Args = []string{"program", "invalidsub"}
-
-	if err := cmdflag.Parse(); err == nil {
-		t.Fatal("expected invalid command error")
-	}
-}
-
-func TestOnecmdflag(t *testing.T) {
-	h1 := 0
-	handle1 := func(fset *flag.FlagSet) cmdflag.Handler {
-		return func(args ...string) error {
-			h1++
-			return nil
-		}
-	}
-	cmdflag.New("sub1", "", "", flag.ExitOnError, handle1)
-
-	args := os.Args
-	defer func() { os.Args = args }()
-	os.Args = []string{"program", "sub1"}
-
-	if err := cmdflag.Parse(); err != nil {
-		t.Fatal(err)
-	}
-
-	if got, want := h1, 1; got != want {
-		t.Fatalf("got %d; want %d", got, want)
-	}
-}
-
-func TestOnecmdflagOneFlag(t *testing.T) {
-	h1 := 0
-	handle1 := func(fset *flag.FlagSet) cmdflag.Handler {
-		h1++
-
-		var v1 string
-		fset.StringVar(&v1, "v1", "val1", "usage1")
-
-		return func(args ...string) error {
-			if got, want := v1, "cli1"; got != want {
-				t.Fatalf("got %s; want %s", got, want)
-			}
-			return nil
-		}
-	}
-	cmdflag.New("sub1flag", "", "", flag.ExitOnError, handle1)
-
-	args := os.Args
-	defer func() { os.Args = args }()
-	os.Args = []string{"program", "sub1flag", "-v1=cli1"}
-
-	if err := cmdflag.Parse(); err != nil {
-		t.Fatal(err)
-	}
-
-	if got, want := h1, 1; got != want {
-		t.Fatalf("got %d; want %d", got, want)
-	}
-}
-
-func TestGlobalFlagOnecmdflag(t *testing.T) {
-	h1 := 0
-	handle1 := func(fset *flag.FlagSet) cmdflag.Handler {
-		h1++
-
-		var v1 string
-		fset.StringVar(&v1, "v1", "val1", "usage1")
-
-		return func(args ...string) error {
-			return nil
-		}
-	}
-	cmdflag.New("subglobal", "", "", flag.ExitOnError, handle1)
-
-	cmd, args := flag.CommandLine, os.Args
-	defer func() { flag.CommandLine, os.Args = cmd, args }()
-
-	flag.CommandLine = flag.NewFlagSet("", flag.ExitOnError)
-	var gv1 string
-	flag.StringVar(&gv1, "v1", "val1", "usage1")
-
-	os.Args = []string{"program", "-v1=gcli1", "subglobal"}
-
-	if err := cmdflag.Parse(); err != nil {
-		t.Fatal(err)
-	}
-
-	if got, want := h1, 1; got != want {
-		t.Fatalf("got %d; want %d", got, want)
-	}
-
-	if got, want := gv1, "gcli1"; got != want {
-		t.Fatalf("got %s; want %s", got, want)
-	}
-}
-
-func TestGlobalFlagOnecmdflagOneFlag(t *testing.T) {
-	h1 := 0
-	handle1 := func(fset *flag.FlagSet) cmdflag.Handler {
-		h1++
-
-		var v1 string
-		fset.StringVar(&v1, "v1", "val1", "usage1")
-
-		return func(args ...string) error {
-			if got, want := v1, "cli1"; got != want {
-				t.Fatalf("got %s; want %s", got, want)
-			}
-			return nil
-		}
-	}
-	cmdflag.New("subglobal1flag", "", "", flag.ExitOnError, handle1)
-
-	cmd, args := flag.CommandLine, os.Args
-	defer func() { flag.CommandLine, os.Args = cmd, args }()
-
-	flag.CommandLine = flag.NewFlagSet("", flag.ExitOnError)
-	var gv1 string
-	flag.StringVar(&gv1, "v1", "val1", "usage1")
-
-	os.Args = []string{"program", "subglobal1flag", "-v1=cli1"}
-
-	if err := cmdflag.Parse(); err != nil {
-		t.Fatal(err)
-	}
-
-	if got, want := h1, 1; got != want {
-		t.Fatalf("got %d; want %d", got, want)
-	}
-}

+ 0 - 45
internal/cmdflag/example_test.go

@@ -1,45 +0,0 @@
-package cmdflag_test
-
-import (
-	"flag"
-	"fmt"
-	"os"
-
-	"github.com/pierrec/lz4/internal/cmdflag"
-)
-
-func ExampleParse() {
-	// Declare the `split` cmdflag.
-	cmdflag.New(
-		"split",
-		"argsdesc",
-		"desc",
-		flag.ExitOnError,
-		func(fs *flag.FlagSet) cmdflag.Handler {
-			// Declare the cmdflag specific flags.
-			var s string
-			fs.StringVar(&s, "s", "", "string to be split")
-
-			// Return the handler to be executed when the cmdflag is found.
-			return func(...string) error {
-				i := len(s) / 2
-				fmt.Println(s[:i], s[i:])
-				return nil
-			}
-		})
-
-	// The following is only used to emulate passing command line arguments to `program`.
-	// It is equivalent to running:
-	// ./program split -s hello
-	args := os.Args
-	defer func() { os.Args = args }()
-	os.Args = []string{"program", "split", "-s", "hello"}
-
-	// Process the command line arguments.
-	if err := cmdflag.Parse(); err != nil {
-		panic(err)
-	}
-
-	// Output:
-	// he llo
-}

+ 0 - 12
internal/cmdflag/fset.go

@@ -1,12 +0,0 @@
-// +build go1.10
-
-package cmdflag
-
-import (
-	"flag"
-	"io"
-)
-
-func fsetOutput(fs *flag.FlagSet) io.Writer {
-	return fs.Output()
-}

+ 0 - 13
internal/cmdflag/fset_1_10.go

@@ -1,13 +0,0 @@
-// +build !go1.10
-
-package cmdflag
-
-import (
-	"flag"
-	"io"
-	"os"
-)
-
-func fsetOutput(fs *flag.FlagSet) io.Writer {
-	return os.Stderr
-}

+ 12 - 12
internal/cmds/compress.go

@@ -9,8 +9,8 @@ import (
 	"code.cloudfoundry.org/bytefmt"
 	"github.com/schollz/progressbar/v2"
 
+	"github.com/pierrec/cmdflag"
 	"github.com/pierrec/lz4"
-	"github.com/pierrec/lz4/internal/cmdflag"
 )
 
 // Compress compresses a set of files or from stdin to stdout.
@@ -24,10 +24,10 @@ func Compress(fs *flag.FlagSet) cmdflag.Handler {
 	var level int
 	fs.IntVar(&level, "l", 0, "compression level (0=fastest)")
 
-	return func(args ...string) error {
+	return func(args ...string) (int, error) {
 		sz, err := bytefmt.ToBytes(blockMaxSize)
 		if err != nil {
-			return err
+			return 0, err
 		}
 
 		zw := lz4.NewWriter(nil)
@@ -43,20 +43,20 @@ func Compress(fs *flag.FlagSet) cmdflag.Handler {
 			zw.Reset(os.Stdout)
 			_, err := io.Copy(zw, os.Stdin)
 			if err != nil {
-				return err
+				return 0, err
 			}
-			return zw.Close()
+			return 0, zw.Close()
 		}
 
-		for _, filename := range args {
+		for fidx, filename := range args {
 			// Input file.
 			file, err := os.Open(filename)
 			if err != nil {
-				return err
+				return fidx, err
 			}
 			finfo, err := file.Stat()
 			if err != nil {
-				return err
+				return fidx, err
 			}
 			mode := finfo.Mode() // use the same mode for the output file
 
@@ -85,19 +85,19 @@ func Compress(fs *flag.FlagSet) cmdflag.Handler {
 			zfilename := fmt.Sprintf("%s%s", filename, lz4.Extension)
 			zfile, err := os.OpenFile(zfilename, os.O_CREATE|os.O_WRONLY, mode)
 			if err != nil {
-				return err
+				return fidx, err
 			}
 			zw.Reset(zfile)
 
 			// Compress.
 			_, err = io.Copy(zw, file)
 			if err != nil {
-				return err
+				return fidx, err
 			}
 			for _, c := range []io.Closer{zw, zfile} {
 				err := c.Close()
 				if err != nil {
-					return err
+					return fidx, err
 				}
 			}
 
@@ -106,6 +106,6 @@ func Compress(fs *flag.FlagSet) cmdflag.Handler {
 			}
 		}
 
-		return nil
+		return len(args), nil
 	}
 }

+ 11 - 11
internal/cmds/uncompress.go

@@ -9,31 +9,31 @@ import (
 
 	"github.com/schollz/progressbar/v2"
 
+	"github.com/pierrec/cmdflag"
 	"github.com/pierrec/lz4"
-	"github.com/pierrec/lz4/internal/cmdflag"
 )
 
 // Uncompress uncompresses a set of files or from stdin to stdout.
 func Uncompress(_ *flag.FlagSet) cmdflag.Handler {
-	return func(args ...string) error {
+	return func(args ...string) (int, error) {
 		zr := lz4.NewReader(nil)
 
 		// Use stdin/stdout if no file provided.
 		if len(args) == 0 {
 			zr.Reset(os.Stdin)
 			_, err := io.Copy(os.Stdout, zr)
-			return err
+			return 0, err
 		}
 
-		for _, zfilename := range args {
+		for fidx, zfilename := range args {
 			// Input file.
 			zfile, err := os.Open(zfilename)
 			if err != nil {
-				return err
+				return fidx, err
 			}
 			zinfo, err := zfile.Stat()
 			if err != nil {
-				return err
+				return fidx, err
 			}
 			mode := zinfo.Mode() // use the same mode for the output file
 
@@ -41,13 +41,13 @@ func Uncompress(_ *flag.FlagSet) cmdflag.Handler {
 			filename := strings.TrimSuffix(zfilename, lz4.Extension)
 			file, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY, mode)
 			if err != nil {
-				return err
+				return fidx, err
 			}
 			zr.Reset(zfile)
 
 			zfinfo, err := zfile.Stat()
 			if err != nil {
-				return err
+				return fidx, err
 			}
 			var (
 				size  int
@@ -72,12 +72,12 @@ func Uncompress(_ *flag.FlagSet) cmdflag.Handler {
 			// Uncompress.
 			_, err = io.Copy(out, zr)
 			if err != nil {
-				return err
+				return fidx, err
 			}
 			for _, c := range []io.Closer{zfile, file} {
 				err := c.Close()
 				if err != nil {
-					return err
+					return fidx, err
 				}
 			}
 
@@ -87,6 +87,6 @@ func Uncompress(_ *flag.FlagSet) cmdflag.Handler {
 			}
 		}
 
-		return nil
+		return len(args), nil
 	}
 }