Skip to content

Commit

Permalink
Fixed presenter regarding new style annotations
Browse files Browse the repository at this point in the history
 * fixed presentation of flow mappings inside block collections
 * improved logic checking whether a collection can be written on a
   single line
 * fixed tests
  • Loading branch information
flyx committed Nov 14, 2023
1 parent a698289 commit bf87d50
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 65 deletions.
6 changes: 4 additions & 2 deletions test/tnative.nim
Original file line number Diff line number Diff line change
Expand Up @@ -676,14 +676,16 @@ suite "Serialization":
flowChild: AsFlow(a: "abc", b: "abc", c: "abc"),
blockChild: AsFlow(a: "a\nc", b: "abc", c: "ab:")
)
var output = blockOnlyDumper().dump(input)
var dumper = blockOnlyDumper()
dumper.presentation.maxLineLength = some(20)
var output = dumper.dump(input)
assertStringEqual "flowChild: {\n" &
" a: 'abc',\n" &
" b: \"abc\",\n" &
" c: abc\n" &
" }\n" &
"blockChild:\n" &
" a: \"a\\\nc\"\n" &
" a: \"a\\nc\"\n" &
" b: \"abc\"\n" &
" c: \"ab:\"\n", output

2 changes: 1 addition & 1 deletion test/tpresenter.nim
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ suite "Presenter":

test "Forced multiline flow sequence":
var input = inputSingle(startSeqEvent(), scalarEvent("1"), scalarEvent("2"), endSeqEvent())
assertOutput(input, "[\n 1,\n 2\n]\n", PresentationOptions(outputVersion: ovNone, condenseFlow: false))
assertOutput(input, "[\n 1,\n 2\n]\n", PresentationOptions(outputVersion: ovNone, condenseFlow: false, containers: cFlow))

test "Compact flow mapping":
var input = inputSingle(startMapEvent(), scalarEvent("1"), scalarEvent("2"), endMapEvent())
Expand Down
3 changes: 2 additions & 1 deletion yaml/dumping.nim
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ proc setMinimalStyle*(dumper: var Dumper) =
suppressAttrs: false,
quoting: sqJson,
condenseFlow: true,
explicitKeys: false
explicitKeys: false,
maxLineLength: none(int)
)
dumper.serialization = SerializationOptions(
tagStyle: tsNone,
Expand Down
3 changes: 0 additions & 3 deletions yaml/native.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1243,7 +1243,6 @@ proc recGenFieldRepresenters(
))
when `fieldAccessor`.hasCustomPragma(scalar):
ctx.overridingScalarStyle = `fieldAccessor`.getCustomPragmaVal(scalar)
echo "set scalar style to ", $ctx.overridingScalarStyle
when `fieldAccessor`.hasCustomPragma(collection):
ctx.overridingCollectionStyle = `fieldAccessor`.getCustomPragmaVal(collection)
ctx.representChild(`fieldAccessor`)
Expand Down Expand Up @@ -1281,7 +1280,6 @@ proc recGenFieldRepresenters(
))
when `itemAccessor`.hasCustomPragma(scalar):
ctx.overridingScalarStyle = `itemAccessor`.getCustomPragmaVal(scalar)
echo "set scalar style to ", $ctx.overridingScalarStyle
when `itemAccessor`.hasCustomPragma(collection):
ctx.overridingCollectionStyle = `itemAccessor`.getCustomPragmaVal(collection)
ctx.representChild(`itemAccessor`)
Expand All @@ -1307,7 +1305,6 @@ proc recGenFieldRepresenters(
))
when `childAccessor`.hasCustomPragma(scalar):
ctx.overridingScalarStyle = `childAccessor`.getCustomPragmaVal(scalar)
echo "set scalar style to ", $ctx.overridingScalarStyle
when `childAccessor`.hasCustomPragma(collection):
ctx.overridingCollectionStyle = `childAccessor`.getCustomPragmaVal(collection)
ctx.representChild(`childAccessor`)
Expand Down
119 changes: 61 additions & 58 deletions yaml/presenter.nim
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,13 @@ type
needsWhitespace: int
wroteDirectivesEnd: bool
lastImplicitKeyLen: int
cached: DeQue[Event]

ItemKind = enum
ikCompactScalar, ikMultilineFlowScalar, ikBlockScalar, ikCollection

MapParseState = enum
mpInitial, mpKey, mpValue, mpNeedBlock

proc level(ctx: var Context): var DumperLevel = ctx.levels[^1]

Expand Down Expand Up @@ -595,7 +599,7 @@ proc startItem(
of dFlowSequenceItem:
ctx.append(',')
ctx.whitespace(true)
if not ctx.options.condenseFlow:
if not ctx.level.singleLine:
ctx.newline()
t.write(repeat(' ', ctx.indentation))
except CatchableError as ce:
Expand Down Expand Up @@ -644,19 +648,61 @@ proc nextItem(
else:
result = s.next()

proc checkSingleLine(
ctx : var Context,
s : YamlStream,
item : Event,
mapping: bool
): (bool, MapParseState) =
let style = if mapping: item.mapStyle else: item.seqStyle
if ctx.options.newlines == nlNone: return (true, mpInitial)
if not ctx.options.condenseFlow: return (false, mpNeedBlock)
if (ctx.levels.len > 0 and ctx.state.isFlow) or style == csFlow or
(style == csAny and ctx.options.containers != cBlock):
result[1] = mpInitial
var length = 0
while not mapping or result[1] != mpNeedBlock:
let next = s.next()
ctx.cached.addLast(next)
case next.kind
of yamlScalar:
length += 2 + next.scalarContent.len
if next.scalarStyle in [ssFolded, ssLiteral]:
length = high(int)
result[1] = mpNeedBlock
break
case result[1]
of mpInitial: result[1] = mpKey
of mpKey: result[1] = mpValue
else: result[1] = mpNeedBlock
of yamlAlias:
length += 6
case result[1]
of mpInitial: result[1] = mpKey
of mpKey: result[1] = mpValue
else: result[1] = mpNeedBlock
of yamlEndSeq, yamlEndMap: break
else:
length = high(int)
result[1] = mpNeedBlock
break
result[0] = (not mapping or result[1] != mpNeedBlock) and
(ctx.options.maxLineLength.isNone or
length < ctx.options.maxLineLength.get() - ctx.indentation - 2)
else: result = (false, mpNeedBlock)

proc doPresent(
ctx: var Context,
s : YamlStream,
) {.raises: [
YamlPresenterJsonError, YamlPresenterOutputError,
YamlStreamError
].} =
var
cached = initDeQue[Event]()
unclosedDoc = false
var unclosedDoc = false
ctx.cached = initDeQue[Event]()
ctx.wroteDirectivesEnd = false
while true:
let item = nextItem(cached, s)
let item = nextItem(ctx.cached, s)
case item.kind
of yamlStartStream: discard
of yamlEndStream: break
Expand Down Expand Up @@ -801,6 +847,7 @@ proc doPresent(
e.parent = ce
raise e
of yamlStartSeq:
let (singleLine, _) = ctx.checkSingleLine(s, item, false)
var nextState: DumperState
if (ctx.levels.len > 0 and ctx.state.isFlow) or item.seqStyle == csFlow:
nextState = dFlowSequenceStart
Expand All @@ -810,31 +857,13 @@ proc doPresent(
else:
case ctx.options.containers
of cMixed:
var length = 0
while true:
let next = s.next()
cached.addLast(next)
case next.kind
of yamlScalar:
length += 2 + next.scalarContent.len
if next.scalarStyle in [ssFolded, ssLiteral]:
length = high(int)
break
of yamlAlias: length += 6
of yamlEndSeq: break
else:
length = high(int)
break
nextState = if length <= 60: dFlowSequenceStart else: dBlockSequenceItem
nextState = if singleLine: dFlowSequenceStart else: dBlockSequenceItem
of cFlow: nextState = dFlowSequenceStart
of cBlock:
let next = s.peek()
if next.kind == yamlEndSeq: nextState = dFlowSequenceStart
else: nextState = dBlockSequenceItem
nextState = if next.kind == yamlEndSeq: dFlowSequenceStart else: dBlockSequenceItem

var indentation = 0
var singleLine = ctx.options.condenseFlow or ctx.options.newlines == nlNone

var wroteAnything = false
if ctx.levels.len > 0: wroteAnything = ctx.state == dBlockImplicitMapKey

Expand All @@ -844,6 +873,8 @@ proc doPresent(
else:
ctx.startItem(ikCollection)
indentation = ctx.indentation + ctx.options.indentationStep
if nextState.isFlow and not ctx.state.isFlow:
inc(indentation, ctx.options.indentationStep)

let wroteAttrs = ctx.writeTagAndAnchor(item.seqProperties)
if wroteAttrs or (ctx.wroteDirectivesEnd and ctx.levels.len == 0):
Expand All @@ -854,12 +885,9 @@ proc doPresent(
if wroteAttrs or ctx.wroteDirectivesEnd: ctx.safeNewline()
ctx.safeWrite('[')

if ctx.levels.len > 0 and not ctx.options.condenseFlow and
ctx.state in [dBlockExplicitMapKey, dBlockMapValue,
dBlockImplicitMapKey, dBlockSequenceItem]:
if ctx.options.newlines != nlNone: singleLine = false
ctx.levels.add (nextState, indentation, singleLine, wroteAnything)
of yamlStartMap:
let (singleLine, mps) = ctx.checkSingleLine(s, item, true)
var nextState: DumperState
if (ctx.levels.len > 0 and ctx.state.isFlow) or item.mapStyle == csFlow:
nextState = dFlowMapStart
Expand All @@ -869,27 +897,6 @@ proc doPresent(
else:
case ctx.options.containers
of cMixed:
type MapParseState = enum
mpInitial, mpKey, mpValue, mpNeedBlock
var mps: MapParseState = mpInitial
while mps != mpNeedBlock:
let next = s.next()
cached.addLast(next)
case next.kind
of yamlScalar:
case mps
of mpInitial: mps = mpKey
of mpKey: mps = mpValue
else: mps = mpNeedBlock
if next.scalarStyle in [ssFolded, ssLiteral]:
mps = mpNeedBlock
of yamlAlias:
case mps
of mpInitial: mps = mpKey
of mpKey: mps = mpValue
else: mps = mpNeedBlock
of yamlEndMap: break
else: mps = mpNeedBlock
if mps == mpNeedBlock:
nextState = dBlockMapValue
elif ctx.levels.len == 0 or ctx.state == dBlockSequenceItem and item.emptyProperties:
Expand All @@ -903,8 +910,6 @@ proc doPresent(
else: nextState = dBlockMapValue

var indentation = 0
var singleLine = ctx.options.condenseFlow or ctx.options.newlines == nlNone

var wroteAnything = false
if ctx.levels.len > 0: wroteAnything = ctx.state == dBlockImplicitMapKey

Expand All @@ -914,6 +919,8 @@ proc doPresent(
else:
ctx.startItem(ikCollection)
indentation = ctx.indentation + ctx.options.indentationStep
if nextState.isFlow and not ctx.state.isFlow:
inc(indentation, ctx.options.indentationStep)

let wroteAttrs = ctx.writeTagAndAnchor(item.properties)
if wroteAttrs or (ctx.wroteDirectivesEnd and ctx.levels.len == 0):
Expand All @@ -924,10 +931,6 @@ proc doPresent(
if wroteAttrs or ctx.wroteDirectivesEnd: ctx.safeNewline()
ctx.safeWrite('{')

if ctx.levels.len > 0 and not ctx.options.condenseFlow and
ctx.state in [dBlockExplicitMapKey, dBlockMapValue,
dBlockImplicitMapKey, dBlockSequenceItem]:
if ctx.options.newlines != nlNone: singleLine = false
ctx.levels.add (nextState, indentation, singleLine, wroteAnything)
of yamlEndSeq:
yAssert ctx.levels.len > 0
Expand All @@ -937,7 +940,7 @@ proc doPresent(
try:
if not level.singleLine:
ctx.newline()
ctx.target.write(repeat(' ', ctx.indentation))
ctx.target.write(repeat(' ', level.indentation - ctx.options.indentationStep))
ctx.target.write(']')
except CatchableError as ce:
var e = newException(YamlPresenterOutputError, "")
Expand All @@ -954,7 +957,7 @@ proc doPresent(
try:
if not level.singleLine:
ctx.safeNewline()
ctx.target.write(repeat(' ', ctx.indentation))
ctx.target.write(repeat(' ', level.indentation - ctx.options.indentationStep))
ctx.append('}')
except CatchableError as ce:
var e = newException(YamlPresenterOutputError, "")
Expand Down

0 comments on commit bf87d50

Please sign in to comment.