urfave / cli Goto Github PK
View Code? Open in Web Editor NEWA simple, fast, and fun package for building command line apps in Go
Home Page: https://cli.urfave.org
License: MIT License
A simple, fast, and fun package for building command line apps in Go
Home Page: https://cli.urfave.org
License: MIT License
Currently, when a user passes an unidentified argument, like app --badargument
, the ShowAppHelp
function is called, which uses the AppHelpTemplate
.
This behavior is fine, but, I think showing the entire help might not always be nice idea. Like git
only shows the common usage when a bad argument is passed.
So, it'll be better if there were a separate IncorrectUsageTemplate
which will offer greater flexibility.
would be nice to have
In my opinion it would make more sense to have -v
/--version
as a subcommand than a global option. It seems like the general theme is that subcommands make the app do something, whereas global options modify the behavior of whatever subcommand is selected. In this vein I think it would also make sense to remove -h
/--help
and solely use the h
/help
subcommands.
Let me know what you think. Obviously this breaks the API slightly, so maybe it would have to wait a version? If this seems like a good idea I'd be happy to submit a pull request implementing it.
PS: Thanks for how awesome and easy to use cli is. ❤️
@kytrinyx @msgehard This may affect you guys so I would like to know what you think about this.
I got bit recently by this, basically when an error occurs, like incorrect usage in a FlagSet or failing to find a help topic we call an os.Exit(1)
. This is convenient for the most part also terminates the app when you may not desire it.
The proposal is to basically replace the os.Exit(1) with a error return on app.Run()
. That way these errors can be handled any way the developer wants to. This also feels a lot more idiomatic in terms of Go.
Let me know what you think. I would really love to get this to 1.0 So the api can get locked in.
The help template prints titles like OPTIONS or DESCRIPTION even when there is no content for them. Maybe a few {{if}}
’s in there to reduce the verbosity when there is nothing to say?
(Happy to implement if we agree this is desirable.)
When it comes here:
https://github.com/codegangsta/cli/blob/master/context.go#L220
It cannot set correct value for StringSlice type.
It causes that if I set:
cli.StringSliceFlag{"peers, C", &cli.StringSlice{}, "a comma-delimited list of machine addresses in the cluster (default: {\"127.0.0.1:4001\"})"},
and input:
--peers 1.1.1.1
it will return the value
[1.1.1.1 [1.1.1.1] [1.1.1.1 [1.1.1.1]]]
app.Commands = []cli.Command{
{
Name: "command",
Action: func(c *cli.Context) {
println("command")
},
},
}
I expected appending --help
with only show usage but:
$ ./app command --help
Usage of command:
command
Hi,
I was just wondering if it is desired to run <prog> <subcmd> -h
and still have the action assigned to that subcommand executed. That is what is happening now for me - the action is triggered even though -h
is present.
I think that this would lead to having all the subcommand actions starting with like if -h is present then exit(1)
.
Cheers
I maybe missing this, and I have looked through most of the other issues both open and closed, but I cant find anything related to this issue/feature.
If I have a sub command of a command cli command sub-command
, is there a help section for the sub-command
.
When I run cli help
, I get the global help template with commands and global flags, and when running cli help command
I again get the help template with description and command specific flag options, but I can't seem to find anyway on getting help with sub-commands of a command.
IE
If I had a cli that had a command called server
, and sub-commands to server
called start
, stop
, etc... Is there a way to get a list of those sub-commands via help?
Is there any way to do that?
I did give it a shot, but got this error:
./main.go:244: cannot use []cli.Flag literal (type []cli.Flag) as type []cli.Command in field value
I'd really to be able to create interactive flags: when it's used, it will read it's value from standard input.
example:
$ mycmdlineapp --ask-password
password: *******
It's golang usage could like:
cli.InteractiveFlag{"ask-password, a, password", "default-password", "Asks for password"}
What do you think?
Hi,
Like what is already possible for 'Before' actions, i found useful and somewhat logical to have 'Actions' return something on exit, so that app.Run() gets to catch all errors, if any, underneath it. Please look at 52496bf in case you care.
All the best
It would to be nice to parse arrays for string and int types
example:
./app create -dns 8.8.8.8 -dns 8.8.4.4 server.domain.tld
something like :
cli.ArrayStringFlag{"dns", "8.8.8.8", "set one or more dns Servers"}
Thanks in advance for this awesome app
This may already be doable..
In my own Python lib called Skal (which does the same thing as this one) inserting the default command in the args before using the library works but is a ugly work around. I tried this in Go also, and it works! But it is still a little unclean:
func main() {
fmt.Println(os.Args)
// Make sure to only add "test" if no other subcommand is set..
os.Args = append(os.Args, "test")
fmt.Println(os.Args)
}
Would it be possible to set which subcommand (or another command) that will be called when no subcommand is specified?
The help template contains just [arguments...]
, but it would be very useful if it was possible to define those arguments (optional arguments including) and see them in help, i.e. to se ARG1 ARG2 [ARG2]
in the usage if ARG2
is optional instead of just [arguments...]
.
I want to be able to use the classic --
command parsing terminator in an app using the cli package. However, something strange happens:
./example --lang english echo foobar python myscript.py
foobar [python myscript.py]
./example --lang english echo foobar -- python myscript.py -d
python [myscript.py -d foobar]
foobar is jumping from the 0th arg to the 2nd arg if the --
terminator is given! I haven't started digging into the code but this is rather suprising.
package main
import (
"fmt"
"os"
"github.com/codegangsta/cli"
)
func main() {
app := cli.NewApp()
app.Flags = []cli.Flag {
cli.StringFlag{"lang, l", "english", "language for the greeting"},
}
app.Commands = []cli.Command{
{
Name: "echo",
Flags: []cli.Flag{
cli.StringFlag{"newline, n", "yes", "print newline"},
},
Action: func(c *cli.Context) {
args := c.Args()
println(args[0], fmt.Sprintf("%v", args[1:]))
},
},
}
app.Run(os.Args)
}
List sub-command options on:
$ cli help
and
$ cli sub-command help
Now it only lists global options
I'd love to be able to use cli.go to create a telnet interface for applications that would allow me to inspect and manipulate the program's running state. I haven't looked into how easy or difficult this would be, but consider it a wishlist item if you get the time for it :-)
Using a flag such as
cli.StringSliceFlag{"lang", &cli.StringSlice{"english", "spanish"}, "language for the greeting"},
results in help output like this:
OPTIONS:
--lang [english spanish] `-lang option -lang option` language for the greeting
What exactly is the intended meaning of "-lang option -lang option
"? Am I just uninformed or is this a WIP? I'd be happy to work on it if I know what it's supposed to do! :)
I recently came across a problem when accessing Args from Context. I expected to get the same args in "Action" and "Before" functions, but "Action" has it's name at index 0 and arguments start from index 1, in "Before" arguments start from index 0.
An example to demonstrate: http://play.golang.org/p/CIrOdw3noq
Also looking at the examples https://github.com/codegangsta/cli#subcommands
I'd expect c.Args().First()
to contain the first argument, not the command name itself. Is this desired behaviour, please?
I apologize if this is obvious and I'm just missing it, but I'm trying to figure out how to os.Exit(0)
when help is called via help
, h
, --help
and -h
. All print the help message, but none exit by default and I can't seem to find a simple way to for the exit. I attempted adding checking to my app.Action
declaration, but that seems to be executed only if help
isn't specified. This seems like something most applications would want to do by default.
Here's a simplified example -- http://play.golang.org/p/PEdNXSMvJ8.
Cheers and thanks in advance,
J
Hi, is it a conscious design decision not to have help flags? I just wonder because this seems nasty but I don't know how else to do it.
rnd.Action = func(context *cli.Context) {
// halp hax
for _, comm := range rnd.Commands {
if comm.HasName("help") {
comm.Action(context)
os.Exit(0)
}
}
// do some stuff in the default (empty) context
fmt.Printf("Debug: %v\n", context.Bool("debug"))
fmt.Printf("Port: %d\n", context.Int("port"))
}
Or maybe I'm just missing something fundamental =]
I noticed that in some applications, character flags are grouped by a single hyphen, while keyword flags must be prepended with a double-hyphen.
For example:
myapp -asdf
Would be the equivalent to:
myapp -a -s -d -f
However,
myapp --asdf
Refers to the keyword flag 'asdf'
Is this something that may be considered for a later version?
Basically,
$ go vet ./...
app_test.go:46: cli.StringFlag composite literal uses unkeyed fields
cli_test.go:50: cli.StringFlag composite literal uses unkeyed fields
cli_test.go:60: cli.StringFlag composite literal uses unkeyed fields
cli_test.go:70: cli.StringFlag composite literal uses unkeyed fields
exit status 1
It would be really nice to have required flags and required arguments. I'm mostly putting this here as a place holder to discuss although I would be willing to put some work in on this if we can talk about how we would like to implement it.
I was thinking the easiest would just add a new field to the struct called "Required". Internally we could have some checking and fail if the required flag is not set.
type Flag interface {
fmt.Stringer
Required bool
// Apply Flag settings to the given flag set
Apply(*flag.FlagSet)
getName() string
}
func (f *Flag) IsRequired() bool {
return f.Required
}
Would there be any interest in adding a couple additional flag types?
The ones I am missing are int64 and a "duration" that parses to time.Duration.
how can I make a mandatory argument?
also I want to use the first parameter without the flag, but include it in the help also. whats the best way?
eg
Usage: myapp myargument
if a Command
is invoked as cli cmd arg1 -f arg2
where -f
is a BoolFlag
the result of ctx.Args()
in the command function will be [arg2 arg1]
.
This appears to be related to #36
I have made the test case below (which currrently fails), but I am not really able to find a decent fix.
func TestApp_CommandWithBoolFlagAfterArgs(t *testing.T) {
var args []string
app := cli.NewApp()
command := cli.Command{
Name: "cmd",
Flags: []cli.Flag{
cli.BoolFlag{
Name: "f",
Usage: "foo",
},
},
Action: func(c *cli.Context) {
args = c.Args()
},
}
app.Commands = []cli.Command{command}
app.Run([]string{"", "cmd", "1", "2", "-f", "3"})
expect := []string{"1", "2", "3"}
if !reflect.DeepEqual(args, expect) {
t.Errorf("Got %v (type %T) - expected %v (type %T)", args, args, expect, expect)
}
}
Fails with
app_test.go:216: Got [3 1 2] (type []string) - expected [1 2 3] (type []string)
Hope you can come up with something good.
I'm not sure if I'm doing something wrong or if cli
doesn't support this. I have an app with lots of subcommands, and I'd like to have some global flags that apply for every command (e.g. specifying the location of a config file). (Right now the commands don't have any command-specific flags, but potentially I could want both global flags and command specific flags).
If I specify the flags in the top level app.Flags
, I can't seem to extract their value from the context in the action -- I always get empty strings back. Instead, I have to repeat the flags in each command definition for it to work. Is this the intended behaviour (top-level flags don't do anything for commands)?
We noticed this in our CI:
cd /mnt/jenkins/jobs/tabasco-runtime-cf-deploy/workspace/gospace/src/github.com/codegangsta/cli; git pull --ff-only
fatal: Not possible to fast-forward, aborting.
package github.com/cloudfoundry-incubator/spiff
imports github.com/cloudfoundry-incubator/spiff/compare
imports github.com/cloudfoundry-incubator/spiff/yaml
imports launchpad.net/goyaml
imports github.com/cloudfoundry-incubator/spiff/dynaml
imports github.com/cloudfoundry-incubator/spiff/flow
imports github.com/codegangsta/cli: exit status 128
error: Command failed: "go get -u -v github.com/cloudfoundry-incubator/spiff" (options: {}) # 2014-01-06 23:37:14 +0000
The commit was:
commit eb027661af08a193a5f8a33528a44a80e9dc58ae
Merge: 1cb2291 69b5310
Author: Jeremy Saenz <[email protected]>
Date: Thu Jan 2 08:36:08 2014 -0800
Merge pull request #58 from tjarratt/master
Allow flags to omit their default value in String()
I'm writing a CLI app and we've customized the help output for the application by creating a help command that you can invoke with my-tool help
. We can't just override the template because we also want to change the order of some commands and group them. Today we noticed that if you just provide the -h
or --help
flag then the app help is printed from codegangsta/cli, and not our custom help command.
It's great that you can customize the application help template by overriding the cli.AppHelpTemplate
string, but it seems like a more useful thing would be to allow applications to set a function that prints out the app help.
eg:
cli/help.go
// Prints help for the App
var HelpPrinter = printHelp
func ShowAppHelp(c *Context) {
HelpPrinter(AppHelpTemplate, c.App)
}
Thoughts? I'd be more than willing to write a PR for this behavior if this seems reasonable.
Sample code:
app := cli.NewApp()
app.Name = "test"
app.Usage = "hello"
command := cli.Command{
Name: "cmd",
Usage: "does stuff",
Flags: []cli.Flag{
cli.IntSliceFlag{Name: "p", Value: &cli.IntSlice{}, Usage: "set one or more ip addr"},
cli.StringSliceFlag{Name: "ip", Value: &cli.StringSlice{}, Usage: "set one or more ports to open"},
},
Action: func(c *cli.Context) {
},
}
app.Commands = []cli.Command{command}
//app.Run([]string{"", "cmd", "my-arg", "-p", "22", "-p", "80", "-ip", "8.8.8.8", "-ip", "8.8.4.4"})
app.Run([]string{"", "help", "cmd"})
results in:
NAME:
cmd - does stuff
USAGE:
command cmd [command options] [arguments...]
DESCRIPTION:
OPTIONS:
-p '-p option -p option' set one or more ip addr
-- 'ip' -ip option -ip option%!(EXTRA string=set one or more ports to open)
If Action
s wish to write out to console while remaining stateless, they should have access to means for doing so on the Context. Calling fmt.Print or os.Stdout from within the Action
func feels stateful, and it is.
Seems more desirable that Actions might write to Context.Stdout or to Context.Writer or similar. Then the entire context really is within Context.
(Heck, os.Stdout is an os.File, that opens up a nice set of functionality.)
I want to print some parts (like usage examples) of the AppHelpTemplate
in color (using ANSI escape codes).
I tried wrapping the text in escape codes, but couldn't get it to work. Rather than escaping, the text is printed on the terminal as is along with the codes.
I did something like:
var AppHelpTemplate = `\x1b[33;1m{{.Name}} - {{.Usage}}\x1b[0m`
One of the ideas behind cli.go is progressive enhancement. A app developer should just be able to get running with cli.go in 2 lines:
cli.Action = func(){ println("Hello world") }
cli.Run(os.Args)
Still a couple things to cover:
right now appending default flags assumes that the app will only be run once. This is fine in most circumstances but got bit by it in a new command line app I am working on
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.