-
Notifications
You must be signed in to change notification settings - Fork 440
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 manifestToml(v) function #149
Comments
Is there a formal grammar of it anywhere? |
Oddly enough I don't think they have a finalized grammar, but there is an ABNF description in toml-lang/toml#236. I suppose the canonical specification is in this document: https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.4.0.md, which links to a ton of implementations and a validation suite. |
I've taken a stab at a basic version of this: https://gist.github.com/benley/4fe6d2d354c3ac004de82ab51499eccb It probably still has some weird edge cases, but it works for what I've tried so far. |
Are there any plans to include the gist into the stdlib? |
@flyingmutant We're happy to accept PRs adding this functionality. |
oh hey, I had forgotten all about this. I have some free time and will try to get a PR put together for it in the next couple of days. |
Hey @benley ... so it's been a few days :) Do you need some help with this? I'd love to see this merged. |
I've added support for table arrays. And also fixed But here is the code that worked for me: // Render any jsonnet value (except functions) to TOML format.
local
inlineTable(body) =
"{" +
std.join(", ", ["%s = %s" % [escapeKeyToml(k), renderBody(body[k])] for k in std.objectFields(body)]) +
"}",
renderArray(body) =
local
types = std.set([std.type(x) for x in body]),
// If any of the values are non-integer, we need to force all values to be rendered as floats.
forceFloat = std.foldl(function(result, item) result || (std.floor(item) != item), body, false);
if std.length(types) > 1
then error "TOML Arrays must be uniform-type. Multiple types found: %s" % std.join(", ", types)
else "[" + std.join(", ", [renderBody(x, forceFloat=forceFloat) for x in body]) + "]",
renderBody(body, forceFloat=false) =
if std.type(body) == "object" then inlineTable(body) else
if std.type(body) == "array" then renderArray(body) else
if std.type(body) == "number" && forceFloat then "%f" % body else
if std.type(body) == "number" then body else
if std.type(body) == "string" then escapeStringToml(body) else
if std.type(body) == "boolean" then body else
error "unsupported value for toml: got %s" % std.type(body),
renderItem(k, v) =
["%s = %s" % [escapeKeyToml(k), renderBody(v)]],
renderSection(path, v) =
["[%s]" % std.join(".", std.map(escapeKeyToml, path))] + topTable(v, path=path),
renderSectionArray(path, v) =
local lines = std.flattenArrays([
(["[[%s]]" % std.join(".", std.map(escapeKeyToml, path))] + topTable(s, path=path) + [""])
for s in v
]);
std.slice(lines, 0, std.length(lines) - 1, 1),
topTable(body, path=[]) =
local
nonObjects = std.flattenArrays([renderItem(k, body[k]) for k in std.objectFields(body) if std.type(body[k]) != "object" && (std.type(body[k]) != "array" || std.type(body[k][0]) != "object")]),
objects = std.flattenArrays([renderSection(path + [k], body[k]) for k in std.objectFields(body) if std.type(body[k]) == "object"]),
hasBoth = std.length(nonObjects) > 0 && std.length(objects) > 0,
objectArrays = std.flattenArrays([renderSectionArray(path + [k], body[k]) for k in std.objectFields(body) if std.type(body[k]) == "array" && std.type(body[k][0]) == "object"]);
nonObjects
+ (if hasBoth then [""] else [])
+ objects
+ (if std.length(objectArrays) > 0 && (std.length(nonObjects) > 0 || std.length(objects) > 0) then [""] else [])
+ objectArrays,
escapeKeyToml(str) =
local bare_allowed = std.set(std.stringChars("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-"));
if std.setUnion(std.set(std.stringChars(str)), bare_allowed) == bare_allowed then str else "%s" % escapeStringToml(str),
// JSON string encoding rules are a superset of TOML's - ie. all valid JSON strings are valid TOML strings
// but not vice versa (specifically, TOML only requires escaping control chars U+000, U+001f and U+007f,
// whereas JSON does not allow any control chars). Allowed escapes are the same.
escapeStringToml = std.escapeStringJson;
function(body)
if std.type(body) != "object"
then error "TOML body must be an object. Got %s" % std.type(body)
else std.lines(topTable(body))
|
agh, I'm sorry for dropping the ball on this. I was unemployed for a year and was finding it hard to stay motivated on projects like these. @anyname2, please feel free to take over and finish this if you're so inclined. |
It should be fairly easy to write a TOML output function; the syntax is simple and it maps unambiguously to json objects.
The text was updated successfully, but these errors were encountered: