GithubHelp home page GithubHelp logo

flaeg's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

flaeg's Issues

`PrintHelp` without reflection

I've stumbled unto the situation where I am using sub commands as a primary mechanism to interact with an application. This means that the rootCmd performs no particular action at all and is left blank. As a first issue, omitting the Run attribute yields a:

panic: runtime error: invalid memory address or nil pointer dereference

However, as primary issue, it would be beneficial to be able to simply print the help output to indicate to the user of the need to use a sub-command. Perhaps, simply, as flaeg.PrintHelp(config) or during the omission of the Run attribute.

In other cases, perhaps more abstractly in the concept of contextualizing arguments and their values, printing the help output would also be useful in the aim of decreasing the likelihood of program misuse.

Currently, the PrintHelp method is exported but requires most of the backbone of the flaeg application to perform reflection and config reading in order to work.

Default pointer value of a pointer field under a pointer field

If only a the flag on the first level pointer field is called, the field under a pointer field must keep nil value.

Example : In the following configuration structure :

//StructPtr : Struct with pointer
type StructPtr struct {
    PtrStruct1    *Struct1      `description:"Enable Struct1"`
    DurationField time.Duration `description:"Duration Field"`
}

//Struct1 : Struct with pointer
type Struct1 struct {
    S1Bool       bool     `description:"Struct 1 Bool"`
    S1PtrStruct3 *Struct3 `description:"Enable Struct3"`
}

//Struct3 : trivial Struct
type Struct3 struct {
    S3Float64 float64 `description:"Struct 3 float64"`
}

S1PtrStruct3 is a pointer field under a pointer field.
If only a the flag --prtstruct1 is called, the field S1PtrStruct3 must keep nil value.
But if the flag prtstruct1.s1ptrstruct3 is called, the field S1PtrStruct3 must get the value of the DefaultPointers structure.

panic!

./traefik -
panic: runtime error: slice bounds out of range

goroutine 1 [running]:
panic(0xdffac0, 0xc820010110)
    /home/martin/.gvm/gos/go1.6/src/runtime/panic.go:464 +0x3e6
github.com/containous/traefik/vendor/github.com/containous/flaeg.argToLower(0x7fffdd35df19, 0x1, 0x0, 0x0)
    /home/martin/go/src/github.com/containous/traefik/vendor/github.com/containous/flaeg/flaeg.go:765 +0x1cb
github.com/containous/traefik/vendor/github.com/containous/flaeg.argsToLower(0xc8200a0070, 0x1, 0x1, 0x0, 0x0, 0x0)
    /home/martin/go/src/github.com/containous/traefik/vendor/github.com/containous/flaeg/flaeg.go:783 +0x109
github.com/containous/traefik/vendor/github.com/containous/flaeg.parseArgs(0xc8200a0070, 0x1, 0x1, 0xc82019f4f8, 0xc8202ebad0, 0x16, 0x0, 0x0)
    /home/martin/go/src/github.com/containous/traefik/vendor/github.com/containous/flaeg/flaeg.go:149 +0x7d2
github.com/containous/traefik/vendor/github.com/containous/flaeg.LoadWithCommand(0xc820246c80, 0xc8200a0070, 0x1, 0x1, 0xc8202eba40, 0xc820277530, 0x2, 0x2, 0x0, 0x0)
    /home/martin/go/src/github.com/containous/traefik/vendor/github.com/containous/flaeg/flaeg.go:538 +0x3c2
github.com/containous/traefik/vendor/github.com/containous/flaeg.(*Flaeg).Parse(0xc8201eacc0, 0xc820246c80, 0x1, 0x0, 0x0)
    /home/martin/go/src/github.com/containous/traefik/vendor/github.com/containous/flaeg/flaeg.go:701 +0xb8
main.main()
    /home/martin/go/src/github.com/containous/traefik/traefik.go:57 +0xd58

parser panic on wrong type conversion

Flaeg panics if types in custom parsers don't match each other
In func (s *SliceStrings) SetValue(val interface{})

panic: interface conversion: interface is Namespaces, not []string

Example :

// Namespaces holds kubernetes namespaces
type Namespaces []string
//...
f.AddParser(reflect.TypeOf(Namespaces{}), &flaeg.SliceStrings{})

Cannot parse root and sub commands together

There seems to be a problem with parsing both root- and sub-commands together.

I've put together this example which illustrates the in-ability to parse sub commands and their flags when a root flag is added. In this example, a GlobalConfiguration would be used to store the verbosity of logging under the -l or --loglevel flag. A subcomand, foo, is added which has is own FooConfiguration containing the flag --bar to be used solely by its processor and not necessarily elsewhere:

package main

import (
	"fmt"
	"os"

	"github.com/containous/flaeg"
)

type GlobalConfiguration struct {
	LogLevel string `short:"l" long:"loglevel" description:"Output verbosity"`
}

type FooConfiguration struct {
	Bar string `description:"Foo"`
}

var globalConfig = &GlobalConfiguration{
	LogLevel: "info",
}
var globalPointersConfig = &GlobalConfiguration{}

var fooConfig = &FooConfiguration{
	Bar: "bar",
}
var fooPointersConfig = &FooConfiguration{}

