Skip to content

TOML lens #91

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

Merged
merged 4 commits into from
Nov 29, 2018
Merged

TOML lens #91

merged 4 commits into from
Nov 29, 2018

Conversation

raphink
Copy link
Member

@raphink raphink commented Mar 6, 2014

TOML was brought to my attention several times recently: https://github.com/mojombo/toml

The attached patchset covers all the examples provided in the docs.

CAVEATS

QUOTES! Bare data types need to be clearly identified in order to force quoting only for values that are not integers, floats, booleans or datetimes… Even then, could a user want a quoted boolean? If so, we'll have to put quotes in the values, which is really ugly…

One way to fix this would be to type values strictly using subnodes for examples:

{ "foo" = "42" { "type" = "integer" } }
{ "bar" = "baz" { "type" = "string" } }

or simply marking them as quoted/bare:

{ "foo" = "bar" { "quoted" } }

or

{ "foo" = "true" { "bare" } }

@raphink raphink self-assigned this Mar 1, 2014
@tlimoncelli
Copy link

Any update on this? I think a TOML parser would be very useful. Plus, I think the TOML project would benefit from having a lens because it assures that the language is regular.

@raphink
Copy link
Member Author

raphink commented May 19, 2015

@tlimoncelli do you have an opinion on the possible implementation choices outlined above?

@raphink raphink force-pushed the dev/toml branch 2 times, most recently from 1ae2414 to e890a47 Compare May 19, 2015 20:06
@tlimoncelli
Copy link

I guess the decision comes down to: should the subnodes reflect the TOML standard, which says that each value has a type; or should it reflect how it is formatted (quoted or bare).

IMHO either is fine. I think the quoted/bare is sufficient; recording the type also works but seems to add detail that isn't used. Implement whatever is easiest.

I would make sure a tests that include:

foo = "false"
bar = "true"

as well as

foo = false
bar = true

There should also be a tests that set the value (to the string and to the boolean).

I do have a concern that the subnode could be confused with actual data if someone were to iterate over the data. Is that a possibility?

Does any other lens use this technique of creating subnotes to store metadata?

@raphink
Copy link
Member Author

raphink commented May 20, 2015

@tlimoncelli I currently have no use for that lens, but I'm willing to get it in shape. The current implementation parses the string and boolean values the same way. What would you suggest as a tree to keep the TOML functionalities?

@tlimoncelli
Copy link

I'm not entirely sure I understand the question but that rarely prevents me from answering :-)

At a high level the request is that the lens should retain quotes (or lack of quotes) when it parses foo = "true" or bar = true. The first is a string value, the second is a boolean.

Of the implementation proposals listed above, I think the best is to add subnodes that indicate whether the element was quoted or not. For example this file:

foo = "true"
bar = true

should create this tree:

{ "foo" = "true" { "quoted" } }
{ "bar" = "true" { "bare" } }

@raphink
Copy link
Member Author

raphink commented Jun 12, 2015

@tlimoncelli I see the issue. The tree should definitely denote the typing.

@tlimoncelli
Copy link

It has dawned on me that instead of "quoted" and "bare", better words might be "string" and "boolean".

{ "foo" = "true" { "string" } }
{ "bar" = "true" { "boolean" } }

@tlimoncelli
Copy link

Any update?

@raphink
Copy link
Member Author

raphink commented Aug 25, 2015

@tlimoncelli sorry, haven't looked at it for some time.

@raphink
Copy link
Member Author

raphink commented Aug 25, 2015

The thing with "string"/"boolean" is that it only fixes the issue for booleans, not general quoting.

@raphink
Copy link
Member Author

raphink commented Aug 26, 2015

I've just played around a little. If we want to reflect the typing, we will have to make a lens with a complex tree like Json.lns to avoid ambiguities.

@descrepes
Copy link

Hi,

I just play around with that lens but got some issues.
Here is the scenario with the "TOML Example" file :
(Just tried to modify the title)

augtool -A -t 'Toml incl /root/test.toml'
augtool> print /files/root/test.toml                                              
/files/root/test.toml
/files/root/test.toml/#comment = "This is a TOML document."
/files/root/test.toml/title = "TOML Example"
/files/root/test.toml/@table[1] = "owner"
/files/root/test.toml/@table[1]/name = "Tom Preston-Werner"
/files/root/test.toml/@table[1]/dob = "1979-05-27T07:32:00-08:00"
/files/root/test.toml/@table[1]/dob/#comment = "First class dates"
/files/root/test.toml/@table[2] = "database"
/files/root/test.toml/@table[2]/server = "192.168.1.1"
/files/root/test.toml/@table[2]/ports
/files/root/test.toml/@table[2]/ports/elem[1] = "8001"
/files/root/test.toml/@table[2]/ports/elem[2] = "8001"
/files/root/test.toml/@table[2]/ports/elem[3] = "8002"
/files/root/test.toml/@table[2]/connection_max = "5000"
/files/root/test.toml/@table[2]/enabled = "true"
/files/root/test.toml/@table[3] = "servers"
/files/root/test.toml/@table[3]/#comment = "Indentation (tabs and/or spaces) is allowed but not required"
/files/root/test.toml/@table[4] = "servers.alpha"
/files/root/test.toml/@table[4]/ip = "10.0.0.1"
/files/root/test.toml/@table[4]/dc = "eqdc10"
/files/root/test.toml/@table[5] = "servers.beta"
/files/root/test.toml/@table[5]/ip = "10.0.0.2"
/files/root/test.toml/@table[5]/dc = "eqdc10"
/files/root/test.toml/@table[6] = "clients"
/files/root/test.toml/@table[6]/data
/files/root/test.toml/@table[6]/data/elem[1]
/files/root/test.toml/@table[6]/data/elem[1]/elem[1] = "gamma"
/files/root/test.toml/@table[6]/data/elem[1]/elem[2] = "delta"
/files/root/test.toml/@table[6]/data/elem[2]
/files/root/test.toml/@table[6]/data/elem[2]/elem[1] = "1"
/files/root/test.toml/@table[6]/data/elem[2]/elem[2] = "2"
/files/root/test.toml/@table[6]/#comment = "Line breaks are OK when inside arrays"
/files/root/test.toml/@table[6]/hosts
/files/root/test.toml/@table[6]/hosts/elem[1] = "alpha"
/files/root/test.toml/@table[6]/hosts/elem[2] = "omega"
augtool> set /files/root/test.toml/title "totototot"
augtool> print /files/root/test.toml                                              
/files/root/test.toml
/files/root/test.toml/#comment = "This is a TOML document."
/files/root/test.toml/title = "totototot"
/files/root/test.toml/@table[1] = "owner"
/files/root/test.toml/@table[1]/name = "Tom Preston-Werner"
/files/root/test.toml/@table[1]/dob = "1979-05-27T07:32:00-08:00"
/files/root/test.toml/@table[1]/dob/#comment = "First class dates"
/files/root/test.toml/@table[2] = "database"
/files/root/test.toml/@table[2]/server = "192.168.1.1"
/files/root/test.toml/@table[2]/ports
/files/root/test.toml/@table[2]/ports/elem[1] = "8001"
/files/root/test.toml/@table[2]/ports/elem[2] = "8001"
/files/root/test.toml/@table[2]/ports/elem[3] = "8002"
/files/root/test.toml/@table[2]/connection_max = "5000"
/files/root/test.toml/@table[2]/enabled = "true"
/files/root/test.toml/@table[3] = "servers"
/files/root/test.toml/@table[3]/#comment = "Indentation (tabs and/or spaces) is allowed but not required"
/files/root/test.toml/@table[4] = "servers.alpha"
/files/root/test.toml/@table[4]/ip = "10.0.0.1"
/files/root/test.toml/@table[4]/dc = "eqdc10"
/files/root/test.toml/@table[5] = "servers.beta"
/files/root/test.toml/@table[5]/ip = "10.0.0.2"
/files/root/test.toml/@table[5]/dc = "eqdc10"
/files/root/test.toml/@table[6] = "clients"
/files/root/test.toml/@table[6]/data
/files/root/test.toml/@table[6]/data/elem[1]
/files/root/test.toml/@table[6]/data/elem[1]/elem[1] = "gamma"
/files/root/test.toml/@table[6]/data/elem[1]/elem[2] = "delta"
/files/root/test.toml/@table[6]/data/elem[2]
/files/root/test.toml/@table[6]/data/elem[2]/elem[1] = "1"
/files/root/test.toml/@table[6]/data/elem[2]/elem[2] = "2"
/files/root/test.toml/@table[6]/#comment = "Line breaks are OK when inside arrays"
/files/root/test.toml/@table[6]/hosts
/files/root/test.toml/@table[6]/hosts/elem[1] = "alpha"
/files/root/test.toml/@table[6]/hosts/elem[2] = "omega"
augtool> save
error: Failed to execute command
saving failed (run 'print /augeas//error' for details)
augtool> print /augeas//error
/augeas/files/root/test.toml/error = "put_failed"
/augeas/files/root/test.toml/error/path = "/files/root/test.toml"
/augeas/files/root/test.toml/error/lens = "/usr/share/augeas/lenses/dist/toml.aug:95.10-.45:"
/augeas/files/root/test.toml/error/message = "Failed to match \n    ({ /[A-Za-z][.0-9A-Z_a-z-]+/ = /([^]\\001-\\004\\t\\n\\r \"#,[](([^]\\001-\\004\\r#,=[]+)*[^]\\001-\\004\\t\\n\\r \"#,[])?)/ } | { /[A-Za-z][.0-9A-Z_a-z-]+/ = /([^]\\001-\\004\\n\\r\"[]*#+[^]\\001-\\004\\n\\r\"[]*)/ } | { /[A-Za-z][.0-9A-Z_a-z-]+/ } | { } | { /#comment/ = /[^\\001-\\004\\t\\n\\r ][^\\001-\\004\\n]*[^\\001-\\004\\t\\n\\r ]|[^\\001-\\004\\t\\n\\r ]/ })*({ /@table/ = /[^]\\001-\\004\\n\\r.]+(\\\\.[^]\\001-\\004\\n\\r.]+)*/ } | { /@@table/ = /[^]\\001-\\004\\n\\r.]+(\\\\.[^]\\001-\\004\\n\\r.]+)*/ })*\n  with tree\n    { \"#comment\" = \"This is a TOML document.\" } {  } { \"title\" = \"totototot\" } {  } { \"@table\" = \"owner\" } { \"@table\" = \"database\" } { \"@table\" = \"servers\" } { \"@table\" = \"servers.alpha\" } { \"@table\" = \"servers.beta\" } { \"@table\" = \"clients\" }"

I'm using augeas 1.2.

Any ideas ?

Thx a lot :)

@jrabbit
Copy link

jrabbit commented Aug 20, 2016

any update on this?

@flyinbutrs
Copy link

Any movement on this? @raphink?

@raphink
Copy link
Member Author

raphink commented Mar 13, 2017

@jrabbit @flyinbutrs no, I haven't had a use for this (although I do use TOML in other contexts). If someone wants to work on it, I'd welcome patches.

TODO: inline tables
@raphink
Copy link
Member Author

raphink commented Oct 16, 2018

@tlimoncelli @descrepes @jrabbit @flyinbutrs I've just restarted work on this, using the Json (fully typed) approach. Afaik it's only missing inline table support and quotes/dots on keys 🤢, so testing/feedback is most welcome!

@lutter
Copy link
Member

lutter commented Oct 18, 2018

Is this enough to parse your typical Cargo.toml ? If so, I'd be all for committing this now and refining it later.

@raphink
Copy link
Member Author

raphink commented Oct 18, 2018

Do you have a full example @lutter?

@raphink
Copy link
Member Author

raphink commented Oct 19, 2018

At least https://github.com/slog-rs/example-lib/blob/master/Cargo.toml parses properly:

$ augtool -At "Toml.lns incl /tmp/cargo.toml" -I lenses/ print /files
/files
/files/tmp
/files/tmp/cargo.toml
/files/tmp/cargo.toml/table[1] = "package"
/files/tmp/cargo.toml/table[1]/entry[1] = "name"
/files/tmp/cargo.toml/table[1]/entry[1]/string = "slog-example-lib"
/files/tmp/cargo.toml/table[1]/entry[2] = "version"
/files/tmp/cargo.toml/table[1]/entry[2]/string = "0.3.0"
/files/tmp/cargo.toml/table[1]/entry[3] = "authors"
/files/tmp/cargo.toml/table[1]/entry[3]/array
/files/tmp/cargo.toml/table[1]/entry[3]/array/string = "Dawid Ci\304\231\305\274arkiewicz <[email protected]>"
/files/tmp/cargo.toml/table[1]/entry[4] = "description"
/files/tmp/cargo.toml/table[1]/entry[4]/string = "Example of a library utilizing slog-rs"
/files/tmp/cargo.toml/table[1]/entry[5] = "keywords"
/files/tmp/cargo.toml/table[1]/entry[5]/array
/files/tmp/cargo.toml/table[1]/entry[5]/array/string[1] = "log"
/files/tmp/cargo.toml/table[1]/entry[5]/array/string[2] = "logging"
/files/tmp/cargo.toml/table[1]/entry[5]/array/string[3] = "structured"
/files/tmp/cargo.toml/table[1]/entry[5]/array/string[4] = "hierarchical"
/files/tmp/cargo.toml/table[1]/entry[5]/array/string[5] = "example"
/files/tmp/cargo.toml/table[1]/entry[6] = "license"
/files/tmp/cargo.toml/table[1]/entry[6]/string = "MPL-2.0"
/files/tmp/cargo.toml/table[1]/entry[7] = "documentation"
/files/tmp/cargo.toml/table[1]/entry[7]/string = "https://dpc.github.io/slog-rs/"
/files/tmp/cargo.toml/table[1]/entry[8] = "homepage"
/files/tmp/cargo.toml/table[1]/entry[8]/string = "https://github.com/dpc/slog-rs"
/files/tmp/cargo.toml/table[1]/entry[9] = "repository"
/files/tmp/cargo.toml/table[1]/entry[9]/string = "https://github.com/dpc/slog-rs"
/files/tmp/cargo.toml/table[1]/entry[10] = "readme"
/files/tmp/cargo.toml/table[1]/entry[10]/string = "README.md"
/files/tmp/cargo.toml/table[2] = "lib"
/files/tmp/cargo.toml/table[2]/entry = "path"
/files/tmp/cargo.toml/table[2]/entry/string = "lib.rs"
/files/tmp/cargo.toml/table[3] = "dependencies"
/files/tmp/cargo.toml/table[3]/entry[1] = "slog"
/files/tmp/cargo.toml/table[3]/entry[1]/string = "2"
/files/tmp/cargo.toml/table[3]/entry[2] = "slog-stdlog"
/files/tmp/cargo.toml/table[3]/entry[2]/string = "3"
/files/tmp/cargo.toml/table[4] = "dev-dependencies"
/files/tmp/cargo.toml/table[4]/entry[1] = "env_logger"
/files/tmp/cargo.toml/table[4]/entry[1]/string = "0.3.5"
/files/tmp/cargo.toml/table[4]/entry[2] = "slog-term"
/files/tmp/cargo.toml/table[4]/entry[2]/string = "2"
/files/tmp/cargo.toml/table[4]/entry[3] = "slog-async"
/files/tmp/cargo.toml/table[4]/entry[3]/string = "2"

