refactor: move completely cli outside golang (#7)

Co-authored-by: Tran Hau <ngtranhau@gmail.com>
main
sudo pacman -Syu 2021-04-22 17:07:19 +07:00 committed by GitHub
parent 4fa12066d0
commit 992bba6640
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 222 additions and 197 deletions

200
main.go
View File

@ -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()
}

93
pkg/cli/action.go Normal file
View File

@ -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...)
}
}

126
pkg/cli/app.go Normal file
View File

@ -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())
}
}