diff --git a/compiler/docgen.nim b/compiler/docgen.nim
index 8cb36cc4662ef..0d4e68e17a740 100644
--- a/compiler/docgen.nim
+++ b/compiler/docgen.nim
@@ -17,7 +17,8 @@ import
packages/docutils/rst, packages/docutils/rstgen,
json, xmltree, cgi, trees, types,
typesrenderer, astalgo, lineinfos, intsets,
- pathutils, trees, tables
+ pathutils, trees, tables,
+ renderverbatim
const
exportSection = skField
@@ -492,91 +493,6 @@ proc runAllExamples(d: PDoc) =
rawMessage(d.conf, hintSuccess, ["runnableExamples: " & outp.string])
# removeFile(outp.changeFileExt(ExeExt)) # it's in nimcache, no need to remove
-proc lastNodeRec(n: PNode): PNode =
- # MOVE
- result = n
- while result.safeLen > 0:
- result = result[^1]
-
-proc isInIndentationBlock(src: string, indent: int): bool =
- #[
- MOVE
- returns whether source code line `src` is indented within indentation block
- indented at `indent`, taking care of comments,
- Limitation: following extreme edge case isn't supported, it's trivial
- to work around it. As a benefit, we dont miss comments after the last
- declaration inside runnableExamples, which alternative implementations would.
-
- TODO: handle nested comments properly
-
- runnableExamples:
- echo [
- 1,
- # this comment works fine
- 2,
- #[
-sneaky_indentation # this comment won't work
- ]#
- ] # this will be wrongly skipped because of previous edge case
- ]#
-
- for j in 0.. last.line and not isInIndentationBlock(src, indent):
- # if line > last.line:
- break
- if line > first.line: ret.add "\n"
- if src.len > indent:
- ret.add src[indent..^1]
- lastNonemptyPos = ret.len
- ret = ret[0..$1", "\\spanStringLit{$1}", [escLit])
- # result.add "$2" % [class, val]
- result.add "$2" % [class, buf]
-
- while true:
- getNextToken(toknizr, langNim)
- case toknizr.kind
- of gtEof: break # End Of File (or string)
- else:
- # TODO: avoid alloc; maybe toOpenArray
- append(toknizr.kind, substr(code, toknizr.start, toknizr.length + toknizr.start - 1))
-
proc prepareExample(d: PDoc; n: PNode): tuple[rdoccmd: string, code: string] =
## returns `rdoccmd` and source code for this runnableExamples
var rdoccmd = ""
@@ -594,10 +510,9 @@ proc prepareExample(d: PDoc; n: PNode): tuple[rdoccmd: string, code: string] =
docComment,
newTree(nkImportStmt, newStrNode(nkStrLit, d.filename)))
runnableExamples.info = n.info
- let ret = extractRunnableExamplesSource(d, n)
- echo ret
+ let ret = extractRunnableExamplesSource(d.conf, n)
for a in n.lastSon: runnableExamples.add a
- # TODO: use ret instead here too?
+ # we could also use `ret` instead here, to keep sources verbatim
writeExample(d, runnableExamples, rdoccmd)
result = (rdoccmd, ret)
when false:
diff --git a/compiler/renderverbatim.nim b/compiler/renderverbatim.nim
new file mode 100644
index 0000000000000..ed493bf9c48f2
--- /dev/null
+++ b/compiler/renderverbatim.nim
@@ -0,0 +1,67 @@
+import strutils
+from xmltree import addEscaped
+
+import ast, options, msgs
+import packages/docutils/highlite
+
+proc lastNodeRec(n: PNode): PNode =
+ # MOVE
+ result = n
+ while result.safeLen > 0:
+ result = result[^1]
+
+proc isInIndentationBlock(src: string, indent: int): bool =
+ #[
+ we stop at the first de-indentation; there's an inherent ambiguity with non
+ doc comments since they can have arbitrary indentation, so we just take the
+ practical route and require a runnableExamples to keep its code (including non
+ doc comments) to its indentation level.
+ ]#
+ for j in 0.. last.line and not isInIndentationBlock(src, indent):
+ break
+ if line > first.line: ret.add "\n"
+ if src.len > indent:
+ ret.add src[indent..^1]
+ lastNonemptyPos = ret.len
+ ret = ret[0..$1", "\\spanStringLit{$1}", [escLit])
+ # result.add "$2" % [class, val]
+ result.add "$2" % [class, buf]
+
+ while true:
+ getNextToken(toknizr, langNim)
+ case toknizr.kind
+ of gtEof: break # End Of File (or string)
+ else:
+ # TODO: avoid alloc; maybe toOpenArray
+ append(toknizr.kind, substr(code, toknizr.start, toknizr.length + toknizr.start - 1))
diff --git a/nimdoc/testproject/expected/testproject.html b/nimdoc/testproject/expected/testproject.html
index 4eb8ed44ca89e..ff7263f52acfd 100644
--- a/nimdoc/testproject/expected/testproject.html
+++ b/nimdoc/testproject/expected/testproject.html
@@ -170,7 +170,9 @@ testproject
Templates
@@ -184,13 +186,11 @@ testproject
This is the top level module.
Example:
-import
- subdir / subdir_b / utils
-
-doAssert bar(3, 4) == 7
-foo(enumValueA, enumValueB)
-for x in "xx":
- discard
+import subdir / subdir_b / utils
+doAssert bar(3, 4) == 7
+foo(enumValueA, enumValueB)
+
+for x in "xx": discard
@@ -328,6 +328,26 @@
+
+template myfn()
+-
+
+
+
Example:
+import std/strutils
+
+
+doAssert "'foo" == "'foo"
+
+doAssert: not "foo".startsWith "ba"
+block:
+ discard 0xff
+
+
+
template foo(a, b: SomeType)
-
diff --git a/nimdoc/testproject/expected/theindex.html b/nimdoc/testproject/expected/theindex.html
index a76f5961f6b88..f78be11eeef16 100644
--- a/nimdoc/testproject/expected/theindex.html
+++ b/nimdoc/testproject/expected/theindex.html
@@ -143,6 +143,10 @@
Index
- testproject: isValid[T](x: T): bool
+- myfn:
- someFunc:
- testproject: someFunc()
diff --git a/nimdoc/testproject/testproject.nim b/nimdoc/testproject/testproject.nim
index d1fcf58cd83e4..b2976fe9a5495 100644
--- a/nimdoc/testproject/testproject.nim
+++ b/nimdoc/testproject/testproject.nim
@@ -9,6 +9,22 @@ runnableExamples:
# bug #11078
for x in "xx": discard
+template myfn*() =
+ runnableExamples:
+ import std/strutils
+ ## line doc comment
+ # bar
+ doAssert "'foo" == "'foo"
+ ##[
+ foo
+ bar
+ ]##
+ doAssert: not "foo".startsWith "ba"
+ block:
+ discard 0xff # elu par cette crapule
+ # should be in
+ # should be out
+
const
C_A* = 0x7FF0000000000000'f64
C_B* = 0o377'i8