diff --git a/cli/cli.go b/cli/cli.go index 65f03ae..77ae8a2 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -36,6 +36,7 @@ type CLI struct { replaceExpr string isOverwrite bool filters rawStrings + help bool } func NewCLI(outStream, errStream io.Writer, inputStream io.Reader) *CLI { @@ -49,6 +50,11 @@ func (c *CLI) Run(args []string) int { return ExitCodeParseFlagError } + if c.help { + flags.Usage() + return ExitCodeOK + } + err = c.validateInput(flags) if err != nil { fmt.Fprintf(c.errStream, "Failed to validate input: %s\n", err) @@ -130,6 +136,12 @@ func (c *CLI) parseFlags(args []string) (*flag.FlagSet, error) { flags.BoolVar(&c.isOverwrite, "overwrite", false, "overwrite the file in place") flags.StringVar(&c.replaceExpr, "replace", "", `Replacement expression, e.g., "@search@replace@"`) flags.Var(&c.filters, "filter", `Filter expression`) + flags.BoolVar(&c.help, "help", false, `Show help`) + + flags.Usage = func() { + fmt.Fprintln(c.errStream, "Usage: purl [options] [file]") + flags.PrintDefaults() + } err := flags.Parse(args[1:]) if err != nil { diff --git a/cli/cli_test.go b/cli/cli_test.go index 63ff4c3..4857367 100644 --- a/cli/cli_test.go +++ b/cli/cli_test.go @@ -60,6 +60,32 @@ func TestRun_success(t *testing.T) { } } +func TestRun_help(t *testing.T) { + testCases := []struct { + desc string + args []string + expectedCode int + }{ + { + desc: "help option", + args: []string{"purl", "-help"}, + expectedCode: 0, + }, + } + + for _, tc := range testCases { + t.Run(tc.desc, func(t *testing.T) { + t.Parallel() + outStream, errStream := new(bytes.Buffer), new(bytes.Buffer) + cl := cli.NewCLI(outStream, errStream, os.Stdin) + + if got := cl.Run(tc.args); got != tc.expectedCode { + t.Fatalf("Expected exit code %d, but got %d; error: %q", tc.expectedCode, got, errStream.String()) + } + }) + } +} + func TestRun_failToProvideStdin(t *testing.T) { testCases := []struct { desc string