diff --git a/compiler/docgen.nim b/compiler/docgen.nim index 2c99adba30a5..08311eade0b8 100644 --- a/compiler/docgen.nim +++ b/compiler/docgen.nim @@ -164,6 +164,7 @@ template declareClosures = of meNewSectionExpected: k = errNewSectionExpected of meGeneralParseError: k = errGeneralParseError of meInvalidDirective: k = errInvalidDirectiveX + of meInvalidRstField: k = errInvalidRstField of meFootnoteMismatch: k = errFootnoteMismatch of mwRedefinitionOfLabel: k = warnRedefinitionOfLabel of mwUnknownSubstitution: k = warnUnknownSubstitutionX diff --git a/compiler/lineinfos.nim b/compiler/lineinfos.nim index 052dae272c50..abe6bce7cdc3 100644 --- a/compiler/lineinfos.nim +++ b/compiler/lineinfos.nim @@ -37,6 +37,7 @@ type errGeneralParseError, errNewSectionExpected, errInvalidDirectiveX, + errInvalidRstField, errFootnoteMismatch, errProveInit, # deadcode errGenerated, @@ -96,6 +97,7 @@ const errGeneralParseError: "general parse error", errNewSectionExpected: "new section expected $1", errInvalidDirectiveX: "invalid directive: '$1'", + errInvalidRstField: "invalid field: $1", errFootnoteMismatch: "number of footnotes and their references don't match: $1", errProveInit: "Cannot prove that '$1' is initialized.", # deadcode errGenerated: "$1", diff --git a/lib/packages/docutils/rst.nim b/lib/packages/docutils/rst.nim index 031a86d98c99..64910aa193b9 100644 --- a/lib/packages/docutils/rst.nim +++ b/lib/packages/docutils/rst.nim @@ -225,6 +225,7 @@ type meNewSectionExpected = "new section expected $1", meGeneralParseError = "general parse error", meInvalidDirective = "invalid directive: '$1'", + meInvalidRstField = "invalid field: $1", meFootnoteMismatch = "mismatch in number of footnotes and their refs: $1", mwRedefinitionOfLabel = "redefinition of label '$1'", mwUnknownSubstitution = "unknown substitution '$1'", diff --git a/lib/packages/docutils/rstgen.nim b/lib/packages/docutils/rstgen.nim index e3f8892835ea..82917726353b 100644 --- a/lib/packages/docutils/rstgen.nim +++ b/lib/packages/docutils/rstgen.nim @@ -907,6 +907,25 @@ proc renderSmiley(d: PDoc, n: PRstNode, result: var string) = "\\includegraphics{$1}", [d.config.getOrDefault"doc.smiley_format" % n.text]) +proc getField1Int(d: PDoc, n: PRstNode, fieldName: string): int = + # TODO: proper column/line info + template err(msg: string) = + d.msgHandler(d.filename, 1, 0, meInvalidRstField, msg) + let value = n.getFieldValue + var number: int + let nChars = parseInt(value, number) + if nChars == 0: + if value.len == 0: + err("field $1 requires an argument" % [fieldName]) + else: + err("field $1 requires an integer, but '$2' was given" % + [fieldName, value]) + elif nChars < value.len: + err("extra arguments were given to $1: '$2'" % + [fieldName, value[nChars..^1]]) + else: + result = number + proc parseCodeBlockField(d: PDoc, n: PRstNode, params: var CodeBlockParams) = ## Parses useful fields which can appear before a code block. ## @@ -916,9 +935,7 @@ proc parseCodeBlockField(d: PDoc, n: PRstNode, params: var CodeBlockParams) = of "number-lines": params.numberLines = true # See if the field has a parameter specifying a different line than 1. - var number: int - if parseInt(n.getFieldValue, number) > 0: - params.startLine = number + params.startLine = getField1Int(d, n, "number-lines") of "file", "filename": # The ``file`` option is a Nim extension to the official spec, it acts # like it would for other directives like ``raw`` or ``cvs-table``. This @@ -936,9 +953,7 @@ proc parseCodeBlockField(d: PDoc, n: PRstNode, params: var CodeBlockParams) = # consider whether `$docCmd` should be appended here too params.testCmd = unescape(params.testCmd) of "status", "exitcode": - var status: int - if parseInt(n.getFieldValue, status) > 0: - params.status = status + params.status = getField1Int(d, n, n.getArgument) of "default-language": params.langStr = n.getFieldValue.strip params.lang = params.langStr.getSourceLanguage @@ -954,7 +969,6 @@ proc parseCodeBlockParams(d: PDoc, n: PRstNode): CodeBlockParams = if n.isNil: return assert n.kind in {rnCodeBlock, rnInlineCode} - assert(not n.sons[2].isNil) # Parse the field list for rendering parameters if there are any. if not n.sons[1].isNil: @@ -1028,8 +1042,8 @@ proc renderCode(d: PDoc, n: PRstNode, result: var string) = ## option to differentiate between a plain code block and Nim's code block ## extension. assert n.kind in {rnCodeBlock, rnInlineCode} - if n.sons[2] == nil: return var params = d.parseCodeBlockParams(n) + if n.sons[2] == nil: return var m = n.sons[2].sons[0] assert m.kind == rnLeaf diff --git a/tests/stdlib/trstgen.nim b/tests/stdlib/trstgen.nim index 300229648a5f..d5d902e1d9f7 100644 --- a/tests/stdlib/trstgen.nim +++ b/tests/stdlib/trstgen.nim @@ -1136,6 +1136,18 @@ Test1 check "
55\n
" in output check "x" in output + test "Nim code-block indentation": + let input = dedent """ + .. code-block:: nim + :number-lines: 55 + let a = 1 + """ + var error = new string + let output = input.toHtml(error=error) + check(error[] == "input(1, 1) Error: invalid field: " & + "extra arguments were given to number-lines: ' let a = 1'") + check "" == output + test "RST admonitions": # check that all admonitions are implemented let input0 = dedent """