diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index bd6f7d7..263fc8a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,7 +4,7 @@ jobs: test: strategy: matrix: - platform: [ubuntu-latest, macos-latest, windows-latest] + platform: [ubuntu-latest] runs-on: ${{ matrix.platform }} steps: - name: Install Go @@ -14,17 +14,8 @@ jobs: go-version: '^1.15' # The Go version to download (if necessary) and use. - name: Checkout code uses: actions/checkout@v2 - - name: Use Cache(on Windows) - if: runner.os == 'Windows' - uses: actions/cache@preview - with: - path: ~/go/pkg/mod - key: ${{ runner.os }}-go-${{ hashFiles('**\go.sum') }} - restore-keys: | - ${{ runner.os }}-go- - name: Use Cache - if: runner.os != 'Windows' - uses: actions/cache@preview + uses: actions/cache@v2 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} diff --git a/cmd/leetgode/main.go b/cmd/leetgode/main.go index 3d5a53c..1b320ee 100644 --- a/cmd/leetgode/main.go +++ b/cmd/leetgode/main.go @@ -4,6 +4,7 @@ import ( "context" "flag" "fmt" + "io" "io/ioutil" "log" "os" @@ -12,32 +13,51 @@ import ( ) func main() { - flag.Usage = func() { - if err := leetgode.ShowUsage(os.Stdout); err != nil { - panic(err) + if err := run(os.Stdout, os.Stderr, os.Args); err != nil { + fmt.Fprintf(os.Stderr, "%v\n", err) + os.Exit(1) + } +} + +func run(stdout, stderr io.Writer, args []string) error { + if len(args) < 2 { + cmd := &leetgode.HelpCmd{} + if err := cmd.Run(context.Background(), stdout, []string{}); err != nil { + return fmt.Errorf("help command is failed: %w", err) } + return nil } - flag.Parse() - sub := flag.Arg(0) - if len(sub) == 0 { - fmt.Printf("TODO: show help\n") - return + sub := args[1] + // implement into each sub command if use different options by each sub command + f := flag.NewFlagSet(sub, flag.ContinueOnError) + f.Usage = func() { + if err := leetgode.ShowUsage(stdout); err != nil { + fmt.Fprintf(stderr, "failed show useage: %v\n", err) + } + } + var v bool + f.BoolVar(&v, "v", false, "show debug print") + if err := f.Parse(args[2:]); err == flag.ErrHelp { + return err + } else if err != nil { + return fmt.Errorf("%q command with invalid args(%q): %w", sub, args[2:], err) + } + + log.SetOutput(stderr) + if !v { + log.SetOutput(ioutil.Discard) } - // TODO: set os.Stderr if set debug mode - log.SetOutput(ioutil.Discard) if cmd, ok := leetgode.CmdMap[leetgode.CmdName(sub)]; ok { - args := flag.Args()[1:] + args := f.Args() if len(args) != cmd.MaxArg() { - fmt.Printf("%s expects %d options, but %d options\n", cmd.Name(), cmd.MaxArg(), len(args)) - os.Exit(1) + return fmt.Errorf("%q command expects %d options, but %d options\n", cmd.Name(), cmd.MaxArg(), len(args)) } - if err := cmd.Run(context.Background(), args); err != nil { - log.Printf("main: err %v", err) - os.Exit(1) + if err := cmd.Run(context.Background(), stdout, args); err != nil { + return fmt.Errorf("%q command failed: %w", sub, err) } } else { - log.Printf("unknown command %q", sub) - os.Exit(1) + return fmt.Errorf("unknown command %q", sub) } + return nil } diff --git a/core.go b/core.go index eae60d8..ee69b32 100644 --- a/core.go +++ b/core.go @@ -3,6 +3,7 @@ package leetgode import ( "context" "fmt" + "io" ) type CmdName string @@ -20,7 +21,7 @@ type Cmd interface { Name() string Usage() string MaxArg() int - Run(context.Context, []string) error + Run(context.Context, io.Writer, []string) error } var CmdMap = map[CmdName]Cmd{ diff --git a/exec.go b/exec.go index 2cd2578..0c10a7e 100644 --- a/exec.go +++ b/exec.go @@ -3,6 +3,7 @@ package leetgode import ( "context" "fmt" + "io" "io/ioutil" "os" "strconv" @@ -26,7 +27,7 @@ func (c *ExecCmd) Usage() string { } // TODO: refactoring exec and test. -func (c *ExecCmd) Run(ctx context.Context, args []string) error { +func (c *ExecCmd) Run(ctx context.Context, out io.Writer, args []string) error { id, err := strconv.Atoi(args[0]) if err != nil { return err @@ -51,7 +52,7 @@ func (c *ExecCmd) Run(ctx context.Context, args []string) error { if err != nil { return err } - fmt.Print("now sending") + fmt.Fprint(out, "now sending") for { res, err := cli.Check(ctx, q, tr) if err != nil { @@ -59,14 +60,14 @@ func (c *ExecCmd) Run(ctx context.Context, args []string) error { } // FIXME: pretty print if res.State == "SUCCESS" { - fmt.Printf(` + fmt.Fprintf(out, ` executed id: %s problem title: %s result: %s `, q.QuestionID, q.Slug, res.StatusMsg) break } else { - fmt.Print(".") + fmt.Fprint(out, ".") } time.Sleep(1 * time.Second) } diff --git a/generate.go b/generate.go index 127b6c5..43cdf4d 100644 --- a/generate.go +++ b/generate.go @@ -4,7 +4,9 @@ import ( "bytes" "context" "fmt" + "io" "io/ioutil" + "log" "strconv" "text/template" @@ -50,7 +52,7 @@ func (g *GenerateCmd) Usage() string { return "Generate the skeleton code with the test file by id" } -func (g *GenerateCmd) Run(ctx context.Context, args []string) error { +func (g *GenerateCmd) Run(ctx context.Context, out io.Writer, args []string) error { id, err := strconv.Atoi(args[0]) if err != nil { return err @@ -73,7 +75,7 @@ func (g *GenerateCmd) Run(ctx context.Context, args []string) error { if c == nil { return fmt.Errorf("not found the code for Go") } - fmt.Printf("%s\n", fmt.Sprint(c.DefaultCode)) + log.Printf("%s\n", fmt.Sprint(c.DefaultCode)) input := &Format{ Referer: q.Referer, Content: q.Content, @@ -89,11 +91,11 @@ func (g *GenerateCmd) Run(ctx context.Context, args []string) error { if err != nil { panic(err) } - fmt.Printf("%s", buf.String()) + log.Printf("%s", buf.String()) // TODO: どうやってファイル保存とテストしやすさを分けようか? path := buildPath(q.QuestionID, q.Slug) - fmt.Printf("save at %q\n", path) + fmt.Fprintf(out, "save at %q\n", path) if err := ioutil.WriteFile(path, buf.Bytes(), 0644); err != nil { return err } diff --git a/generate_test.go b/generate_test.go index e520040..1d4cb25 100644 --- a/generate_test.go +++ b/generate_test.go @@ -2,6 +2,7 @@ package leetgode import ( "context" + "io/ioutil" "testing" ) @@ -17,7 +18,7 @@ func TestGenerateCmd(t *testing.T) { tt := tt t.Run(tt.name, func(t *testing.T) { cmd := &GenerateCmd{} - if err := cmd.Run(context.TODO(), tt.args); err != nil { + if err := cmd.Run(context.TODO(), ioutil.Discard, tt.args); err != nil { t.Errorf("GenerateCmd() error = %v", err) } }) diff --git a/help.go b/help.go index 9d65052..08c900e 100644 --- a/help.go +++ b/help.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "io" - "os" "sort" "text/tabwriter" ) @@ -49,6 +48,6 @@ func ShowUsage(w io.Writer) error { return tw.Flush() } -func (c *HelpCmd) Run(ctx context.Context, args []string) error { - return ShowUsage(os.Stdout) +func (c *HelpCmd) Run(ctx context.Context, out io.Writer, args []string) error { + return ShowUsage(out) } diff --git a/list.go b/list.go index 846a328..f04486b 100644 --- a/list.go +++ b/list.go @@ -3,6 +3,7 @@ package leetgode import ( "context" "fmt" + "io" "os" "sort" "text/tabwriter" @@ -24,7 +25,7 @@ func (c *ListCmd) Usage() string { return "List problems" } -func (c *ListCmd) Run(ctx context.Context, _ []string) error { +func (c *ListCmd) Run(ctx context.Context, out io.Writer, _ []string) error { cli, err := NewLeetCode() if err != nil { return err diff --git a/list_test.go b/list_test.go index 4eba5a6..37fb913 100644 --- a/list_test.go +++ b/list_test.go @@ -2,12 +2,13 @@ package leetgode import ( "context" + "io/ioutil" "testing" ) func TestListCmd(t *testing.T) { cmd := &ListCmd{} - if err := cmd.Run(context.TODO(), []string{}); err != nil { + if err := cmd.Run(context.TODO(), ioutil.Discard, []string{}); err != nil { t.Errorf("ListCmd() error = %v", err) } } diff --git a/pick.go b/pick.go index c99a13e..cfed951 100644 --- a/pick.go +++ b/pick.go @@ -3,6 +3,7 @@ package leetgode import ( "context" "fmt" + "io" "strconv" ) @@ -23,7 +24,7 @@ func (c *PickCmd) MaxArg() int { return 1 } -func (c *PickCmd) Run(ctx context.Context, args []string) error { +func (c *PickCmd) Run(ctx context.Context, out io.Writer, args []string) error { cli, err := NewLeetCode() if err != nil { return err @@ -38,8 +39,8 @@ func (c *PickCmd) Run(ctx context.Context, args []string) error { return err } - // FIXME: pretty print - fmt.Printf("result: %#v\n", q) + // FIXME: pretty print for HTML + fmt.Fprintf(out, "%s: %s\n%s\n%s", q.QuestionID, q.Slug, q.Referer, q.Content) return nil } diff --git a/test.go b/test.go index ea76a14..8bc0b78 100644 --- a/test.go +++ b/test.go @@ -3,6 +3,7 @@ package leetgode import ( "context" "fmt" + "io" "io/ioutil" "os" "strconv" @@ -25,7 +26,7 @@ func (c *TestCmd) Usage() string { return "Test solution" } -func (c *TestCmd) Run(ctx context.Context, args []string) error { +func (c *TestCmd) Run(ctx context.Context, out io.Writer, args []string) error { id, err := strconv.Atoi(args[0]) if err != nil { return err @@ -50,7 +51,7 @@ func (c *TestCmd) Run(ctx context.Context, args []string) error { if err != nil { return err } - fmt.Print("now sending") + fmt.Fprint(out, "now sending") for { res, err := cli.Check(ctx, q, tr) if err != nil { @@ -58,14 +59,14 @@ func (c *TestCmd) Run(ctx context.Context, args []string) error { } // FIXME: pretty print if res.State == "SUCCESS" { - fmt.Printf(` + fmt.Fprintf(out,` test id: %s problem title: %s result: %s `, q.QuestionID, q.Slug, res.StatusMsg) break } else { - fmt.Print(".") + fmt.Fprint(out, ".") } time.Sleep(1 * time.Second) }