diff --git a/private/fastparse.nim b/private/fastparse.nim index b36fb4c..606ce86 100644 --- a/private/fastparse.nim +++ b/private/fastparse.nim @@ -346,10 +346,11 @@ template handlePossibleMapStart(flow: bool = false, while p.lexer.buf[pos] notin {'\'', '\l', '\c', EndOfFile}: pos.inc() of '&', '*', '!': - pos.inc() - while p.lexer.buf[pos] notin {' ', '\t', '\l', '\c', EndOfFile}: + if pos == p.lexer.bufpos or p.lexer.buf[p.lexer.bufpos] in {'\t', ' '}: pos.inc() - continue + while p.lexer.buf[pos] notin {' ', '\t', '\l', '\c', EndOfFile}: + pos.inc() + continue else: discard if flow and p.lexer.buf[pos] notin {' ', '\t'}: recentJsonStyle = p.lexer.buf[pos] in {']', '}', '\'', '"'} @@ -776,8 +777,8 @@ template handleFlowPlainScalar() {.dirty.} = template ensureCorrectIndentation() {.dirty.} = if level.indentation != indentation: startToken() - parserError("Invalid indentation (expected indentation of " & - $level.indentation & ")") + parserError("Invalid indentation: " & $indentation & + " (expected indentation of " & $level.indentation & ")") template tagHandle(lexer: var BaseLexer, content: var string, shorthandEnd: var int) = @@ -868,7 +869,8 @@ template blockScalar(lexer: BaseLexer, content: var string, blockIndent = int(lexer.buf[lexer.bufpos]) - int('\x30') detectedIndent = true of spaceOrLineEnd: break - else: lexerError(lexer, "Illegal character in block scalar header") + else: lexerError(lexer, "Illegal character in block scalar header: '" & + lexer.buf[lexer.bufpos] & "'") lexer.lineEnding() case lexer.buf[lexer.bufpos] of '\l': lexer.bufpos = lexer.handleLF(lexer.bufpos) diff --git a/private/presenter.nim b/private/presenter.nim index 0fce03e..5509d8b 100644 --- a/private/presenter.nim +++ b/private/presenter.nim @@ -15,10 +15,12 @@ type sLiteral, sFolded, sPlain, sDoubleQuoted proc defineOptions*(style: PresentationStyle = psDefault, - indentationStep: int = 2, newlines: - NewLineStyle = nlOSDefault): PresentationOptions = - result = PresentationOptions(style: style, indentationStep: indentationStep, - newlines: newlines) + indentationStep: int = 2, + newlines: NewLineStyle = nlOSDefault, + outputVersion: OutputYamlVersion = ov1_2): + PresentationOptions = + PresentationOptions(style: style, indentationStep: indentationStep, + newlines: newlines, outputVersion: outputVersion) proc inspect(scalar: string, indentation: int, words, lines: var seq[tuple[start, finish: int]]): @@ -30,7 +32,8 @@ proc inspect(scalar: string, indentation: int, curWord, curLine: tuple[start, finish: int] canUseFolded = true canUseLiteral = true - canUsePlain = scalar.len > 0 and scalar[0] notin {'@', '`'} + canUsePlain = scalar.len > 0 and + scalar[0] notin {'@', '`', '|', '>', '&', '*', '!', ' ', '\t'} for i, c in scalar: case c of ' ': @@ -338,7 +341,10 @@ proc present*(s: var YamlStream, target: Stream, tagLib: TagLibrary, if options.style != psJson: # TODO: tag directives try: - target.write("%YAML 1.2" & newline) + case options.outputVersion + of ov1_2: target.write("%YAML 1.2" & newline) + of ov1_1: target.write("%YAML 1.1" & newLine) + of ovNone: discard if tagLib.secondaryPrefix != yamlTagRepositoryPrefix: target.write("%TAG !! " & tagLib.secondaryPrefix & newline) diff --git a/yaml.nim b/yaml.nim index 2c2eae5..72b8aa6 100644 --- a/yaml.nim +++ b/yaml.nim @@ -210,12 +210,24 @@ type ## - ``nlOSDefault``: Use the target operation system's default newline ## sequence (CRLF on Windows, LF everywhere else). nlLF, nlCRLF, nlOSDefault + + OutputYamlVersion* = enum + ## Specify which YAML version number the presenter shall emit. The + ## presenter will always emit content that is valid YAML 1.1, but by + ## default will write a directive ``%YAML 1.2``. For compatibility with + ## other YAML implementations, it is possible to change this here. + ## + ## It is also possible to specify that the presenter shall not emit any + ## YAML version. The generated content is then guaranteed to be valid + ## YAML 1.1 and 1.2 (but not 1.0 or any newer YAML version). + ov1_2, ov1_1, ovNone PresentationOptions* = object ## Options for generating a YAML character stream style*: PresentationStyle indentationStep*: int newlines*: NewLineStyle + outputVersion*: OutputYamlVersion RefNodeData = object p: pointer @@ -512,9 +524,10 @@ proc parse*(p: YamlParser, s: Stream): YamlStream {.raises: [].} ## Parse the given stream as YAML character stream. proc defineOptions*(style: PresentationStyle = psDefault, - indentationStep: int = 2, newlines: - NewLineStyle = nlOSDefault): PresentationOptions - {.raises: [].} + indentationStep: int = 2, + newlines: NewLineStyle = nlOSDefault, + outputVersion: OutputYamlVersion = ov1_2): + 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.