alecthomas / kingpin Goto Github PK
View Code? Open in Web Editor NEWCONTRIBUTIONS ONLY: A Go (golang) command line and flag parser
License: MIT License
CONTRIBUTIONS ONLY: A Go (golang) command line and flag parser
License: MIT License
Is it possible to do something like this?
I'd like to use Dispatch/Action but I would like to initialize some stuff first (config file, checks, etc), before actually dispatching the func.
This way I could parse, get, work with the values of flags, etc, initialize my stuff, and then execute. Currently I can do that with the switch, but it would be much easier to just use dispatch if this was possible.
Or maybe a .Before() and .After() that would be called before/after Dispatch. That would be awesome aswell.
Doable?
I'm using this style of setup:
update := servers.Command("update", "Update a new cloud server").Action(cmd.update)
update.Arg("identifier", "Identifier of servers to update").Required().StringVar(&cmd.Id)
update.Flag("name", "New name to give server").Short('n').StringVar(&cmd.Name)
But I need to know if the name option was actually provided or not - I can't just check that cmd.Name is empty or not (because the user might be trying to delete the name by providing an empty string).
If I could pass a pointer to a string into StringVar, I could check if it's nil or not, but that's not currently supported.
I could implement my own value type for it I suppose, but it seems like a common requirement - is there a way to do this? If not, should kingpin support it? Should it support the same for all types?
from https://github.com/stretchrcom/testify to https://github.com/stretchr/testify
I had to edit all your tests to have this new import path to get it to work.
I think this also affects your tests in your units repo.
It would be nice if kingpin supported short flags for the builtin --help
and --version
flags. The only reason I see not is it might collide with user added -h
or -v
but couldn't we check for those?
If not automatically having them how can I set them myself?
According to https://godoc.org/gopkg.in/alecthomas/kingpin.v2#FlagClause.Strings a flag should allow the type to be a list of strings:
func (p *FlagClause) Strings() (target *[]string)
Strings accumulates string values into a slice.
Using the following code:
package main
import (
"gopkg.in/alecthomas/kingpin.v2"
"os"
)
var (
app = kingpin.New("my-app", "It does cool things!")
someStrings = app.Flag("strings", "Give me some strings baby!").Short('s').Strings()
)
func main() {
kingpin.MustParse(app.Parse(os.Args[1:]))
}
And running the test app like so: ./test -s hello world
I get the following error: test: error: unexpected world, try --help
This is the help output:
usage: my-app [<flags>]
It does cool things!
Flags:
--help Show help (also see --help-long and --help-man).
-s, --strings=STRINGS
Give me some strings baby!
Consider this test case:
package main
import (
"gopkg.in/alecthomas/kingpin.v2-unstable"
"fmt"
"os"
)
var (
app = kingpin.New("test", "Test case.")
appflag = app.Flag("appflag", "An app flag.").Default("default").String()
something = app.Command("something", "Some command.")
)
func main() {
kingpin.MustParse(app.Parse(os.Args[1:]))
fmt.Printf("App flag is %s\n", *appflag)
}
With v1 it works fine, but with v2-unstable:
$ go run test.go --appflag 123 something
App flag is default
The interspearsed arguments are pretty cool, but since the last commit you can't call with "--help" !
...
download [<flags>] <projectRev>
Retrieve a build Artifact
then:
$ alchemist download --help
alchemist: error: required argument 'projectRev' not provided, try --help
This is more like a question (but maybe a feature request as well).
I am new to Go and very new to Kingpin. I'm about to re-create a simple CLI app in Go which I originally written some time ago in Node.js. (I do not need subcommands for my simple CLI app.) I'm progressing well.
However there are a few customization I would like to make to Kingpin. These are:
-v, --version
with the text Version information
instead of --version
with the text Show application version.
-h, --help
with the text Display help and usage details
instead of --help
with the text Show help (also see --help-long and --help-man).
I don't need --help-long
and --help-man
at all, I just need -h, --help
with customized description.So the first one above I managed to solve by replacing
kingpin.Version("0.0.1")
to this:
kingpin.Flag("version", "Version information").Short('v').Action(func (*kingpin.ParseContext) error {
fmt.Println("0.0.1")
os.Exit(0)
return nil
}).Bool()
This works perfectly the way I want. I can now use the -v
flag or --version
flag and both print out the version info. (Note: The solution to this was not documented at all, I managed to come up with this solution by investigating the source code of Kingpin.)
But the second one (changing --help
to -h, --help
and its description) I cannot figure out.
Is there any way I can customize the default help flag? Especially in a simple CLI app (an app with no subcommands)?
Please let me know,
Thanks!
Some functions exit, some don't. Some write directly to os.Stderr, some don't. Come up with a way to make this consistent.
For example, the "help" command writes to os.Stderr with no way to modify the destination. Perhaps being able to specify the destination io.Writer via a function?
When there are many nested subcommands the Usage information is huge and impossible to understand.
I was thinking of a different approach to Usage information and I would like to propose it.
I think it Application Usage could be greatly simplified by making Usage print only the first set of available commands.
Then, It would be great too if when specifying a correct first command but no subsequent subcommands we could show the Usage for that specific command instead of the whole app.
And so on, instead of having the Application print every possible combination of commands, we could just show the next step in the tree of combinations.
Instead of:
app
would print:
app
Flags:
Commands:
delete user [<flags>]
delete post [<flags>]
For example:
app
would print:
app
Flags:
Commands:
delete <command>
app delete
would print:
app delete
Flags:
Commands:
user [<flags>]
post [<flags>]
I dont know if i make myself clear.
Hope you like my proposal
Cheers!
Hi,
Here is an example:
package main
import (
"fmt"
"os"
"gopkg.in/alecthomas/kingpin.v1"
)
var (
application = kingpin.New("test", "Some test program")
failed_opt = application.Arg("opts", "Some options").
Required().
Strings()
)
func main() {
command := kingpin.MustParse(application.Parse(os.Args[1:]))
fmt.Println(*failed_opt)
}
When I compile and run it with normal string argument, it works as expected:
$ go run test.go hello
[hello]
but if any argument has -
as prefix, program just hangs on parsing. Example:
$ go run test.go hello -world
I understand, it looks like an option but I would like to implement some kind of argument which accepts strings as arguments without any attempts to parse them as an options. Something like --
notation.
tl;dr kingpin help command seems to have broken in v2. In v1, help
without arguments showed the top-level application help, and help
with arguments showed the help of that command. In v2, help
without arguments seems to show the default help for the help
command itself, and adding arguments does nothing.
Here is the example code I'm using:
package main
import "gopkg.in/alecthomas/kingpin.v1"
var (
debug = kingpin.Flag("debug", "enable debug mode").Default("false").Bool()
serverIP = kingpin.Flag("server", "server address").Default("127.0.0.1").IP()
register = kingpin.Command("register", "Register a new user.")
registerNick = register.Arg("nick", "nickname for user").Required().String()
registerName = register.Arg("name", "name of user").Required().String()
post = kingpin.Command("post", "Post a message to a channel.")
postImage = post.Flag("image", "image to post").ExistingFile()
postChannel = post.Arg("channel", "channel to post to").Required().String()
postText = post.Arg("text", "text to post").String()
)
func main() {
switch kingpin.Parse() {
// Register user
case "register":
println(*registerNick)
// Post message
case "post":
if postImage != nil {
}
if *postText != "" {
}
}
}
With kingpin.v1 (tag v1.3.7
), the help command works fine:
$ ./kingpin_example
usage: kingpin_example [<flags>] <command> [<flags>] [<args> ...]
Flags:
--help Show help.
--debug enable debug mode
--server=127.0.0.1 server address
Commands:
help [<command>]
Show help for a command.
register <nick> <name>
Register a new user.
post [<flags>] <channel> [<text>]
Post a message to a channel.
$ ./kingpin_example help
usage: kingpin_example [<flags>] <command> [<flags>] [<args> ...]
Flags:
--help Show help.
--debug enable debug mode
--server=127.0.0.1 server address
Commands:
help [<command>]
Show help for a command.
register <nick> <name>
Register a new user.
post [<flags>] <channel> [<text>]
Post a message to a channel.
$ ./kingpin_example help register
usage: kingpin_example [<flags>] register <nick> <name>
Register a new user.
Args:
<nick> nickname for user
<name> name of user
But if I update the example to kingpin.v2 (tag v2.1.0
), I get this output instead:
$ ./kingpin_example
usage: kingpin_example [<flags>] <command> [<args> ...]
Flags:
--help Show context-sensitive help (also try --help-long and --help-man).
--debug enable debug mode
--server=127.0.0.1 server address
Commands:
help [<command>...]
Show help.
register <nick> <name>
Register a new user.
post [<flags>] <channel> [<text>]
Post a message to a channel.
$ ./kingpin_example help
usage: kingpin_example help [<command>...]
Show help.
Flags:
--help Show context-sensitive help (also try --help-long and --help-man).
--debug enable debug mode
--server=127.0.0.1 server address
Args:
[<command>] Show help on command.
Subcommands:
$ ./kingpin_example help register
usage: kingpin_example help [<command>...]
Show help.
Flags:
--help Show context-sensitive help (also try --help-long and --help-man).
--debug enable debug mode
--server=127.0.0.1 server address
Args:
[<command>] Show help on command.
Subcommands:
If a flag is not Required(), it does not show up in main command --help output; it only shows up in the --help for that specific sub-command. Can this behavior be controlled (I would prefer to have the full flags list in the help at the top level, detail on each flag would still remain in the sub-command specific help)
Hi, this is a simple program that doesn't seem to work as intended :
I have checked out v2.0.8 tag
package main
import (
"fmt"
"os"
"gopkg.in/alecthomas/kingpin.v2"
)
func main() {
app := kingpin.New("test", "testApp").Action(action).PreAction(preAction).Terminate(terminate)
fmt.Println(app.Parse(os.Args[1:]))
}
func action(c *kingpin.ParseContext) error {
fmt.Println("ACTION")
return nil
}
func preAction(c *kingpin.ParseContext) error {
fmt.Println("PRE ACTION")
return nil
}
func terminate(code int) {
fmt.Println("TERMINATE")
os.Exit(code)
}
returns
ACTION
ACTION
<nil>
The help templates do not include the list of possible values when displaying help for enum flags.
Example:
c.Flag("level", "").Enum("info", "warning", "fatal")
Could be rendered with --help-long
as:
--level=LEVEL (options: info, warning, fatal)
I'm trying to use EnumVar but can't figure out the interface and can't find an example for it.
create := token.Command("create", "create a token").Action(cmd.create)
create.Flag("format", "the output format: text, json or curl").Default("text").EnumVar(&cmd.Format, "text", "json", "curl")
I'm a bit of a Go newbie so I assume I'm just missing something, but I think an example in the docs would be useful to others!
Love the library, man. Thank you for your contribution!
You might wanna add getopt-like double dash (--
) behavior so that negative numbers can be used in positional arguments. I tried to do that today in 1.3.2, but it assumes I'm trying to specify a flag. My example had a string positional argument and an Int64 positional argument, like so:
% cmd "my string" -123
error: unexpected arguments '-1 -2 -3', try --help
I was hoping to get -123
as an Int64.
With getopt, I think you can do this and have it work correctly:
% cmd -- "my string" -123
Basically the --
by itself means "everything after this is not a flag".
I wanted to define my kingpin commands with a pattern where adding a new command only required adding new code (i.e. not modifying an existing switch statement), and also I didn't need to duplicate a string constant for my command name.
I propose additions to the kingpin API to support a similar pattern along the lines of this example:
// my-app.go:
var app kingpin.Application = kingpin.New("my-app", "My app")a
func main() {
cmd, err := app.Parse(os.Args[1:])
if err != nil || cmd == "" {
app.Usage(os.Stderr)
return
}
app.RunAction(cmd)
}
// my_job.go:
func init() {
cmd := app.Command("greet", "Greet a user")
argGreetName := cmd.Arg("greet-name", "Name of user to greet").Required().String()
cmd.Action(func() {
fmt.Printf("Hello, %s!", *argGreetName)
})
}
The new kingpin interfaces could be:
// Set the action function for a command
func (*CmdClause) Action(action CommandAction) {}
type CommandAction func(*ActionContext) (interface{}, error)
type ActionContext struct {
Application *Application
Command *CmdClause
// Other stuff here?
}
// Returns whatever values the CommandAction returned.
// cmdName should be a result from Application.Parse()
// Panics if cmdName isn't the name of a registered command, as this is a programmer error.
func (*Application) RunAction(command string) (interface{}, error) {}
// Parses arguments and prints usage on parse error or runs RunAction.
// Other possible names for this function: Run, ParseAndRun, DefaultRun.
func (*Application) ParseAndRunAction(args []string) (interface{}, error) {}
Any thoughts?
Happy to write this up as a PR if people like the idea.
I want to have --no-interaction
flag in my program so I created the following code:
package main
import (
"fmt"
"os"
"gopkg.in/alecthomas/kingpin.v2"
)
var (
app = kingpin.New("Test", "")
foobar = app.Flag("foo-bar", "A flag containing a minus").Default("false").Bool()
noInteraction = app.Flag("no-interaction", "Do not ask for any user input").Default("false").Bool()
)
func main() {
kingpin.MustParse(app.Parse(os.Args[1:]))
fmt.Printf("Foobar: %+v\n", *foobar)
fmt.Printf("noInteraction: %+v\n", *noInteraction)
}
When I run this with go run example.go --foo-bar
it works as intendended but when I want to use the no-interaction
flag kingpin doesnt recognize the flag even though it is listed in go run example.go --help
$ go run example.go --help
usage: Test [<flags>]
Flags:
--help Show help (also see --help-long and --help-man).
--foo-bar A flag containing a minus
--no-interaction Do not ask for any user input
exit status 1
$ go run example.go --no-interaction
example: error: unknown long flag '--no-interaction', try --help
exit status 1
Am I doing something wrong?
Is it possible to support flags in any order? For example:
clitool subcommand arg
clitool subcommand --help arg
clitool subcommand arg --help
Reasoning; with complex commands that have many or long arguments it's fairly annoying to have to seek back to before the arguments and add a flag. Especially if that flag is --help
.
I believe flags can be parsed unambiguously so they could technically be mixed with args, but I know this is probably a complex topic.
In version 2 some of the base functionality has been un-exported. Instead of showing the entire usage when a command fails I wrote a function to show just the subcommand help if we could understand the command that far. This was the code:
func generateHint(app *kingpin.Application, args []string) (string, error) {
output := bytes.NewBuffer(nil)
context := kingpin.Tokenize(args)
token := &kingpin.Token{0, ""}
for token.Type != kingpin.TokenEOL {
token = context.Peek()
if token.Type == kingpin.TokenArg {
if _, ok := commands[token.String()]; ok {
app.CommandUsage(output, token.String())
return output.String(), nil
} else {
// If we hit a real arg and it isn't a sub-command exit.
break
}
} else {
// Skip one additional time to pass over Flag value
context.Next()
}
context.Next()
}
return "", fmt.Errorf("No hints")
}
I don't know if this is the right way to do this, but that is no longer possible. Since our command has about 12 subcommands it's very irritating to see the entire help tree when really they're struggling with a single command.
Currently help prints text like:
usage: chat [<flags>] <command> [<flags>] [<args> ...]
All the angle brackets make it hard to read. I suggest something simpler like:
usage: chat [options] command [command options] [arguments...]
…becouse "github.com/kr/pty" doesn't support Windows (http://pastie.org/private/dehitfvtwpbqvx65r16yg).
"github.com/kr/pty" is used in only one place: in guessWidth() function, which has a strange code:
width := 80
if width == 0 {
Obviously, in this case the condition "width == 0" is always false.
current float parser forces float64.
should be split into two separate parsers.
Float32Var(var * float32) and Float64(var * float64)
Same for int32 holds true for int32 etc.
I'm a first-time Kingpin user and I love it so far!
Unix programs often allow users to specify -
to read from stdin, or allow values to be read from files using @filename syntax. kingpin returns a parse error when -
is passed as a positional argument, and doesn't allow a curl-style use of @-
because the @ anywhere on the command line appears to read command line arguments from a file.
The currently implemented behavior is just different enough from expectations to have caused me grief.
Feature requests:
./main put key @valuefile.txt
to store the contents of valuefile.txt rather than have its contents treated as a command line.-
as the beginning of a command line flag.Thanks!
I want to be able to have:
executable build myproject:123 <flags>
right now, the myproject:123
is registered as an Arg()
and is always placed at the end of the flags. It makes no sense for the users of my CLI tool to put the project name at the end of the flags. I need to at least support it at the beginning, if not anywhere when considered as a positional argument.
Is that possible, how complex would it be to implement ? I was thinking at an option on the Command()
to mark it as not having any sub-commands, so it can handle positional arguments before the flags. What do you think ?
Currently the Help command forces an exit of the application. There a way we can override the dispatch behaviour of help so it doesn't exit?
When I add .Version to my kingpin parser, when there are other .Required fields, instead of printing version on --version, it wants to have the required fields. They should not be required for --version.
I noticed there is a test in flags_test.go, but its missing one assertion at the end of the function and that should be failing right now.
Currently, I have 3 sub commands that take the exact same flags and args. What follows is an example of defining two of them. Is there a cleaner way to do this?
create = app.Command("create", "initial create/deploy of an app")
create_cpu = create.Flag("cpu", "cpu share").Short('c').Required().Float()
create_mem = create.Flag("mem", "mem share (integer MB)").Short('m').Required().Int()
create_instances = create.Flag("instances", "instance count").Short('i').Required().Int()
create_app_name = create.Arg("app_name", "application name").Required().String()
create_app_build = create.Arg("app_build", "application build").Required().String()
create_app_revision = create.Arg("app_revision", "application revision name").Required().String()
create_app_extension = create.Arg("app_extension", "application file extension").Required().String()
create_app_run_as = create.Arg("app_run_as", "application run as user").Required().String()
update = app.Command("update", "update definition of an app (automatically deploys new definition)")
update_cpu = update.Flag("cpu", "cpu share").Short('c').Required().Float()
update_mem = update.Flag("mem", "mem share (integer MB)").Short('m').Required().Int()
update_instances = update.Flag("instances", "instance count").Short('i').Required().Int()
update_app_name = update.Arg("app_name", "application name").Required().String()
update_app_build = update.Arg("app_build", "application build").Required().String()
update_app_revision = update.Arg("app_revision", "application revision name").Required().String()
update_app_extension = update.Arg("app_extension", "application file extension").Required().String()
update_app_run_as = update.Arg("app_run_as", "application run as user").Required().String()
Here's my code:
var (
stress = kingpin.Flag("stress", "Stress Test Mode").Bool()
)
func main() {
kingpin.Parse()
fmt.Printf("stress: %v\n", *stress)
}
And running it:
$ go run main.go --stress
stress: false
I'm expecting stress
to be true, since I'm passing the --stress
flag. What am I doing wrong?
Right now, if you have a Command added to your kingpin.New() app, and no sub-command is specified at runtime, usage is printed and the program aborts.
My attempt to achieve this with the below failed:
var (
appCommand = kingpin.New("myapp", "Yum yum yum.")
mySubcommand = appCommand.Command("mysubcommand", "Frob the bars")
)
func main() {
switch kingpin.MustParse(appCommand.Parse(os.Args[1:])) {
case mySubcommand():
log.Print("my subcommand was selected")
default:
// default action - alas, usage is printed and we never make it here
log.Print("my default action")
}
}
Using the chat example, when I just run the "chat" command with no arguments I'd like to get the help output as if I had specified "--help".
Hi,
We have a cli application with many (~35) flags. This amount of flags is unfortunately necessary.
Using the default help template the usage line doesn't display optional flags. It would be nice to print them in brackets, like in man pages :
usage : app command --required-flag1 --required-flag-2 ( --optional-flag-1 )
also in the flag section there is no differentiation between required and optional flags. It would be nice if you could add this.
Last question :
Would it be possible to add another template, which would print usage section like this :
usage : app command --flag-1
--flag-2
--flag-3
--flag-4 \
this would greatly increase readability for applications with many flags ( like ours )
Best regards,
Maciej
It'd be great if we could alias commands and/or flags. For example, something like:
someFlag = app.Flag("v", "Be verbose!").Bool()
app.Flag("verbose").alias(someFlag)
It would be nice if it was possible to print the help on STDOUT instead of STDERR so that when the help text gets long there is no need to redirect before piping to less for example. FWIW standard Linux tools don't seem to print help to STDERR (try ls --help
, cp --help
).
I have a need for an optional argument or two.
This program would behave differently based on whether it has 0, 1, or 2 arguments. I don't see a way to handle that cleanly in kingpin. I suspect that is because of the multi-level command support.
Could we add OptionalArg which cannot be followed by anything else (except another OptionalArg)?
debug = kingpin.Flag("debug", "Enable debug mode.").Bool(),
flagged = kingpin.Flag("flagged", "Enable flagged mode. (make each key name as to whether it came from vault (v) or consul (c)").Bool(),
productGroup = kingpin.OptionalArg("product-group", "product group to list.").String(),
template_file = kingpin.OptionalArg("template-filename", "filename of the template file to verify.").String(),
ehj
ehj group
ehj group template_file
Can not be overridden...badness.
error: default value for --geoip is invalid: path './data/GeoLiteCity.dat' does not exist
It would be nice if shortname flags did not require a space
cli -u username
<- valid
cli -uusername
<- not valid
From this line of code, it looks like a flag with both OverrideDefaultFromEnvar
and Required
will cause the parsing to error out, even when an envar is present, since defaultValue is checked on L166 before it is overridden on L172.
Line 165 in a727460
In the chat example, "chat help" and "chat help post" show help in v1 but do nothing in v2-unstable.
My understanding of the following:
jobId = kingpin.Arg("jobid", "").String()
argString = kingpin.Arg("argstring", "").Strings()
Would allow you to pass argString
with strings that look like normal args. Yet I seem to be running into an issue:
bin/rundeck-run-job 41972a2d-5929-464e-9ba2-fa30cc3591f8 -aws_secret_key ${AWS_SECRET_ACCESS_KEY} -orgname jv-test-org -aws_access_key ${AWS_ACCESS_KEY_ID}
rundeck-run-job: error: unknown short flag '-a', try --help
The Rundeck API for calling jobs, takes arguments in a format that look like arguments (http://rundeck.org/docs/api/#running-a-job)
Am I mistaken that my above example SHOULD work or am I using it wrong?
I'm pleasure that default command feature is added, however, it seems a problem here.
package main
import (
"fmt"
"gopkg.in/alecthomas/kingpin.v2"
)
func main() {
modules := kingpin.Command("enable", "").Default().Arg("modules", "").Strings()
fmt.Println(kingpin.Parse())
fmt.Println(*modules)
}
if this file is run like "cmd aaa", the output will be:
enable
[aaa]
What I expect is "unknown command", isn't you?
Also see TestDefaultSubcommandWithArg. This looks nice, but I don't think this is what we want at the most time. This behaviour is confusing. I do not known is there any program works like this either.
$ go get gopkg.in/alecthomas/kingpin.v1
shows
# gopkg.in/alecthomas/kingpin.v1
../../../gopkg.in/alecthomas/kingpin.v1/global.go:46: CommandLine.ParseWithFileExpansion undefined (type *Application has no field or method ParseWithFileExpansion)
../../../gopkg.in/alecthomas/kingpin.v1/global.go:46: not enough arguments in call to MustParse
go versions 1.3.3 and 1.4.1
I didn't found about the case. Could somebody bring me one? Thanks
--- FAIL: TestParseExistingFile (0.00s)
Location: parsers_test.go:57
Error: No error is expected but got path '/etc/hosts' does not exist
Location: parsers_test.go:58
Error: Not equal: "/etc/hosts" (expected)
!= "" (actual)
If I get a chance to add this I will do so and file a merge request, in the meantime:
I have a use case where there are a set of 4 flags, with the following names:
At a bare minimum, ONE of the above flags is required. It would be great to be able to have a group of flags where one flag is required.
Flags:
--help Show help.
--bind=127.0.0.1:8239 Host and port to bind service to.
--log-level=info Set the default log level.
--log-file=PATH Enable file logging to PATH.
--log-stderr Log to stderr (defaults to true).
--debug Enable debug mode.
-p, --pid-file=/var/folders/sj/cq5qhlq11p1537yg0pp21pb80000gn/T/sbusd.pid Write PID file to PATH.
-d, --daemonize Daemonize the process.
Using code:
app.Flag("endpoint", "Server endpoint.").PlaceHolder("").Default("http://www.example.com:8080/v1").URLVar(&c.endpoint)
This still prints the default as the placeholder.
--endpoint=http://www.example.com:8080/v1
Server endpoint.
The effect I'm trying to get is for no placeholder to be printed. Because it's long and ugly I want to hide the value from the user.
Hi, I was playing with actions a bit more today (on commit d447053 )
I run this app :
package main
import (
"fmt"
"os"
"gopkg.in/alecthomas/kingpin.v2"
)
func main() {
app := kingpin.New("test", "testApp").Action(action)
app.Parse(os.Args[1:])
}
func action(c *kingpin.ParseContext) error {
fmt.Println("ACTION")
return nil
}
and got this :
$ go run main.go
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x602c3]
goroutine 1 [running]:
gopkg.in/alecthomas/kingpin%2ev2.(*Application).applyPreActions(0xc20806a8c0, 0xc208030200, 0x0, 0x0)
/Users/mgalkowski/work/go/src/gopkg.in/alecthomas/kingpin.v2/app.go:462 +0x63
gopkg.in/alecthomas/kingpin%2ev2.(*Application).execute(0xc20806a8c0, 0xc208030200, 0x0, 0x0, 0x0, 0x0)
/Users/mgalkowski/work/go/src/gopkg.in/alecthomas/kingpin.v2/app.go:312 +0x16e
gopkg.in/alecthomas/kingpin%2ev2.(*Application).Parse(0xc20806a8c0, 0xc20800a000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
/Users/mgalkowski/work/go/src/gopkg.in/alecthomas/kingpin.v2/app.go:134 +0x273
main.main()
/Users/mgalkowski/work/go/src/bitbucket.org/globalsign/restfulca/tools/testTool/main.go:12 +0xd5
goroutine 2 [runnable]:
runtime.forcegchelper()
/usr/local/Cellar/go/1.4.2/libexec/src/runtime/proc.go:90
runtime.goexit()
/usr/local/Cellar/go/1.4.2/libexec/src/runtime/asm_amd64.s:2232 +0x1
goroutine 3 [runnable]:
runtime.bgsweep()
/usr/local/Cellar/go/1.4.2/libexec/src/runtime/mgc0.go:82
runtime.goexit()
/usr/local/Cellar/go/1.4.2/libexec/src/runtime/asm_amd64.s:2232 +0x1
goroutine 4 [runnable]:
runtime.runfinq()
/usr/local/Cellar/go/1.4.2/libexec/src/runtime/malloc.go:712
runtime.goexit()
/usr/local/Cellar/go/1.4.2/libexec/src/runtime/asm_amd64.s:2232 +0x1
exit status 2
Any ideas?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.