Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for TOML tables to fftoml package #48

Merged
merged 6 commits into from
Dec 9, 2019

Conversation

GeorgeMac
Copy link
Contributor

This adds support for TOML tables. It does so by concatenating nested keys with the - character.

For example:

[a]
b = "c"

Will set the flag -a-b with the value "c".

var b string
flagset.StringVar(&b, "a-b", "a string")
// ...

This swaps to a different toml parser (namely github.com/pelletier/go-toml), however, upon reflection the BurntSushi version is probably still useable. I can swap to attempt that if that would be more preferrable.

@ChrisHines
Copy link

Consider using a . (period) separator instead of - for nested keys. This would parallel the way the go tool passes args to the testing package (see https://golang.org/cmd/go/#hdr-Testing_flags) and also has precedence in the prior art as implemented by https://godoc.org/github.com/cespare/flagconf#Parse.

@GeorgeMac
Copy link
Contributor Author

I'm totally open to . have any reservations on that @peterbourgon ?

@peterbourgon
Copy link
Owner

I personally never use . in my flag names, but the precedent exists, so I'd love to have it as an option.

@GeorgeMac
Copy link
Contributor Author

@peterbourgon I could have it attempt both? e.g. try . and if that fails try _.
I believe set() returns a sentinel error to denote flag does not exist, is that correct?

@peterbourgon
Copy link
Owner

peterbourgon commented Dec 2, 2019

Interesting. That could definitely work, but it feels a bit too... implicit for my taste. I think I'd rather let users set the separator rune (string?) with a default of . — and let name mismatches fail as usual. Does that seem reasonable? How do you think it's best to parameterize that confit, given the constraints of the Parser definition? Maybe another constructor that takes some functional options like this one and returns a Parser func?

@GeorgeMac
Copy link
Contributor Author

Perhaps an option on the parser itself?

e.g.

package fftoml

func Parser(r io.Reader, set(name, value string) error) error {
    return ParserWith()(r, set)
}

type config struct {
  separator string
}

func FlagSeparator(s string) Option {
    return func(c *config) {
        c.separator = s
    }
}

func ParserWith(opts ...Option) ff.ConfigFileParser {
    config := config{separator: "."}
    for _, opt := range opts {
        opt(&config)
    }

    // ...
}

Then you could do fftoml.ParserWith(fftoml.FlagSeparator("_")) ?

@peterbourgon
Copy link
Owner

Yeah, that's essentially what I had in mind 👍 unless you can think of a nicer API. (A couple of small nits with the example code, but that's better left for review.)

@GeorgeMac
Copy link
Contributor Author

@peterbourgon 👍 I like it. I pushed up that change.

fftoml/fftoml.go Outdated
return ParserWith()(r, set)
}

type config struct {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather see this type as exported, so Config, to avoid having functions in the package's API that operate on unexported types

fftoml/fftoml.go Outdated Show resolved Hide resolved
fftoml/fftoml.go Outdated

// FlagSeparator is an option which configures a separator
// to use when constructing a flag name
func FlagSeparator(s string) Option {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I think this name is too vague. Is there a name for the TOML blocking feature, the thing we're segmenting config information with? I'd prefer something like... BlockSeparator?

Copy link

@ChrisHines ChrisHines Dec 4, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the correct TOML term is a "table" https://github.com/toml-lang/toml#table.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about TableDelimiter(string) ?

fftoml/fftoml.go Outdated
type Option func(*config)

// FlagSeparator is an option which configures a separator
// to use when constructing a flag name
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please make this comment a bit more descriptive, and add a sentence like "The default separator is a period .."

fftoml/fftoml.go Outdated
// By default the returned Parser uses a "." as a separator
func ParserWith(opts ...Option) ff.ConfigFileParser {
return func(r io.Reader, set func(name, value string) error) error {
config := config{separator: "."}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, what do you think about adding a Parse method to the Config struct, matching the ConfigFileParser signature, and returning that? e.g.

func ParserWith(opts ...Option) ff.ConfigFileParser {
    c := Config{
        separator: ".",
    }
    for _, opt := range opts {
        opt(&c)
    }
    return c.Parse
}

Copy link
Contributor Author

@GeorgeMac GeorgeMac Dec 5, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is nice. Does it continue to make sense to call it Config? Perhaps there is a more suitable name. Perhaps ConfigFileParser to match the ff.ConfigFileParser function signature?

fftoml/fftoml_test.go Outdated Show resolved Hide resolved
GeorgeMac and others added 3 commits December 6, 2019 11:44
Restructure call to ff.Parse

Co-Authored-By: Peter Bourgon <peterbourgon@users.noreply.github.com>
@GeorgeMac
Copy link
Contributor Author

@peterbourgon I made some adjustments based on your comments :) What do you think?

Copy link
Owner

@peterbourgon peterbourgon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two very minor things and then I'm happy to merge. Thanks a bunch!

fftoml/fftoml.go Outdated
// used to prefix table names onto keys when constructing
// their associated flag name.
// The default delimeter is "."
func TableDelimeter(d string) Option {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool! Just a minor nit for consistency :)

Suggested change
func TableDelimeter(d string) Option {
func WithTableDelimeter(d string) Option {

fftoml/fftoml.go Outdated
// TableDelimeter is an option which configures a delimeter
// used to prefix table names onto keys when constructing
// their associated flag name.
// The default delimeter is "."
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// The default delimeter is "."
// The default delimeter is "."
//
// For example, given the following TOML
//
// [section.subsection]
// value = 10
//
// Parse will match to a flag with the name `-section.subsection.value` by default.
// If the delimiter is "-", Parse will match to `-section-subsection-value` instead.

@peterbourgon
Copy link
Owner

Oh, oops — it's spelled Delimiter, not Delimeter :)

@GeorgeMac
Copy link
Contributor Author

Ahh good catch 🤦‍♂. Cheers @peterbourgon !

@peterbourgon peterbourgon merged commit c0f6605 into peterbourgon:master Dec 9, 2019
@GeorgeMac GeorgeMac deleted the gm/support-toml-tables branch December 9, 2019 14:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants