From 992bba6640977428c06a9a59dc6a6829a520a1e6 Mon Sep 17 00:00:00 2001 From: Nguyen Tran Hau Date: Thu, 22 Apr 2021 17:07:19 +0700 Subject: [PATCH] refactor: move completely cli outside golang (#7) Co-authored-by: Tran Hau --- main.go | 200 +--------------------------------------------- pkg/cli/action.go | 93 +++++++++++++++++++++ pkg/cli/app.go | 126 +++++++++++++++++++++++++++++ 3 files changed, 222 insertions(+), 197 deletions(-) create mode 100644 pkg/cli/action.go create mode 100644 pkg/cli/app.go diff --git a/main.go b/main.go index 0139d5c..47def18 100644 --- a/main.go +++ b/main.go @@ -1,202 +1,8 @@ package main -import ( - "fmt" - "log" - "os" - "runtime" - - "github.com/haunt98/color" - "github.com/haunt98/dotfiles/pkg/config" - "github.com/urfave/cli/v2" -) - -const ( - appName = "dotfiles" - appUsage = "managing dotfiles" - - // flags - verboseFlag = "verbose" - dryRunFlag = "dry-run" - - // commands - installCommand = "install" - updateCommand = "update" - cleanCommand = "clean" - - // usages - verboseUsage = "show what is going on" - dryRunUsage = "demo mode without actually changing anything" - installUsage = "install user configs from dotfiles" - updateUsage = "update dotfiles from user configs" - cleanUsage = "clean unused dotfiles" - - currentDir = "." -) - -var ( - // aliases - installAliases = []string{"i"} - updateAliases = []string{"u"} - cleanAliases = []string{"c"} - - // denyOSes contains OS which is not supported - // go tool dist list - denyOSes = map[string]struct{}{ - "windows": struct{}{}, - } -) +import "github.com/haunt98/dotfiles/pkg/cli" func main() { - // Prevent running at runtime - if _, ok := denyOSes[runtime.GOOS]; ok { - color.PrintAppError(appName, fmt.Sprintf("OS %s is not supported right now", runtime.GOOS)) - return - } - - a := &action{} - - app := &cli.App{ - Name: appName, - Usage: appUsage, - Commands: []*cli.Command{ - { - Name: installCommand, - Aliases: installAliases, - Usage: installUsage, - Flags: []cli.Flag{ - &cli.BoolFlag{ - Name: verboseFlag, - Usage: verboseUsage, - }, - &cli.BoolFlag{ - Name: dryRunFlag, - Usage: dryRunUsage, - }, - }, - Action: a.RunInstall, - }, - { - Name: updateCommand, - Aliases: updateAliases, - Usage: updateUsage, - Flags: []cli.Flag{ - &cli.BoolFlag{ - Name: verboseFlag, - Usage: verboseUsage, - }, - &cli.BoolFlag{ - Name: dryRunFlag, - Usage: dryRunUsage, - }, - }, - Action: a.RunUpdate, - }, - { - Name: cleanCommand, - Aliases: cleanAliases, - Usage: cleanUsage, - Flags: []cli.Flag{ - &cli.BoolFlag{ - Name: verboseFlag, - Usage: verboseUsage, - }, - &cli.BoolFlag{ - Name: dryRunFlag, - Usage: dryRunUsage, - }, - }, - Action: a.RunClean, - }, - }, - Action: a.RunHelp, - } - - if err := app.Run(os.Args); err != nil { - color.PrintAppError(appName, err.Error()) - } -} - -type action struct { - flags struct { - verbose bool - dryRun bool - } -} - -// Show help by default -func (a *action) RunHelp(c *cli.Context) error { - return cli.ShowAppHelp(c) -} - -func (a *action) RunInstall(c *cli.Context) error { - a.getFlags(c) - a.log("start %s\n", installCommand) - - cfg, err := a.loadConfig() - if err != nil { - return err - } - - if err := cfg.Install(); err != nil { - return fmt.Errorf("failed to install config: %w", err) - } - - return nil -} - -func (a *action) RunUpdate(c *cli.Context) error { - a.getFlags(c) - a.log("start %s\n", updateCommand) - - cfg, err := a.loadConfig() - if err != nil { - return err - } - - if err := cfg.Update(); err != nil { - return fmt.Errorf("failed to update config: %w", err) - } - - return nil -} - -func (a *action) RunClean(c *cli.Context) error { - a.getFlags(c) - a.log("start %s\n", cleanCommand) - - cfg, err := a.loadConfig() - if err != nil { - return err - } - - if err := cfg.Clean(); err != nil { - return fmt.Errorf("failed to clean config: %w", err) - } - - return nil -} - -func (a *action) loadConfig() (config.Config, error) { - cfgReal, cfgDemo, err := config.LoadConfig(currentDir) - if err != nil { - return nil, fmt.Errorf("failed to load config: %w", err) - } - - if a.flags.dryRun { - return cfgDemo, nil - } - - return cfgReal, nil -} - -func (a *action) getFlags(c *cli.Context) { - a.flags.verbose = c.Bool(verboseFlag) - a.flags.dryRun = c.Bool(dryRunFlag) -} - -func (a *action) log(format string, v ...interface{}) { - if a.flags.verbose { - log.Printf(format, v...) - } + app := cli.NewApp() + app.Run() } diff --git a/pkg/cli/action.go b/pkg/cli/action.go new file mode 100644 index 0000000..cc58926 --- /dev/null +++ b/pkg/cli/action.go @@ -0,0 +1,93 @@ +package cli + +import ( + "fmt" + "log" + + "github.com/haunt98/dotfiles/pkg/config" + "github.com/urfave/cli/v2" +) + +type action struct { + flags struct { + verbose bool + dryRun bool + } +} + +// Show help by default +func (a *action) RunHelp(c *cli.Context) error { + return cli.ShowAppHelp(c) +} + +func (a *action) RunInstall(c *cli.Context) error { + a.getFlags(c) + a.log("start %s\n", installCommand) + + cfg, err := a.loadConfig() + if err != nil { + return err + } + + if err := cfg.Install(); err != nil { + return fmt.Errorf("failed to install config: %w", err) + } + + return nil +} + +func (a *action) RunUpdate(c *cli.Context) error { + a.getFlags(c) + a.log("start %s\n", updateCommand) + + cfg, err := a.loadConfig() + if err != nil { + return err + } + + if err := cfg.Update(); err != nil { + return fmt.Errorf("failed to update config: %w", err) + } + + return nil +} + +func (a *action) RunClean(c *cli.Context) error { + a.getFlags(c) + a.log("start %s\n", cleanCommand) + + cfg, err := a.loadConfig() + if err != nil { + return err + } + + if err := cfg.Clean(); err != nil { + return fmt.Errorf("failed to clean config: %w", err) + } + + return nil +} + +func (a *action) loadConfig() (config.Config, error) { + cfgReal, cfgDemo, err := config.LoadConfig(currentDir) + if err != nil { + return nil, fmt.Errorf("failed to load config: %w", err) + } + + if a.flags.dryRun { + return cfgDemo, nil + } + + return cfgReal, nil +} + +func (a *action) getFlags(c *cli.Context) { + a.flags.verbose = c.Bool(verboseFlag) + a.flags.dryRun = c.Bool(dryRunFlag) +} + +func (a *action) log(format string, v ...interface{}) { + if a.flags.verbose { + log.Printf(format, v...) + } +} diff --git a/pkg/cli/app.go b/pkg/cli/app.go new file mode 100644 index 0000000..0fe5c1b --- /dev/null +++ b/pkg/cli/app.go @@ -0,0 +1,126 @@ +package cli + +import ( + "fmt" + "os" + "runtime" + + "github.com/haunt98/color" + "github.com/urfave/cli/v2" +) + +const ( + appName = "dotfiles" + appUsage = "managing dotfiles" + + // flags + verboseFlag = "verbose" + dryRunFlag = "dry-run" + + // commands + installCommand = "install" + updateCommand = "update" + cleanCommand = "clean" + + // usages + verboseUsage = "show what is going on" + dryRunUsage = "demo mode without actually changing anything" + installUsage = "install user configs from dotfiles" + updateUsage = "update dotfiles from user configs" + cleanUsage = "clean unused dotfiles" + + currentDir = "." +) + +var ( + // aliases + installAliases = []string{"i"} + updateAliases = []string{"u"} + cleanAliases = []string{"c"} +) + +// denyOSes contains OS which is not supported +// go tool dist list +var denyOSes = map[string]struct{}{ + "windows": struct{}{}, +} + +type App struct { + cliApp *cli.App +} + +func NewApp() *App { + a := &action{} + + cliApp := &cli.App{ + Name: appName, + Usage: appUsage, + Commands: []*cli.Command{ + { + Name: installCommand, + Aliases: installAliases, + Usage: installUsage, + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: verboseFlag, + Usage: verboseUsage, + }, + &cli.BoolFlag{ + Name: dryRunFlag, + Usage: dryRunUsage, + }, + }, + Action: a.RunInstall, + }, + { + Name: updateCommand, + Aliases: updateAliases, + Usage: updateUsage, + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: verboseFlag, + Usage: verboseUsage, + }, + &cli.BoolFlag{ + Name: dryRunFlag, + Usage: dryRunUsage, + }, + }, + Action: a.RunUpdate, + }, + { + Name: cleanCommand, + Aliases: cleanAliases, + Usage: cleanUsage, + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: verboseFlag, + Usage: verboseUsage, + }, + &cli.BoolFlag{ + Name: dryRunFlag, + Usage: dryRunUsage, + }, + }, + Action: a.RunClean, + }, + }, + Action: a.RunHelp, + } + + return &App{ + cliApp: cliApp, + } +} + +func (a *App) Run() { + // Prevent running at runtime + if _, ok := denyOSes[runtime.GOOS]; ok { + color.PrintAppError(appName, fmt.Sprintf("OS %s is not supported right now", runtime.GOOS)) + return + } + + if err := a.cliApp.Run(os.Args); err != nil { + color.PrintAppError(appName, err.Error()) + } +}