commit 6091893d302c865877e9d9e0b0e47539d34ea5a7 Author: Stanislav Nikitin Date: Sun Aug 20 14:59:51 2017 +0500 Initial commit. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..16c1a1f --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*DS_Store* diff --git a/README.md b/README.md new file mode 100644 index 0000000..39fcabd --- /dev/null +++ b/README.md @@ -0,0 +1,13 @@ +# Flagger + +Flagger is an arbitrary CLI flags parser, like argparse in Python. + +# Installation + +``` +go get -u -v lab.pztrn.name/golibs/flagger +``` + +# Usage + +//TBW// diff --git a/exported.go b/exported.go new file mode 100644 index 0000000..273a198 --- /dev/null +++ b/exported.go @@ -0,0 +1,29 @@ +// Flagger - arbitrary CLI flags parser. +// +// Copyright (c) 2017, Stanislav N. aka pztrn. +// All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package flagger + +var ( + logger LoggerInterface +) + +func New(l LoggerInterface) *Flagger { + logger = l + f := Flagger{} + return &f +} diff --git a/flag.go b/flag.go new file mode 100644 index 0000000..f233260 --- /dev/null +++ b/flag.go @@ -0,0 +1,31 @@ +// Flagger - arbitrary CLI flags parser. +// +// Copyright (c) 2017, Stanislav N. aka pztrn. +// All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package flagger + +// This structure represents addable flag for Flagger. +type Flag struct { + // Flag name. It will be accessible using this name later. + Name string + // Description for help output. + Description string + // Type can be one of "bool", "int", "string". + Type string + // This value will be reflected. + DefaultValue interface{} +} diff --git a/flagger.go b/flagger.go new file mode 100644 index 0000000..a7da953 --- /dev/null +++ b/flagger.go @@ -0,0 +1,121 @@ +// Flagger - arbitrary CLI flags parser. +// +// Copyright (c) 2017, Stanislav N. aka pztrn. +// All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package flagger + +import ( + // stdlib + "errors" + "flag" + "sync" +) + +// Flagger implements (kinda) extended CLI parameters parser. As it +// available from CommonContext, these flags will be available to +// whole application. +// +// It uses reflection to determine what kind of variable we should +// parse or get. +type Flagger struct { + // Flags that was added by user. + flags map[string]*Flag + flagsMutex sync.Mutex + + // Flags that will be passed to flag module. + flagsBool map[string]*bool + flagsInt map[string]*int + flagsString map[string]*string +} + +// Adds flag to list of flags we will pass to ``flag`` package. +func (f *Flagger) AddFlag(flag *Flag) error { + _, present := f.flags[flag.Name] + if present { + logger.Fatalln("Cannot add flag '" + flag.Name + "' - already added!") + return errors.New("Cannot add flag '" + flag.Name + "' - already added!") + } + + f.flags[flag.Name] = flag + return nil +} + +// This function returns boolean value for flag with given name. +// Returns bool value for flag and nil as error on success +// and false bool plus error with text on error. +func (f *Flagger) GetBoolValue(name string) (bool, error) { + fl, present := f.flagsBool[name] + if !present { + return false, errors.New("No such flag: " + name) + } + return (*fl), nil +} + +// This function returns integer value for flag with given name. +// Returns integer on success and 0 on error. +func (f *Flagger) GetIntValue(name string) (int, error) { + fl, present := f.flagsInt[name] + if !present { + return 0, errors.New("No such flag: " + name) + } + return (*fl), nil +} + +// This function returns string value for flag with given name. +// Returns string on success or empty string on error. +func (f *Flagger) GetStringValue(name string) (string, error) { + fl, present := f.flagsString[name] + if !present { + return "", errors.New("No such flag: " + name) + } + return (*fl), nil +} + +// Flagger initialization. +func (f *Flagger) Initialize() { + logger.Println("Initializing CLI parameters parser...") + + f.flags = make(map[string]*Flag) + + f.flagsBool = make(map[string]*bool) + f.flagsInt = make(map[string]*int) + f.flagsString = make(map[string]*string) +} + +// This function adds flags from flags map to flag package and parse +// them. They can be obtained later by calling GetTYPEValue(name), +// where TYPE is one of Bool, Int, String. +func (f *Flagger) Parse() { + for name, fl := range f.flags { + if fl.Type == "bool" { + fdef := fl.DefaultValue.(bool) + f.flagsBool[name] = &fdef + flag.BoolVar(&fdef, name, fdef, fl.Description) + } else if fl.Type == "int" { + fdef := fl.DefaultValue.(int) + f.flagsInt[name] = &fdef + flag.IntVar(&fdef, name, fdef, fl.Description) + } else if fl.Type == "string" { + fdef := fl.DefaultValue.(string) + f.flagsString[name] = &fdef + flag.StringVar(&fdef, name, fdef, fl.Description) + } + } + + logger.Println("Parsing CLI parameters...") + flag.Parse() +} diff --git a/flagger_test.go b/flagger_test.go new file mode 100644 index 0000000..12c5b07 --- /dev/null +++ b/flagger_test.go @@ -0,0 +1,125 @@ +// Flagger - arbitrary CLI flags parser. +// +// Copyright (c) 2017, Stanislav N. aka pztrn. +// All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package flagger + +import ( + // stdlib + "log" + "os" + "testing" +) + +var ( + f *Flagger +) + +func TestFlaggerInitialization(t *testing.T) { + f = New(LoggerInterface(log.New(os.Stdout, "testing logger: ", log.Lshortfile))) + if f == nil { + t.Fatal("Logger initialization failed!") + t.FailNow() + } + f.Initialize() +} + +func TestFlaggerAddBoolFlag(t *testing.T) { + flag_testbool := Flag{ + Name: "testboolflag", + Description: "Testing boolean flag", + Type: "bool", + DefaultValue: true, + } + err := f.AddFlag(&flag_testbool) + if err != nil { + t.Fatal("Failed to add boolean flag!") + t.FailNow() + } +} + +func TestFlaggerAddIntFlag(t *testing.T) { + flag_testint := Flag{ + Name: "testintflag", + Description: "Testing integer flag", + Type: "int", + DefaultValue: 1, + } + err := f.AddFlag(&flag_testint) + if err != nil { + t.Fatal("Failed to add integer flag!") + t.FailNow() + } +} + +func TestFlaggerAddStringFlag(t *testing.T) { + flag_teststring := Flag{ + Name: "teststringflag", + Description: "Testing string flag", + Type: "string", + DefaultValue: "superstring", + } + err := f.AddFlag(&flag_teststring) + if err != nil { + t.Fatal("Failed to add string flag!") + t.FailNow() + } +} + +// This test doing nothing more but launching flags parsing. +func TestFlaggerParse(t *testing.T) { + f.Parse() +} + +func TestFlaggerGetBoolFlag(t *testing.T) { + val, err := f.GetBoolValue("testboolflag") + if err != nil { + t.Fatal("Failed to get boolean flag: " + err.Error()) + t.FailNow() + } + + if !val { + t.Fatal("Failed to get boolean flag - should be true, but false received") + t.FailNow() + } +} + +func TestFlaggerGetIntFlag(t *testing.T) { + val, err := f.GetIntValue("testintflag") + if err != nil { + t.Fatal("Failed to get integer flag: " + err.Error()) + t.FailNow() + } + + if val == 0 { + t.Fatal("Failed to get integer flag - should be 1, but 0 received") + t.FailNow() + } +} + +func TestFlaggerGetStringFlag(t *testing.T) { + val, err := f.GetStringValue("teststringflag") + if err != nil { + t.Fatal("Failed to get string flag: " + err.Error()) + t.FailNow() + } + + if val == "" { + t.Fatal("Failed to get string flag - should be 'superstring', but nothing received") + t.FailNow() + } +} diff --git a/loggerinterface.go b/loggerinterface.go new file mode 100644 index 0000000..28aa9ab --- /dev/null +++ b/loggerinterface.go @@ -0,0 +1,26 @@ +// Flagger - arbitrary CLI flags parser. +// +// Copyright (c) 2017, Stanislav N. aka pztrn. +// All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package flagger + +// LoggerInterface provide logging interface, so everyone can inject own +// logging handlers. +type LoggerInterface interface { + Fatalln(args ...interface{}) + Println(v ...interface{}) +}