@raphink
Copy link
Member Author

raphink commented Oct 19, 2018

Note: in principle, arrays don't allow mixing types for elements (I don't really see why btw), but this lens allows it.

@raphink
Copy link
Member Author

raphink commented Nov 9, 2018

@lutter do you want to merge this as is?

@raphink
Copy link
Member Author

raphink commented Nov 29, 2018

I'll just merge as it is.

@raphink raphink merged commit 5e1cd31 into hercules-team:master Nov 29, 2018
@lutter
Copy link
Member

lutter commented Nov 29, 2018

Thanks for doing that ! THat's what I've been meaning to do, too.

@raphink
Copy link
Member Author

raphink commented Nov 30, 2018

There's still a few details to fix imo, I'll try to run it on as many TOML files as possible and open issues.

georgehansper added a commit that referenced this pull request May 6, 2022
* fix(lens): toml: add write support

The toml lens fails to save simple toml files due to problems with multi
dimensional (>2) arrays.
Therefore disable arrays with more than 2 dimensions for now to enable
basic usage again.

This commit fixes issue #715 by applying the suggested workaround. If
anyone can come up with a better solution please feel free to do so.

Fixes: 5e1cd31 (TOML lens (#91), 2018-11-29)
Signed-off-by: Richard Leitner <[email protected]>

* fix(lens): toml: update reference link

toml.io now provides a versioned reference URL, therefore use this
instead of the old GitHub repo link.

Signed-off-by: Richard Leitner <[email protected]>

* fix(lens): toml: typo in About: License

Signed-off-by: Richard Leitner <[email protected]>

* test(lens): toml: add basic write

This test covers the bug described in issue #715.

Signed-off-by: Richard Leitner <[email protected]>

* test(lens): toml: fix "array of arrays"

The "Test: Toml.array_norec; Array of arrays" tested a 3 dimensional
array. This commit fixes the test to actually test a 2 dimensional
array.

More than 2 dimensional arrays are currently not supported due to
issue #715.

Signed-off-by: Richard Leitner <[email protected]>

Co-authored-by: George Hansper <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants