Git Product home page Git Product logo

kong'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

kong's Issues

Allow single dash as argument value

Some CLI tools traditionally use the single dash to mean "stdin".

Examples are tar tvfz - or cat -

Kong however chokes when encountering a - not followed with a letter with error: expected short flag.

embedding reusable subcommands from the same struct

In my current project, I faced the following challenge. I have a cli whichs commands are composed of two subcommand sets. E.g, build and find as root commands and both have the same sub commands with the same methods, e.g., build foo, build goo, find foo, and find goo. Ideally, there would be only one sub command struct for foo and goo that is embedded in the root commands. However, I could not find an idiomatic way to call the root commands (i.e, parents) from the sub commands Run methods. I had to access context.Command() and identify the struct field using reflection.

So I'm wondering if you considered such a case - maybe I haven't seen the obvious again - or if you would like to see a feature that allows to traverse to parent command structs and execute a Run on it. Thereby, someone could create quite advanced command chains.

cannot parse int to int16 value

hcl config:

kafka {
  replication-factor = 3
}

struct to set

type KafkaConfig struct {
	BootstrapServer   string `help:"The advertised address and port of the kafka brokers" default:"localhost:9093"`
	ReplicationFactor int16  `help:"The replication factor for topics" default:"1"`
}
 panic: mapper kong.MapperFunc failed to apply to --kafka-replication-factor=1: reflect.Set: value of type int is not assignable to type int16 [recovered]

happens at

kong/mapper.go

Line 340 in 51a1ea9

target.Set(reflect.ValueOf(v))

Config file path

How to load configuration from the path defined in the CLI/ENV? Do it parse twice?

type Cli struct {
    Config string `type:"path"`
    ...
}

func main() {
    var cli Cli
    _ := kong.Parse(&cli)
    ctx := kong.Parse(&cli, kong.Configuration(kong.JSON, cli.Config))
}

optional branching positional arguments

Since I am unclear how to describe this, I will just show the DSL for the behaviour I would like:

Usage: cli <command>

Commands:
  cmd [<arg> [sub <arg>]]
  cmd sub

I can construct a struct where, ./cli cmd executes cmd other, thus effectively giving me cmd [<arg>]: (both the docs do not show this, and it feels like a hack, is there a better way?)

Usage: cli <command>

Commands:
  cmd other
  cmd <arg>
  cmd sub
var CLI struct {
        Cmd struct{
                Other struct{} `cmd default:"1"`
                Arg struct {
                        Arg string `arg`
                } `arg`
                Sub struct{} `cmd`
        } `cmd`
}

Again trickery with default:"1" gives me ./cli cmd arg which executes cmd <arg>, but it does not document well:

Usage: cli <command>

Commands:
  cmd other
  cmd <arg> other
  cmd <arg> sub [<arg>]
  cmd sub
var CLI struct {
        Cmd struct{
                Other struct{} `cmd default:"1"`
                Arg struct {
                        Arg string `arg`
                        Other struct{} `cmd default:"1"`
                        Sub struct{
                                Arg string `arg optional`
                        } `cmd`
                } `arg`
                Sub struct{} `cmd`
        } `cmd`
}

If there is a better way, I am all ears, otherwise I the following workaround would make the docs read correctly without refactoring the parsing logic:

Usage: cli <command>

Commands:
  cmd                             # this is implied by `default:"1"`
  cmd other                       # I am fine with this being visible, but somebody may want to hide it
  cmd <arg>                       # this is implied by `default"1"`
  cmd <arg> sub [<arg>]
  cmd sub
var CLI struct {
        Cmd struct{
                Other struct{} `cmd default:"1"`
                Arg struct {
                        Arg string `arg`  // with `cmd <arg>` now visible, either this tag
                        Other struct{} `cmd hidden default:"1"`
                        Sub struct{
                                Arg string `arg optional`
                        } `cmd`
                } `arg` // or this one should control visibility
                Sub struct{} `cmd`
        } `cmd`
}

Show used config files (if any)

Hi

Thanks for the cool library. One thing I am missing is, how to show which config file was used (if any).

Something like this would be great:

$ command subcommand
using configuration file: .test.json
...

It would be possible to do that in the Configuration Option like:

func Configuration(loader ConfigurationLoader, showUsedConfigs bool, paths ...string) Option {
        return OptionFunc(func(k *Kong) error {
                k.loader = loader
                for _, path := range paths {
                        resolver, _ := k.LoadConfig(path)
                        if resolver != nil {
                                if showUsedConfigs {
                                        fmt.Fprintf(k.Stderr, "using configuration file: %s\n", path)
                                }
                                k.resolvers = append(k.resolvers, resolver)
                        }
                }
                return nil
        })
}

But there are two problems:

  1. It would break the existing API.
  2. Is also prints the used configs with the --help flag.

Any interests in adding such a feature?

I could also create a custom config file Resolver. I suppose in that case I would be able to get the value of the help flag and there would be no API break.

Show environment variable in help

Discoverability of environment variables is an issue in general. Command-line arguments can probably help with this. It would be great if when you invoke the help (e.g. --help) if the arguments that have associate environment variables could be shown there.

For example, I have this snippet in my struct:

WhiteList  []string `env:"ANONYMIZER_WHITE_LIST" sep:";" help:"List of tags that should be white listed." default:"(0008,103e);(0020,0011)"`

But, when I invoke my command with --help there is no mention of the environment variable:

Flags:
...
      --white-list=(0008,103e);(0020,0011),...
                   List of tags that should be white listed.

What if the output showed something like this for flags with the 'env' property:

Flags:
...
      --white-list=(0008,103e);(0020,0011),...
                   List of tags that should be white listed.
                   Environment variable: ANONYMIZER_WHITE_LIST

Option for full text search across all help

Using the AWS CLI illustrates how useful that would be, as it's basically impossible to discover how to use it unless you already know exactly what you're looking for. Something like a --help[=<foo>] would be excellent.

Combination of `required` and `enum` cause other sub-command failure

For given sample:

package main

import (
	"fmt"

	"github.com/alecthomas/kong"
)

var CLI struct {
	One struct {
		OneArg string `arg:"" required:""`
	} `cmd: ""`
	Two struct {
		TwoArg string `arg:"" enum:"a,b,c" required:""`
	} `cmd: ""`
}

func main() {
	ctx := kong.Parse(&CLI)
	switch cmd := ctx.Command(); cmd {
	case "one <one-arg>", "two <two-arg>":
		fmt.Println("command:", cmd)
	default:
		panic(ctx.Command())
	}
}

I expect the following behaviour:

> go run main.go one X
command: one <one-arg>
> go run main.go two a
command: two <two-arg>

However, I get:

> go run main.go one X          
main: error: <two-arg> must be one of "a","b","c" but got ""
exit status 1
> go run main.go two a
command: two <two-arg>

When I remove the enum tag or replace required with default:"a" in command two, command one behaves as expected.

Set short name for default help flag

Hi Alec,

I was wondering if there is a way to set the short name for the default help flag. I was able to do it by adding the following option after forking your project:

// DefaultHelpShort sets the short name for the default help flag.
func DefaultHelpShort(v rune) Option {
	return OptionFunc(func(k *Kong) error {
		k.postBuildOptions = append(k.postBuildOptions, OptionFunc(func(k *Kong) error {
			k.Model.HelpFlag.Short = v
			return nil
		}))
		return nil
	})
}

Is there a better way to do this that already exists? If not, would you consider adding this functionality?

Thank you.

Is it possible to disable to automatically add envar to help?

Sorry to bother again.

I am writing a custom HelpPrinter but since the latest commit I had to add the following:

newHelp = strings.ReplaceAll(help, "($"+envVar+")", "")

This works, but is error-prone. Should you decide to change the format the above code can break.

Is there a better way to disable that new behavior?

int mapper tests fail on 32-bit systems

On armv7hl and i686 builds (both 32-bit), these tests fail due to constant overflow:

# github.com/alecthomas/kong_test [github.com/alecthomas/kong.test]
./mapper_test.go:287:26: constant 9223372036854775807 overflows int
./mapper_test.go:290:26: constant 4294967295 overflows int
./mapper_test.go:312:16: constant -9223372036854775808 overflows int
FAIL	github.com/alecthomas/kong [build failed]

mapsep tag

Would a pull request for a mapsep tag be accepted? A ; char is very unfortunate since ot terminates the command if you don‘t put it into ‘.

Help Option Exit Code 1

Currently if the the default --help option is used the app returns exit code 1. I personally don't think that someone specifically calling --help should result in an exit code other than 0. Is there a way to change this behavior? I've reviewed the docs and Issues pretty thoroughly and can't find anything.

I'm also open to any rational that presents a good argument for why a program should return an exit code other than 0 for a user (person or automation) specifically calling --help as the only parameter sent to a program.

Default env variables for flags

I'm struggling to understand if there's a way in Kong to enable automatic resolution for flag from environment variables without specifying the env tag on each flag. I've tried playing around with hooks and resolvers but couldn't get it working.

What I want is to be able to pull configuration values from flags, config files and environment variables automatically. Also would be great to be able to specify a prefix for environment variables if needed.

Counter named type doesn't accept arguments

When using counter named type, only the short version is allowed, even though --help shows I should be able to provide an int type value as an argument in the longer flag version as well.

Configuration:

type cli struct {
    Verbosity int `short:"v" type"counter" help:"Set verbosity level."`
}

--help output:

Flags:
      --help                      Show context-sensitive help.
  -v, --verbosity=INT             Set verbosity level.

When I try executing with the longer version:

go run main.go --verbosity=3
main: error: unexpected flag argument "3"
exit status 1

Can’t bind values for interfaces

Given this source:

package main

import (
	"context"
	"fmt"

	"github.com/alecthomas/kong"
)

type Cmd struct {
}

func (Cmd) Run(ctx context.Context) error {
	fmt.Println("ok")
	return nil
}

type Options struct {
	Cmd Cmd `cmd:""`
}

func main() {
	var opts Options
	cli := kong.Parse(&opts)
	ctx := context.TODO()
	cli.FatalIfErrorf(cli.Run(ctx))
}

When I run go run example.go cmd, I get the following error:

example: error: couldn't find binding of type context.Context for parameter 0 of main.Cmd.Run(), use kong.Bind(context.Context)

I can bind values of concrete types, but it doesn’t seem like I can bind interface values. Am I missing something?

(Thanks for making Kong, BTW. Great library.)

`-x` in an `arg` string slice confuses kong

I'm writing a program that takes a bunch of arguments, as well as a shell command as input (interpreted by kong as an arg) and exec's that command after doing a little processing. Unfortunately, kong doesn't deal well with the presence of short arguments given to the command-as-argument confuse kong and it errors. Here's an example:

package main

import (
	"fmt"

	"github.com/alecthomas/kong"
)

var CLI struct {
	Run struct {
		Cmd []string `arg name:"command" help:"Command to run."`
	} `cmd help:"Run command."`
}

func main() {
	ctx := kong.Parse(&CLI)
	switch ctx.Command() {
	case "run <command>":
		fmt.Println(CLI)
	default:
		panic(ctx.Command())
	}
}

Results

A plain command works:

$ go run main.go run ls
{{[ls]}}

A command with flags works after a --:

$ go run main.go run -- ls -la
{{[ls -la]}}

A command with flags is interpreted by kong and errors:

$ go run main.go run ls -la
main: error: unknown flag -l
exit status 1

Expected result

I would have expected kong to stop parsing further arguments once it finds things fitting the terminating argument string slice & treat the command line given above like it does it in the "works after a --" example.

Workaround

Have users pass in the -- flag, but that they can pass the un----escaped command line means if they start out without the escape and then add flags later, the command may fail without them realizing (or expecting) it.

Counter type value.

Is there a simple way to create a counter-like value?

The main idea behind this is to increase verbosity level. For example:

foo -v

or

foo -vvv

Thanks in advance.

default values are ignored when used in Go standard struct tag syntax.

When using the Go standard syntax, the default struct tag is ignored:

var cli struct {
	URL  string `help:"URL of the AMQP server" default:"127.0.0.1:5432"`
        Bind string `kong:"help:'address to bind to',default:'0.0.0.0:9000'"`
}
[...]
	log.Printf("Config: %#v", cli)

results in (indentations by me to enhance readability)

2020/04/26 15:16:18 Config: struct { 
URL string "help:\"URL of the AMQP server\" default:\"127.0.0.1:5432\"";
Bind string "kong:\"help:'address to bind to',default:'0.0.0.0:9000'\"" }
{URL:"127.0.0.1:5432", Bind:""}

In and of itself, it is not much of a problem, one can use the simplified syntax. However, every linter gets a bit crazy about that.

Extend Tag for non-core decoders

From @alecthomas:

We need a solution for non-core decoders, plugins, etc. that need configuration through tags.

For example, the "slice" decoder supports an optional sep=',' parameter, which is currently extracted from tags. Two options I can think of, but if you have any ideas I'd be interested:

  1. Extend Tag to support arbitrary key/value lookups for non-core tags. eg. Tag.Get("sep")
  2. Replace Tag entirely with a generic key/value thing. eg. Tag.GetBool("cmd"), Tag.Get("help"), Tag.GetRune("short"), etc.

Children under hidden parent revealed in help/usage print out

Problem

Children command under a hidden parent is hidden in the root usage print out but revealed in helped text one level above the hidden parent.

Gist to demo the problem

https://gist.github.com/lyonlai/9ba5a40861759612a20ee69d010e0976

Steps to reproduce

  1. compile the file.
  2. run ./main and you should see no database update commands
  3. run ./main database and you will see the intended to be hidden update commands shows up in the print out

Doesn't handle numbers in command names

    Vitess2 vitess2.Commands `cmd hidden:"" help:""`
main: error: unexpected argument vitess2, did you mean "vitess"?

This works:

    NewVitess vitess2.Commands `cmd hidden:"" help:""`

Add default short -h to --help flag, conditionally

Dear Alec,

I noticed that -h is not enabled by default. I would like to suggest to enable it in root command conditionally, if no other command uses the -h shorthand in postBuild. Do you think it is a good idea? If so, I can PR it, just let me know. Or, even simpler: just enable -h shorthand by default - is it not Linux standard?

Shell completions

Would you be open to adding bash and/or zsh completion generation in a manner similar to cobra?

Print usage on input without commands/args/flags

In the scenario of app invocation from terminal without any command/flags

> my-app

I'd expect the same output of:

> my-app --help

Instead, I have the error about the missing command.

my-app: error: expected one of "cmd1", "cmd2"

Is there a way/configuration to achieve my expected outcome?

The closest function I've found is kong.UsageOnError(), except it prints usage help for any error (when for any other type of error I'd expect to just print the specific error).

Default sub-command

Apologies in advance if I'm missing the obvious.

I'm aiming to have a command with subcommands where there is a default subcommand when no subcommand is entered on the command line. The help message for that would look something like this:

cli --help
Commands:
  command        command help
  command sub    sub-command help

cli command --help
Flags:
  --command-opt=STRING    command-opt help. Should NOT be part of sub command.

cli command sub --help
Flags:
  --sub-opt=STRING    sub-opt help. Should ONLY be part of sub command.

I've tried a couple of alternatives:

  1. Create a DefaultCommand with empty name in tag: name:"" (full file).
    This doesn't work and prints:
Commands:
  command default    command help
  command sub        sub help
  1. Command as parent command with Sub as nested command field.
    Here I don't get command command help listed in cli --help and
    the --command-opt appears in cli command sub --help (full file).

  2. Command and Sub as "sibling" commands with Sub name being: command sub (full file).

var cli struct {
	Command CommandCmd `cmd:"" help:"command help"`
	Sub     SubCmd     `cmd:"" help:"sub-command help" name:"sub"`
}

Here I get an error when trying to run cli command sub:
main: error: unexpected argument sub.

Support bare tag parsing

kong:"" tags are good because they are the standard form, but are also quite verbose. We should also support raw tags like so:

type cli struct {
  Flag bool `required help:"A flag."`
  Arg string `arg optional help:"An arg."`
}

The complication here is that the standard Go tag parser only supports tags in the form <key>:"<value>". However, we are in luck because @gak's parser already effectively supports the above form, with some minor enhancements. If we parameterise the separator, the quote character and the assignment character, and allow multiple contiguous separator characters, we'll have a parser that works.

Inside kong:"" parser:

separator=","
quote="'"
assignment=":"

Outside:

separator=" " (space)
quote="\""
assignment="="

No license is specified for Kong?

Hi! It appears that no license information is specified for Kong, with the exception of camelcase.go and levenshtein.go from 3rd-party sources which you carefully documented.

This came to my attention when I used the dh-make-golang tool to create a preliminary Debian package for Kong (for Chroma 0.6.1) and saw the following warning:

2018/12/22 21:49:17 Could not determine license for "github.com/alecthomas/kong":
    GET https://api.github.com/repos/alecthomas/kong/license: 404 Not Found []

Thanks in advance for any clarification!

commandTree unexported

Hi

To experiment I tried to create my own HelpPrinter by copying DefaultHelpPrinter and make some changes.

The Problem I have now, is that CommandTree is unexported. Would a PR accepted to change that?

Positional args before command

I'd like to write a tool similar to pg_ctlcluster which synopsis is:

pg_ctlcluster <VERSION> <CLUSTER> <COMMAND>

where COMMAND can be something lile start, stop, etc...

For some reasons I'd like to have the command in that specific order without flags for neither VERSION nor CLUSTER.

A very naive approach is something like:

var CLI struct {
	Version string `arg`
	Cluster string `arg`
	Start struct {} `cmd`
	Stop struct {} `cmd`
}

Which results to:

panic: can't mix positional arguments and branching arguments on *struct { Version string "arg"; Cluster string "arg"; Start struct {} "cmd"; Stop struct {} "cmd" }

Am I missing something?

command aliases (short commands)

Some flag handling packages allow shortcuts for commands.
I can do it my putting commands double in the parent struct like this, but it is kind of ugly:

type rootCmd struct {
	LongName    longNameCmd        `cmd:"" help:"Do something."`
	X1                 longNameCmd        `cmd:"" name:"ln"`
}

Is there a better way? Should I (try to) make a pull request for an extra tag, or to enable the short tag for commands as well?

Discussion about Help

While I was working on custom HelpPrinter implementation I realized that I had to copy a lot of code from the DefaultHelpPrinter function. And with the newly added interpolation of the $env variable, the current HelpPrinter function is very close to what I was looking for. To close the gap I would like propose the following changes:

1) Better representation of enum values as placeholder

For the following Tags:

StringFlag string `enum:"a,b,c" help:"Help."`

I would like to see the following placeholder:

Flags:
      --string-flag=a|b|c        Help.

And if there is a default tag:

StringFlag string `enum:"a,b,c" help:"Help." default:"b"`

Maybe something like this:

Flags:
      --string-flag=a|(b)|c        Help.

Or maybe even make the selected value bold with github.com/fatih/color.

2) AutomaticEnv option

Add a new Option AutomaticEnv which would do the following:

Visit all flags and args and sets the empty env field tags with the following:

strings.ToUpper(app.Model.Name+"_"+strings.ReplaceAll(flag.Name,"-","_"))

So a flag-name would correspond to APPNAME_FLAG_NAME

Let me know what you think. I am willing to do the implementation if you want.

Factor parsing state into a "ParseContext".

This will hold the state for the parse, which we can then use for not only parsing, but for context-sensitive help, and context-sensitive completion.

For example, if at a subcommand app cmd --help, the parse context would have the cumulative flags, cumulative commands, as well as the current node. This allows help to be context-sensitive, and completion as well.

examples

hi.
Was a fan of kingpin. I know you moved onto kong. Was wondering if you can provide some examples of

  1. how to check if evvironment variables is set
  2. select from set of values

hope this library is as great as kingpin!

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.