Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add writeas config command #25

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion cmd/writeas/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,13 +289,37 @@ func main() {
},
},
},
{
Name: "config",
Usage: "Get and set options",
UsageText: "config name [value]\n writeas config [command options]",
Action: cmdOptions,
Flags: []cli.Flag{
cli.BoolFlag{
Name: "edit, e",
Usage: "Opens an editor to modify the config file",
},
cli.BoolFlag{
Name: "list, l",
Usage: "List all variables set in config file, along with their values",
},
cli.BoolFlag{
Name: "list-all, a",
Usage: "List all config variables, along with their values",
},
cli.BoolFlag{
Name: "verbose, v",
Usage: "Make the operation more talkative",
},
},
},
}

cli.CommandHelpTemplate = `NAME:
{{.Name}} - {{.Usage}}

USAGE:
writeas {{.Name}}{{if .Flags}} [command options]{{end}} [arguments...]{{if .Description}}
writeas {{if .UsageText}}{{.UsageText}}{{else}}{{.Name}}{{if .Flags}} [command options]{{end}} [arguments...]{{end}}{{if .Description}}

DESCRIPTION:
{{.Description}}{{end}}{{if .Flags}}
Expand Down
77 changes: 77 additions & 0 deletions cmd/writeas/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
"strconv"
)

func cmdPost(c *cli.Context) error {
Expand Down Expand Up @@ -240,3 +241,79 @@ func cmdAuth(c *cli.Context) error {
func cmdLogOut(c *cli.Context) error {
return DoLogOut(c)
}

func cmdOptions(c *cli.Context) error {

// Edit config file
if c.Bool("e") {
composeConfig()

// List configs
} else if c.Bool("l") || c.Bool("a") {
uc, err := loadConfig()
if err != nil {
ErrorlnQuit(fmt.Sprintf("Error loading config: %v", err), 1)
}
printConfig(uc, "", c.Bool("a"))

// Check arguments
} else {
nargs := len(c.Args())

// No arguments nor options: display command usage
if nargs == 0 {
cli.ShowSubcommandHelp(c)
return nil
}
name := c.Args().Get(0)
value := c.Args().Get(1)

// Load config file
uc, err := loadConfig()
if err != nil {
ErrorlnQuit(fmt.Sprintf("Error loading config: %v", err), 1)
}

// Get reflection of field
rval, err := getConfigField(uc, name)
if err != nil {
ErrorlnQuit(fmt.Sprintf("%v", err), 1)
}

// Print value
if nargs == 1 {
fmt.Printf("%s=%v\n", name, *rval)

// Set value
} else {

// Cast and set value
switch typ := rval.Kind().String(); typ {
case "bool":
b, err := strconv.ParseBool(value)
if err != nil {
ErrorlnQuit(fmt.Sprintf("error: \"%s\" is not a valid boolean", value), 1)
}
rval.SetBool(b)

case "int":
i, err := strconv.ParseInt(value, 0, 0)
if err != nil {
ErrorlnQuit(fmt.Sprintf("error: \"%s\" is not a valid integer", value), 1)
}
rval.SetInt(i)

case "string":
rval.SetString(value)
}

// Save config to file
err = saveConfig(uc)
if err != nil {
ErrorlnQuit(fmt.Sprintf("Unable to save config: %s", err), 1)
}
fmt.Println("Saved config.")
}
}
return nil
}
98 changes: 98 additions & 0 deletions cmd/writeas/userconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ import (
"gopkg.in/ini.v1"
"io/ioutil"
"path/filepath"
"reflect"
"fmt"
"os"
"strings"
)

const (
Expand Down Expand Up @@ -88,3 +92,97 @@ func saveUser(u *writeas.AuthUser) error {
}
return nil
}

// Prints all values of the given struct
// For subfields: the field name is separated with dots (ex: Posts.Directory=)
func printConfig(x interface{}, prefix string, showEmptyValues bool) {
values := reflect.ValueOf(x)

if values.Kind() == reflect.Ptr {
values = values.Elem()
}
typ := values.Type()

for i := 0; i < typ.NumField(); i++ {
val := values.Field(i)
name := typ.Field(i).Name

if prefix != "" {
name = prefix + "." + name
}
if(val.Kind() == reflect.Struct) {
printConfig(val.Interface(), name, showEmptyValues)
} else {
if showEmptyValues || val.Interface() != reflect.Zero(val.Type()).Interface() {
fmt.Printf("%s=%v\n", name, val)
}
}
}
}

// Get the value of a given field
// For subfields: the name should be separated with dots (ex: Posts.Directory)
func getConfigField(x interface{}, name string) (*reflect.Value, error) {
path := strings.Split(name, ".")
values := reflect.ValueOf(x)

if values.Kind() == reflect.Ptr {
values = values.Elem()
}
for _, part := range path {
values = values.FieldByName(part)

if !values.IsValid() {
err := fmt.Errorf("error: key does not contain a section: %v", name)
return nil, err
}
}
if values.Kind() == reflect.Struct {
err := fmt.Errorf("error: key does not contain a section: %v", name)
return nil, err
}
return &values, nil
}

// Opens an editor to modify the config file
func composeConfig() error {
filename := filepath.Join(userDataDir(), userConfigFile)

// Open the editor
cmd := editPostCmd(filename)
if cmd == nil {
fmt.Println(noEditorErr)
return nil
}
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
if err := cmd.Start(); err != nil {
if debug {
panic(err)
} else {
Errorln("Error starting editor: %s", err)
return nil
}
}

// Wait until the editor is closed
if err := cmd.Wait(); err != nil {
if debug {
panic(err)
} else {
Errorln("Editor finished with error: %s", err)
return nil
}
}

// Check if the config file is valid
_, err := loadConfig()
if err != nil {
if debug {
panic(err)
} else {
Errorln("Error loading config: %s", err)
return nil
}
}
return nil
}