Code Monkey home page Code Monkey logo

goptions's People

Contributors

akrennmair avatar daemonl avatar itzg avatar surma avatar

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

goptions's Issues

os.File type of option for output

I have the following in option in my file:

    Fileo *os.File `goptions:"-o, --output, description='The dump output', wronly"`

And my main begins with:

func main() {
goptions.ParseAndFail(&options)

Howerver, when I invoke my program with

my_program -o /tmp/out 

It errors out, with the following message:

Error: open /tmp/out: no such file or directory
Usage: ....

I think for wronly option, that is meant solely for output, the package should create the file instead of error out.

I have 'obligatory' set in a few of my options for a nested verb, but it's not failing on ParseAndFail

For example:

options := struct {
        AwsAccessKey string        `goptions:"--aws-access-key, description='AWS Access Key'" json:"aws_access_key"`
        Help         goptions.Help `goptions:"-h, --help, description='Show this help'"`

        Verb goptions.Verbs
        Run  struct {
            Name        string `goptions:"--name, mutexgroup='input', description='name'"`
            Volume      string `goptions:"-v, --volume, obligatory, description='volume'"`
            Remainder   goptions.Remainder
        } `goptions:"run"`

If I run it with no parameters at all, ParseAndFail doesn't fail or print an error or anything.

Index out of range on flag with no values

package main

import "github.com/voxelbrain/goptions"
import "os"

func main() {
        var options struct {
                Server    string `goptions:"-s, --server, obligatory, description='Server to connect to'"`
                Password  string `goptions:"-p, --password, description='Don\\'t prompt for password'"`
                Verbosity int    `goptions:"-v, --verbose, accumulate, description='Set output threshold level'"`
                goptions.Help    `goptions:"-h, --help, description='Show this help'"`

                goptions.Verbs
                Create struct {
                        Name      string `goptions:"-n, --name, obligatory, description='Name of the entity to be created'"`
                        Directory bool   `goptions:"--directory, mutexgroup='type', description='Create a directory'"`
                        File      bool   `goptions:"--file, mutexgroup='type', description='Create a file'"`
                } `goptions:"create"`
                Delete struct {
                        Name      string `goptions:"-n, --name, obligatory, description='Name of the entity to be deleted'"`
                        Directory bool   `goptions:"--directory, mutexgroup='type', description='Delete a directory'"`
                        File      bool   `goptions:"--file, mutexgroup='type', description='Delete a file'"`
                } `goptions:"delete"`
        }
        fs := goptions.NewFlagSet("goptions", &options)
        err := fs.Parse(os.Args[1:])
        if err != nil{
                println(err.Error())
                fs.PrintHelp(os.Stderr)
                return
        }
}

./main -p

panic: runtime error: index out of range

goroutine 1 [running]:
github.com/voxelbrain/goptions.(*FlagSet).parseShortFlagCluster(0xf840001b40, 0xf8400371c0, 0x0, 0x7fff00000001, 0x0, ...)
        /home/nsf/waytogo/src/github.com/voxelbrain/goptions/flagset.go:235 +0x4a5
github.com/voxelbrain/goptions.(*FlagSet).parseNextItem(0xf840001b40, 0xf8400371b0, 0x100000001, 0xf84005b000, 0x4eb9c0, ...)
        /home/nsf/waytogo/src/github.com/voxelbrain/goptions/flagset.go:180 +0x26c
github.com/voxelbrain/goptions.(*FlagSet).Parse(0xf840001b40, 0xf8400371b0, 0x100000001, 0xf840000e00, 0xf840001b40, ...)
        /home/nsf/waytogo/src/github.com/voxelbrain/goptions/flagset.go:147 +0x5c
main.main()
        /home/nsf/tmp/another/main.go:28 +0xaa

goroutine 2 [syscall]:
created by runtime.main
        /home/nsf/go/src/pkg/runtime/proc.c:221

Embedded structs not supported

I'm not sure if your v3 will be using structs to define the layout of options as this version does, but I noticed that embedded structs were not implemented.

During the reflection/parsing of the struct, if you check the reflect.Value.Anonymous (bool) field and get true you could recurse into that single embedded struct. This allows user to 'reuse' subsets of field structs defined in separate structs but embedding them in the main field struct.

Can't use struct with unexported fields as a verb.

package main

import (
    "github.com/voxelbrain/goptions"
)

type A struct {
    Foo string
    bar string
}

func main() {
    foo := struct {
        goptions.Verbs

        A A `goptions:"a"`
    }{}

    goptions.ParseAndFail(&foo)
}

renders

panic: reflect.Value.Interface: cannot return value obtained from unexported field or method

goroutine 1 [running]:
reflect.valueInterface(0x522e60, 0xc200086380, 0x187, 0x5c8501, 0x588e40, ...)
        /usr/lib/go/src/pkg/reflect/value.go:983 +0xbb
reflect.Value.Interface(0x522e60, 0xc200086380, 0x187, 0x0, 0x0, ...)
        /usr/lib/go/src/pkg/reflect/value.go:972 +0x50
github.com/voxelbrain/goptions.parseStructField(0x522e60, 0xc200086380, 0x187, 0x588e40, 0x0, ...)
        ${HOME}/.local/go/twitterybot/src/github.com/voxelbrain/goptions/tagparser.go:24 +0x52
github.com/voxelbrain/goptions.newFlagset(0x59a19a, 0x1, 0x562500, 0xc200086370, 0x196, ...)
        ${HOME}/.local/go/twitterybot/src/github.com/voxelbrain/goptions/flagset.go:69 +0x298
github.com/voxelbrain/goptions.newFlagset(0x7fff791a42f2, 0x1, 0x55d820, 0xc200086360, 0x196, ...)
        ${HOME}/.local/go/twitterybot/src/github.com/voxelbrain/goptions/flagset.go:97 +0x634
github.com/voxelbrain/goptions.NewFlagSet(0x7fff791a42f2, 0x1, 0x519fe0, 0xc200086360, 0xc200086360, ...)
        ${HOME}/.local/go/twitterybot/src/github.com/voxelbrain/goptions/flagset.go:46 +0x184
github.com/voxelbrain/goptions.ParseAndFail(0x519fe0, 0xc200086360)
        ${HOME}/.local/go/twitterybot/src/github.com/voxelbrain/goptions/goptions.go:79 +0x6d
main.main()
        ${HOME}/a.go:19 +0x6c

upon execution.

If I remove the A.bar field, it works fine.

Can't override boolean with default value set to true

I'd like to add this global option:

Dry        bool         `goptions:"-d, --dry, description='do a dry run'"`

and set its default value to true. However, I cannot override that in the command line: when I pass --dry=false, I get Error: Invalid trailing arguments: [--dry=false ....

I tried the same with regular flags, and it was possible.

Is this something that can be fixed?

ability to pass '-' as a value to remainder

if you pass in '-' as an possition option (eg - Remainder), you get a panic: runtime error: slice bounds our of range on line 118 in flagset.go

basically, it assumes the next character is a short option. In this case, it is a "file" (stdin)

it would be really nice if it checked if there was a character after the dash before trying ot access it.

Short flags with values within a single argument (-p22)

If you strive to reach the complete GNU style compatibility, instead of getting an error when a value-flag in a short flag cluster is not the last one, you should parse the rest of the arg as its value.

A typical example would be a -p parameter (let's say a port). And let's assume we have two boolean parameters -x and -y. That's the possible ways to specify flags and their values:

app -xyp22 yields -x -y -p=22
app -pxy22 yields -p=xy22
app -xy -p22 yields -x -y -p=22

That's a feature request.

Any way to handle none-option parameters?

Does goptions support handling none-option parameters?

For e.g., rsync takes an awful lot of options, but besides them, at the end of command line, there needs to be source and option destination. Can goptions handle cases like this?

Thanks

Improve Documentation

Looks pretty cool but it's not quite obvious that to get the chosen verb one needs just options.Verbs.

And I couldn't figure out how to define command that accepts nargs, aka

<command> 1*<arg>

Also I'm missing information on how to use the verbs. Like if the user is supposed to switch on the options.Verbs or if there is a way to define struct that can be run by goptions or if there is other project that implements this functionality on top of goptions (I think that would be preferred option for me)

So, I fiigured I can do

    options := struct {
        Help     goptions.Help `goptions:"-h, --help, description='Show this help'"`

        goptions.Verbs
        My struct {
            Command *MyCommand
        } `goptions:"my"`

    a := MyCommand{}
    options.My.Command = &a
    goptions.ParseAndFail(&options)

    structValue := reflect.ValueOf(options)
    verb_ := UpFirst(string(options.Verbs))
    verb := structValue.FieldByName(verb_)
    command := verb.FieldByName("Command").Interface().(VerbCommand)
    command.Run()

Remainder not supported with Verbs

I'm just getting started in Go and should probably NOT submit any code yet, however when using your excellent options library that I read about here (http://dave.cheney.net/2013/11/07/subcommand-handling-in-go). I ran into a problem. The solution might just be to amend the documentation, or perhaps there's an actual fix. But when I used Remainder in the top level struct with verbs, I got a nasty reflect error:

panic: reflect: NumField of non-struct type

goroutine 1 [running]:
reflect.(*rtype).NumField(0x5e5560, 0xc20802e530)
/images/opt/go/src/reflect/type.go:657 +0x7a
github.com/voxelbrain/goptions.newFlagset(0x0, 0x0, 0x5e5560, 0xc20802e530, 0xd7, 0xc2080117a0, 0x7ffb282ca7e8)
/home/jagipson/go/src/github.com/voxelbrain/goptions/flagset.go:66 +0x23c
github.com/voxelbrain/goptions.newFlagset(0x695710, 0x4, 0x664e00, 0xc20802e500, 0xd9, 0x0, 0x7ffb282bd000)
/home/jagipson/go/src/github.com/voxelbrain/goptions/flagset.go:102 +0x889
github.com/voxelbrain/goptions.NewFlagSet(0x695710, 0x4, 0x5d5be0, 0xc20802e500, 0x0)
/home/jagipson/go/src/github.com/voxelbrain/goptions/flagset.go:46 +0x1a6
main.main()
/home/jagipson/go/src/github.com/jagipson/goreps/cmd/reps/reps.go:55 +0x84
exit status 2

That happens for this:

options := struct {
    DataStorePath string        `goptions:"-d, --datastore, description='Specify DataStore path. (default: ~/.gorepsdata)'"`
    Verbosity     bool          `goptions:"-v, --verbose", description='firehose verbosity'"`
    Help          goptions.Help `goptions:"-h, --help, description='Show this help'"`

    goptions.Verbs
    List struct {
        Colorize bool `goptions:"-c, --color, description='Colorize the output (not implemented yet)'"`
        Long     bool `goptions:"-l, --long, description='extra data'"`
        Help     bool `goptions:"-h, --help, description='Print List Help'"`

        goptions.Verbs
        Models struct{} `goptions:"models"`
        Items  struct{} `goptions:"items"`
    } `goptions:"list"`

    New struct {
        Foo bool `goptions:"-f"`
    } `goptions:"new"`

    Remainder goptions.Remainder
}{}

And goes away when I comment out the Remainder line

Using goptions variables as global variable

Hi Surma,

Would there be any side-affects if I use a goptions variable as global (configuration) variable? I.e., using them for program configuration/behavior purpose, so that not to define another set of variables having the exact same purpose?

The question may seems strange. That's because I'm having an extremely strange problem using goptions variable as global (configuration) variable. Please take a look at the changes made in

AntonioSun/wts@7fae008

--- a/wts-dump.go
+++ b/wts-dump.go
@@ -323,7 +323,7 @@ func treatWtsXml(w io.Writer, checkOnly bool, decoder *xml.Decoder) error {
 }

 func treatComment(w io.Writer, v string) {
-       if options.Dump.Cnr {
+       if cnr {
                debug("here", 1)
                v = cmtRe.ReplaceAllString(v, "[]")
        }
@@ -471,6 +471,7 @@ func minify(xs string) string {
        return re.ReplaceAllString(xs, "")
 }

+var cnr bool
 var cmtRe *regexp.Regexp
 var tmsRe *regexp.Regexp

@@ -485,10 +486,11 @@ func dumpCmd(options Options) error {
        }
        defer fileo.Close()

+       cnr = options.Dump.Cnr
        if options.Dump.Raw {
-               options.Dump.Cnr = true
+               cnr = true
        }
-       if options.Dump.Cnr {
+       if cnr {
                cmtRe = regexp.MustCompile(`\[#\d+]`)
                debug("here", 1)
        }

The only thing that I did, was to replace the global variable options.Dump.Cnr with global variable cnr. and the if statement in func treatComment changed from not working to working.

Any idea why this is happening?

Here is a sample file, if you need to test it yourself.

<?xml version="1.0" encoding="utf-8"?>
<WebTest Name="Test" Id="a60ebdf8-..." Owner="" Priority="0" Enabled="True" CssProjectStructure="" CssIteration="" Timeout="0" WorkItemIds="" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010" Description="" CredentialUserName="" CredentialPassword="" PreAuthenticate="True" Proxy="default" StopOnError="False" RecordedResultFile="" ResultsLocale="">
  <Items>
    <Comment CommentText="[#1]" />
    <Request Method="GET" Guid="5477c561-3508-43dc-af23-eb6b78ef8f81" Version="1.1" Url="http://my.site.com/" ThinkTime="7" Timeout="60" ParseDependentRequests="True" FollowRedirects="False" RecordResult="True" Cache="False" ResponseTimeGoal="0" Encoding="utf-8" ExpectedHttpStatusCode="0" ExpectedResponseUrl="" ReportingName="" IgnoreHttpStatusCode="False" />
    <Comment CommentText="[#7]" />
  </Items>
</WebTest>

To summary up, using a goptions variable as global configuration variable for program configuration/behavior purpose works, but only if not changing its values programmatically from outside voxelbrain/goptions.

Thanks

Wish item: Use environment variables to specify options

Hi Surma, once again along the line of writing down my thought that will help to get goptions better, (since I knew you are contemplating a new goptions version)...

Before using goptions, I use my own home-made solution, which gives me (beside the program description, usage line customization and the help footer), the ability to use environment variables to specify options.

Please refers to Showcasing the power of easygen with ffcvt if you like to see a concrete example.

Thanks

Wish item: Help description and footer

Hi Surma, the more I use goptions, the more I like it. So I'm writing down my thought that will help to get it better. I.e.,

The thing I'm missing from goptions is a program description entry, which briefly describes what the program is for, and a footer, for something to mention after listing all the options.

Most of the programs have them. I.e., the help output of rsync is a good example.

Thanks

Positional remainder options?

It doesn't look currently possible to define verb-like flags which take a variable.

i.e. something like

myprog [global options] <template> <data>

Could this be supported in a similar way to verbs, by allowing a non-dashed flag name to represent a positional argument for the current verb?

Nested Verbs?

As far as I can tell there is currently no support for nesting verbs?

Is that something you could forsee wanting / adding?

Long options with =

Long options with values after = does not seems to be working:

$ go run main.go --env=dev
Error: Invalid trailing arguments: [--env=dev]
Usage: main [global options] 

Global options:
        -e, --env     Application environment, defines config section (default: prod)
        -r, --rebuild Rebuild index only, do not start web server
        -h, --help    Show this help


exit status 1

W/out equal sign works fine.

$ go run main.go --env dev
[LOG] 2014/12/23 - 04:11:39 | Loading config with env set to dev

Type os.File option problem on output to "-", and setting default value issues

I think I've found a Type os.File option bug when output to "-",

The https://godoc.org/github.com/voxelbrain/goptions says,

Type: *os.File The given string is interpreted as a path to a file. If the string is "-"
os.Stdin or os.Stdout will be used. os.Stdin will be returned, if the
rdonly flag was set. os.Stdout will be returned, if wronly was set.

However, when I try it, I think it is not writing to Stdout. This is my parameter:

    Fo      *os.File `goptions:"-o, --output, description='The output', wronly"`

The whole program is available at
https://github.com/suntong/lang/blob/master/lang/Go/src/sys/CommandLineGoptionsBug.go

Here is how I prove there is a problem:

$ go run CommandLineGoptionsBug.go execute -c test -o - 
Selected verb: execute
Execute.Command: test
 with verbosity: 0
To output, Check str: ''
To os.Stdout, Check str: ''

Note the two "Check str" output line. Now,

$ go run CommandLineGoptionsBug.go execute -c test -o - > /dev/null 
To output, Check str: ''

The print out to os.Stdout is redirected, while the output of "-o -" is not. This is the problem, and I found that it is not redirecting to stderr either:

$ go run CommandLineGoptionsBug.go execute -c test -o - > /dev/null 2>&1
To output, Check str: ''

Still there, even stderr is redirected.

Also, I wasn't able to give options.Execute.Check a default value -- When I enable line 36,
https://github.com/suntong/lang/blob/master/lang/Go/src/sys/CommandLineGoptionsBug.go#L36
I got invalid field name Execute.Check in struct initializer error.

Please help.
Thanks

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.