func main() {
	rootCmd := &flaeg.Command{
		Name:                  "test",
		Description:           `Test flaeg sub-commands`,
		Config:                globalConfig,
		DefaultPointersConfig: globalPointersConfig,
		Run: func() error {
			fmt.Println("I should have access to --loglevel but not --bar!")

			fmt.Println("Loglevel: ", globalConfig.LogLevel)
			fmt.Println("Bar: ", fooConfig.Bar)
			return nil
		},
	}

	fooCmd := &flaeg.Command{
		Name:                  "foo",
		Description:           `Foo sub-command`,
		Config:                fooConfig,
		DefaultPointersConfig: fooPointersConfig,
		Run: func() error {
			fmt.Println("I should have access to --loglevel and --bar!")

			fmt.Println("Loglevel:  ", globalConfig.LogLevel)
			fmt.Println("Bar: ", fooConfig.Bar)
			return nil
		},
	}

	// init flaeg
	flaeg := flaeg.New(rootCmd, os.Args[1:])

	// add sub-command foo
	flaeg.AddCommand(fooCmd)

	// run test
	if err := flaeg.Run(); err != nil {
		fmt.Println("Error %s", err.Error())
	}
}

Under the normal assumption, and as per the declaration of usage, [flags] can be put aftere the command name, in this case test.

$ ./test -h
Test flaeg sub-commands

Usage: test [flags] <command> [<arguments>]

Use "test <command> --help" for help on any command.

Commands:
        foo                                                Foo sub-command

Flag's usage: test [--flag=flag_argument] [-f[flag_argument]] ...     set flag_argument to flag(s)
          or: test [--flag[=true|false| ]] [-f[true|false| ]] ...     set true/false to boolean flag(s)

Flags:
-l, --loglevel Output verbosity                   (default "info")
-h, --help     Print Help (this message) and exit
Error %s pflag: help requested

A subcommand, foo, is available and still makes these assumptions:

$ ./test foo -h
Foo sub-command

Usage: foo [flags] <command> [<arguments>]

Use "foo <command> --help" for help on any command.

Flag's usage: foo [--flag=flag_argument] [-f[flag_argument]] ...     set flag_argument to flag(s)
          or: foo [--flag[=true|false| ]] [-f[true|false| ]] ...     set true/false to boolean flag(s)

Flags:
    --bar  Foo                                (default "bar")
-h, --help Print Help (this message) and exit
Error %s pflag: help requested

However, when adding "global", or root, flags to a sub-command call, we are immediately prompted with the inability to recognise the subcommand foo:

./test --loglevel=debug foo --bar=foo
Error here : unknown flag: --bar
Test flaeg sub-commands

Usage: test [flags] <command> [<arguments>]

Use "test <command> --help" for help on any command.

Commands:
        foo                                                Foo sub-command

Flag's usage: test [--flag=flag_argument] [-f[flag_argument]] ...     set flag_argument to flag(s)
          or: test [--flag[=true|false| ]] [-f[true|false| ]] ...     set true/false to boolean flag(s)

Flags:
-l, --loglevel Output verbosity                   (default "info")
-h, --help     Print Help (this message) and exit
Error %s unknown flag: --bar

Running the following yields the same result:

$ ./test --loglevel=debug --bar=foo foo

Wrong flag generated with anonymous embedded struct

The doc says that you can use anonymous sub-structures, and the example implies that when the flag name is generated, the sub-structure is "squashed" (see --db.ip in the example).

I have a case that demonstrates a bug in the generation of the flag name, when an anonymous sub-structure follows a named sub-structure.

This configuration:

type EmbeddedConfig struct {
	P2 int `description:"p2"`
}

type Config struct{
	P1 int `description:"p1"`
	EmbeddedConfig
}

generates the following flags:

Flags:
    --p1    p1                                 (default "0")
    --p1.p2 p2                                 (default "0")

The second flag should be --p2, not --p1.p2

If you swap the members of Config (P1 after the anonymous EmbeddedConfig), the flags are generated correctly
Attached is a source file that shows this behaviour.

flaeg_test.go.zip

Pull parser.go into a separate package

To implement containous/staert#35 and reuse the parsing code, it will be good to reuse flaeg parser, as suggested for a previous tentative : https://traefik.slackarchive.io/dev/page-17/ts-1497598028679523

This requires quite a lot of renaming and prefixing in the code, so I'd like to make sure I plan this right

  • Suggested package name : parse
  • Keep it under flaeg, not a different repo
  • Move parser.go and parser_test.go into a parse folder. rename files to parse.go/parse_test.go
  • Import github.com/containous/flaeg/parse in flaeg
  • Make all types in parse public
  • Prefix every call to parse types by parse.
  • Same in test files
  • There is a lot of repetition in the flaeg tests, maybe look into refactoring

Sounds good?

panic on unexported pointer field under pointer

Flaeg doesn't manage unexported fields under a pointer on a Sub-Structure
Like this :

type ConfigPointerField struct {
    PtrSubConfig *SubConfigWithUnexportedField `description:"pointer on a SubConfig with one unexported pointer field"`
}
type SubConfigWithUnexportedField struct {
    Exported        string `description:"Exported string field"`
    ptrSubSubConfig *SubSubConfig
}
type SubSubConfig struct {
    unexported string
}

It panics : panic: reflect: reflect.Value.Set using value obtained using unexported field

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.