mirror of
https://github.com/status-im/NimYAML.git
synced 2025-01-12 04:24:16 +00:00
Improved presenter.
* added maxLineLength to PresentationOptions. Fixes #119 * write a newline to the end of the document. required for the output files to be POSIX-compliant text files. also improves QoL when dumping to stdout.
This commit is contained in:
parent
a5552a1a18
commit
5f7677d914
12
flake.lock
generated
12
flake.lock
generated
@ -2,11 +2,11 @@
|
||||
"nodes": {
|
||||
"nix-filter": {
|
||||
"locked": {
|
||||
"lastModified": 1653590866,
|
||||
"narHash": "sha256-E4yKIrt/S//WfW5D9IhQ1dVuaAy8RE7EiCMfnbrOC78=",
|
||||
"lastModified": 1661201956,
|
||||
"narHash": "sha256-RizGJH/buaw9A2+fiBf9WnXYw4LZABB5kMAZIEE5/T8=",
|
||||
"owner": "numtide",
|
||||
"repo": "nix-filter",
|
||||
"rev": "3e81a637cdf9f6e9b39aeb4d6e6394d1ad158e16",
|
||||
"rev": "3b821578685d661a10b563cba30b1861eec05748",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@ -40,11 +40,11 @@
|
||||
},
|
||||
"utils": {
|
||||
"locked": {
|
||||
"lastModified": 1653893745,
|
||||
"narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=",
|
||||
"lastModified": 1659877975,
|
||||
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1",
|
||||
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -147,7 +147,7 @@ suite "Serialization":
|
||||
test "Dump integer without fixed length":
|
||||
var input = -4247
|
||||
var output = dump(input, tsNone, asTidy, blockOnly)
|
||||
assertStringEqual yamlDirs & "\n\"-4247\"", output
|
||||
assertStringEqual yamlDirs & "\n\"-4247\"\n", output
|
||||
|
||||
when sizeof(int) == sizeof(int64):
|
||||
input = int(int32.high) + 1
|
||||
@ -232,7 +232,7 @@ suite "Serialization":
|
||||
test "Dump string sequence":
|
||||
var input = @["a", "b"]
|
||||
var output = dump(input, tsNone, asTidy, blockOnly)
|
||||
assertStringEqual yamlDirs & "\n- a\n- b", output
|
||||
assertStringEqual yamlDirs & "\n- a\n- b\n", output
|
||||
|
||||
test "Load char set":
|
||||
let input = "- a\n- b"
|
||||
@ -245,7 +245,7 @@ suite "Serialization":
|
||||
test "Dump char set":
|
||||
var input = {'a', 'b'}
|
||||
var output = dump(input, tsNone, asTidy, blockOnly)
|
||||
assertStringEqual yamlDirs & "\n- a\n- b", output
|
||||
assertStringEqual yamlDirs & "\n- a\n- b\n", output
|
||||
|
||||
test "Load array":
|
||||
let input = "- 23\n- 42\n- 47"
|
||||
@ -258,7 +258,7 @@ suite "Serialization":
|
||||
test "Dump array":
|
||||
let input = [23'i32, 42'i32, 47'i32]
|
||||
var output = dump(input, tsNone, asTidy, blockOnly)
|
||||
assertStringEqual yamlDirs & "\n- 23\n- 42\n- 47", output
|
||||
assertStringEqual yamlDirs & "\n- 23\n- 42\n- 47\n", output
|
||||
|
||||
test "Load Option":
|
||||
let input = "- Some\n- !!null ~"
|
||||
@ -271,7 +271,7 @@ suite "Serialization":
|
||||
test "Dump Option":
|
||||
let input = [none(int32), some(42'i32), none(int32)]
|
||||
let output = dump(input, tsNone, asTidy, blockOnly)
|
||||
assertStringEqual yamlDirs & "\n- !!null ~\n- 42\n- !!null ~", output
|
||||
assertStringEqual yamlDirs & "\n- !!null ~\n- 42\n- !!null ~\n", output
|
||||
|
||||
test "Load Table[int, string]":
|
||||
let input = "23: dreiundzwanzig\n42: zweiundvierzig"
|
||||
@ -286,7 +286,7 @@ suite "Serialization":
|
||||
input[23] = "dreiundzwanzig"
|
||||
input[42] = "zweiundvierzig"
|
||||
var output = dump(input, tsNone, asTidy, blockOnly)
|
||||
assertStringEqual(yamlDirs & "\n23: dreiundzwanzig\n42: zweiundvierzig",
|
||||
assertStringEqual(yamlDirs & "\n23: dreiundzwanzig\n42: zweiundvierzig\n",
|
||||
output)
|
||||
|
||||
test "Load OrderedTable[tuple[int32, int32], string]":
|
||||
@ -321,7 +321,7 @@ suite "Serialization":
|
||||
" ? \n" &
|
||||
" a: 13\n" &
|
||||
" b: 47\n" &
|
||||
" : dreizehnsiebenundvierzig", output)
|
||||
" : dreizehnsiebenundvierzig\n", output)
|
||||
|
||||
test "Load Sequences in Sequence":
|
||||
let input = " - [1, 2, 3]\n - [4, 5]\n - [6]"
|
||||
@ -335,7 +335,7 @@ suite "Serialization":
|
||||
test "Dump Sequences in Sequence":
|
||||
let input = @[@[1.int32, 2.int32, 3.int32], @[4.int32, 5.int32], @[6.int32]]
|
||||
var output = dump(input, tsNone)
|
||||
assertStringEqual yamlDirs & "\n- [1, 2, 3]\n- [4, 5]\n- [6]", output
|
||||
assertStringEqual yamlDirs & "\n- [1, 2, 3]\n- [4, 5]\n- [6]\n", output
|
||||
|
||||
test "Load Enum":
|
||||
let input =
|
||||
@ -350,7 +350,7 @@ suite "Serialization":
|
||||
test "Dump Enum":
|
||||
let input = @[tlRed, tlGreen, tlYellow]
|
||||
var output = dump(input, tsNone, asTidy, blockOnly)
|
||||
assertStringEqual yamlDirs & "\n- tlRed\n- tlGreen\n- tlYellow", output
|
||||
assertStringEqual yamlDirs & "\n- tlRed\n- tlGreen\n- tlYellow\n", output
|
||||
|
||||
test "Load Tuple":
|
||||
let input = "str: value\ni: 42\nb: true"
|
||||
@ -363,7 +363,7 @@ suite "Serialization":
|
||||
test "Dump Tuple":
|
||||
let input = (str: "value", i: 42.int32, b: true)
|
||||
var output = dump(input, tsNone)
|
||||
assertStringEqual yamlDirs & "\nstr: value\ni: 42\nb: true", output
|
||||
assertStringEqual yamlDirs & "\nstr: value\ni: 42\nb: true\n", output
|
||||
|
||||
test "Load Tuple - unknown field":
|
||||
let input = "str: value\nfoo: bar\ni: 42\nb: true"
|
||||
@ -410,7 +410,7 @@ suite "Serialization":
|
||||
let input = Person(firstnamechar: 'P', surname: "Pan", age: 12)
|
||||
var output = dump(input, tsNone, asTidy, blockOnly)
|
||||
assertStringEqual(yamlDirs &
|
||||
"\nfirstnamechar: P\nsurname: Pan\nage: 12", output)
|
||||
"\nfirstnamechar: P\nsurname: Pan\nage: 12\n", output)
|
||||
|
||||
test "Load custom object - unknown field":
|
||||
let input = " firstnamechar: P\n surname: Pan\n age: 12\n occupation: free"
|
||||
@ -442,7 +442,7 @@ suite "Serialization":
|
||||
let input = @["one", "two"]
|
||||
var output = dump(input, tsAll, asTidy, blockOnly)
|
||||
assertStringEqual(yamlDirs & "!n!system:seq(" &
|
||||
"tag:yaml.org;2002:str) \n- !!str one\n- !!str two", output)
|
||||
"tag:yaml.org;2002:str) \n- !!str one\n- !!str two\n", output)
|
||||
|
||||
test "Load custom object with explicit root tag":
|
||||
let input =
|
||||
@ -457,7 +457,7 @@ suite "Serialization":
|
||||
let input = Person(firstnamechar: 'P', surname: "Pan", age: 12)
|
||||
var output = dump(input, tsRootOnly, asTidy, blockOnly)
|
||||
assertStringEqual(yamlDirs &
|
||||
"!n!custom:Person \nfirstnamechar: P\nsurname: Pan\nage: 12", output)
|
||||
"!n!custom:Person \nfirstnamechar: P\nsurname: Pan\nage: 12\n", output)
|
||||
|
||||
test "Load custom variant object":
|
||||
let input =
|
||||
@ -491,7 +491,7 @@ suite "Serialization":
|
||||
" - \n" &
|
||||
" kind: akDog\n" &
|
||||
" - \n" &
|
||||
" barkometer: 13", output
|
||||
" barkometer: 13\n", output
|
||||
|
||||
test "Load custom variant object - missing field":
|
||||
let input = "[{name: Bastet}, {kind: akCat}]"
|
||||
@ -517,7 +517,7 @@ suite "Serialization":
|
||||
test "Dump non-variant object with transient fields":
|
||||
let input = NonVariantWithTransient(a: "a", b: "b", c: "c", d: "d")
|
||||
let output = dump(input, tsNone, asTidy, blockOnly)
|
||||
assertStringEqual yamlDirs & "\nb: b\nd: d", output
|
||||
assertStringEqual yamlDirs & "\nb: b\nd: d\n", output
|
||||
|
||||
test "Load variant object with transient fields":
|
||||
let input = "[[gStorable: gs, kind: deA, cStorable: cs], [gStorable: a, kind: deC]]"
|
||||
@ -554,7 +554,7 @@ suite "Serialization":
|
||||
" - \n" &
|
||||
" gStorable: a\n" &
|
||||
" - \n" &
|
||||
" kind: deC", output
|
||||
" kind: deC\n", output
|
||||
|
||||
test "Load object with ignored key":
|
||||
let input = "[{x: 1, y: 2}, {x: 3, z: 4, y: 5}, {z: [1, 2, 3], x: 4, y: 5}]"
|
||||
@ -590,7 +590,7 @@ suite "Serialization":
|
||||
" value: b\n" &
|
||||
" next: \n" &
|
||||
" value: c\n" &
|
||||
" next: *a", output
|
||||
" next: *a\n", output
|
||||
|
||||
test "Load cyclic data structure":
|
||||
let input = yamlDirs & """!n!system:seq(example.net:Node)
|
||||
@ -652,4 +652,4 @@ suite "Serialization":
|
||||
assertStringEqual yamlDirs & "!n!system:seq(test:BetterInt) \n" &
|
||||
"- !test:BetterInt 1\n" &
|
||||
"- !test:BetterInt 9_998_887\n" &
|
||||
"- !test:BetterInt 98_312", output
|
||||
"- !test:BetterInt 98_312\n", output
|
||||
|
@ -10,7 +10,7 @@
|
||||
##
|
||||
## This is the presenter API, used for generating YAML character streams.
|
||||
|
||||
import streams, deques, strutils
|
||||
import std / [streams, deques, strutils, options]
|
||||
import data, taglib, stream, private/internal, hints, parser
|
||||
|
||||
type
|
||||
@ -85,6 +85,7 @@ type
|
||||
indentationStep*: int
|
||||
newlines*: NewLineStyle
|
||||
outputVersion*: OutputYamlVersion
|
||||
maxLineLength*: Option[int]
|
||||
|
||||
YamlPresenterJsonError* = object of ValueError
|
||||
## Exception that may be raised by the YAML presenter when it is
|
||||
@ -116,17 +117,19 @@ type
|
||||
const
|
||||
defaultPresentationOptions* =
|
||||
PresentationOptions(style: psDefault, indentationStep: 2,
|
||||
newlines: nlOSDefault)
|
||||
newlines: nlOSDefault, maxLineLength: some(80))
|
||||
|
||||
proc defineOptions*(style: PresentationStyle = psDefault,
|
||||
indentationStep: int = 2,
|
||||
newlines: NewLineStyle = nlOSDefault,
|
||||
outputVersion: OutputYamlVersion = ov1_2):
|
||||
outputVersion: OutputYamlVersion = ov1_2,
|
||||
maxLineLength: Option[int] = some(80)):
|
||||
PresentationOptions {.raises: [].} =
|
||||
## Define a set of options for presentation. Convenience proc that requires
|
||||
## you to only set those values that should not equal the default.
|
||||
PresentationOptions(style: style, indentationStep: indentationStep,
|
||||
newlines: newlines, outputVersion: outputVersion)
|
||||
newlines: newlines, outputVersion: outputVersion,
|
||||
maxLineLength: maxLineLength)
|
||||
|
||||
proc state(c: Context): DumperState = c.levels[^1]
|
||||
|
||||
@ -147,7 +150,8 @@ proc searchHandle(c: Context, tag: string):
|
||||
result.handle = item.handle
|
||||
|
||||
proc inspect(scalar: string, indentation: int,
|
||||
words, lines: var seq[tuple[start, finish: int]]):
|
||||
words, lines: var seq[tuple[start, finish: int]],
|
||||
lineLength: Option[int]):
|
||||
ScalarStyle {.raises: [].} =
|
||||
var
|
||||
inLine = false
|
||||
@ -177,7 +181,8 @@ proc inspect(scalar: string, indentation: int,
|
||||
of '\l':
|
||||
canUsePlain = false # we don't use multiline plain scalars
|
||||
curWord.finish = i - 1
|
||||
if curWord.finish - curWord.start + 1 > 80 - indentation:
|
||||
if lineLength.isSome and
|
||||
curWord.finish - curWord.start + 1 > lineLength.get() - indentation:
|
||||
return if canUsePlain: sPlain else: sDoubleQuoted
|
||||
words.add(curWord)
|
||||
inWord = false
|
||||
@ -186,7 +191,8 @@ proc inspect(scalar: string, indentation: int,
|
||||
if not inLine: curLine.start = i
|
||||
inLine = false
|
||||
curLine.finish = i - 1
|
||||
if curLine.finish - curLine.start + 1 > 80 - indentation:
|
||||
if lineLength.isSome and
|
||||
curLine.finish - curLine.start + 1 > lineLength.get() - indentation:
|
||||
canUseLiteral = false
|
||||
lines.add(curLine)
|
||||
else:
|
||||
@ -197,7 +203,8 @@ proc inspect(scalar: string, indentation: int,
|
||||
inLine = true
|
||||
if not inWord:
|
||||
if not multipleSpaces:
|
||||
if curWord.finish - curWord.start + 1 > 80 - indentation:
|
||||
if lineLength.isSome and
|
||||
curWord.finish - curWord.start + 1 > lineLength.get() - indentation:
|
||||
return if canUsePlain: sPlain else: sDoubleQuoted
|
||||
words.add(curWord)
|
||||
curWord.start = i
|
||||
@ -205,15 +212,17 @@ proc inspect(scalar: string, indentation: int,
|
||||
multipleSpaces = false
|
||||
if inWord:
|
||||
curWord.finish = scalar.len - 1
|
||||
if curWord.finish - curWord.start + 1 > 80 - indentation:
|
||||
if lineLength.isSome and
|
||||
curWord.finish - curWord.start + 1 > lineLength.get() - indentation:
|
||||
return if canUsePlain: sPlain else: sDoubleQuoted
|
||||
words.add(curWord)
|
||||
if inLine:
|
||||
curLine.finish = scalar.len - 1
|
||||
if curLine.finish - curLine.start + 1 > 80 - indentation:
|
||||
if lineLength.isSome and
|
||||
curLine.finish - curLine.start + 1 > lineLength.get() - indentation:
|
||||
canUseLiteral = false
|
||||
lines.add(curLine)
|
||||
if scalar.len <= 80 - indentation:
|
||||
if lineLength.isNone or scalar.len <= lineLength.get() - indentation:
|
||||
result = if canUsePlain: sPlain else: sDoubleQuoted
|
||||
elif canUseLiteral: result = sLiteral
|
||||
elif canUseFolded: result = sFolded
|
||||
@ -227,7 +236,7 @@ template append(target: ptr[string], val: string | char) =
|
||||
target[].add(val)
|
||||
|
||||
proc writeDoubleQuoted(c: Context, scalar: string, indentation: int,
|
||||
newline: string)
|
||||
newline: string, lineLength: Option[int])
|
||||
{.raises: [YamlPresenterOutputError].} =
|
||||
var curPos = indentation
|
||||
let t = c.target
|
||||
@ -235,7 +244,7 @@ proc writeDoubleQuoted(c: Context, scalar: string, indentation: int,
|
||||
t.append('"')
|
||||
curPos.inc()
|
||||
for c in scalar:
|
||||
if curPos == 79:
|
||||
if lineLength.isSome and curPos == lineLength.get() - 1:
|
||||
t.append('\\')
|
||||
t.append(newline)
|
||||
t.append(repeat(' ', indentation))
|
||||
@ -316,17 +325,19 @@ proc writeFolded(c: Context, scalar: string, indentation, indentStep: int,
|
||||
newline: string)
|
||||
{.raises: [YamlPresenterOutputError].} =
|
||||
let t = c.target
|
||||
let lineLength = (
|
||||
if c.options.maxLineLength.isSome: c.options.maxLineLength.get() else: 1024)
|
||||
try:
|
||||
t.append(">")
|
||||
if scalar[^1] != '\l': t.append('-')
|
||||
if scalar[0] in [' ', '\t']: t.append($indentStep)
|
||||
var curPos = 80
|
||||
var curPos = lineLength
|
||||
for word in words:
|
||||
if word.start > 0 and scalar[word.start - 1] == '\l':
|
||||
t.append(newline & newline)
|
||||
t.append(repeat(' ', indentation + indentStep))
|
||||
curPos = indentation + indentStep
|
||||
elif curPos + (word.finish - word.start + 1) > 80:
|
||||
elif curPos + (word.finish - word.start + 1) > lineLength:
|
||||
t.append(newline)
|
||||
t.append(repeat(' ', indentation + indentStep))
|
||||
curPos = indentation + indentStep
|
||||
@ -528,18 +539,21 @@ proc doPresent(c: var Context, s: var YamlStream) =
|
||||
else: c.writeDoubleQuotedJson(item.scalarContent)
|
||||
elif c.options.style == psCanonical:
|
||||
c.writeDoubleQuoted(item.scalarContent,
|
||||
indentation + c.options.indentationStep, newline)
|
||||
indentation + c.options.indentationStep, newline,
|
||||
c.options.maxLineLength)
|
||||
else:
|
||||
var words, lines = newSeq[tuple[start, finish: int]]()
|
||||
case item.scalarContent.inspect(
|
||||
indentation + c.options.indentationStep, words, lines)
|
||||
indentation + c.options.indentationStep, words, lines,
|
||||
c.options.maxLineLength)
|
||||
of sLiteral: c.writeLiteral(item.scalarContent, indentation,
|
||||
c.options.indentationStep, lines, newline)
|
||||
of sFolded: c.writeFolded(item.scalarContent, indentation,
|
||||
c.options.indentationStep, words, newline)
|
||||
of sPlain: c.safeWrite(item.scalarContent)
|
||||
of sDoubleQuoted: c.writeDoubleQuoted(item.scalarContent,
|
||||
indentation + c.options.indentationStep, newline)
|
||||
indentation + c.options.indentationStep, newline,
|
||||
c.options.maxLineLength)
|
||||
of yamlAlias:
|
||||
if c.options.style == psJson:
|
||||
raise newException(YamlPresenterJsonError,
|
||||
@ -727,6 +741,7 @@ proc doPresent(c: var Context, s: var YamlStream) =
|
||||
indentation -= c.options.indentationStep
|
||||
of yamlEndDoc:
|
||||
firstDoc = false
|
||||
c.safeWrite(newline)
|
||||
|
||||
proc present*(s: var YamlStream, target: Stream,
|
||||
options: PresentationOptions = defaultPresentationOptions)
|
||||
|
Loading…
x
Reference in New Issue
Block a user