* runnableExamples "-b:cpp -r:off": code
This commit is contained in:
parent
4ae341353d
commit
3d20f14193
6 changed files with 104 additions and 37 deletions
|
|
@ -17,7 +17,7 @@ import
|
|||
packages/docutils/rst, packages/docutils/rstgen,
|
||||
json, xmltree, cgi, trees, types,
|
||||
typesrenderer, astalgo, lineinfos, intsets,
|
||||
pathutils, trees
|
||||
pathutils, trees, tables
|
||||
|
||||
const
|
||||
exportSection = skField
|
||||
|
|
@ -26,6 +26,12 @@ const
|
|||
|
||||
type
|
||||
TSections = array[TSymKind, Rope]
|
||||
ExampleGroup = ref object
|
||||
## a group of runnableExamples with same rdoccmd
|
||||
rdoccmd: string ## from 1st arg in `runnableExamples(rdoccmd): body`
|
||||
docCmd: string ## from user config, eg --doccmd:-d:foo
|
||||
code: string ## contains imports; each import contains `body`
|
||||
index: int ## group index
|
||||
TDocumentor = object of rstgen.RstGenerator
|
||||
modDesc: Rope # module description
|
||||
module: PSym
|
||||
|
|
@ -44,7 +50,7 @@ type
|
|||
# already. See bug #3655
|
||||
destFile*: AbsoluteFile
|
||||
thisDir*: AbsoluteDir
|
||||
examples: string
|
||||
exampleGroups: OrderedTable[string, ExampleGroup]
|
||||
wroteCss*: bool
|
||||
|
||||
PDoc* = ref TDocumentor ## Alias to type less.
|
||||
|
|
@ -443,54 +449,72 @@ proc nodeToHighlightedHtml(d: PDoc; n: PNode; result: var Rope; renderFlags: TRe
|
|||
dispA(d.conf, result, "<span class=\"Other\">$1</span>", "\\spanOther{$1}",
|
||||
[escLit])
|
||||
|
||||
proc testExample(d: PDoc; ex: PNode) =
|
||||
proc exampleOutputDir(d: PDoc): AbsoluteDir = d.conf.getNimcacheDir / RelativeDir"runnableExamples"
|
||||
|
||||
proc writeExample(d: PDoc; ex: PNode, rdoccmd: string) =
|
||||
if d.conf.errorCounter > 0: return
|
||||
let outputDir = d.conf.getNimcacheDir / RelativeDir"runnableExamples"
|
||||
let outputDir = d.exampleOutputDir
|
||||
createDir(outputDir)
|
||||
inc d.exampleCounter
|
||||
# PRTEMP
|
||||
let outp = outputDir / RelativeFile(extractFilename(d.filename.changeFileExt"" &
|
||||
"_examples" & $d.exampleCounter & ".nim"))
|
||||
#let nimcache = outp.changeFileExt"" & "_nimcache"
|
||||
renderModule(ex, d.filename, outp.string, conf = d.conf)
|
||||
d.examples.add "import r\"" & outp.string & "\"\n"
|
||||
if rdoccmd notin d.exampleGroups: d.exampleGroups[rdoccmd] = ExampleGroup(rdoccmd: rdoccmd, docCmd: d.conf.docCmd, index: d.exampleGroups.len)
|
||||
d.exampleGroups[rdoccmd].code.add "import r\"$1\"\n" % outp.string
|
||||
|
||||
proc runAllExamples(d: PDoc) =
|
||||
let docCmd = d.conf.docCmd
|
||||
let backend = d.conf.backend
|
||||
# This used to be: `let backend = if isDefined(d.conf, "js"): "js"` (etc), however
|
||||
# using `-d:js` (etc) cannot work properly, eg would fail with `importjs`
|
||||
# since semantics are affected by `config.backend`, not by isDefined(d.conf, "js")
|
||||
if d.examples.len == 0 or docCmd == docCmdSkip: return
|
||||
let outputDir = d.conf.getNimcacheDir / RelativeDir"runnableExamples"
|
||||
let outp = outputDir / RelativeFile(extractFilename(d.filename.changeFileExt"" &
|
||||
"_examples.nim"))
|
||||
writeFile(outp, d.examples)
|
||||
let cmd = "$nim $backend -r --warning:UnusedImport:off --path:$path --nimcache:$nimcache $docCmd $file" % [
|
||||
"nim", os.getAppFilename(),
|
||||
"backend", $d.conf.backend,
|
||||
"path", quoteShell(d.conf.projectPath),
|
||||
"nimcache", quoteShell(outputDir),
|
||||
"file", quoteShell(outp),
|
||||
"docCmd", docCmd,
|
||||
]
|
||||
if os.execShellCmd(cmd) != 0:
|
||||
quit "[runnableExamples] failed: generated file: '$1' cmd: $2" % [outp.string, cmd]
|
||||
else:
|
||||
# keep generated source file `outp` to allow inspection.
|
||||
rawMessage(d.conf, hintSuccess, ["runnableExamples: " & outp.string])
|
||||
removeFile(outp.changeFileExt(ExeExt))
|
||||
let outputDir = d.exampleOutputDir
|
||||
for _, group in d.exampleGroups:
|
||||
if group.docCmd == docCmdSkip: continue
|
||||
let outp = outputDir / RelativeFile("$1_group$2_examples.nim" % [d.filename.splitFile.name, $group.index])
|
||||
group.code = "# autogenerated by docgen\n# source: $1\n# rdoccmd: $2\n$3" % [d.filename, group.rdoccmd, group.code]
|
||||
writeFile(outp, group.code)
|
||||
# most useful semantics is that `docCmd` comes after `rdoccmd`, so that we can (temporarily) override
|
||||
# via command line
|
||||
let cmd = "$nim $backend -r --warning:UnusedImport:off --path:$path --nimcache:$nimcache $rdoccmd $docCmd $file" % [
|
||||
"nim", os.getAppFilename(),
|
||||
"backend", $d.conf.backend,
|
||||
"path", quoteShell(d.conf.projectPath),
|
||||
"nimcache", quoteShell(outputDir),
|
||||
"file", quoteShell(outp),
|
||||
"rdoccmd", group.rdoccmd,
|
||||
"docCmd", group.docCmd,
|
||||
]
|
||||
if os.execShellCmd(cmd) != 0:
|
||||
quit "[runnableExamples] failed: generated file: '$1' group: '$2' cmd: $3" % [outp.string, $group[], cmd]
|
||||
else:
|
||||
# keep generated source file `outp` to allow inspection.
|
||||
rawMessage(d.conf, hintSuccess, ["runnableExamples: " & outp.string])
|
||||
# removeFile(outp.changeFileExt(ExeExt)) # it's in nimcache, no need to remove
|
||||
|
||||
proc prepareExample(d: PDoc; n: PNode): string =
|
||||
## returns `rdoccmd` for this runnableExamples
|
||||
var rdoccmd = ""
|
||||
if n.len < 2 or n.len > 3: globalError(d.conf, n.info, "runnableExamples invalid")
|
||||
if n.len == 3:
|
||||
let n1 = n[1]
|
||||
# xxx this should be evaluated during sempass
|
||||
if n1.kind notin nkStrKinds: globalError(d.conf, n1.info, "string litteral expected")
|
||||
rdoccmd = n1.strVal
|
||||
|
||||
proc prepareExamples(d: PDoc; n: PNode) =
|
||||
var docComment = newTree(nkCommentStmt)
|
||||
let loc = d.conf.toFileLineCol(n.info)
|
||||
docComment.comment = "autogenerated by docgen from " & loc
|
||||
|
||||
docComment.comment = "autogenerated by docgen\nloc: $1\nrdoccmd: $2" % [loc, rdoccmd]
|
||||
var runnableExamples = newTree(nkStmtList,
|
||||
docComment,
|
||||
newTree(nkImportStmt, newStrNode(nkStrLit, d.filename)))
|
||||
runnableExamples.info = n.info
|
||||
|
||||
for a in n.lastSon: runnableExamples.add a
|
||||
testExample(d, runnableExamples)
|
||||
writeExample(d, runnableExamples, rdoccmd)
|
||||
result = rdoccmd
|
||||
when false:
|
||||
proc extractImports(n: PNode; result: PNode) =
|
||||
if n.kind in {nkImportStmt, nkImportExceptStmt, nkFromStmt}:
|
||||
|
|
@ -510,9 +534,11 @@ proc getAllRunnableExamplesRec(d: PDoc; n, orig: PNode; dest: var Rope) =
|
|||
of nkCallKinds:
|
||||
if isRunnableExamples(n[0]) and
|
||||
n.len >= 2 and n.lastSon.kind == nkStmtList:
|
||||
prepareExamples(d, n)
|
||||
let rdoccmd = prepareExample(d, n)
|
||||
var msg = "Example:"
|
||||
if rdoccmd.len > 0: msg.add " cmd: " & rdoccmd
|
||||
dispA(d.conf, dest, "\n<p><strong class=\"examples_text\">$1</strong></p>\n",
|
||||
"\n\\textbf{$1}\n", [rope"Examples:"])
|
||||
"\n\\textbf{$1}\n", [msg.rope])
|
||||
inc d.listingCounter
|
||||
let id = $d.listingCounter
|
||||
dest.add(d.config.getOrDefault"doc.listing_start" % [id, "langNim"])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue