docgen: implement cross-document links (#20990)

* docgen: implement cross-document links

Fully implements https://github.com/nim-lang/RFCs/issues/125
Follow-up of: https://github.com/nim-lang/Nim/pull/18642 (for internal links)
and https://github.com/nim-lang/Nim/issues/20127.

Overview
--------

Explicit import-like directive is required, called `.. importdoc::`.
(the syntax is % RST, Markdown will use it for a while).

Then one can reference any symbols/headings/anchors, as if they
were in the local file (but they will be prefixed with a module name
or markup document in link text).
It's possible to reference anything from anywhere (any direction
in `.nim`/`.md`/`.rst` files).

See `doc/docgen.md` for full description.

Working is based on `.idx` files, hence one needs to generate
all `.idx` beforehand. A dedicated option `--index:only` is introduced
(and a separate stage for `--index:only` is added to `kochdocs.nim`).

Performance note
----------------

Full run for `./koch docs` now takes 185% of the time before this PR.
(After: 315 s, before: 170 s on my PC).
All the time seems to be spent on `--index:only` run, which takes
almost as much (85%) of normal doc run -- it seems that most time
is spent on file parsing, turning off HTML generation phase has not
helped much.
(One could avoid it by specifying list of files that can be referenced
and pre-processing only them. But it can become error-prone and I assume
that these linke will be **everywhere** in the repository anyway,
especially considering https://github.com/nim-lang/RFCs/issues/478.
So every `.nim`/`.md` file is processed for `.idx` first).

But that's all without significant part of repository converted to
cross-module auto links. To estimate impact I checked the time for
`doc`ing a few files (after all indexes have been generated), and
everywhere difference was **negligible**.
E.g. for `lib/std/private/osfiles.nim` that `importdoc`s large
`os.idx` and hence should have been a case with relatively large
performance impact, but:

* After: 0.59 s.
* Before: 0.59 s.

So Nim compiler works so slow that doc part basically does not matter :-)

Testing
-------

1) added `extlinks` test to `nimdoc/`
2) checked that `theindex.html` is still correct
2) fixed broken auto-links for modules that were derived from `os.nim`
   by adding appropriate ``importdoc``

Implementation note
-------------------

Parsing and formating of `.idx` entries is moved into a dedicated
`rstidx.nim` module from `rstgen.nim`.

`.idx` file format changed:

* fields are not escaped in most cases because we need original
  strings for referencing, not HTML ones
  (the exception is linkTitle for titles and headings).
  Escaping happens later -- on the stage of `rstgen` buildIndex, etc.
* all lines have fixed number of columns 6
* added discriminator tag as a first column,
  it always allows distinguish Nim/markup entries, titles/headings, etc.
  `rstgen` does not rely any more (in most cases) on ad-hoc logic
  to determine what type each entry is.
* there is now always a title entry added at the first line.
* add a line number as 6th column
* linkTitle (4th) column has a different format: before it was like
  `module: funcName()`, now it's `proc funcName()`.
  (This format is also propagated to `theindex.html` and search results,
  I kept it that way since I like it more though it's discussible.)
  This column is what used for Nim symbols resolution.
* also changed details on column format for headings and titles:
  "keyword" is original, "linkTitle" is HTML one

* fix paths on Windows + more clear code

* Update compiler/docgen.nim

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>

* Handle .md and .nim paths uniformly in findRefFile

* handle titles better + more comments

* don't allow markup overwrite index title for .nim files

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
This commit is contained in:
Andrey Makarov
2023-01-04 23:19:01 +03:00
committed by GitHub
parent b2328b44ba
commit 2620da9bf9
45 changed files with 1863 additions and 491 deletions

View File

@@ -820,7 +820,13 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
if conf != nil: conf.headerFile = arg
incl(conf.globalOptions, optGenIndex)
of "index":
processOnOffSwitchG(conf, {optGenIndex}, arg, pass, info)
case arg.normalize
of "", "on": conf.globalOptions.incl {optGenIndex}
of "only": conf.globalOptions.incl {optGenIndexOnly, optGenIndex}
of "off": conf.globalOptions.excl {optGenIndex, optGenIndexOnly}
else: localError(conf, info, errOnOrOffExpectedButXFound % arg)
of "noimportdoc":
processOnOffSwitchG(conf, {optNoImportdoc}, arg, pass, info)
of "import":
expectArg(conf, switch, arg, pass, info)
if pass in {passCmd2, passPP}:

View File

@@ -7,13 +7,17 @@
# distribution, for details about the copyright.
#
# This is the documentation generator. Cross-references are generated
# by knowing how the anchors are going to be named.
## This is the Nim documentation generator. Cross-references are generated
## by knowing how the anchors are going to be named.
##
## .. importdoc:: ../docgen.md
##
## For corresponding users' documentation see [Nim DocGen Tools Guide].
import
ast, strutils, strtabs, algorithm, sequtils, options, msgs, os, idents,
wordrecg, syntaxes, renderer, lexer,
packages/docutils/[rst, rstgen, dochelpers],
packages/docutils/[rst, rstidx, rstgen, dochelpers],
json, xmltree, trees, types,
typesrenderer, astalgo, lineinfos, intsets,
pathutils, tables, nimpaths, renderverbatim, osproc, packages
@@ -91,7 +95,7 @@ type
jEntriesFinal: JsonNode # final JSON after RST pass 2 and rendering
types: TStrTable
sharedState: PRstSharedState
standaloneDoc: bool
standaloneDoc: bool # is markup (.rst/.md) document?
conf*: ConfigRef
cache*: IdentCache
exampleCounter: int
@@ -225,7 +229,7 @@ proc attachToType(d: PDoc; p: PSym): PSym =
if params.len > 0: check(0)
for i in 2..<params.len: check(i)
template declareClosures =
template declareClosures(currentFilename: AbsoluteFile, destFile: string) =
proc compilerMsgHandler(filename: string, line, col: int,
msgKind: rst.MsgKind, arg: string) {.gcsafe.} =
# translate msg kind:
@@ -249,6 +253,7 @@ template declareClosures =
of mwBrokenLink: k = warnRstBrokenLink
of mwUnsupportedLanguage: k = warnRstLanguageXNotSupported
of mwUnsupportedField: k = warnRstFieldXNotSupported
of mwUnusedImportdoc: k = warnRstUnusedImportdoc
of mwRstStyle: k = warnRstStyle
{.gcsafe.}:
globalError(conf, newLineInfo(conf, AbsoluteFile filename, line, col), k, arg)
@@ -259,10 +264,29 @@ template declareClosures =
result = getCurrentDir() / s
if not fileExists(result): result = ""
proc docgenFindRefFile(targetRelPath: string):
tuple[targetPath: string, linkRelPath: string] {.gcsafe.} =
let fromDir = splitFile(destFile).dir # dir where we reference from
let basedir = os.splitFile(currentFilename.string).dir
let outDirPath: RelativeFile =
presentationPath(conf, AbsoluteFile(basedir / targetRelPath))
# use presentationPath because `..` path can be be mangled to `_._`
result.targetPath = string(conf.outDir / outDirPath)
if not fileExists(result.targetPath):
# this can happen if targetRelPath goes to parent directory `OUTDIR/..`.
# Trying it, this may cause ambiguities, but allows us to insert
# "packages" into each other, which is actually used in Nim repo itself.
let destPath = fromDir / targetRelPath
if destPath != result.targetPath and fileExists(destPath):
result.targetPath = destPath
result.linkRelPath = relativePath(result.targetPath.splitFile.dir,
fromDir).replace('\\', '/')
proc parseRst(text: string,
line, column: int,
conf: ConfigRef, sharedState: PRstSharedState): PRstNode =
declareClosures()
result = rstParsePass1(text, line, column, sharedState)
proc getOutFile2(conf: ConfigRef; filename: RelativeFile,
@@ -283,7 +307,8 @@ proc newDocumentor*(filename: AbsoluteFile; cache: IdentCache; conf: ConfigRef,
outExt: string = HtmlExt, module: PSym = nil,
standaloneDoc = false, preferMarkdown = true,
hasToc = true): PDoc =
declareClosures()
let destFile = getOutFile2(conf, presentationPath(conf, filename), outExt, false).string
declareClosures(currentFilename = filename, destFile = destFile)
new(result)
result.module = module
result.conf = conf
@@ -298,7 +323,7 @@ proc newDocumentor*(filename: AbsoluteFile; cache: IdentCache; conf: ConfigRef,
result.hasToc = hasToc
result.sharedState = newRstSharedState(
options, filename.string,
docgenFindFile, compilerMsgHandler, hasToc)
docgenFindFile, docgenFindRefFile, compilerMsgHandler, hasToc)
initRstGenerator(result[], (if conf.isLatexCmd: outLatex else: outHtml),
conf.configVars, filename.string,
docgenFindFile, compilerMsgHandler)
@@ -373,7 +398,7 @@ proc newDocumentor*(filename: AbsoluteFile; cache: IdentCache; conf: ConfigRef,
if gotten != status:
rawMessage(conf, errGenerated, "snippet failed: cmd: '$1' status: $2 expected: $3 output: $4" % [cmd, $gotten, $status, output])
result.emitted = initIntSet()
result.destFile = getOutFile2(conf, presentationPath(conf, filename), outExt, false).string
result.destFile = destFile
result.thisDir = result.destFile.AbsoluteFile.splitFile.dir
template dispA(conf: ConfigRef; dest: var string, xml, tex: string,
@@ -765,21 +790,24 @@ proc isVisible(d: PDoc; n: PNode): bool =
elif n.kind == nkPragmaExpr:
result = isVisible(d, n[0])
proc getName(d: PDoc, n: PNode, splitAfter = -1): string =
proc getName(n: PNode): string =
case n.kind
of nkPostfix: result = getName(d, n[1], splitAfter)
of nkPragmaExpr: result = getName(d, n[0], splitAfter)
of nkSym: result = esc(d.target, n.sym.renderDefinitionName, splitAfter)
of nkIdent: result = esc(d.target, n.ident.s, splitAfter)
of nkPostfix: result = getName(n[1])
of nkPragmaExpr: result = getName(n[0])
of nkSym: result = n.sym.renderDefinitionName
of nkIdent: result = n.ident.s
of nkAccQuoted:
result = esc(d.target, "`")
for i in 0..<n.len: result.add(getName(d, n[i], splitAfter))
result.add esc(d.target, "`")
result = "`"
for i in 0..<n.len: result.add(getName(n[i]))
result = "`"
of nkOpenSymChoice, nkClosedSymChoice:
result = getName(d, n[0], splitAfter)
result = getName(n[0])
else:
result = ""
proc getNameEsc(d: PDoc, n: PNode): string =
esc(d.target, getName(n))
proc getNameIdent(cache: IdentCache; n: PNode): PIdent =
case n.kind
of nkPostfix: result = getNameIdent(cache, n[1])
@@ -928,6 +956,13 @@ proc symbolPriority(k: TSymKind): int =
else: 0 # including skProc which have higher priority
# documentation itself has even higher priority 1
proc getTypeKind(n: PNode): string =
case n[2].kind
of nkEnumTy: "enum"
of nkObjectTy: "object"
of nkTupleTy: "tuple"
else: ""
proc toLangSymbol(k: TSymKind, n: PNode, baseName: string): LangSymbol =
## Converts symbol info (names/types/parameters) in `n` into format
## `LangSymbol` convenient for ``rst.nim``/``dochelpers.nim``.
@@ -971,17 +1006,13 @@ proc toLangSymbol(k: TSymKind, n: PNode, baseName: string): LangSymbol =
if kind != tkSpaces:
result.generics.add(literal.nimIdentNormalize)
if k == skType:
case n[2].kind
of nkEnumTy: result.symTypeKind = "enum"
of nkObjectTy: result.symTypeKind = "object"
of nkTupleTy: result.symTypeKind = "tuple"
else: discard
if k == skType: result.symTypeKind = getTypeKind(n)
proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind, docFlags: DocFlags) =
if (docFlags != kForceExport) and not isVisible(d, nameNode): return
let
name = getName(d, nameNode)
name = getName(nameNode)
nameEsc = esc(d.target, name)
var plainDocstring = getPlainDocstring(n) # call here before genRecComment!
var result = ""
var literal, plainName = ""
@@ -1008,9 +1039,12 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind, docFlags: DocFlags) =
inc(d.id)
let
plainNameEsc = esc(d.target, plainName.strip)
detailedName = k.toHumanStr & " " & (
typeDescr =
if k == skType and getTypeKind(n) != "": getTypeKind(n)
else: k.toHumanStr
detailedName = typeDescr & " " & (
if k in routineKinds: plainName else: name)
uniqueName = if k in routineKinds: plainNameEsc else: name
uniqueName = if k in routineKinds: plainNameEsc else: nameEsc
sortName = if k in routineKinds: plainName.strip else: name
cleanPlainSymbol = renderPlainSymbolName(nameNode)
complexSymbol = complexName(k, n, cleanPlainSymbol)
@@ -1024,8 +1058,9 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind, docFlags: DocFlags) =
let lineinfo = rstast.TLineInfo(
line: nameNode.info.line, col: nameNode.info.col,
fileIndex: addRstFileIndex(d, nameNode.info))
addAnchorNim(d.sharedState, refn = symbolOrId, tooltip = detailedName,
rstLangSymbol, priority = symbolPriority(k), info = lineinfo)
addAnchorNim(d.sharedState, external = false, refn = symbolOrId,
tooltip = detailedName, langSym = rstLangSymbol,
priority = symbolPriority(k), info = lineinfo)
nodeToHighlightedHtml(d, n, result, {renderNoBody, renderNoComments,
renderDocComments, renderSyms, renderExpandUsing}, symbolOrIdEnc)
@@ -1060,8 +1095,10 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind, docFlags: DocFlags) =
if e.sym.kind != skEnumField: continue
let plain = renderPlainSymbolName(e)
let symbolOrId = d.newUniquePlainSymbol(plain)
setIndexTerm(d[], external, symbolOrId, plain, nameNode.sym.name.s & '.' & plain,
xmltree.escape(getPlainDocstring(e).docstringSummary))
setIndexTerm(d[], ieNim, htmlFile = external, id = symbolOrId,
term = plain, linkTitle = nameNode.sym.name.s & '.' & plain,
linkDesc = xmltree.escape(getPlainDocstring(e).docstringSummary),
line = n.info.line.int)
d.tocSimple[k].add TocItem(
sortName: sortName,
@@ -1076,22 +1113,17 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind, docFlags: DocFlags) =
"itemSymOrID", symbolOrId.replace(",", ",<wbr>"),
"itemSymOrIDEnc", symbolOrIdEnc])
# Ironically for types the complexSymbol is *cleaner* than the plainName
# because it doesn't include object fields or documentation comments. So we
# use the plain one for callable elements, and the complex for the rest.
var linkTitle = changeFileExt(extractFilename(d.filename), "") & ": "
if n.kind in routineDefs: linkTitle.add(xmltree.escape(plainName.strip))
else: linkTitle.add(xmltree.escape(complexSymbol.strip))
setIndexTerm(d[], external, symbolOrId, name, linkTitle,
xmltree.escape(plainDocstring.docstringSummary))
setIndexTerm(d[], ieNim, htmlFile = external, id = symbolOrId, term = name,
linkTitle = detailedName,
linkDesc = xmltree.escape(plainDocstring.docstringSummary),
line = n.info.line.int)
if k == skType and nameNode.kind == nkSym:
d.types.strTableAdd nameNode.sym
proc genJsonItem(d: PDoc, n, nameNode: PNode, k: TSymKind): JsonItem =
if not isVisible(d, nameNode): return
var
name = getName(d, nameNode)
name = getNameEsc(d, nameNode)
comm = genRecComment(d, n)
r: TSrcGen
initTokRender(r, n, {renderNoBody, renderNoComments, renderDocComments, renderExpandUsing})
@@ -1337,9 +1369,31 @@ proc generateDoc*(d: PDoc, n, orig: PNode, docFlags: DocFlags = kDefault) =
proc overloadGroupName(s: string, k: TSymKind): string =
## Turns a name like `f` into anchor `f-procs-all`
#s & " " & k.toHumanStr & "s all"
s & "-" & k.toHumanStr & "s-all"
proc setIndexTitle(d: PDoc, useMetaTitle: bool) =
let titleKind = if d.standaloneDoc: ieMarkupTitle else: ieNimTitle
let external = AbsoluteFile(d.destFile)
.relativeTo(d.conf.outDir, '/')
.changeFileExt(HtmlExt)
.string
var term, linkTitle: string
if useMetaTitle and d.meta[metaTitle].len != 0:
term = d.meta[metaTitleRaw]
linkTitle = d.meta[metaTitleRaw]
else:
let filename = extractFilename(d.filename)
term =
if d.standaloneDoc: filename # keep .rst/.md extension
else: changeFileExt(filename, "") # rm .nim extension
linkTitle =
if d.standaloneDoc: term # keep .rst/.md extension
else: canonicalImport(d.conf, AbsoluteFile d.filename)
if not d.standaloneDoc:
linkTitle = "module " & linkTitle
setIndexTerm(d[], titleKind, htmlFile = external, id = "",
term = term, linkTitle = linkTitle)
proc finishGenerateDoc*(d: var PDoc) =
## Perform 2nd RST pass for resolution of links/footnotes/headings...
# copy file map `filenames` to ``rstgen.nim`` for its warnings
@@ -1352,7 +1406,24 @@ proc finishGenerateDoc*(d: var PDoc) =
firstRst = fragment.rst
break
d.hasToc = d.hasToc or d.sharedState.hasToc
preparePass2(d.sharedState, firstRst)
# in --index:only mode we do NOT want to load other .idx, only write ours:
let importdoc = optGenIndexOnly notin d.conf.globalOptions and
optNoImportdoc notin d.conf.globalOptions
preparePass2(d.sharedState, firstRst, importdoc)
if optGenIndexOnly in d.conf.globalOptions:
# Top-level doc.comments may contain titles and :idx: statements:
for fragment in d.modDescPre:
if fragment.isRst:
traverseForIndex(d[], fragment.rst)
setIndexTitle(d, useMetaTitle = d.standaloneDoc)
# Symbol-associated doc.comments may contain :idx: statements:
for k in TSymKind:
for _, overloadChoices in d.section[k].secItems:
for item in overloadChoices:
for fragment in item.descRst:
if fragment.isRst:
traverseForIndex(d[], fragment.rst)
# add anchors to overload groups before RST resolution
for k in TSymKind:
@@ -1362,14 +1433,25 @@ proc finishGenerateDoc*(d: var PDoc) =
let refn = overloadGroupName(plainName, k)
let tooltip = "$1 ($2 overloads)" % [
k.toHumanStr & " " & plainName, $overloadChoices.len]
addAnchorNim(d.sharedState, refn, tooltip,
let name = nimIdentBackticksNormalize(plainName)
# save overload group to ``.idx``
let external = d.destFile.AbsoluteFile.relativeTo(d.conf.outDir, '/').
changeFileExt(HtmlExt).string
setIndexTerm(d[], ieNimGroup, htmlFile = external, id = refn,
term = name, linkTitle = k.toHumanStr,
linkDesc = "", line = overloadChoices[0].info.line.int)
if optGenIndexOnly in d.conf.globalOptions: continue
addAnchorNim(d.sharedState, external=false, refn, tooltip,
LangSymbol(symKind: k.toHumanStr,
name: nimIdentBackticksNormalize(plainName),
name: name,
isGroup: true),
priority = symbolPriority(k),
# select index `0` just to have any meaningful warning:
info = overloadChoices[0].info)
if optGenIndexOnly in d.conf.globalOptions:
return
# Finalize fragments of ``.nim`` or ``.rst`` file
proc renderItemPre(d: PDoc, fragments: ItemPre, result: var string) =
for f in fragments:
@@ -1421,6 +1503,9 @@ proc finishGenerateDoc*(d: var PDoc) =
d.jEntriesFinal.add entry.json # generates docs
setIndexTitle(d, useMetaTitle = d.standaloneDoc)
completePass2(d.sharedState)
proc add(d: PDoc; j: JsonItem) =
if j.json != nil or j.rst != nil: d.jEntriesPre.add j
@@ -1467,7 +1552,7 @@ proc generateJson*(d: PDoc, n: PNode, includeComments: bool = true) =
else: discard
proc genTagsItem(d: PDoc, n, nameNode: PNode, k: TSymKind): string =
result = getName(d, nameNode) & "\n"
result = getNameEsc(d, nameNode) & "\n"
proc generateTags*(d: PDoc, n: PNode, r: var string) =
case n.kind
@@ -1574,13 +1659,7 @@ proc genOutFile(d: PDoc, groupedToc = false): string =
# Extract the title. Non API modules generate an entry in the index table.
if d.meta[metaTitle].len != 0:
title = d.meta[metaTitle]
let external = AbsoluteFile(d.destFile)
.relativeTo(d.conf.outDir, '/')
.changeFileExt(HtmlExt)
.string
setIndexTerm(d[], external, "", title)
else:
# Modules get an automatic title for the HTML, but no entry in the index.
title = canonicalImport(d.conf, AbsoluteFile d.filename)
title = esc(d.target, title)
var subtitle = ""
@@ -1619,11 +1698,17 @@ proc genOutFile(d: PDoc, groupedToc = false): string =
code = content
result = code
proc indexFile(d: PDoc): AbsoluteFile =
let dir = d.conf.outDir
result = dir / changeFileExt(presentationPath(d.conf,
AbsoluteFile d.filename),
IndexExt)
let (finalDir, _, _) = result.string.splitFile
createDir(finalDir)
proc generateIndex*(d: PDoc) =
if optGenIndex in d.conf.globalOptions:
let dir = d.conf.outDir
createDir(dir)
let dest = dir / changeFileExt(presentationPath(d.conf, AbsoluteFile d.filename), IndexExt)
let dest = indexFile(d)
writeIndexFile(d[], dest.string)
proc updateOutfile(d: PDoc, outfile: AbsoluteFile) =
@@ -1634,6 +1719,9 @@ proc updateOutfile(d: PDoc, outfile: AbsoluteFile) =
d.conf.outFile = splitPath(d.conf.outFile.string)[1].RelativeFile
proc writeOutput*(d: PDoc, useWarning = false, groupedToc = false) =
if optGenIndexOnly in d.conf.globalOptions:
d.conf.outFile = indexFile(d).relativeTo(d.conf.outDir) # just for display
return
runAllExamples(d)
var content = genOutFile(d, groupedToc)
if optStdout in d.conf.globalOptions:
@@ -1772,6 +1860,8 @@ proc commandTags*(cache: IdentCache, conf: ConfigRef) =
rawMessage(conf, errCannotOpenFile, filename.string)
proc commandBuildIndex*(conf: ConfigRef, dir: string, outFile = RelativeFile"") =
if optGenIndexOnly in conf.globalOptions:
return
var content = mergeIndexes(dir)
var outFile = outFile

View File

@@ -57,6 +57,7 @@ type
warnRstBrokenLink = "BrokenLink",
warnRstLanguageXNotSupported = "LanguageXNotSupported",
warnRstFieldXNotSupported = "FieldXNotSupported",
warnRstUnusedImportdoc = "UnusedImportdoc",
warnRstStyle = "warnRstStyle",
warnCommentXIgnored = "CommentXIgnored",
warnTypelessParam = "TypelessParam",
@@ -142,6 +143,7 @@ const
warnRstBrokenLink: "broken link '$1'",
warnRstLanguageXNotSupported: "language '$1' not supported",
warnRstFieldXNotSupported: "field '$1' not supported",
warnRstUnusedImportdoc: "importdoc for '$1' is not used",
warnRstStyle: "RST style: $1",
warnCommentXIgnored: "comment '$1' ignored",
warnTypelessParam: "", # deadcode

View File

@@ -78,6 +78,8 @@ type # please make sure we have under 32 options
optThreadAnalysis, # thread analysis pass
optTlsEmulation, # thread var emulation turned on
optGenIndex # generate index file for documentation;
optGenIndexOnly # generate only index file for documentation
optNoImportdoc # disable loading external documentation files
optEmbedOrigSrc # embed the original source in the generated code
# also: generate header file
optIdeDebug # idetools: debug mode

View File

@@ -130,7 +130,9 @@ Advanced options:
select which memory management to use; default is 'orc'
--exceptions:setjmp|cpp|goto|quirky
select the exception handling implementation
--index:on|off turn index file generation on|off
--index:on|off|only docgen: turn index file generation? (`only` means
not generate output files like HTML)
--noImportdoc:on|off disable loading documentation ``.idx`` files?
--putenv:key=value set an environment variable
--NimblePath:PATH add a path for Nimble support
--noNimblePath deactivate the Nimble path

View File

@@ -9,6 +9,7 @@
.. include:: rstcommon.rst
.. contents::
.. importdoc:: markdown_rst.md, compiler/docgen.nim
Introduction
============
@@ -103,6 +104,64 @@ won't influence RST formatting.
## Paragraph.
```
Structuring output directories
------------------------------
Basic directory for output is set by `--outdir:OUTDIR`:option: switch,
by default `OUTDIR` is ``htmldocs`` sub-directory in the directory of
the processed file.
There are 2 basic options as to how generated HTML output files are stored:
1) complex hierarchy when docgen-compiling with `--project`:option:,
which follows directory structure of the project itself.
So `nim doc`:cmd: replicates project's directory structure
inside `--outdir:OUTDIR`:option: directory.
`--project`:option: is well suited for projects that have 1 main module.
File name clashes are impossible in this case.
2) flattened structure, where user-provided script goes through all
needed input files and calls commands like `nim doc`:cmd:
with `--outdir:OUTDIR`:option: switch, thus putting all HTML (and
``.idx``) files into 1 directory.
.. Important:: Make sure that you don't have files with same base name
like ``x.nim`` and ``x.md`` in the same package, otherwise you'll
have name conflict for ``x.html``.
.. Tip:: To structure your output directories and avoid file name
clashes you can split your project into
different *packages* -- parts of your repository that are
docgen-compiled with different `--outdir:OUTDIR`:option: options.
An example of such strategy is Nim repository itself which has:
* its stdlib ``.nim`` files from different directories and ``.md``
documentation from ``doc/`` directory are all docgen-compiled
into `--outdir:web/upload/<version>/`:option: directory
* its ``.nim`` files from ``compiler/`` directory are docgen-compiled
into `--outdir:web/upload/<version>/compiler/`:option: directory.
Interestingly, it's compiled with complex hierarchy using
`--project`:option: switch.
Contents of ``web/upload/<version>`` are then deployed into Nim's
Web server.
This output directory structure allows to work correctly with files like
``compiler/docgen.nim`` (implementation) and ``doc/docgen.md`` (user
documentation) in 1 repository.
Index files
-----------
Index (``.idx``) files are used for 2 different purposes:
1. easy cross-referencing between different ``.nim`` and/or ``.md`` / ``.rst``
files described in [Nim external referencing]
2. creating a whole-project index for searching of symbols and keywords,
see [Buildindex command].
Document Types
==============
@@ -226,13 +285,46 @@ Note that the `jsondoc`:option: command outputs its JSON without pretty-printing
while `jsondoc0`:option: outputs pretty-printed JSON.
Referencing Nim symbols: simple documentation links
===================================================
Simple documentation links
==========================
You can reference Nim identifiers from Nim documentation comments, currently
only inside their ``.nim`` file (or inside a ``.rst`` file included from
a ``.nim``). The point is that such links will be resolved automatically
by `nim doc`:cmd: (or `nim jsondoc`:cmd: or `nim doc2tex`:cmd:).
It's possible to use normal Markdown/RST syntax to *manually*
reference Nim symbols using HTML anchors, however Nim has an *automatic*
facility that makes referencing inside ``.nim`` and ``.md/.rst`` files and
between them easy and seamless.
The point is that such links will be resolved automatically
by `nim doc`:cmd: (or `md2html`:option:, or `jsondoc`:option:,
or `doc2tex`:option:, ...). And, unlike manual links, such automatic
links **check** that their target exists -- a warning is emitted for
any broken link, so you avoid broken links in your project.
Nim treats both ``.md/.rst`` files and ``.nim`` modules (their doc comment
part) as *documents* uniformly.
Hence all directions of referencing are equally possible having the same syntax:
1. ``.md/rst`` -> itself (internal). See [Markup local referencing].
2. ``.md/rst`` -> external ``.md/rst``. See [Markup external referencing].
To summarize, referencing in `.md`/`.rst` files was already described in
[Nim-flavored Markdown and reStructuredText]
(particularly it described usage of index files for referencing),
while in this document we focus on Nim-specific details.
3. ``.md/rst`` -> external ``.nim``. See [Nim external referencing].
4. ``.nim`` -> itself (internal). See [Nim local referencing].
5. ``.nim`` -> external ``.md/rst``. See [Markup external referencing].
6. ``.nim`` -> external ``.nim``. See [Nim external referencing].
To put it shortly, local referencing always works out of the box,
external referencing requires to use ``.. importdoc:: <file>``
directive to import `file` and to ensure that the corresponding
``.idx`` file was generated.
Nim local referencing
---------------------
You can reference Nim identifiers from Nim documentation comments
inside their ``.nim`` file (or inside a ``.rst`` file included from
a ``.nim``).
This pertains to any exported symbol like `proc`, `const`, `iterator`, etc.
Syntax for referencing is basically a normal RST one: addition of
underscore `_` to a *link text*.
@@ -405,6 +497,143 @@ recognized fine:
...
## Ref. `CopyFlag enum`_
Nim external referencing
------------------------
Just like for [Markup external referencing], which saves markup anchors,
the Nim symbols are also saved in ``.idx`` files, so one needs
to generate them beforehand, and they should be loaded by
an ``.. importdoc::`` directive. Arguments to ``.. importdoc::`` is a
comma-separated list of Nim modules or Markdown/RST documents.
`--index:only`:option: tells Nim to only generate ``.idx`` file and
do **not** attempt to generate HTML/LaTeX output.
For ``.nim`` modules there are 2 alternatives to work with ``.idx`` files:
1. using [Project switch] implies generation of ``.idx`` files,
however, if ``importdoc`` is called on upper modules as its arguments,
their ``.idx`` are not yet created. Thus one should generate **all**
required ``.idx`` first:
```cmd
nim doc --project --index:only <main>.nim
nim doc --project <main>.nim
```
2. or run `nim doc --index:only <module.nim>`:cmd: command for **all** (used)
Nim modules in your project. Then run `nim doc <module.nim>` on them for
output HTML generation.
.. Warning:: A mere `nim doc --index:on`:cmd: may fail on an attempt to do
``importdoc`` from another module (for which ``.idx`` was not yet
generated), that's why `--index:only`:option: shall be used instead.
For ``.md``/``.rst`` markup documents point 2 is the only option.
Then, you can freely use something like this in ``your_module.nim``:
```nim
## .. importdoc:: user_manual.md, another_module.nim
...
## Ref. [some section from User Manual].
...
## Ref. [proc f]
## (assuming you have a proc `f` in ``another_module``).
```
and compile it by `nim doc`:cmd:. Note that link text will
be automatically prefixed by the module name of symbol,
so you will see something like "Ref. [another_module: proc f](#)"
in the generated output.
It's also possible to reference a whole module by prefixing or
suffixing full canonical module name with "module":
Ref. [module subdir/name] or [subdir/name module].
Markup documents as a whole can be referenced just by their title
(or by their file name if the title was not set) without any prefix.
.. Tip:: During development process the stage of ``.idx`` files generation
can be done only *once*, after that you use already generated ``.idx``
files while working with a document *being developed* (unless you do
incompatible changes to *referenced* documents).
.. Hint:: After changing a *referenced* document file one may need
to regenerate its corresponding ``.idx`` file to get correct results.
Of course, when referencing *internally* inside any given ``.nim`` file,
it's not needed, one can even immediately use any freshly added anchor
(a document's own ``.idx`` file is not used for resolving its internal links).
If an ``importdoc`` directive fails to find a ``.idx``, then an error
is emitted.
In case of such compilation failures please note that:
* **all** relative paths, given to ``importdoc``, relate to insides of
``OUTDIR``, and **not** project's directory structure.
* ``importdoc`` searches for ``.idx`` in `--outdir:OUTDIR`:option: directory
(``htmldocs`` by default) and **not** around original modules, so:
.. Tip:: look into ``OUTDIR`` to understand what's going on.
* also keep in mind that ``.html`` and ``.idx`` files should always be
output to the same directory, so check this and, if it's not true, check
that both runs *with* and *without* `--index:only`:option: have all
other options the same.
To summarize, for 2 basic options of [Structuring output directories]
compilation options are different:
1) complex hierarchy with `--project`:option: switch.
As the **original** project's directory structure is replicated in
`OUTDIR`, all passed paths are related to this structure also.
E.g. if a module ``path1/module.nim`` does
``.. importdoc:: path2/another.nim`` then docgen tries to load file
``OUTDIR/path1/path2/another.idx``.
.. Note:: markup documents are just placed into the specified directory
`OUTDIR`:option: by default (i.e. they are **not** affected by
`--project`:option:), so if you have ``PROJECT/doc/manual.md``
document and want to use complex hirearchy (with ``doc/``),
compile it with `--docroot`:option:\:
```cmd
# 1st stage
nim md2html --outdir:OUTDIR --docroot:/absolute/path/to/PROJECT \
--index:only PROJECT/doc/manual.md
...
# 2nd stage
nim md2html --outdir:OUTDIR --docroot:/absolute/path/to/PROJECT \
PROJECT/doc/manual.md
```
Then the output file will be placed as ``OUTDIR/doc/manual.idx``.
So if you have ``PROJECT/path1/module.nim``, then ``manual.md`` can
be referenced as ``../doc/manual.md``.
2) flattened structure.
E.g. if a module ``path1/module.nim`` does
``.. importdoc:: path2/another.nim`` then docgen tries to load
``OUTDIR/path2/another.idx``, so the path ``path1``
does not matter and providing ``path2`` can be useful only
in the case it contains another package that was placed there
using `--outdir:OUTDIR/path2`:option:.
The links' text will be prefixed as ``another: ...`` in both cases.
.. Warning:: Again, the same `--outdir:OUTDIR`:option: option should
be provided to both `doc --index:only`:option: /
`md2html --index:only`:option: and final generation by
`doc`:option:/`md2html`:option: inside 1 package.
To temporarily disable ``importdoc``, e.g. if you don't need
correct link resolution at the moment, use a `--noImportdoc`:option: switch
(only warnings about unresolved links will be generated for external references).
Related Options
===============
@@ -434,10 +663,21 @@ index file is line-oriented (newlines have to be escaped). Each line
represents a tab-separated record of several columns, the first two mandatory,
the rest optional. See the [Index (idx) file format] section for details.
.. Note:: `--index`:option: switch only affects creation of ``.idx``
index files, while user-searchable Index HTML file is created by
`buildIndex`:option: commmand.
Buildindex command
------------------
Once index files have been generated for one or more modules, the Nim
compiler command `buildIndex directory` can be run to go over all the index
compiler command `nim buildIndex directory`:cmd: can be run to go over all the index
files in the specified directory to generate a [theindex.html](theindex.html)
file.
file:
```cmd
nim buildIndex -o:path/to/htmldocs/theindex.html path/to/htmldocs
```
See source switch
-----------------
@@ -568,10 +808,22 @@ references so they can be later concatenated into a big index file with
the file format in detail.
Index files are line-oriented and tab-separated (newline and tab characters
have to be escaped). Each line represents a record with at least two fields
but can have up to four (additional columns are ignored). The content of these
columns is:
have to be escaped). Each line represents a record with 6 fields.
The content of these columns is:
0. Discriminator tag denoting type of the index entry, allowed values are:
`markupTitle`
: a title for ``.md``/``.rst`` document
`nimTitle`
: a title of ``.nim`` module
`heading`
: heading of sections, can be both in Nim and markup files
`idx`
: terms marked with :idx: role
`nim`
: a Nim symbol
`nimgrp`
: a Nim group for overloadable symbols like `proc`s
1. Mandatory term being indexed. Terms can include quoting according to
Nim's rules (e.g. \`^\`).
2. Base filename plus anchor hyperlink (e.g. ``algorithm.html#*,int,SortOrder``).
@@ -581,29 +833,20 @@ columns is:
not for an API symbol but for a TOC entry.
4. Optional title or description of the hyperlink. Browsers usually display
this as a tooltip after hovering a moment over the hyperlink.
5. A line number of file where the entry was defined.
The index generation tools try to differentiate between documentation
generated from ``.nim`` files and documentation generated from ``.txt`` or
``.rst`` files. The former are always closely related to source code and
consist mainly of API entries. The latter are generic documents meant for
human reading.
The index generation tools differentiate between documentation
generated from ``.nim`` files and documentation generated from ``.md`` or
``.rst`` files by tag `nimTitle` or `markupTitle` in the 1st line of
the ``.idx`` file.
To differentiate both types (documents and APIs), the index generator will add
to the index of documents an entry with the title of the document. Since the
title is the topmost element, it will be added with a second field containing
just the filename without any HTML anchor. By convention, this entry without
anchor is the *title entry*, and since entries in the index file are added as
they are scanned, the title entry will be the first line. The title for APIs
is not present because it can be generated concatenating the name of the file
to the word **Module**.
Normal symbols are added to the index with surrounding whitespaces removed. An
exception to this are the table of content (TOC) entries. TOC entries are added to
the index file with their third column having as much prefix spaces as their
level is in the TOC (at least 1 character). The prefix whitespace helps to
filter TOC entries from API or text symbols. This is important because the
amount of spaces is used to replicate the hierarchy for document TOCs in the
final index, and TOC entries found in ``.nim`` files are discarded.
.. TODO Normal symbols are added to the index with surrounding whitespaces removed. An
exception to this are the table of content (TOC) entries. TOC entries are added to
the index file with their third column having as much prefix spaces as their
level is in the TOC (at least 1 character). The prefix whitespace helps to
filter TOC entries from API or text symbols. This is important because the
amount of spaces is used to replicate the hierarchy for document TOCs in the
final index, and TOC entries found in ``.nim`` files are discarded.
Additional resources
@@ -615,6 +858,8 @@ Additional resources
[Markdown and RST markup languages](markdown_rst.html), which also
contains the list of implemented features of these markup languages.
* the implementation is in [module compiler/docgen].
The output for HTML and LaTeX comes from the ``config/nimdoc.cfg`` and
``config/nimdoc.tex.cfg`` configuration files. You can add and modify these
files to your project to change the look of the docgen output.

View File

@@ -9,6 +9,8 @@ Nim-flavored Markdown and reStructuredText
.. include:: rstcommon.rst
.. contents::
.. importdoc:: docgen.md
Both `Markdown`:idx: (md) and `reStructuredText`:idx: (RST) are markup
languages whose goal is to typeset texts with complex structure,
formatting and references using simple plaintext representation.
@@ -110,6 +112,8 @@ Supported standard RST features:
Additional Nim-specific features
--------------------------------
* referencing to definitions in external files, see
[Markup external referencing] section
* directives: ``code-block`` \[cmp:Sphinx], ``title``,
``index`` \[cmp:Sphinx]
* predefined roles
@@ -170,6 +174,86 @@ Optional additional features, by default turned on:
.. warning:: Using Nim-specific features can cause other RST implementations
to fail on your document.
Referencing
===========
To be able to copy and share links Nim generates anchors for all
main document elements:
* headlines (including document title)
* footnotes
* explicitly set anchors: RST internal cross-references and
inline internal targets
* Nim symbols (external referencing), see [Nim DocGen Tools Guide] for details.
But direct use of those anchors have 2 problems:
1. the anchors are usually mangled (e.g. spaces substituted to minus
signs, etc).
2. manual usage of anchors is not checked, so it's easy to get broken
links inside your project if e.g. spelling has changed for a heading
or you use a wrong relative path to your document.
That's why Nim implementation has syntax for using
*original* labels for referencing.
Such referencing can be either local/internal or external:
* Local referencing (inside any given file) is defined by
RST standard or Pandoc Markdown User guide.
* External (cross-document) referencing is a Nim-specific feature,
though it's not really different from local referencing by its syntax.
Markup local referencing
------------------------
There are 2 syntax option available for referencing to objects
inside any given file, e.g. for headlines:
Markdown RST
Some headline Some headline
============= =============
Ref. [Some headline] Ref. `Some headline`_
Markup external referencing
---------------------------
The syntax is the same as for local referencing, but the anchors are
saved in ``.idx`` files, so one needs to generate them beforehand,
and they should be loaded by an `.. importdoc::` directive.
E.g. if we want to reference section "Some headline" in ``file1.md``
from ``file2.md``, then ``file2.md`` may look like:
```
.. importdoc:: file1.md
Ref. [Some headline]
```
```cmd
nim md2html --index:only file1.md # creates ``htmldocs/file1.idx``
nim md2html file2.md # creates ``htmldocs/file2.html``
```
To allow cross-references between any files in any order (especially, if
circular references are present), it's strongly reccommended
to make a run for creating all the indexes first:
```cmd
nim md2html --index:only file1.md # creates ``htmldocs/file1.idx``
nim md2html --index:only file2.md # creates ``htmldocs/file2.idx``
nim md2html file1.md # creates ``htmldocs/file1.html``
nim md2html file2.md # creates ``htmldocs/file2.html``
```
and then one can freely reference any objects as if these 2 documents
are actually 1 file.
Other
=====
Idiosyncrasies
--------------

View File

@@ -23,6 +23,8 @@ when defined(nimPreviewSlimSystem):
## .. include:: ../../doc/astspec.txt
## .. importdoc:: system.nim
# If you look for the implementation of the magic symbol
# ``{.magic: "Foo".}``, search for `mFoo` and `opcFoo`.

View File

@@ -13,7 +13,7 @@
## `type LangSymbol`_ in ``rst.nim``, while `match(generated, docLink)`_
## matches it with `generated`, produced from `PNode` by ``docgen.rst``.
import rstast
import rstast, strutils
when defined(nimPreviewSlimSystem):
import std/[assertions, syncio]
@@ -35,6 +35,12 @@ type
## name-type seq, e.g. for proc
outType*: string ## result type, e.g. for proc
proc `$`*(s: LangSymbol): string = # for debug
("(symkind=$1, symTypeKind=$2, name=$3, generics=$4, isGroup=$5, " &
"parametersProvided=$6, parameters=$7, outType=$8)") % [
s.symKind, s.symTypeKind , s.name, s.generics, $s.isGroup,
$s.parametersProvided, $s.parameters, s.outType]
func nimIdentBackticksNormalize*(s: string): string =
## Normalizes the string `s` as a Nim identifier.
##
@@ -71,6 +77,12 @@ func nimIdentBackticksNormalize*(s: string): string =
else: discard # just omit '`' or ' '
if j != s.len: setLen(result, j)
proc langSymbolGroup*(kind: string, name: string): LangSymbol =
if kind notin ["proc", "func", "macro", "method", "iterator",
"template", "converter"]:
raise newException(ValueError, "unknown symbol kind $1" % [kind])
result = LangSymbol(symKind: kind, name: name, isGroup: true)
proc toLangSymbol*(linkText: PRstNode): LangSymbol =
## Parses `linkText` into a more structured form using a state machine.
##
@@ -82,11 +94,14 @@ proc toLangSymbol*(linkText: PRstNode): LangSymbol =
##
## This proc should be kept in sync with the `renderTypes` proc from
## ``compiler/typesrenderer.nim``.
assert linkText.kind in {rnRstRef, rnInner}
template fail(msg: string) =
raise newException(ValueError, msg)
if linkText.kind notin {rnRstRef, rnInner}:
fail("toLangSymbol: wrong input kind " & $linkText.kind)
const NimDefs = ["proc", "func", "macro", "method", "iterator",
"template", "converter", "const", "type", "var",
"enum", "object", "tuple"]
"enum", "object", "tuple", "module"]
template resolveSymKind(x: string) =
if x in ["enum", "object", "tuple"]:
result.symKind = "type"
@@ -109,11 +124,11 @@ proc toLangSymbol*(linkText: PRstNode): LangSymbol =
template flushIdent() =
if curIdent != "":
case state
of inBeginning: doAssert false, "incorrect state inBeginning"
of inBeginning: fail("incorrect state inBeginning")
of afterSymKind: resolveSymKind curIdent
of beforeSymbolName: doAssert false, "incorrect state beforeSymbolName"
of beforeSymbolName: fail("incorrect state beforeSymbolName")
of atSymbolName: result.name = curIdent.nimIdentBackticksNormalize
of afterSymbolName: doAssert false, "incorrect state afterSymbolName"
of afterSymbolName: fail("incorrect state afterSymbolName")
of genericsPar: result.generics = curIdent
of parameterName: result.parameters.add (curIdent, "")
of parameterType:

View File

@@ -22,7 +22,7 @@
import
os, strutils, rstast, dochelpers, std/enumutils, algorithm, lists, sequtils,
std/private/miscdollars, tables, strscans
std/private/miscdollars, tables, strscans, rstidx
from highlite import SourceLanguage, getSourceLanguage
when defined(nimPreviewSlimSystem):
@@ -40,7 +40,7 @@ type
roNimFile ## set for Nim files where default interpreted
## text role should be :nim:
roSandboxDisabled ## this option enables certain options
## (e.g. raw, include)
## (e.g. raw, include, importdoc)
## which are disabled by default as they can
## enable users to read arbitrary data and
## perform XSS if the parser is used in a web
@@ -73,11 +73,17 @@ type
mwUnsupportedLanguage = "language '$1' not supported",
mwUnsupportedField = "field '$1' not supported",
mwRstStyle = "RST style: $1",
mwUnusedImportdoc = "importdoc for '$1' is not used",
meSandboxedDirective = "disabled directive: '$1'",
MsgHandler* = proc (filename: string, line, col: int, msgKind: MsgKind,
arg: string) {.closure, gcsafe.} ## what to do in case of an error
FindFileHandler* = proc (filename: string): string {.closure, gcsafe.}
FindRefFileHandler* =
proc (targetRelPath: string):
tuple[targetPath: string, linkRelPath: string] {.closure, gcsafe.}
## returns where .html or .idx file should be found by its relative path;
## `linkRelPath` is a prefix to be added before a link anchor from such file
proc rstnodeToRefname*(n: PRstNode): string
proc addNodes*(n: PRstNode): string
@@ -333,7 +339,8 @@ type
arInternalRst, ## For automatically generated RST anchors (from
## headings, footnotes, inline internal targets):
## case-insensitive, 1-space-significant (by RST spec)
arNim ## For anchors generated by ``docgen.rst``: Nim-style case
arExternalRst, ## For external .nim doc comments or .rst/.md
arNim ## For anchors generated by ``docgen.nim``: Nim-style case
## sensitivity, etc. (see `proc normalizeNimName`_ for details)
arHyperlink, ## For links with manually set anchors in
## form `text <pagename.html#anchor>`_
@@ -349,11 +356,15 @@ type
of arInternalRst:
anchorType: RstAnchorKind
target: PRstNode
of arExternalRst:
anchorTypeExt: RstAnchorKind
refnameExt: string
of arNim:
tooltip: string # displayed tooltip for Nim-generated anchors
langSym: LangSymbol
refname: string # A reference name that will be inserted directly
# into HTML/Latex.
external: bool
AnchorSubstTable = Table[string, seq[AnchorSubst]]
# use `seq` to account for duplicate anchors
FootnoteType = enum
@@ -372,6 +383,12 @@ type
RstFileTable* = object
filenameToIdx*: Table[string, FileIndex]
idxToFilename*: seq[string]
ImportdocInfo = object
used: bool # was this import used?
fromInfo: TLineInfo # place of `.. importdoc::` directive
idxPath: string # full path to ``.idx`` file
linkRelPath: string # prefix before target anchor
title: string # document title obtained from ``.idx``
RstSharedState = object
options*: RstParseOptions # parsing options
hLevels: LevelMap # hierarchy of heading styles
@@ -393,12 +410,17 @@ type
footnotes: seq[FootnoteSubst] # correspondence b/w footnote label,
# number, order of occurrence
msgHandler: MsgHandler # How to handle errors.
findFile: FindFileHandler # How to find files.
findFile: FindFileHandler # How to find files for include.
findRefFile: FindRefFileHandler
# How to find files imported by importdoc.
filenames*: RstFileTable # map file name <-> FileIndex (for storing
# file names for warnings after 1st stage)
currFileIdx*: FileIndex # current index in `filenames`
tocPart*: seq[PRstNode] # all the headings of a document
hasToc*: bool
idxImports*: Table[string, ImportdocInfo]
# map `importdoc`ed filename -> it's info
nimFileImported*: bool # Was any ``.nim`` module `importdoc`ed ?
PRstSharedState* = ref RstSharedState
ManualAnchor = object
@@ -452,6 +474,9 @@ proc defaultFindFile*(filename: string): string =
if fileExists(filename): result = filename
else: result = ""
proc defaultFindRefFile*(filename: string): (string, string) =
(filename, "")
proc defaultRole(options: RstParseOptions): string =
if roNimFile in options: "nim" else: "literal"
@@ -492,12 +517,16 @@ proc getFilename(filenames: RstFileTable, fid: FileIndex): string =
$fid.int, $(filenames.len - 1)])
result = filenames.idxToFilename[fid.int]
proc getFilename(s: PRstSharedState, subst: AnchorSubst): string =
getFilename(s.filenames, subst.info.fileIndex)
proc currFilename(s: PRstSharedState): string =
getFilename(s.filenames, s.currFileIdx)
proc newRstSharedState*(options: RstParseOptions,
filename: string,
findFile: FindFileHandler,
findRefFile: FindRefFileHandler,
msgHandler: MsgHandler,
hasToc: bool): PRstSharedState =
let r = defaultRole(options)
@@ -507,6 +536,9 @@ proc newRstSharedState*(options: RstParseOptions,
options: options,
msgHandler: if not isNil(msgHandler): msgHandler else: defaultMsgHandler,
findFile: if not isNil(findFile): findFile else: defaultFindFile,
findRefFile:
if not isNil(findRefFile): findRefFile
else: defaultFindRefFile,
hasToc: hasToc
)
setCurrFilename(result, filename)
@@ -525,6 +557,14 @@ proc rstMessage(p: RstParser, msgKind: MsgKind, arg: string) =
proc rstMessage(s: PRstSharedState, msgKind: MsgKind, arg: string) =
s.msgHandler(s.currFilename, LineRstInit, ColRstInit, msgKind, arg)
proc rstMessage(s: PRstSharedState, msgKind: MsgKind, arg: string;
line, col: int) =
s.msgHandler(s.currFilename, line, col, msgKind, arg)
proc rstMessage(s: PRstSharedState, filename: string, msgKind: MsgKind,
arg: string) =
s.msgHandler(filename, LineRstInit, ColRstInit, msgKind, arg)
proc rstMessage*(filenames: RstFileTable, f: MsgHandler,
info: TLineInfo, msgKind: MsgKind, arg: string) =
## Print warnings using `info`, i.e. in 2nd-pass warnings for
@@ -756,6 +796,14 @@ proc internalRefPriority(k: RstAnchorKind): int =
of footnoteAnchor: result = 4
of headlineAnchor: result = 3
proc `$`(subst: AnchorSubst): string = # for debug
let s =
case subst.kind
of arInternalRst: "type=" & $subst.anchorType
of arExternalRst: "type=" & $subst.anchorTypeExt
of arNim: "langsym=" & $subst.langSym
result = "(kind=$1, priority=$2, $3)" % [$subst.kind, $subst.priority, s]
proc addAnchorRst(p: var RstParser, name: string, target: PRstNode,
anchorType: RstAnchorKind) =
## Associates node `target` (which has field `anchor`) with an
@@ -771,31 +819,49 @@ proc addAnchorRst(p: var RstParser, name: string, target: PRstNode,
info: prevLineInfo(p), anchorType: anchorType))
p.curAnchors.setLen 0
proc addAnchorNim*(s: var PRstSharedState, refn: string, tooltip: string,
proc addAnchorExtRst(s: var PRstSharedState, key: string, refn: string,
anchorType: RstAnchorKind, info: TLineInfo) =
let name = key.toLowerAscii
let prio = internalRefPriority(anchorType)
s.anchors.mgetOrPut(name, newSeq[AnchorSubst]()).add(
AnchorSubst(kind: arExternalRst, refnameExt: refn, priority: prio,
info: info,
anchorTypeExt: anchorType))
proc addAnchorNim*(s: var PRstSharedState, external: bool, refn: string, tooltip: string,
langSym: LangSymbol, priority: int,
info: TLineInfo) =
## Adds an anchor `refn`, which follows
## the rule `arNim` (i.e. a symbol in ``*.nim`` file)
s.anchors.mgetOrPut(langSym.name, newSeq[AnchorSubst]()).add(
AnchorSubst(kind: arNim, refname: refn, langSym: langSym,
AnchorSubst(kind: arNim, external: external, refname: refn, langSym: langSym,
tooltip: tooltip, priority: priority,
info: info))
proc findMainAnchorNim(s: PRstSharedState, signature: PRstNode,
info: TLineInfo):
seq[AnchorSubst] =
let langSym = toLangSymbol(signature)
var langSym: LangSymbol
try:
langSym = toLangSymbol(signature)
except ValueError: # parsing failed, not a Nim symbol
return
let substitutions = s.anchors.getOrDefault(langSym.name,
newSeq[AnchorSubst]())
if substitutions.len == 0:
return
# map symKind (like "proc") -> found symbols/groups:
var found: Table[string, seq[AnchorSubst]]
for s in substitutions:
if s.kind == arNim:
if match(s.langSym, langSym):
found.mgetOrPut(s.langSym.symKind, newSeq[AnchorSubst]()).add s
for symKind, sList in found:
# logic to select only groups instead of concrete symbols
# with overloads, note that the same symbol can be defined
# in multiple modules and `importdoc`ed:
type GroupKey = tuple[symKind: string, origModule: string]
# map (symKind, file) (like "proc", "os.nim") -> found symbols/groups:
var found: Table[GroupKey, seq[AnchorSubst]]
for subst in substitutions:
if subst.kind == arNim:
if match(subst.langSym, langSym):
let key: GroupKey = (subst.langSym.symKind, getFilename(s, subst))
found.mgetOrPut(key, newSeq[AnchorSubst]()).add subst
for key, sList in found:
if sList.len == 1:
result.add sList[0]
else: # > 1, there are overloads, potential ambiguity in this `symKind`
@@ -812,14 +878,16 @@ proc findMainAnchorNim(s: PRstSharedState, signature: PRstNode,
result.add s
foundGroup = true
break
doAssert foundGroup, "docgen has not generated the group"
doAssert(foundGroup,
"docgen has not generated the group for $1 (file $2)" % [
langSym.name, getFilename(s, sList[0]) ])
proc findMainAnchorRst(s: PRstSharedState, linkText: string, info: TLineInfo):
seq[AnchorSubst] =
let name = linkText.toLowerAscii
let substitutions = s.anchors.getOrDefault(name, newSeq[AnchorSubst]())
for s in substitutions:
if s.kind == arInternalRst:
if s.kind in {arInternalRst, arExternalRst}:
result.add s
proc addFootnoteNumManual(p: var RstParser, num: int) =
@@ -3251,6 +3319,15 @@ proc dirRaw(p: var RstParser): PRstNode =
else:
dirRawAux(p, result, rnRaw, parseSectionWrapper)
proc dirImportdoc(p: var RstParser): PRstNode =
result = parseDirective(p, rnDirective, {}, parseLiteralBlock)
assert result.sons[2].kind == rnLiteralBlock
assert result.sons[2].sons[0].kind == rnLeaf
let filenames: seq[string] = split(result.sons[2].sons[0].text, seps = {','})
proc rmSpaces(s: string): string = s.split.join("")
for origFilename in filenames:
p.s.idxImports[origFilename.rmSpaces] = ImportdocInfo(fromInfo: lineInfo(p))
proc selectDir(p: var RstParser, d: string): PRstNode =
result = nil
let tok = p.tok[p.idx-2] # report on directive in ".. directive::"
@@ -3271,6 +3348,7 @@ proc selectDir(p: var RstParser, d: string): PRstNode =
of "hint": result = dirAdmonition(p, d)
of "image": result = dirImage(p)
of "important": result = dirAdmonition(p, d)
of "importdoc": result = dirImportdoc(p)
of "include": result = dirInclude(p)
of "index": result = dirIndex(p)
of "note": result = dirAdmonition(p, d)
@@ -3401,11 +3479,90 @@ proc rstParsePass1*(fragment: string,
getTokens(fragment, p.tok)
result = parseDoc(p)
proc preparePass2*(s: PRstSharedState, mainNode: PRstNode) =
proc extractLinkEnd(x: string): string =
## From links like `path/to/file.html#/%` extract `file.html#/%`.
let i = find(x, '#')
let last =
if i >= 0: i
else: x.len - 1
let j = rfind(x, '/', start=0, last=last)
if j >= 0:
result = x[j+1 .. ^1]
else:
result = x
proc loadIdxFile(s: var PRstSharedState, origFilename: string) =
doAssert roSandboxDisabled in s.options
var info: TLineInfo
info.fileIndex = addFilename(s, origFilename)
var (dir, basename, ext) = origFilename.splitFile
if ext notin [".md", ".rst", ".nim", ""]:
rstMessage(s.filenames, s.msgHandler, s.idxImports[origFilename].fromInfo,
meCannotOpenFile, origFilename & ": unknown extension")
let idxFilename = dir / basename & ".idx"
let (idxPath, linkRelPath) = s.findRefFile(idxFilename)
s.idxImports[origFilename].linkRelPath = linkRelPath
var
fileEntries: seq[IndexEntry]
title: IndexEntry
try:
(fileEntries, title) = parseIdxFile(idxPath)
except IOError:
rstMessage(s.filenames, s.msgHandler, s.idxImports[origFilename].fromInfo,
meCannotOpenFile, idxPath)
except ValueError as e:
s.msgHandler(idxPath, LineRstInit, ColRstInit, meInvalidField, e.msg)
var isMarkup = false # for sanity check to avoid mixing .md <-> .nim
for entry in fileEntries:
# Though target .idx already has inside it the path to HTML relative
# project's root, we won't rely on it and use `linkRelPath` instead.
let refn = extractLinkEnd(entry.link)
# select either markup (rst/md) or Nim cases:
if entry.kind in {ieMarkupTitle, ieNimTitle}:
s.idxImports[origFilename].title = entry.keyword
case entry.kind
of ieIdxRole, ieHeading, ieMarkupTitle:
if ext == ".nim" and entry.kind == ieMarkupTitle:
rstMessage(s, idxPath, meInvalidField,
$ieMarkupTitle & " in supposedly .nim-derived file")
if entry.kind == ieMarkupTitle:
isMarkup = true
info.line = entry.line.uint16
addAnchorExtRst(s, key = entry.keyword, refn = refn,
anchorType = headlineAnchor, info=info)
of ieNim, ieNimGroup, ieNimTitle:
if ext in [".md", ".rst"] or isMarkup:
rstMessage(s, idxPath, meInvalidField,
$entry.kind & " in supposedly markup-derived file")
s.nimFileImported = true
var langSym: LangSymbol
if entry.kind in {ieNim, ieNimTitle}:
var q: RstParser
initParser(q, s)
info.line = entry.line.uint16
setLen(q.tok, 0)
q.idx = 0
getTokens(entry.linkTitle, q.tok)
var sons = newSeq[PRstNode](q.tok.len)
for i in 0 ..< q.tok.len: sons[i] = newLeaf(q.tok[i].symbol)
let linkTitle = newRstNode(rnInner, sons)
langSym = linkTitle.toLangSymbol
else: # entry.kind == ieNimGroup
langSym = langSymbolGroup(kind=entry.linkTitle, name=entry.keyword)
addAnchorNim(s, external = true, refn = refn, tooltip = entry.linkDesc,
langSym = langSym, priority = -4, # lowest
info=info)
doAssert s.idxImports[origFilename].title != ""
proc preparePass2*(s: var PRstSharedState, mainNode: PRstNode, importdoc = true) =
## Records titles in node `mainNode` and orders footnotes.
countTitles(s, mainNode)
fixHeadlines(s)
orderFootnotes(s)
if importdoc:
for origFilename in s.idxImports.keys:
loadIdxFile(s, origFilename)
proc resolveLink(s: PRstSharedState, n: PRstNode) : PRstNode =
# Associate this link alias with its target and change node kind to
@@ -3423,6 +3580,9 @@ proc resolveLink(s: PRstSharedState, n: PRstNode) : PRstNode =
tooltip: string
target: PRstNode
info: TLineInfo
externFilename: string
# when external anchor: origin filename where anchor was defined
isTitle: bool
proc cmp(x, y: LinkDef): int =
result = cmp(x.priority, y.priority)
if result == 0:
@@ -3435,26 +3595,67 @@ proc resolveLink(s: PRstSharedState, n: PRstNode) : PRstNode =
target: y.value, info: y.info,
tooltip: "(" & $y.kind & ")")
let substRst = findMainAnchorRst(s, alias.addNodes, n.info)
template getExternFilename(subst: AnchorSubst): string =
if subst.kind == arExternalRst or
(subst.kind == arNim and subst.external):
getFilename(s, subst)
else: ""
for subst in substRst:
foundLinks.add LinkDef(ar: arInternalRst, priority: subst.priority,
target: newLeaf(subst.target.anchor),
var refname, fullRefname: string
if subst.kind == arInternalRst:
refname = subst.target.anchor
fullRefname = refname
else: # arExternalRst
refname = subst.refnameExt
fullRefname = s.idxImports[getFilename(s, subst)].linkRelPath &
"/" & refname
let anchorType =
if subst.kind == arInternalRst: subst.anchorType
else: subst.anchorTypeExt # arExternalRst
foundLinks.add LinkDef(ar: subst.kind, priority: subst.priority,
target: newLeaf(fullRefname),
info: subst.info,
tooltip: "(" & $subst.anchorType & ")")
externFilename: getExternFilename(subst),
isTitle: isDocumentationTitle(refname),
tooltip: "(" & $anchorType & ")")
# find anchors automatically generated from Nim symbols
if roNimFile in s.options:
if roNimFile in s.options or s.nimFileImported:
let substNim = findMainAnchorNim(s, signature=alias, n.info)
for subst in substNim:
foundLinks.add LinkDef(ar: arNim, priority: subst.priority,
target: newLeaf(subst.refname),
let fullRefname =
if subst.external:
s.idxImports[getFilename(s, subst)].linkRelPath &
"/" & subst.refname
else: subst.refname
foundLinks.add LinkDef(ar: subst.kind, priority: subst.priority,
target: newLeaf(fullRefname),
externFilename: getExternFilename(subst),
isTitle: isDocumentationTitle(subst.refname),
info: subst.info, tooltip: subst.tooltip)
foundLinks.sort(cmp = cmp, order = Descending)
let aliasStr = addNodes(alias)
if foundLinks.len >= 1:
let kind = if foundLinks[0].ar == arHyperlink: rnHyperlink
elif foundLinks[0].ar == arNim: rnNimdocRef
if foundLinks[0].externFilename != "":
s.idxImports[foundLinks[0].externFilename].used = true
let kind = if foundLinks[0].ar in {arHyperlink, arExternalRst}: rnHyperlink
elif foundLinks[0].ar == arNim:
if foundLinks[0].externFilename == "": rnNimdocRef
else: rnHyperlink
else: rnInternalRef
result = newRstNode(kind)
result.sons = @[newRstNode(rnInner, desc.sons), foundLinks[0].target]
let documentName = # filename without ext for `.nim`, title for `.md`
if foundLinks[0].ar == arNim:
changeFileExt(foundLinks[0].externFilename.extractFilename, "")
elif foundLinks[0].externFilename != "":
s.idxImports[foundLinks[0].externFilename].title
else: foundLinks[0].externFilename.extractFilename
let linkText =
if foundLinks[0].externFilename != "":
if foundLinks[0].isTitle: newLeaf(addNodes(desc))
else: newLeaf(documentName & ": " & addNodes(desc))
else:
newRstNode(rnInner, desc.sons)
result.sons = @[linkText, foundLinks[0].target]
if kind == rnNimdocRef: result.tooltip = foundLinks[0].tooltip
if foundLinks.len > 1: # report ambiguous link
var targets = newSeq[string]()
@@ -3568,20 +3769,28 @@ proc resolveSubs*(s: PRstSharedState, n: PRstNode): PRstNode =
inc i
result.sons = newSons
proc completePass2*(s: PRstSharedState) =
for (filename, importdocInfo) in s.idxImports.pairs:
if not importdocInfo.used:
rstMessage(s.filenames, s.msgHandler, importdocInfo.fromInfo,
mwUnusedImportdoc, filename)
proc rstParse*(text, filename: string,
line, column: int,
options: RstParseOptions,
findFile: FindFileHandler = nil,
findRefFile: FindRefFileHandler = nil,
msgHandler: MsgHandler = nil):
tuple[node: PRstNode, filenames: RstFileTable, hasToc: bool] =
## Parses the whole `text`. The result is ready for `rstgen.renderRstToOut`,
## note that 2nd tuple element should be fed to `initRstGenerator`
## argument `filenames` (it is being filled here at least with `filename`
## and possibly with other files from RST ``.. include::`` statement).
var sharedState = newRstSharedState(options, filename, findFile,
var sharedState = newRstSharedState(options, filename, findFile, findRefFile,
msgHandler, hasToc=false)
let unresolved = rstParsePass1(text, line, column, sharedState)
preparePass2(sharedState, unresolved)
result.node = resolveSubs(sharedState, unresolved)
completePass2(sharedState)
result.filenames = sharedState.filenames
result.hasToc = sharedState.hasToc

View File

@@ -39,7 +39,8 @@
## No backreferences are generated since finding all references of a footnote
## can be done by simply searching for ``[footnoteName]``.
import strutils, os, hashes, strtabs, rstast, rst, highlite, tables, sequtils,
import strutils, os, hashes, strtabs, rstast, rst, rstidx,
highlite, tables, sequtils,
algorithm, parseutils, std/strbasics
@@ -59,7 +60,7 @@ type
outLatex # output is Latex
MetaEnum* = enum
metaNone, metaTitle, metaSubtitle, metaAuthor, metaVersion
metaNone, metaTitleRaw, metaTitle, metaSubtitle, metaAuthor, metaVersion
EscapeMode* = enum # in Latex text inside options [] and URLs is
# escaped slightly differently than in normal text
@@ -321,31 +322,8 @@ proc renderAux(d: PDoc, n: PRstNode, html, tex: string, result: var string) =
# ---------------- index handling --------------------------------------------
proc quoteIndexColumn(text: string): string =
## Returns a safe version of `text` for serialization to the ``.idx`` file.
##
## The returned version can be put without worries in a line based tab
## separated column text file. The following character sequence replacements
## will be performed for that goal:
##
## * ``"\\"`` => ``"\\\\"``
## * ``"\n"`` => ``"\\n"``
## * ``"\t"`` => ``"\\t"``
result = newStringOfCap(text.len + 3)
for c in text:
case c
of '\\': result.add "\\"
of '\L': result.add "\\n"
of '\C': discard
of '\t': result.add "\\t"
else: result.add c
proc unquoteIndexColumn(text: string): string =
## Returns the unquoted version generated by ``quoteIndexColumn``.
result = text.multiReplace(("\\t", "\t"), ("\\n", "\n"), ("\\\\", "\\"))
proc setIndexTerm*(d: var RstGenerator, htmlFile, id, term: string,
linkTitle, linkDesc = "") =
proc setIndexTerm*(d: var RstGenerator; k: IndexEntryKind, htmlFile, id, term: string,
linkTitle, linkDesc = "", line = 0) =
## Adds a `term` to the index using the specified hyperlink identifier.
##
## A new entry will be added to the index using the format
@@ -368,21 +346,8 @@ proc setIndexTerm*(d: var RstGenerator, htmlFile, id, term: string,
## <#writeIndexFile,RstGenerator,string>`_. The purpose of the index is
## documented in the `docgen tools guide
## <docgen.html#related-options-index-switch>`_.
var
entry = term
isTitle = false
entry.add('\t')
entry.add(htmlFile)
if id.len > 0:
entry.add('#')
entry.add(id)
else:
isTitle = true
if linkTitle.len > 0 or linkDesc.len > 0:
entry.add('\t' & linkTitle.quoteIndexColumn)
entry.add('\t' & linkDesc.quoteIndexColumn)
entry.add("\n")
let (entry, isTitle) = formatIndexEntry(k, htmlFile, id, term,
linkTitle, linkDesc, line)
if isTitle: d.theIndex.insert(entry)
else: d.theIndex.add(entry)
@@ -395,6 +360,15 @@ proc hash(n: PRstNode): int =
result = result !& hash(n.sons[i])
result = !$result
proc htmlFileRelPath(d: PDoc): string =
if d.outDir.len == 0:
# /foo/bar/zoo.nim -> zoo.html
changeFileExt(extractFilename(d.filename), HtmlExt)
else: # d is initialized in docgen.nim
# outDir = /foo -\
# destFile = /foo/bar/zoo.html -|-> bar/zoo.html
d.destFile.relativePath(d.outDir, '/')
proc renderIndexTerm*(d: PDoc, n: PRstNode, result: var string) =
## Renders the string decorated within \`foobar\`\:idx\: markers.
##
@@ -411,17 +385,12 @@ proc renderIndexTerm*(d: PDoc, n: PRstNode, result: var string) =
var term = ""
renderAux(d, n, term)
setIndexTerm(d, changeFileExt(extractFilename(d.filename), HtmlExt), id, term, d.currentSection)
setIndexTerm(d, ieIdxRole,
htmlFileRelPath(d), id, term, d.currentSection)
dispA(d.target, result, "<span id=\"$1\">$2</span>", "\\nimindexterm{$1}{$2}",
[id, term])
type
IndexEntry* = object
keyword*: string
link*: string
linkTitle*: string ## contains a prettier text for the href
linkDesc*: string ## the title attribute of the final href
IndexedDocs* = Table[IndexEntry, seq[IndexEntry]] ## \
## Contains the index sequences for doc types.
##
@@ -432,21 +401,6 @@ type
## The value indexed by this IndexEntry is a sequence with the real index
## entries found in the ``.idx`` file.
proc cmp(a, b: IndexEntry): int =
## Sorts two ``IndexEntry`` first by `keyword` field, then by `link`.
result = cmpIgnoreStyle(a.keyword, b.keyword)
if result == 0:
result = cmpIgnoreStyle(a.link, b.link)
proc hash(x: IndexEntry): Hash =
## Returns the hash for the combined fields of the type.
##
## The hash is computed as the chained hash of the individual string hashes.
result = x.keyword.hash !& x.link.hash
result = result !& x.linkTitle.hash
result = result !& x.linkDesc.hash
result = !$result
when defined(gcDestructors):
template `<-`(a, b: var IndexEntry) = a = move(b)
else:
@@ -455,6 +409,7 @@ else:
shallowCopy a.link, b.link
shallowCopy a.linkTitle, b.linkTitle
shallowCopy a.linkDesc, b.linkDesc
shallowCopy a.module, b.module
proc sortIndex(a: var openArray[IndexEntry]) =
# we use shellsort here; fast and simple
@@ -494,16 +449,20 @@ proc generateSymbolIndex(symbols: seq[IndexEntry]): string =
result = "<dl>"
var i = 0
while i < symbols.len:
let keyword = symbols[i].keyword
let keyword = esc(outHtml, symbols[i].keyword)
let cleanedKeyword = keyword.escapeLink
result.addf("<dt><a name=\"$2\" href=\"#$2\"><span>$1:</span></a></dt><dd><ul class=\"simple\">\n",
[keyword, cleanedKeyword])
var j = i
while j < symbols.len and keyword == symbols[j].keyword:
while j < symbols.len and symbols[i].keyword == symbols[j].keyword:
let
url = symbols[j].link.escapeLink
text = if symbols[j].linkTitle.len > 0: symbols[j].linkTitle else: url
desc = if symbols[j].linkDesc.len > 0: symbols[j].linkDesc else: ""
module = symbols[j].module
text =
if symbols[j].linkTitle.len > 0:
esc(outHtml, module & ": " & symbols[j].linkTitle)
else: url
desc = symbols[j].linkDesc
if desc.len > 0:
result.addf("""<li><a class="reference external"
title="$3" data-doc-search-tag="$2" href="$1">$2</a></li>
@@ -517,13 +476,6 @@ proc generateSymbolIndex(symbols: seq[IndexEntry]): string =
i = j
result.add("</dl>")
proc isDocumentationTitle(hyperlink: string): bool =
## Returns true if the hyperlink is actually a documentation title.
##
## Documentation titles lack the hash. See `mergeIndexes()
## <#mergeIndexes,string>`_ for a more detailed explanation.
result = hyperlink.find('#') < 0
proc stripTocLevel(s: string): tuple[level: int, text: string] =
## Returns the *level* of the toc along with the text without it.
for c in 0 ..< s.len:
@@ -557,17 +509,15 @@ proc generateDocumentationToc(entries: seq[IndexEntry]): string =
level = 1
levels.newSeq(entries.len)
for entry in entries:
let (rawLevel, rawText) = stripTocLevel(entry.linkTitle or entry.keyword)
let (rawLevel, rawText) = stripTocLevel(entry.linkTitle)
if rawLevel < 1:
# This is a normal symbol, push it *inside* one level from the last one.
levels[L].level = level + 1
# Also, ignore the linkTitle and use directly the keyword.
levels[L].text = entry.keyword
else:
# The level did change, update the level indicator.
level = rawLevel
levels[L].level = rawLevel
levels[L].text = rawText
levels[L].text = rawText
inc L
# Now generate hierarchical lists based on the precalculated levels.
@@ -598,7 +548,7 @@ proc generateDocumentationIndex(docs: IndexedDocs): string =
for title in titles:
let tocList = generateDocumentationToc(docs.getOrDefault(title))
result.add("<ul><li><a href=\"" &
title.link & "\">" & title.keyword & "</a>\n" & tocList & "</li></ul>\n")
title.link & "\">" & title.linkTitle & "</a>\n" & tocList & "</li></ul>\n")
proc generateDocumentationJumps(docs: IndexedDocs): string =
## Returns a plain list of hyperlinks to documentation TOCs in HTML.
@@ -610,7 +560,7 @@ proc generateDocumentationJumps(docs: IndexedDocs): string =
var chunks: seq[string] = @[]
for title in titles:
chunks.add("<a href=\"" & title.link & "\">" & title.keyword & "</a>")
chunks.add("<a href=\"" & title.link & "\">" & title.linkTitle & "</a>")
result.add(chunks.join(", ") & ".<br/>")
@@ -639,39 +589,11 @@ proc readIndexDir*(dir: string):
# Scan index files and build the list of symbols.
for path in walkDirRec(dir):
if path.endsWith(IndexExt):
var
fileEntries: seq[IndexEntry]
title: IndexEntry
f = 0
newSeq(fileEntries, 500)
setLen(fileEntries, 0)
for line in lines(path):
let s = line.find('\t')
if s < 0: continue
setLen(fileEntries, f+1)
fileEntries[f].keyword = line.substr(0, s-1)
fileEntries[f].link = line.substr(s+1)
# See if we detect a title, a link without a `#foobar` trailing part.
if title.keyword.len == 0 and fileEntries[f].link.isDocumentationTitle:
title.keyword = fileEntries[f].keyword
title.link = fileEntries[f].link
if fileEntries[f].link.find('\t') > 0:
let extraCols = fileEntries[f].link.split('\t')
fileEntries[f].link = extraCols[0]
assert extraCols.len == 3
fileEntries[f].linkTitle = extraCols[1].unquoteIndexColumn
fileEntries[f].linkDesc = extraCols[2].unquoteIndexColumn
else:
fileEntries[f].linkTitle = ""
fileEntries[f].linkDesc = ""
inc f
var (fileEntries, title) = parseIdxFile(path)
# Depending on type add this to the list of symbols or table of APIs.
if title.keyword.len == 0:
for i in 0 ..< f:
# Don't add to symbols TOC entries (they start with a whitespace).
let toc = fileEntries[i].linkTitle
if toc.len > 0 and toc[0] == ' ':
if title.kind == ieNimTitle:
for i in 0 ..< fileEntries.len:
if fileEntries[i].kind != ieNim:
continue
# Ok, non TOC entry, add it.
setLen(result.symbols, L + 1)
@@ -687,7 +609,7 @@ proc readIndexDir*(dir: string):
result.modules.add(x.changeFileExt(""))
else:
# Generate the symbolic anchor for index quickjumps.
title.linkTitle = "doc_toc_" & $result.docs.len
title.aux = "doc_toc_" & $result.docs.len
result.docs[title] = fileEntries
proc mergeIndexes*(dir: string): string =
@@ -747,24 +669,6 @@ proc mergeIndexes*(dir: string): string =
# ----------------------------------------------------------------------------
proc stripTocHtml(s: string): string =
## Ugly quick hack to remove HTML tags from TOC titles.
##
## A TocEntry.header field already contains rendered HTML tags. Instead of
## implementing a proper version of renderRstToOut() which recursively
## renders an rst tree to plain text, we simply remove text found between
## angled brackets. Given the limited possibilities of rst inside TOC titles
## this should be enough.
result = s
var first = result.find('<')
while first >= 0:
let last = result.find('>', first)
if last < 0:
# Abort, since we didn't found a closing angled bracket.
return
result.delete(first..last)
first = result.find('<', first)
proc renderHeadline(d: PDoc, n: PRstNode, result: var string) =
var tmp = ""
for i in countup(0, len(n) - 1): renderRstToOut(d, n.sons[i], tmp)
@@ -785,19 +689,12 @@ proc renderHeadline(d: PDoc, n: PRstNode, result: var string) =
# Generate index entry using spaces to indicate TOC level for the output HTML.
assert n.level >= 0
let
htmlFileRelPath = if d.outDir.len == 0:
# /foo/bar/zoo.nim -> zoo.html
changeFileExt(extractFilename(d.filename), HtmlExt)
else: # d is initialized in docgen.nim
# outDir = /foo -\
# destFile = /foo/bar/zoo.html -|-> bar/zoo.html
d.destFile.relativePath(d.outDir, '/')
setIndexTerm(d, htmlFileRelPath, n.anchor, tmp.stripTocHtml,
spaces(max(0, n.level)) & tmp)
setIndexTerm(d, ieHeading, htmlFile = d.htmlFileRelPath, id = n.anchor,
term = n.addNodes, linkTitle = spaces(max(0, n.level)) & tmp)
proc renderOverline(d: PDoc, n: PRstNode, result: var string) =
if n.level == 0 and d.meta[metaTitle].len == 0:
d.meta[metaTitleRaw] = n.addNodes
for i in countup(0, len(n)-1):
renderRstToOut(d, n.sons[i], d.meta[metaTitle])
d.currentSection = d.meta[metaTitle]
@@ -813,6 +710,8 @@ proc renderOverline(d: PDoc, n: PRstNode, result: var string) =
dispA(d.target, result, "<h$1$2><center>$3</center></h$1>",
"\\rstov$4[$5]{$3}$2\n", [$n.level,
n.anchor.idS, tmp, $chr(n.level - 1 + ord('A')), tocName])
setIndexTerm(d, ieHeading, htmlFile = d.htmlFileRelPath, id = n.anchor,
term = n.addNodes, linkTitle = spaces(max(0, n.level)) & tmp)
proc renderTocEntry(d: PDoc, n: PRstNode, result: var string) =
var header = ""
@@ -1197,6 +1096,18 @@ proc renderHyperlink(d: PDoc, text, link: PRstNode, result: var string,
"\\hyperlink{$2}{$1} (p.~\\pageref{$2})",
[textStr, linkStr, nimDocStr, tooltipStr])
proc traverseForIndex*(d: PDoc, n: PRstNode) =
## A version of [renderRstToOut] that only fills entries for ``.idx`` files.
var discarded: string
if n == nil: return
case n.kind
of rnIdx: renderIndexTerm(d, n, discarded)
of rnHeadline, rnMarkdownHeadline: renderHeadline(d, n, discarded)
of rnOverline: renderOverline(d, n, discarded)
else:
for i in 0 ..< len(n):
traverseForIndex(d, n.sons[i])
proc renderRstToOut(d: PDoc, n: PRstNode, result: var string) =
if n == nil: return
case n.kind
@@ -1451,6 +1362,7 @@ proc renderRstToOut(d: PDoc, n: PRstNode, result: var string) =
of rnTitle:
d.meta[metaTitle] = ""
renderRstToOut(d, n.sons[0], d.meta[metaTitle])
d.meta[metaTitleRaw] = n.sons[0].addNodes
# -----------------------------------------------------------------------------
@@ -1616,11 +1528,13 @@ proc rstToHtml*(s: string, options: RstParseOptions,
proc myFindFile(filename: string): string =
# we don't find any files in online mode:
result = ""
proc myFindRefFile(filename: string): (string, string) =
result = ("", "")
const filen = "input"
let (rst, filenames, t) = rstParse(s, filen,
line=LineRstInit, column=ColRstInit,
options, myFindFile, msgHandler)
options, myFindFile, myFindRefFile, msgHandler)
var d: RstGenerator
initRstGenerator(d, outHtml, config, filen, myFindFile, msgHandler,
filenames, hasToc = t)

View File

@@ -0,0 +1,138 @@
#
# Nim's Runtime Library
# (c) Copyright 2022 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
## Nim `idx`:idx: file format related definitions.
import strutils, std/syncio, hashes
from os import splitFile
type
IndexEntryKind* = enum ## discriminator tag
ieMarkupTitle = "markupTitle"
## RST/Markdown title, text in `keyword` +
## HTML text in `linkTitle`
ieNimTitle = "nimTitle"
## Nim title
ieHeading = "heading" ## RST/Markdown markup heading, escaped
ieIdxRole = "idx" ## RST :idx: definition, escaped
ieNim = "nim" ## Nim symbol, unescaped
ieNimGroup = "nimgrp" ## Nim overload group, unescaped
IndexEntry* = object
kind*: IndexEntryKind ## 0.
keyword*: string ## 1.
link*: string ## 2.
linkTitle*: string ## 3. contains a prettier text for the href
linkDesc*: string ## 4. the title attribute of the final href
line*: int ## 5.
module*: string ## origin file, NOT a field in ``.idx`` file
aux*: string ## auxuliary field, NOT a field in ``.idx`` file
proc isDocumentationTitle*(hyperlink: string): bool =
## Returns true if the hyperlink is actually a documentation title.
##
## Documentation titles lack the hash. See `mergeIndexes()
## <#mergeIndexes,string>`_ for a more detailed explanation.
result = hyperlink.find('#') < 0
proc `$`*(e: IndexEntry): string =
"""("$1", "$2", "$3", "$4", $5)""" % [
e.keyword, e.link, e.linkTitle, e.linkDesc, $e.line]
proc quoteIndexColumn(text: string): string =
## Returns a safe version of `text` for serialization to the ``.idx`` file.
##
## The returned version can be put without worries in a line based tab
## separated column text file. The following character sequence replacements
## will be performed for that goal:
##
## * ``"\\"`` => ``"\\\\"``
## * ``"\n"`` => ``"\\n"``
## * ``"\t"`` => ``"\\t"``
result = newStringOfCap(text.len + 3)
for c in text:
case c
of '\\': result.add "\\"
of '\L': result.add "\\n"
of '\C': discard
of '\t': result.add "\\t"
else: result.add c
proc unquoteIndexColumn*(text: string): string =
## Returns the unquoted version generated by ``quoteIndexColumn``.
result = text.multiReplace(("\\t", "\t"), ("\\n", "\n"), ("\\\\", "\\"))
proc formatIndexEntry*(kind: IndexEntryKind; htmlFile, id, term, linkTitle,
linkDesc: string, line: int):
tuple[entry: string, isTitle: bool] =
result.entry = $kind
result.entry.add('\t')
result.entry.add term
result.entry.add('\t')
result.entry.add(htmlFile)
if id.len > 0:
result.entry.add('#')
result.entry.add(id)
result.isTitle = false
else:
result.isTitle = true
result.entry.add('\t' & linkTitle.quoteIndexColumn)
result.entry.add('\t' & linkDesc.quoteIndexColumn)
result.entry.add('\t' & $line)
result.entry.add("\n")
proc parseIndexEntryKind(s: string): IndexEntryKind =
result = case s:
of "nim": ieNim
of "nimgrp": ieNimGroup
of "heading": ieHeading
of "idx": ieIdxRole
of "nimTitle": ieNimTitle
of "markupTitle": ieMarkupTitle
else: raise newException(ValueError, "unknown index entry value $1" % [s])
proc parseIdxFile*(path: string):
tuple[fileEntries: seq[IndexEntry], title: IndexEntry] =
var
f = 0
newSeq(result.fileEntries, 500)
setLen(result.fileEntries, 0)
let (_, base, _) = path.splitFile
for line in lines(path):
let s = line.find('\t')
if s < 0: continue
setLen(result.fileEntries, f+1)
let cols = line.split('\t')
result.fileEntries[f].kind = parseIndexEntryKind(cols[0])
result.fileEntries[f].keyword = cols[1]
result.fileEntries[f].link = cols[2]
if result.title.keyword.len == 0:
result.fileEntries[f].module = base
else:
result.fileEntries[f].module = result.title.keyword
result.fileEntries[f].linkTitle = cols[3].unquoteIndexColumn
result.fileEntries[f].linkDesc = cols[4].unquoteIndexColumn
result.fileEntries[f].line = parseInt(cols[5])
if result.fileEntries[f].kind in {ieNimTitle, ieMarkupTitle}:
result.title = result.fileEntries[f]
inc f
proc cmp*(a, b: IndexEntry): int =
## Sorts two ``IndexEntry`` first by `keyword` field, then by `link`.
result = cmpIgnoreStyle(a.keyword, b.keyword)
if result == 0:
result = cmpIgnoreStyle(a.link, b.link)
proc hash*(x: IndexEntry): Hash =
## Returns the hash for the combined fields of the type.
##
## The hash is computed as the chained hash of the individual string hashes.
result = x.keyword.hash !& x.link.hash
result = result !& x.linkTitle.hash
result = result !& x.linkDesc.hash
result = !$result

View File

@@ -11,6 +11,8 @@
## retrieving environment variables, working with directories,
## running shell commands, etc.
## .. importdoc:: symlinks.nim, appdirs.nim, dirs.nim, ospaths2.nim
runnableExamples:
let myFile = "/path/to/my/file.nim"
assert splitPath(myFile) == (head: "/path/to/my", tail: "file.nim")

View File

@@ -1,5 +1,7 @@
## This module implements helpers for determining special directories used by apps.
## .. importdoc:: paths.nim
from std/private/osappdirs import nil
import std/paths
import std/envvars

View File

@@ -1,3 +1,5 @@
## .. importdoc:: paths.nim, dirs.nim
include system/inclrtl
import std/envvars
import std/private/ospaths2

View File

@@ -5,6 +5,8 @@ import std/[oserrors]
when defined(nimPreviewSlimSystem):
import std/[syncio, assertions, widestrs]
## .. importdoc:: osdirs.nim, os.nim
const weirdTarget* = defined(nimscript) or defined(js)

View File

@@ -1,3 +1,5 @@
## .. importdoc:: osfiles.nim, appdirs.nim, paths.nim
include system/inclrtl
import std/oserrors

View File

@@ -7,6 +7,7 @@ export fileExists
import ospaths2, ossymlinks
## .. importdoc:: osdirs.nim, os.nim
when defined(nimPreviewSlimSystem):
import std/[syncio, assertions, widestrs]
@@ -420,4 +421,4 @@ proc moveFile*(source, dest: string) {.rtl, extern: "nos$1",
removeFile(source)
except:
discard tryRemoveFile(dest)
raise
raise

View File

@@ -10,6 +10,8 @@ export ReadDirEffect, WriteDirEffect
when defined(nimPreviewSlimSystem):
import std/[syncio, assertions, widestrs]
## .. importdoc:: osappdirs.nim, osdirs.nim, osseps.nim, os.nim
const weirdTarget = defined(nimscript) or defined(js)
when weirdTarget:

View File

@@ -3,6 +3,8 @@
# Improved based on info in 'compiler/platform.nim'
## .. importdoc:: ospaths2.nim
const
doslikeFileSystem* = defined(windows) or defined(OS2) or defined(DOS)

View File

@@ -31,6 +31,7 @@ elif defined(js):
else:
{.pragma: noNimJs.}
## .. importdoc:: os.nim
proc createSymlink*(src, dest: string) {.noWeirdTarget.} =
## Create a symbolic link at `dest` which points to the item specified

View File

@@ -1,10 +1,11 @@
## This module implements symlink (symbolic link) handling.
## .. importdoc:: os.nim
from paths import Path, ReadDirEffect
from std/private/ossymlinks import symlinkExists, createSymlink, expandSymlink
proc symlinkExists*(link: Path): bool {.inline, tags: [ReadDirEffect].} =
## Returns true if the symlink `link` exists. Will return true
## regardless of whether the link points to a directory or file.

View File

@@ -0,0 +1,17 @@
===================
Nothing User Manual
===================
.. importdoc:: ../main.nim, .. / sub / submodule.nim, ../../util.nim
First section
=============
Second *section* &
==================
Ref. [`</a>`] or [submoduleInt] from [module nimdoc/extlinks/project/sub/submodule].
Ref. [proc mainfunction*(): int].
Ref. [utilfunction(x: int)].

View File

@@ -0,0 +1,104 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!-- This file is generated by Nim. -->
<html xmlns="https://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>nimdoc/extlinks/util</title>
<!-- Favicon -->
<link rel="shortcut icon" href="data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AAAAAAUAAAAF////AP///wD///8A////AP///wD///8A////AP///wD///8A////AAAAAAIAAABbAAAAlQAAAKIAAACbAAAAmwAAAKIAAACVAAAAWwAAAAL///8A////AP///wD///8A////AAAAABQAAADAAAAAYwAAAA3///8A////AP///wD///8AAAAADQAAAGMAAADAAAAAFP///wD///8A////AP///wAAAACdAAAAOv///wD///8A////AP///wD///8A////AP///wD///8AAAAAOgAAAJ3///8A////AP///wAAAAAnAAAAcP///wAAAAAoAAAASv///wD///8A////AP///wAAAABKAAAAKP///wAAAABwAAAAJ////wD///8AAAAAgQAAABwAAACIAAAAkAAAAJMAAACtAAAAFQAAABUAAACtAAAAkwAAAJAAAACIAAAAHAAAAIH///8A////AAAAAKQAAACrAAAAaP///wD///8AAAAARQAAANIAAADSAAAARf///wD///8AAAAAaAAAAKsAAACk////AAAAADMAAACcAAAAnQAAABj///8A////AP///wAAAAAYAAAAGP///wD///8A////AAAAABgAAACdAAAAnAAAADMAAAB1AAAAwwAAAP8AAADpAAAAsQAAAE4AAAAb////AP///wAAAAAbAAAATgAAALEAAADpAAAA/wAAAMMAAAB1AAAAtwAAAOkAAAD/AAAA/wAAAP8AAADvAAAA3gAAAN4AAADeAAAA3gAAAO8AAAD/AAAA/wAAAP8AAADpAAAAtwAAAGUAAAA/AAAA3wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADfAAAAPwAAAGX///8A////AAAAAEgAAADtAAAAvwAAAL0AAADGAAAA7wAAAO8AAADGAAAAvQAAAL8AAADtAAAASP///wD///8A////AP///wD///8AAAAAO////wD///8A////AAAAAIcAAACH////AP///wD///8AAAAAO////wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A//8AAP//AAD4HwAA7/cAAN/7AAD//wAAoYUAAJ55AACf+QAAh+EAAAAAAADAAwAA4AcAAP5/AAD//wAA//8AAA=="/>
<link rel="icon" type="image/png" sizes="32x32" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH4QQQEwksSS9ZWwAAAk1JREFUWMPtll2ITVEUx39nn/O7Y5qR8f05wtCUUr6ZIS++8pEnkZInPImneaCQ5METNdOkeFBKUhMPRIkHKfEuUZSUlGlKPN2TrgfncpvmnntnmlEyq1Z7t89/rf9a6+y99oZxGZf/XeIq61EdtgKXgdXA0xrYAvBjOIF1AI9zvjcC74BSpndrJPkBWDScTF8Aa4E3wDlgHbASaANmVqlcCnwHvgDvgVfAJ+AikAAvgfVZwLnSVZHZaOuKoQi3ZOMi4NkYkpe1p4J7A8BpYAD49hfIy/oqG0+hLomiKP2L5L+1ubn5115S+3OAn4EnwBlgMzCjyt6ZAnQCJ4A7wOs88iRJHvw50HoujuPBoCKwHWiosy8MdfZnAdcHk8dxXFJ3VQbQlCTJvRBCGdRbD4M6uc5glpY3eAihpN5S5w12diSEcCCEcKUO4ljdr15T76ur1FDDLIQQ3qv71EdDOe3Kxj3leRXyk+pxdWnFWod6Wt2bY3de3aSuUHcPBVimHs7mK9WrmeOF6lR1o9qnzskh2ar2qm1qizpfXaPeVGdlmGN5pb09qMxz1Xb1kLqgzn1RyH7JUXW52lr5e/Kqi9qpto7V1atuUzfnARrV7jEib1T76gG2qxdGmXyiekkt1GswPTtek0aBfJp6YySGBfWg2tPQ0FAYgf1stUfdmdcjarbYJEniKIq6gY/Aw+zWHAC+p2labGpqiorFYgGYCEzN7oQdQClN07O1/EfDyGgC0ALMBdYAi4FyK+4H3gLPsxfR1zRNi+NP7nH5J+QntnXe5B5mpfQAAAAASUVORK5CYII=">
<!-- CSS -->
<link rel="stylesheet" type="text/css" href="../nimdoc.out.css">
<!-- JS -->
<script type="text/javascript" src="../dochack.js"></script>
</head>
<body>
<div class="document" id="documentId">
<div class="container">
<h1 class="title">nimdoc/extlinks/util</h1>
<div class="row">
<div class="three columns">
<div class="theme-select-wrapper">
<label for="theme-select">Theme:&nbsp;</label>
<select id="theme-select" onchange="setTheme(this.value)">
<option value="auto">🌗 Match OS</option>
<option value="dark">🌑 Dark</option>
<option value="light">🌕 Light</option>
</select>
</div>
<div id="global-links">
<ul class="simple">
<li><a id="indexLink" href="../theindex.html">Index</a></li>
</ul>
</div>
<div id="searchInputDiv">
Search: <input type="search" id="searchInput" onkeyup="search()"/>
</div>
<div>
Group by:
<select onchange="groupBy(this.value)">
<option value="section">Section</option>
<option value="type">Type</option>
</select>
</div>
<ul class="simple simple-toc" id="toc-list">
<li>
<details open>
<summary><a class="reference reference-toplevel" href="#12" id="62">Procs</a></summary>
<ul class="simple simple-toc-section">
<ul class="simple nested-toc-section">utilfunction
<li><a class="reference" href="#utilfunction%2Cint" title="utilfunction(x: int): int">utilfunction(x: int): int</a></li>
</ul>
</ul>
</details>
</li>
</ul>
</div>
<div class="nine columns" id="content">
<div id="tocRoot"></div>
<p class="module-desc"></p>
<div class="section" id="12">
<h1><a class="toc-backref" href="#12">Procs</a></h1>
<dl class="item">
<div id="utilfunction-procs-all">
<div id="utilfunction,int">
<dt><pre><span class="Keyword">proc</span> <a href="#utilfunction%2Cint"><span class="Identifier">utilfunction</span></a><span class="Other">(</span><span class="Identifier">x</span><span class="Other">:</span> <span class="Identifier">int</span><span class="Other">)</span><span class="Other">:</span> <span class="Identifier">int</span> {.<span><span class="Other pragmadots">...</span></span><span class="pragmawrap"><span class="Identifier">raises</span><span class="Other">:</span> <span class="Other">[</span><span class="Other">]</span><span class="Other">,</span> <span class="Identifier">tags</span><span class="Other">:</span> <span class="Other">[</span><span class="Other">]</span><span class="Other">,</span> <span class="Identifier">forbids</span><span class="Other">:</span> <span class="Other">[</span><span class="Other">]</span></span>.}</pre></dt>
<dd>
</dd>
</div>
</div>
</dl>
</div>
</div>
</div>
<div class="twelve-columns footer">
<span class="nim-sprite"></span>
<br>
<small style="color: var(--hint);">Made with Nim. Generated: 1970-01-02 03:46:40 UTC</small>
</div>
</div>
</div>
<!-- Google fonts -->
<link href='https://fonts.googleapis.com/css?family=Lato:400,600,900' rel='stylesheet' type='text/css'/>
<link href='https://fonts.googleapis.com/css?family=Source+Code+Pro:400,500,600' rel='stylesheet' type='text/css'/>
</body>
</html>

View File

@@ -0,0 +1,2 @@
nimTitle util _._/util.html module nimdoc/extlinks/util 0
nim utilfunction _._/util.html#utilfunction,int proc utilfunction(x: int): int 1

View File

@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!-- This file is generated by Nim. -->
<html xmlns="https://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Nothing User Manual</title>
<!-- Favicon -->
<link rel="shortcut icon" href="data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AAAAAAUAAAAF////AP///wD///8A////AP///wD///8A////AP///wD///8A////AAAAAAIAAABbAAAAlQAAAKIAAACbAAAAmwAAAKIAAACVAAAAWwAAAAL///8A////AP///wD///8A////AAAAABQAAADAAAAAYwAAAA3///8A////AP///wD///8AAAAADQAAAGMAAADAAAAAFP///wD///8A////AP///wAAAACdAAAAOv///wD///8A////AP///wD///8A////AP///wD///8AAAAAOgAAAJ3///8A////AP///wAAAAAnAAAAcP///wAAAAAoAAAASv///wD///8A////AP///wAAAABKAAAAKP///wAAAABwAAAAJ////wD///8AAAAAgQAAABwAAACIAAAAkAAAAJMAAACtAAAAFQAAABUAAACtAAAAkwAAAJAAAACIAAAAHAAAAIH///8A////AAAAAKQAAACrAAAAaP///wD///8AAAAARQAAANIAAADSAAAARf///wD///8AAAAAaAAAAKsAAACk////AAAAADMAAACcAAAAnQAAABj///8A////AP///wAAAAAYAAAAGP///wD///8A////AAAAABgAAACdAAAAnAAAADMAAAB1AAAAwwAAAP8AAADpAAAAsQAAAE4AAAAb////AP///wAAAAAbAAAATgAAALEAAADpAAAA/wAAAMMAAAB1AAAAtwAAAOkAAAD/AAAA/wAAAP8AAADvAAAA3gAAAN4AAADeAAAA3gAAAO8AAAD/AAAA/wAAAP8AAADpAAAAtwAAAGUAAAA/AAAA3wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADfAAAAPwAAAGX///8A////AAAAAEgAAADtAAAAvwAAAL0AAADGAAAA7wAAAO8AAADGAAAAvQAAAL8AAADtAAAASP///wD///8A////AP///wD///8AAAAAO////wD///8A////AAAAAIcAAACH////AP///wD///8AAAAAO////wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A//8AAP//AAD4HwAA7/cAAN/7AAD//wAAoYUAAJ55AACf+QAAh+EAAAAAAADAAwAA4AcAAP5/AAD//wAA//8AAA=="/>
<link rel="icon" type="image/png" sizes="32x32" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH4QQQEwksSS9ZWwAAAk1JREFUWMPtll2ITVEUx39nn/O7Y5qR8f05wtCUUr6ZIS++8pEnkZInPImneaCQ5METNdOkeFBKUhMPRIkHKfEuUZSUlGlKPN2TrgfncpvmnntnmlEyq1Z7t89/rf9a6+y99oZxGZf/XeIq61EdtgKXgdXA0xrYAvBjOIF1AI9zvjcC74BSpndrJPkBWDScTF8Aa4E3wDlgHbASaANmVqlcCnwHvgDvgVfAJ+AikAAvgfVZwLnSVZHZaOuKoQi3ZOMi4NkYkpe1p4J7A8BpYAD49hfIy/oqG0+hLomiKP2L5L+1ubn5115S+3OAn4EnwBlgMzCjyt6ZAnQCJ4A7wOs88iRJHvw50HoujuPBoCKwHWiosy8MdfZnAdcHk8dxXFJ3VQbQlCTJvRBCGdRbD4M6uc5glpY3eAihpN5S5w12diSEcCCEcKUO4ljdr15T76ur1FDDLIQQ3qv71EdDOe3Kxj3leRXyk+pxdWnFWod6Wt2bY3de3aSuUHcPBVimHs7mK9WrmeOF6lR1o9qnzskh2ar2qm1qizpfXaPeVGdlmGN5pb09qMxz1Xb1kLqgzn1RyH7JUXW52lr5e/Kqi9qpto7V1atuUzfnARrV7jEib1T76gG2qxdGmXyiekkt1GswPTtek0aBfJp6YySGBfWg2tPQ0FAYgf1stUfdmdcjarbYJEniKIq6gY/Aw+zWHAC+p2labGpqiorFYgGYCEzN7oQdQClN07O1/EfDyGgC0ALMBdYAi4FyK+4H3gLPsxfR1zRNi+NP7nH5J+QntnXe5B5mpfQAAAAASUVORK5CYII=">
<!-- CSS -->
<link rel="stylesheet" type="text/css" href="../nimdoc.out.css">
<!-- JS -->
<script type="text/javascript" src="../dochack.js"></script>
</head>
<body>
<div class="document" id="documentId">
<div class="container">
<h1 class="title">Nothing User Manual</h1>
<h1 id="first-section">First section</h1>
<h1 id="second-section-amp">Second <em>section</em> &amp;</h1><p>Ref. <a class="reference external" href="../sub/submodule.html#&lt;/a&gt;,int,int">submodule: `&lt;/a&gt;`</a> or <a class="reference external" href="../sub/submodule.html#submoduleInt">submodule: submoduleInt</a> from <a class="reference external" href="../sub/submodule.html">module nimdoc/extlinks/project/sub/submodule</a>.</p>
<p>Ref. <a class="reference external" href="../main.html#mainfunction">main: proc mainfunction*(): int</a>.</p>
<p>Ref. <a class="reference external" href="../_._/util.html#utilfunction,int">util: utilfunction(x: int)</a>. </p>
<div class="twelve-columns footer">
<span class="nim-sprite"></span>
<br>
<small style="color: var(--hint);">Made with Nim. Generated: 1970-01-02 03:46:40 UTC</small>
</div>
</div>
</div>
<!-- Google fonts -->
<link href='https://fonts.googleapis.com/css?family=Lato:400,600,900' rel='stylesheet' type='text/css'/>
<link href='https://fonts.googleapis.com/css?family=Source+Code+Pro:400,500,600' rel='stylesheet' type='text/css'/>
</body>
</html>

View File

@@ -0,0 +1,3 @@
markupTitle Nothing User Manual doc/manual.html Nothing User Manual 0
heading First section doc/manual.html#first-section First section 0
heading Second section & doc/manual.html#second-section-amp Second <em>section</em> &amp; 0

View File

@@ -0,0 +1,144 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!-- This file is generated by Nim. -->
<html xmlns="https://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>nimdoc/extlinks/project/main</title>
<!-- Favicon -->
<link rel="shortcut icon" href="data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AAAAAAUAAAAF////AP///wD///8A////AP///wD///8A////AP///wD///8A////AAAAAAIAAABbAAAAlQAAAKIAAACbAAAAmwAAAKIAAACVAAAAWwAAAAL///8A////AP///wD///8A////AAAAABQAAADAAAAAYwAAAA3///8A////AP///wD///8AAAAADQAAAGMAAADAAAAAFP///wD///8A////AP///wAAAACdAAAAOv///wD///8A////AP///wD///8A////AP///wD///8AAAAAOgAAAJ3///8A////AP///wAAAAAnAAAAcP///wAAAAAoAAAASv///wD///8A////AP///wAAAABKAAAAKP///wAAAABwAAAAJ////wD///8AAAAAgQAAABwAAACIAAAAkAAAAJMAAACtAAAAFQAAABUAAACtAAAAkwAAAJAAAACIAAAAHAAAAIH///8A////AAAAAKQAAACrAAAAaP///wD///8AAAAARQAAANIAAADSAAAARf///wD///8AAAAAaAAAAKsAAACk////AAAAADMAAACcAAAAnQAAABj///8A////AP///wAAAAAYAAAAGP///wD///8A////AAAAABgAAACdAAAAnAAAADMAAAB1AAAAwwAAAP8AAADpAAAAsQAAAE4AAAAb////AP///wAAAAAbAAAATgAAALEAAADpAAAA/wAAAMMAAAB1AAAAtwAAAOkAAAD/AAAA/wAAAP8AAADvAAAA3gAAAN4AAADeAAAA3gAAAO8AAAD/AAAA/wAAAP8AAADpAAAAtwAAAGUAAAA/AAAA3wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADfAAAAPwAAAGX///8A////AAAAAEgAAADtAAAAvwAAAL0AAADGAAAA7wAAAO8AAADGAAAAvQAAAL8AAADtAAAASP///wD///8A////AP///wD///8AAAAAO////wD///8A////AAAAAIcAAACH////AP///wD///8AAAAAO////wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A//8AAP//AAD4HwAA7/cAAN/7AAD//wAAoYUAAJ55AACf+QAAh+EAAAAAAADAAwAA4AcAAP5/AAD//wAA//8AAA=="/>
<link rel="icon" type="image/png" sizes="32x32" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH4QQQEwksSS9ZWwAAAk1JREFUWMPtll2ITVEUx39nn/O7Y5qR8f05wtCUUr6ZIS++8pEnkZInPImneaCQ5METNdOkeFBKUhMPRIkHKfEuUZSUlGlKPN2TrgfncpvmnntnmlEyq1Z7t89/rf9a6+y99oZxGZf/XeIq61EdtgKXgdXA0xrYAvBjOIF1AI9zvjcC74BSpndrJPkBWDScTF8Aa4E3wDlgHbASaANmVqlcCnwHvgDvgVfAJ+AikAAvgfVZwLnSVZHZaOuKoQi3ZOMi4NkYkpe1p4J7A8BpYAD49hfIy/oqG0+hLomiKP2L5L+1ubn5115S+3OAn4EnwBlgMzCjyt6ZAnQCJ4A7wOs88iRJHvw50HoujuPBoCKwHWiosy8MdfZnAdcHk8dxXFJ3VQbQlCTJvRBCGdRbD4M6uc5glpY3eAihpN5S5w12diSEcCCEcKUO4ljdr15T76ur1FDDLIQQ3qv71EdDOe3Kxj3leRXyk+pxdWnFWod6Wt2bY3de3aSuUHcPBVimHs7mK9WrmeOF6lR1o9qnzskh2ar2qm1qizpfXaPeVGdlmGN5pb09qMxz1Xb1kLqgzn1RyH7JUXW52lr5e/Kqi9qpto7V1atuUzfnARrV7jEib1T76gG2qxdGmXyiekkt1GswPTtek0aBfJp6YySGBfWg2tPQ0FAYgf1stUfdmdcjarbYJEniKIq6gY/Aw+zWHAC+p2labGpqiorFYgGYCEzN7oQdQClN07O1/EfDyGgC0ALMBdYAi4FyK+4H3gLPsxfR1zRNi+NP7nH5J+QntnXe5B5mpfQAAAAASUVORK5CYII=">
<!-- CSS -->
<link rel="stylesheet" type="text/css" href="nimdoc.out.css">
<!-- JS -->
<script type="text/javascript" src="dochack.js"></script>
</head>
<body>
<div class="document" id="documentId">
<div class="container">
<h1 class="title">nimdoc/extlinks/project/main</h1>
<div class="row">
<div class="three columns">
<div class="theme-select-wrapper">
<label for="theme-select">Theme:&nbsp;</label>
<select id="theme-select" onchange="setTheme(this.value)">
<option value="auto">🌗 Match OS</option>
<option value="dark">🌑 Dark</option>
<option value="light">🌕 Light</option>
</select>
</div>
<div id="global-links">
<ul class="simple">
<li><a id="indexLink" href="theindex.html">Index</a></li>
</ul>
</div>
<div id="searchInputDiv">
Search: <input type="search" id="searchInput" onkeyup="search()"/>
</div>
<div>
Group by:
<select onchange="groupBy(this.value)">
<option value="section">Section</option>
<option value="type">Type</option>
</select>
</div>
<ul class="simple simple-toc" id="toc-list">
<li><a class="reference" id="my-heading_toc" href="#my-heading">my heading</a></li>
<li>
<a class="reference reference-toplevel" href="#6" id="56">Imports</a>
</li>
<li>
<details open>
<summary><a class="reference reference-toplevel" href="#7" id="57">Types</a></summary>
<ul class="simple simple-toc-section">
<li><a class="reference" href="#A" title="A = object
x: int">A</a></li>
</ul>
</details>
</li>
<li>
<details open>
<summary><a class="reference reference-toplevel" href="#12" id="62">Procs</a></summary>
<ul class="simple simple-toc-section">
<ul class="simple nested-toc-section">mainfunction
<li><a class="reference" href="#mainfunction" title="mainfunction(): int">mainfunction(): int</a></li>
</ul>
</ul>
</details>
</li>
</ul>
</div>
<div class="nine columns" id="content">
<div id="tocRoot"></div>
<p class="module-desc">
<h1><a class="toc-backref" id="my-heading" href="#my-heading">my heading</a></h1><p>See also <a class="reference external" href="_._/util.html">module nimdoc/extlinks/util</a> or <a class="reference external" href="sub/submodule.html">nimdoc/extlinks/project/sub/submodule module</a>.</p>
<p>Ref. <a class="reference external" href="sub/submodule.html#&lt;/a&gt;,int,int">submodule: `&lt;/a&gt;` proc</a>.</p>
<p>Ref. <a class="reference external" href="doc/manual.html#first-section">Nothing User Manual: First section</a> or <a class="reference external" href="doc/manual.html#second-section-amp">Nothing User Manual: Second section &amp;</a> from <a class="reference external" href="doc/manual.html">Nothing User Manual</a>.</p>
</p>
<div class="section" id="6">
<h1><a class="toc-backref" href="#6">Imports</a></h1>
<dl class="item">
<a class="reference external" href="_._/util.html">../util</a>, <a class="reference external" href="sub/submodule.html">sub/submodule</a>
</dl>
</div>
<div class="section" id="7">
<h1><a class="toc-backref" href="#7">Types</a></h1>
<dl class="item">
<div id="A">
<dt><pre><a href="main.html#A"><span class="Identifier">A</span></a> <span class="Other">=</span> <span class="Keyword">object</span>
<span class="Identifier">x</span><span class="Other">:</span> <span class="Identifier">int</span>
</pre></dt>
<dd>
</dd>
</div>
</dl>
</div>
<div class="section" id="12">
<h1><a class="toc-backref" href="#12">Procs</a></h1>
<dl class="item">
<div id="mainfunction-procs-all">
<div id="mainfunction">
<dt><pre><span class="Keyword">proc</span> <a href="#mainfunction"><span class="Identifier">mainfunction</span></a><span class="Other">(</span><span class="Other">)</span><span class="Other">:</span> <span class="Identifier">int</span> {.<span><span class="Other pragmadots">...</span></span><span class="pragmawrap"><span class="Identifier">raises</span><span class="Other">:</span> <span class="Other">[</span><span class="Other">]</span><span class="Other">,</span> <span class="Identifier">tags</span><span class="Other">:</span> <span class="Other">[</span><span class="Other">]</span><span class="Other">,</span> <span class="Identifier">forbids</span><span class="Other">:</span> <span class="Other">[</span><span class="Other">]</span></span>.}</pre></dt>
<dd>
</dd>
</div>
</div>
</dl>
</div>
</div>
</div>
<div class="twelve-columns footer">
<span class="nim-sprite"></span>
<br>
<small style="color: var(--hint);">Made with Nim. Generated: 1970-01-02 03:46:40 UTC</small>
</div>
</div>
</div>
<!-- Google fonts -->
<link href='https://fonts.googleapis.com/css?family=Lato:400,600,900' rel='stylesheet' type='text/css'/>
<link href='https://fonts.googleapis.com/css?family=Source+Code+Pro:400,500,600' rel='stylesheet' type='text/css'/>
</body>
</html>

View File

@@ -0,0 +1,4 @@
nimTitle main main.html module nimdoc/extlinks/project/main 0
nim A main.html#A object A 17
nim mainfunction main.html#mainfunction proc mainfunction(): int 20
heading my heading main.html#my-heading my heading 0

View File

@@ -0,0 +1,130 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!-- This file is generated by Nim. -->
<html xmlns="https://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>nimdoc/extlinks/project/sub/submodule</title>
<!-- Favicon -->
<link rel="shortcut icon" href="data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AAAAAAUAAAAF////AP///wD///8A////AP///wD///8A////AP///wD///8A////AAAAAAIAAABbAAAAlQAAAKIAAACbAAAAmwAAAKIAAACVAAAAWwAAAAL///8A////AP///wD///8A////AAAAABQAAADAAAAAYwAAAA3///8A////AP///wD///8AAAAADQAAAGMAAADAAAAAFP///wD///8A////AP///wAAAACdAAAAOv///wD///8A////AP///wD///8A////AP///wD///8AAAAAOgAAAJ3///8A////AP///wAAAAAnAAAAcP///wAAAAAoAAAASv///wD///8A////AP///wAAAABKAAAAKP///wAAAABwAAAAJ////wD///8AAAAAgQAAABwAAACIAAAAkAAAAJMAAACtAAAAFQAAABUAAACtAAAAkwAAAJAAAACIAAAAHAAAAIH///8A////AAAAAKQAAACrAAAAaP///wD///8AAAAARQAAANIAAADSAAAARf///wD///8AAAAAaAAAAKsAAACk////AAAAADMAAACcAAAAnQAAABj///8A////AP///wAAAAAYAAAAGP///wD///8A////AAAAABgAAACdAAAAnAAAADMAAAB1AAAAwwAAAP8AAADpAAAAsQAAAE4AAAAb////AP///wAAAAAbAAAATgAAALEAAADpAAAA/wAAAMMAAAB1AAAAtwAAAOkAAAD/AAAA/wAAAP8AAADvAAAA3gAAAN4AAADeAAAA3gAAAO8AAAD/AAAA/wAAAP8AAADpAAAAtwAAAGUAAAA/AAAA3wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADfAAAAPwAAAGX///8A////AAAAAEgAAADtAAAAvwAAAL0AAADGAAAA7wAAAO8AAADGAAAAvQAAAL8AAADtAAAASP///wD///8A////AP///wD///8AAAAAO////wD///8A////AAAAAIcAAACH////AP///wD///8AAAAAO////wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A//8AAP//AAD4HwAA7/cAAN/7AAD//wAAoYUAAJ55AACf+QAAh+EAAAAAAADAAwAA4AcAAP5/AAD//wAA//8AAA=="/>
<link rel="icon" type="image/png" sizes="32x32" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH4QQQEwksSS9ZWwAAAk1JREFUWMPtll2ITVEUx39nn/O7Y5qR8f05wtCUUr6ZIS++8pEnkZInPImneaCQ5METNdOkeFBKUhMPRIkHKfEuUZSUlGlKPN2TrgfncpvmnntnmlEyq1Z7t89/rf9a6+y99oZxGZf/XeIq61EdtgKXgdXA0xrYAvBjOIF1AI9zvjcC74BSpndrJPkBWDScTF8Aa4E3wDlgHbASaANmVqlcCnwHvgDvgVfAJ+AikAAvgfVZwLnSVZHZaOuKoQi3ZOMi4NkYkpe1p4J7A8BpYAD49hfIy/oqG0+hLomiKP2L5L+1ubn5115S+3OAn4EnwBlgMzCjyt6ZAnQCJ4A7wOs88iRJHvw50HoujuPBoCKwHWiosy8MdfZnAdcHk8dxXFJ3VQbQlCTJvRBCGdRbD4M6uc5glpY3eAihpN5S5w12diSEcCCEcKUO4ljdr15T76ur1FDDLIQQ3qv71EdDOe3Kxj3leRXyk+pxdWnFWod6Wt2bY3de3aSuUHcPBVimHs7mK9WrmeOF6lR1o9qnzskh2ar2qm1qizpfXaPeVGdlmGN5pb09qMxz1Xb1kLqgzn1RyH7JUXW52lr5e/Kqi9qpto7V1atuUzfnARrV7jEib1T76gG2qxdGmXyiekkt1GswPTtek0aBfJp6YySGBfWg2tPQ0FAYgf1stUfdmdcjarbYJEniKIq6gY/Aw+zWHAC+p2labGpqiorFYgGYCEzN7oQdQClN07O1/EfDyGgC0ALMBdYAi4FyK+4H3gLPsxfR1zRNi+NP7nH5J+QntnXe5B5mpfQAAAAASUVORK5CYII=">
<!-- CSS -->
<link rel="stylesheet" type="text/css" href="../nimdoc.out.css">
<!-- JS -->
<script type="text/javascript" src="../dochack.js"></script>
</head>
<body>
<div class="document" id="documentId">
<div class="container">
<h1 class="title">nimdoc/extlinks/project/sub/submodule</h1>
<div class="row">
<div class="three columns">
<div class="theme-select-wrapper">
<label for="theme-select">Theme:&nbsp;</label>
<select id="theme-select" onchange="setTheme(this.value)">
<option value="auto">🌗 Match OS</option>
<option value="dark">🌑 Dark</option>
<option value="light">🌕 Light</option>
</select>
</div>
<div id="global-links">
<ul class="simple">
<li><a id="indexLink" href="../theindex.html">Index</a></li>
</ul>
</div>
<div id="searchInputDiv">
Search: <input type="search" id="searchInput" onkeyup="search()"/>
</div>
<div>
Group by:
<select onchange="groupBy(this.value)">
<option value="section">Section</option>
<option value="type">Type</option>
</select>
</div>
<ul class="simple simple-toc" id="toc-list">
<li>
<details open>
<summary><a class="reference reference-toplevel" href="#7" id="57">Types</a></summary>
<ul class="simple simple-toc-section">
<li><a class="reference" href="#submoduleInt" title="submoduleInt = distinct int">submoduleInt</a></li>
</ul>
</details>
</li>
<li>
<details open>
<summary><a class="reference reference-toplevel" href="#12" id="62">Procs</a></summary>
<ul class="simple simple-toc-section">
<ul class="simple nested-toc-section"></a>
<li><a class="reference" href="#%3C%2Fa%3E%2Cint%2Cint" title="`&lt;/a&gt;`(x, y: int): bool">`&lt;/a&gt;`(x, y: int): bool</a></li>
</ul>
</ul>
</details>
</li>
</ul>
</div>
<div class="nine columns" id="content">
<div id="tocRoot"></div>
<p class="module-desc"><p>Ref. <a class="reference external" href="../main.html#A">main: object A</a> from <a class="reference external" href="../main.html">module nimdoc/extlinks/project/main</a>.</p>
<p>Ref. <a class="reference external" href="../_._/util.html#utilfunction,int">util: utilfunction(x: int)</a>.</p>
<p>Ref. <a class="reference external" href="../doc/manual.html#second-section-amp">Nothing User Manual: Second section &amp;</a> from <a class="reference external" href="../doc/manual.html">Nothing User Manual</a>.</p>
</p>
<div class="section" id="7">
<h1><a class="toc-backref" href="#7">Types</a></h1>
<dl class="item">
<div id="submoduleInt">
<dt><pre><a href="submodule.html#submoduleInt"><span class="Identifier">submoduleInt</span></a> <span class="Other">=</span> <span class="Keyword">distinct</span> <span class="Identifier">int</span></pre></dt>
<dd>
</dd>
</div>
</dl>
</div>
<div class="section" id="12">
<h1><a class="toc-backref" href="#12">Procs</a></h1>
<dl class="item">
<div id="&lt;/a&gt;-procs-all">
<div id="</a>,int,int">
<dt><pre><span class="Keyword">proc</span> <a href="#%3C%2Fa%3E%2Cint%2Cint"><span class="Identifier">`&lt;/a&gt;`</span></a><span class="Other">(</span><span class="Identifier">x</span><span class="Other">,</span> <span class="Identifier">y</span><span class="Other">:</span> <span class="Identifier">int</span><span class="Other">)</span><span class="Other">:</span> <span class="Identifier">bool</span> {.<span><span class="Other pragmadots">...</span></span><span class="pragmawrap"><span class="Identifier">raises</span><span class="Other">:</span> <span class="Other">[</span><span class="Other">]</span><span class="Other">,</span> <span class="Identifier">tags</span><span class="Other">:</span> <span class="Other">[</span><span class="Other">]</span><span class="Other">,</span> <span class="Identifier">forbids</span><span class="Other">:</span> <span class="Other">[</span><span class="Other">]</span></span>.}</pre></dt>
<dd>
Attempt to break HTML formatting.
</dd>
</div>
</div>
</dl>
</div>
</div>
</div>
<div class="twelve-columns footer">
<span class="nim-sprite"></span>
<br>
<small style="color: var(--hint);">Made with Nim. Generated: 1970-01-02 03:46:40 UTC</small>
</div>
</div>
</div>
<!-- Google fonts -->
<link href='https://fonts.googleapis.com/css?family=Lato:400,600,900' rel='stylesheet' type='text/css'/>
<link href='https://fonts.googleapis.com/css?family=Source+Code+Pro:400,500,600' rel='stylesheet' type='text/css'/>
</body>
</html>

View File

@@ -0,0 +1,3 @@
nimTitle submodule sub/submodule.html module nimdoc/extlinks/project/sub/submodule 0
nim `</a>` sub/submodule.html#</a>,int,int proc `</a>`(x, y: int): bool 9
nim submoduleInt sub/submodule.html#submoduleInt type submoduleInt 13

View File

@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!-- This file is generated by Nim. -->
<html xmlns="https://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Index</title>
<!-- Favicon -->
<link rel="shortcut icon" href="data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AAAAAAUAAAAF////AP///wD///8A////AP///wD///8A////AP///wD///8A////AAAAAAIAAABbAAAAlQAAAKIAAACbAAAAmwAAAKIAAACVAAAAWwAAAAL///8A////AP///wD///8A////AAAAABQAAADAAAAAYwAAAA3///8A////AP///wD///8AAAAADQAAAGMAAADAAAAAFP///wD///8A////AP///wAAAACdAAAAOv///wD///8A////AP///wD///8A////AP///wD///8AAAAAOgAAAJ3///8A////AP///wAAAAAnAAAAcP///wAAAAAoAAAASv///wD///8A////AP///wAAAABKAAAAKP///wAAAABwAAAAJ////wD///8AAAAAgQAAABwAAACIAAAAkAAAAJMAAACtAAAAFQAAABUAAACtAAAAkwAAAJAAAACIAAAAHAAAAIH///8A////AAAAAKQAAACrAAAAaP///wD///8AAAAARQAAANIAAADSAAAARf///wD///8AAAAAaAAAAKsAAACk////AAAAADMAAACcAAAAnQAAABj///8A////AP///wAAAAAYAAAAGP///wD///8A////AAAAABgAAACdAAAAnAAAADMAAAB1AAAAwwAAAP8AAADpAAAAsQAAAE4AAAAb////AP///wAAAAAbAAAATgAAALEAAADpAAAA/wAAAMMAAAB1AAAAtwAAAOkAAAD/AAAA/wAAAP8AAADvAAAA3gAAAN4AAADeAAAA3gAAAO8AAAD/AAAA/wAAAP8AAADpAAAAtwAAAGUAAAA/AAAA3wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADfAAAAPwAAAGX///8A////AAAAAEgAAADtAAAAvwAAAL0AAADGAAAA7wAAAO8AAADGAAAAvQAAAL8AAADtAAAASP///wD///8A////AP///wD///8AAAAAO////wD///8A////AAAAAIcAAACH////AP///wD///8AAAAAO////wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A//8AAP//AAD4HwAA7/cAAN/7AAD//wAAoYUAAJ55AACf+QAAh+EAAAAAAADAAwAA4AcAAP5/AAD//wAA//8AAA=="/>
<link rel="icon" type="image/png" sizes="32x32" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH4QQQEwksSS9ZWwAAAk1JREFUWMPtll2ITVEUx39nn/O7Y5qR8f05wtCUUr6ZIS++8pEnkZInPImneaCQ5METNdOkeFBKUhMPRIkHKfEuUZSUlGlKPN2TrgfncpvmnntnmlEyq1Z7t89/rf9a6+y99oZxGZf/XeIq61EdtgKXgdXA0xrYAvBjOIF1AI9zvjcC74BSpndrJPkBWDScTF8Aa4E3wDlgHbASaANmVqlcCnwHvgDvgVfAJ+AikAAvgfVZwLnSVZHZaOuKoQi3ZOMi4NkYkpe1p4J7A8BpYAD49hfIy/oqG0+hLomiKP2L5L+1ubn5115S+3OAn4EnwBlgMzCjyt6ZAnQCJ4A7wOs88iRJHvw50HoujuPBoCKwHWiosy8MdfZnAdcHk8dxXFJ3VQbQlCTJvRBCGdRbD4M6uc5glpY3eAihpN5S5w12diSEcCCEcKUO4ljdr15T76ur1FDDLIQQ3qv71EdDOe3Kxj3leRXyk+pxdWnFWod6Wt2bY3de3aSuUHcPBVimHs7mK9WrmeOF6lR1o9qnzskh2ar2qm1qizpfXaPeVGdlmGN5pb09qMxz1Xb1kLqgzn1RyH7JUXW52lr5e/Kqi9qpto7V1atuUzfnARrV7jEib1T76gG2qxdGmXyiekkt1GswPTtek0aBfJp6YySGBfWg2tPQ0FAYgf1stUfdmdcjarbYJEniKIq6gY/Aw+zWHAC+p2labGpqiorFYgGYCEzN7oQdQClN07O1/EfDyGgC0ALMBdYAi4FyK+4H3gLPsxfR1zRNi+NP7nH5J+QntnXe5B5mpfQAAAAASUVORK5CYII=">
<!-- CSS -->
<link rel="stylesheet" type="text/css" href="nimdoc.out.css">
<!-- JS -->
<script type="text/javascript" src="dochack.js"></script>
</head>
<body>
<div class="document" id="documentId">
<div class="container">
<h1 class="title">Index</h1>
Documents: <a href="doc/manual.html">Nothing User Manual</a>.<br/><p />Modules: <a href="_._/util.html">../util</a>, <a href="main.html">main</a>, <a href="sub/submodule.html">sub/submodule</a>.<br/><p /><h2>API symbols</h2>
<dl><dt><a name="%60%26lt%3B/a%26gt%3B%60" href="#%60%26lt%3B/a%26gt%3B%60"><span>`&lt;/a&gt;`:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="submodule: proc `&lt;/a&gt;`(x, y: int): bool" href="sub/submodule.html#%3C/a%3E%2Cint%2Cint">submodule: proc `&lt;/a&gt;`(x, y: int): bool</a></li>
</ul></dd>
<dt><a name="A" href="#A"><span>A:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="main: object A" href="main.html#A">main: object A</a></li>
</ul></dd>
<dt><a name="mainfunction" href="#mainfunction"><span>mainfunction:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="main: proc mainfunction(): int" href="main.html#mainfunction">main: proc mainfunction(): int</a></li>
</ul></dd>
<dt><a name="submoduleInt" href="#submoduleInt"><span>submoduleInt:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="submodule: type submoduleInt" href="sub/submodule.html#submoduleInt">submodule: type submoduleInt</a></li>
</ul></dd>
<dt><a name="utilfunction" href="#utilfunction"><span>utilfunction:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="util: proc utilfunction(x: int): int" href="_._/util.html#utilfunction%2Cint">util: proc utilfunction(x: int): int</a></li>
</ul></dd>
</dl>
<div class="twelve-columns footer">
<span class="nim-sprite"></span>
<br>
<small style="color: var(--hint);">Made with Nim. Generated: 1970-01-02 03:46:40 UTC</small>
</div>
</div>
</div>
<!-- Google fonts -->
<link href='https://fonts.googleapis.com/css?family=Lato:400,600,900' rel='stylesheet' type='text/css'/>
<link href='https://fonts.googleapis.com/css?family=Source+Code+Pro:400,500,600' rel='stylesheet' type='text/css'/>
</body>
</html>

View File

@@ -0,0 +1,23 @@
## my heading
## ==========
##
## .. importdoc:: sub/submodule.nim, ../util.nim, doc/manual.md
##
## .. See also [Second&&&] and particularly [first section] and [Second section &].
##
## See also [module nimdoc/extlinks/util] or [nimdoc/extlinks/project/sub/submodule module].
##
## Ref. [`</a>` proc].
##
## Ref. [First section] or [Second section &] from [Nothing User Manual].
import ../util, sub/submodule
type A* = object
x: int
proc mainfunction*(): int =
# just to suppress "not used" warnings:
if `</a>`(1, 2):
result = utilfunction(0)

View File

@@ -0,0 +1,13 @@
## .. importdoc:: ../../util.nim, ../main.nim, ../doc/manual.md
##
## Ref. [object A] from [module nimdoc/extlinks/project/main].
##
## Ref. [utilfunction(x: int)].
##
## Ref. [Second section &] from [Nothing User Manual].
proc `</a>`*(x, y: int): bool =
## Attempt to break HTML formatting.
result = x < y
type submoduleInt* = distinct int

2
nimdoc/extlinks/util.nim Normal file
View File

@@ -0,0 +1,2 @@
proc utilfunction*(x: int): int =
x + 42

View File

@@ -1 +1,2 @@
foo index.html#foo foo: foo()
nimTitle foo index.html module nimdoc/test_out_index_dot_html/foo 0
nim foo index.html#foo proc foo() 1

View File

@@ -24,7 +24,7 @@
Modules: <a href="index.html">index</a>.<br/><p /><h2>API symbols</h2>
<dl><dt><a name="foo" href="#foo"><span>foo:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="foo: foo()" href="index.html#foo">foo: foo()</a></li>
data-doc-search-tag="foo: proc foo()" href="index.html#foo">foo: proc foo()</a></li>
</ul></dd>
</dl>
<div class="twelve-columns footer">

View File

@@ -12,11 +12,16 @@ var
const
baseDir = "nimdoc"
let
baseDirAbs = getCurrentDir() / baseDir
type
NimSwitches = object
doc: seq[string]
docStage2: seq[string]
buildIndex: seq[string]
md2html: seq[string]
md2htmlStage2: seq[string]
proc exec(cmd: string) =
if execShellCmd(cmd) != 0:
@@ -25,6 +30,9 @@ proc exec(cmd: string) =
proc testNimDoc(prjDir, docsDir: string; switches: NimSwitches; fixup = false) =
let
nimDocSwitches = switches.doc.join(" ")
nimDocStage2Switches = switches.docStage2.join(" ")
nimMd2HtmlSwitches = switches.md2html.join(" ")
nimMd2HtmlStage2Switches = switches.md2htmlStage2.join(" ")
nimBuildIndexSwitches = switches.buildIndex.join(" ")
putEnv("SOURCE_DATE_EPOCH", "100000")
@@ -32,9 +40,23 @@ proc testNimDoc(prjDir, docsDir: string; switches: NimSwitches; fixup = false) =
if nimDocSwitches != "":
exec("$1 doc $2" % [nimExe, nimDocSwitches])
echo("$1 doc $2" % [nimExe, nimDocSwitches])
if nimMd2HtmlSwitches != "":
exec("$1 md2html $2" % [nimExe, nimMd2HtmlSwitches])
echo("$1 md2html $2" % [nimExe, nimMd2HtmlSwitches])
if nimDocStage2Switches != "":
exec("$1 doc $2" % [nimExe, nimDocStage2Switches])
echo("$1 doc $2" % [nimExe, nimDocStage2Switches])
if nimMd2HtmlStage2Switches != "":
exec("$1 md2html $2" % [nimExe, nimMd2HtmlStage2Switches])
echo("$1 md2html $2" % [nimExe, nimMd2HtmlStage2Switches])
if nimBuildIndexSwitches != "":
exec("$1 buildIndex $2" % [nimExe, nimBuildIndexSwitches])
echo("$1 buildIndex $2" % [nimExe, nimBuildIndexSwitches])
for expected in walkDirRec(prjDir / "expected/", checkDir=true):
let produced = expected.replace('\\', '/').replace("/expected/", "/$1/" % [docsDir])
@@ -88,5 +110,46 @@ let
test3Switches = NimSwitches(doc: @["$1/$2.nim" % [test3Dir, test3PrjName]])
testNimDoc(test3Dir, test3DocsDir, test3Switches, fixup)
# Test concise external links (RFC#125) that work with `.idx` files.
# extlinks
# ├── project
# │   ├── main.nim
# │   ├── manual.md
# │   └── sub
# │   └── submodule.nim
# └── util.nim
#
# `main.nim` imports `submodule.nim` and `../utils.nim`.
# `main.nim`, `submodule.nim`, `manual.md` do importdoc and reference each other.
let
test4PrjName = "extlinks/project"
test4Dir = baseDir / test4PrjName
test4DirAbs = baseDirAbs / test4PrjName
test4MainModule = "main"
test4MarkupDoc = "doc" / "manual.md"
test4DocsDir = "htmldocs"
# 1st stage is with --index:only, 2nd is final
test4Switches = NimSwitches(
doc: @["--project",
"--outdir:$1/$2" % [test4Dir, test4DocsDir],
"--index:only",
"$1/$2.nim" % [test4Dir, test4MainModule]],
md2html:
@["--outdir:$1/$2" % [test4Dir, test4DocsDir],
"--docroot:$1" % [test4DirAbs],
"--index:only",
"$1/$2" % [test4Dir, test4MarkupDoc]],
docStage2:
@["--project",
"--outdir:$1/$2" % [test4Dir, test4DocsDir],
"$1/$2.nim" % [test4Dir, test4MainModule]],
md2htmlStage2:
@["--outdir:$1/$2" % [test4Dir, test4DocsDir],
"--docroot:$1" % [test4DirAbs],
"$1/$2" % [test4Dir, test4MarkupDoc]],
)
testNimDoc(test4Dir, test4DocsDir, test4Switches, fixup)
if failures > 0:
quit "$# failures occurred; see note in nimdoc/tester.nim regarding -d:nimTestsNimdocFixup" % $failures

View File

@@ -226,7 +226,7 @@
cmp: proc (x: T; y: K): int {.closure.}): int" href="#binarySearch,openArray[T],K,proc(T,K)">binary search</a>.</p>
<p>Note that <tt class="docutils literal"><span class="pre"><span class="Keyword">proc</span></span></tt> can be used in postfix form: <a class="reference internal nimdoc" title="proc binarySearch[T, K](a: openArray[T]; key: K;
cmp: proc (x: T; y: K): int {.closure.}): int" href="#binarySearch,openArray[T],K,proc(T,K)">binarySearch proc</a>.</p>
<p>Ref. type like <a class="reference internal nimdoc" title="type G" href="#G">G</a> and <a class="reference internal nimdoc" title="type G" href="#G">type G</a> and <a class="reference internal nimdoc" title="type G" href="#G">G[T]</a> and <a class="reference internal nimdoc" title="type G" href="#G">type G*[T]</a>.</p>
<p>Ref. type like <a class="reference internal nimdoc" title="object G" href="#G">G</a> and <a class="reference internal nimdoc" title="object G" href="#G">type G</a> and <a class="reference internal nimdoc" title="object G" href="#G">G[T]</a> and <a class="reference internal nimdoc" title="object G" href="#G">type G*[T]</a>.</p>
<p>Group ref. with capital letters works: <a class="reference internal nimdoc" title="proc fN11 (2 overloads)" href="#fN11-procs-all">fN11</a> or <a class="reference internal nimdoc" title="proc fN11 (2 overloads)" href="#fN11-procs-all">fn11</a> </p>
Ref. <a class="reference internal nimdoc" title="proc `[]`[T](x: G[T]): T" href="#[],G[T]">[]</a> is the same as <a class="reference internal nimdoc" title="proc `[]`[T](x: G[T]): T" href="#[],G[T]">proc `[]`(G[T])</a> because there are no overloads. The full form: <a class="reference internal nimdoc" title="proc `[]`[T](x: G[T]): T" href="#[],G[T]">proc `[]`*[T](x: G[T]): T</a>Ref. <a class="reference internal nimdoc" title="proc `[]=`[T](a: var G[T]; index: int; value: T)" href="#[]=,G[T],int,T">[]=</a> aka <a class="reference internal nimdoc" title="proc `[]=`[T](a: var G[T]; index: int; value: T)" href="#[]=,G[T],int,T">`[]=`(G[T], int, T)</a>.Ref. <a class="reference internal nimdoc" title="proc $ (2 overloads)" href="#$-procs-all">$</a> aka <a class="reference internal nimdoc" title="proc $ (2 overloads)" href="#$-procs-all">proc $</a> or <a class="reference internal nimdoc" title="proc $ (2 overloads)" href="#$-procs-all">proc `$`</a>.Ref. <a class="reference internal nimdoc" title="proc `$`[T](a: ref SomeType): string" href="#$,ref.SomeType">$(a: ref SomeType)</a>.Ref. <a class="reference internal nimdoc" title="iterator fooBar(a: seq[SomeType]): int" href="#fooBar.i,seq[SomeType]">foo_bar</a> aka <a class="reference internal nimdoc" title="iterator fooBar(a: seq[SomeType]): int" href="#fooBar.i,seq[SomeType]">iterator foo_bar_</a>.Ref. <a class="reference internal nimdoc" title="proc fn[T; U, V: SomeFloat]()" href="#fn">fn[T; U,V: SomeFloat]()</a>.Ref. <a class="reference internal nimdoc" title="proc `'big`(a: string): SomeType" href="#'big,string">'big</a> or <a class="reference internal nimdoc" title="proc `'big`(a: string): SomeType" href="#'big,string">func `'big`</a> or <a class="reference internal nimdoc" title="proc `'big`(a: string): SomeType" href="#'big,string">`'big`(string)</a>.
<h1><a class="toc-backref" id="pandoc-markdown" href="#pandoc-markdown">Pandoc Markdown</a></h1><p>Now repeat all the auto links of above in Pandoc Markdown Syntax.</p>
@@ -240,11 +240,11 @@ Ref. <a class="reference internal nimdoc" title="proc `[]`[T](x: G[T]): T" href=
cmp: proc (x: T; y: K): int {.closure.}): int" href="#binarySearch,openArray[T],K,proc(T,K)">binary search</a>.</p>
<p>Note that <tt class="docutils literal"><span class="pre"><span class="Keyword">proc</span></span></tt> can be used in postfix form: <a class="reference internal nimdoc" title="proc binarySearch[T, K](a: openArray[T]; key: K;
cmp: proc (x: T; y: K): int {.closure.}): int" href="#binarySearch,openArray[T],K,proc(T,K)">binarySearch proc</a>.</p>
<p>Ref. type like <a class="reference internal nimdoc" title="type G" href="#G">G</a> and <a class="reference internal nimdoc" title="type G" href="#G">type G</a> and <a class="reference internal nimdoc" title="type G" href="#G">G[T]</a> and <a class="reference internal nimdoc" title="type G" href="#G">type G*[T]</a>.</p>
<p>Ref. type like <a class="reference internal nimdoc" title="object G" href="#G">G</a> and <a class="reference internal nimdoc" title="object G" href="#G">type G</a> and <a class="reference internal nimdoc" title="object G" href="#G">G[T]</a> and <a class="reference internal nimdoc" title="object G" href="#G">type G*[T]</a>.</p>
<p>Group ref. with capital letters works: <a class="reference internal nimdoc" title="proc fN11 (2 overloads)" href="#fN11-procs-all">fN11</a> or <a class="reference internal nimdoc" title="proc fN11 (2 overloads)" href="#fN11-procs-all">fn11</a></p>
<p>Ref. <a class="reference internal nimdoc" title="proc `[]`[T](x: G[T]): T" href="#[],G[T]">`[]`</a> is the same as <a class="reference internal nimdoc" title="proc `[]`[T](x: G[T]): T" href="#[],G[T]">proc `[]`(G[T])</a> because there are no overloads. The full form: <a class="reference internal nimdoc" title="proc `[]`[T](x: G[T]): T" href="#[],G[T]">proc `[]`*[T](x: G[T]): T</a> Ref. <a class="reference internal nimdoc" title="proc `[]=`[T](a: var G[T]; index: int; value: T)" href="#[]=,G[T],int,T">`[]=`</a> aka <a class="reference internal nimdoc" title="proc `[]=`[T](a: var G[T]; index: int; value: T)" href="#[]=,G[T],int,T">`[]=`(G[T], int, T)</a>. Ref. <a class="reference internal nimdoc" title="proc $ (2 overloads)" href="#$-procs-all">$</a> aka <a class="reference internal nimdoc" title="proc $ (2 overloads)" href="#$-procs-all">proc $</a> or <a class="reference internal nimdoc" title="proc $ (2 overloads)" href="#$-procs-all">proc `$`</a>. Ref. <a class="reference internal nimdoc" title="proc `$`[T](a: ref SomeType): string" href="#$,ref.SomeType">$(a: ref SomeType)</a>. Ref. <a class="reference internal nimdoc" title="iterator fooBar(a: seq[SomeType]): int" href="#fooBar.i,seq[SomeType]">foo_bar</a> aka <a class="reference internal nimdoc" title="iterator fooBar(a: seq[SomeType]): int" href="#fooBar.i,seq[SomeType]">iterator foo_bar_</a>. Ref. <a class="reference internal nimdoc" title="proc fn[T; U, V: SomeFloat]()" href="#fn">fn[T; U,V: SomeFloat]()</a>. Ref. <a class="reference internal nimdoc" title="proc `'big`(a: string): SomeType" href="#'big,string">'big</a> or <a class="reference internal nimdoc" title="proc `'big`(a: string): SomeType" href="#'big,string">func `'big`</a> or <a class="reference internal nimdoc" title="proc `'big`(a: string): SomeType" href="#'big,string">`'big`(string)</a>.</p>
<h2><a class="toc-backref" id="pandoc-markdown-link-name-syntax" href="#pandoc-markdown-link-name-syntax">Link name syntax</a></h2><p>Pandoc Markdown has synax for changing text of links: Ref. <a class="reference internal nimdoc" title="proc `[]`[T](x: G[T]): T" href="#[],G[T]">this proc</a> or <a class="reference internal nimdoc" title="type G" href="#G">another symbol</a>.</p>
<h2><a class="toc-backref" id="pandoc-markdown-link-name-syntax" href="#pandoc-markdown-link-name-syntax">Link name syntax</a></h2><p>Pandoc Markdown has synax for changing text of links: Ref. <a class="reference internal nimdoc" title="proc `[]`[T](x: G[T]): T" href="#[],G[T]">this proc</a> or <a class="reference internal nimdoc" title="object G" href="#G">another symbol</a>.</p>
<h2><a class="toc-backref" id="pandoc-markdown-symbols-documentation" href="#pandoc-markdown-symbols-documentation">Symbols documentation</a></h2><p>Let us repeat auto links from symbols section below:</p>
<p>There is also variant <a class="reference internal nimdoc" title="proc f(x: G[string])" href="#f,G[string]">f(G[string])</a>. See also <a class="reference internal nimdoc" title="proc f(x: G[int])" href="#f,G[int]">f(G[int])</a>.</p>

View File

@@ -1,41 +1,46 @@
funWithGenerics subdir/subdir_b/utils.html#funWithGenerics,T,U utils: funWithGenerics[T, U: SomeFloat](a: T; b: U)
enumValueA subdir/subdir_b/utils.html#enumValueA SomeType.enumValueA
enumValueB subdir/subdir_b/utils.html#enumValueB SomeType.enumValueB
enumValueC subdir/subdir_b/utils.html#enumValueC SomeType.enumValueC
SomeType subdir/subdir_b/utils.html#SomeType utils: SomeType
G subdir/subdir_b/utils.html#G utils: G
someType subdir/subdir_b/utils.html#someType_2 utils: someType(): SomeType
fn2 subdir/subdir_b/utils.html#fn2 utils: fn2()
fn2 subdir/subdir_b/utils.html#fn2,int utils: fn2(x: int)
fn2 subdir/subdir_b/utils.html#fn2,int,float utils: fn2(x: int; y: float)
binarySearch subdir/subdir_b/utils.html#binarySearch,openArray[T],K,proc(T,K) utils: binarySearch[T, K](a: openArray[T]; key: K;\n cmp: proc (x: T; y: K): int {.closure.}): int
fn3 subdir/subdir_b/utils.html#fn3 utils: fn3(): auto
fn4 subdir/subdir_b/utils.html#fn4 utils: fn4(): auto
fn5 subdir/subdir_b/utils.html#fn5 utils: fn5()
fn6 subdir/subdir_b/utils.html#fn6 utils: fn6()
fn7 subdir/subdir_b/utils.html#fn7 utils: fn7()
fn8 subdir/subdir_b/utils.html#fn8 utils: fn8(): auto
fn9 subdir/subdir_b/utils.html#fn9,int utils: fn9(a: int): int
fn10 subdir/subdir_b/utils.html#fn10,int utils: fn10(a: int): int
fN11 subdir/subdir_b/utils.html#fN11 utils: fN11()
fN11 subdir/subdir_b/utils.html#fN11,int utils: fN11(x: int)
aEnum subdir/subdir_b/utils.html#aEnum.t utils: aEnum(): untyped
bEnum subdir/subdir_b/utils.html#bEnum.t utils: bEnum(): untyped
fromUtilsGen subdir/subdir_b/utils.html#fromUtilsGen.t utils: fromUtilsGen(): untyped
f subdir/subdir_b/utils.html#f,G[int] utils: f(x: G[int])
f subdir/subdir_b/utils.html#f,G[string] utils: f(x: G[string])
`[]` subdir/subdir_b/utils.html#[],G[T] utils: `[]`[T](x: G[T]): T
`[]=` subdir/subdir_b/utils.html#[]=,G[T],int,T utils: `[]=`[T](a: var G[T]; index: int; value: T)
`$` subdir/subdir_b/utils.html#$,G[T] utils: `$`[T](a: G[T]): string
`$` subdir/subdir_b/utils.html#$,ref.SomeType utils: `$`[T](a: ref SomeType): string
fooBar subdir/subdir_b/utils.html#fooBar.i,seq[SomeType] utils: fooBar(a: seq[SomeType]): int
fn subdir/subdir_b/utils.html#fn utils: fn[T; U, V: SomeFloat]()
`'big` subdir/subdir_b/utils.html#'big,string utils: `&apos;big`(a: string): SomeType
This is now a header subdir/subdir_b/utils.html#this-is-now-a-header This is now a header
Next header subdir/subdir_b/utils.html#this-is-now-a-header-next-header Next header
And so on subdir/subdir_b/utils.html#next-header-and-so-on And so on
More headers subdir/subdir_b/utils.html#more-headers More headers
Up to level 6 subdir/subdir_b/utils.html#more-headers-up-to-level-6 Up to level 6
Pandoc Markdown subdir/subdir_b/utils.html#pandoc-markdown Pandoc Markdown
Link name syntax subdir/subdir_b/utils.html#pandoc-markdown-link-name-syntax Link name syntax
Symbols documentation subdir/subdir_b/utils.html#pandoc-markdown-symbols-documentation Symbols documentation
nimTitle utils subdir/subdir_b/utils.html module subdir/subdir_b/utils 0
nim funWithGenerics subdir/subdir_b/utils.html#funWithGenerics,T,U proc funWithGenerics[T, U: SomeFloat](a: T; b: U) 1
nim enumValueA subdir/subdir_b/utils.html#enumValueA SomeType.enumValueA 45
nim enumValueB subdir/subdir_b/utils.html#enumValueB SomeType.enumValueB 45
nim enumValueC subdir/subdir_b/utils.html#enumValueC SomeType.enumValueC 45
nim SomeType subdir/subdir_b/utils.html#SomeType enum SomeType 45
nim G subdir/subdir_b/utils.html#G object G 49
nim someType subdir/subdir_b/utils.html#someType_2 proc someType(): SomeType 52
nim fn2 subdir/subdir_b/utils.html#fn2 proc fn2() 57
nim fn2 subdir/subdir_b/utils.html#fn2,int proc fn2(x: int) 58
nim fn2 subdir/subdir_b/utils.html#fn2,int,float proc fn2(x: int; y: float) 61
nim binarySearch subdir/subdir_b/utils.html#binarySearch,openArray[T],K,proc(T,K) proc binarySearch[T, K](a: openArray[T]; key: K;\n cmp: proc (x: T; y: K): int {.closure.}): int 63
nim fn3 subdir/subdir_b/utils.html#fn3 proc fn3(): auto 66
nim fn4 subdir/subdir_b/utils.html#fn4 proc fn4(): auto 67
nim fn5 subdir/subdir_b/utils.html#fn5 proc fn5() 69
nim fn6 subdir/subdir_b/utils.html#fn6 proc fn6() 70
nim fn7 subdir/subdir_b/utils.html#fn7 proc fn7() 72
nim fn8 subdir/subdir_b/utils.html#fn8 proc fn8(): auto 75
nim fn9 subdir/subdir_b/utils.html#fn9,int proc fn9(a: int): int 78
nim fn10 subdir/subdir_b/utils.html#fn10,int proc fn10(a: int): int 79
nim fN11 subdir/subdir_b/utils.html#fN11 proc fN11() 85
nim fN11 subdir/subdir_b/utils.html#fN11,int proc fN11(x: int) 86
nim aEnum subdir/subdir_b/utils.html#aEnum.t template aEnum(): untyped 90
nim bEnum subdir/subdir_b/utils.html#bEnum.t template bEnum(): untyped 95
nim fromUtilsGen subdir/subdir_b/utils.html#fromUtilsGen.t template fromUtilsGen(): untyped 106
nim f subdir/subdir_b/utils.html#f,G[int] proc f(x: G[int]) 130
nim f subdir/subdir_b/utils.html#f,G[string] proc f(x: G[string]) 133
nim `[]` subdir/subdir_b/utils.html#[],G[T] proc `[]`[T](x: G[T]): T 140
nim `[]=` subdir/subdir_b/utils.html#[]=,G[T],int,T proc `[]=`[T](a: var G[T]; index: int; value: T) 144
nim `$` subdir/subdir_b/utils.html#$,G[T] proc `$`[T](a: G[T]): string 148
nim `$` subdir/subdir_b/utils.html#$,ref.SomeType proc `$`[T](a: ref SomeType): string 152
nim fooBar subdir/subdir_b/utils.html#fooBar.i,seq[SomeType] iterator fooBar(a: seq[SomeType]): int 156
nim fn subdir/subdir_b/utils.html#fn proc fn[T; U, V: SomeFloat]() 160
nim `'big` subdir/subdir_b/utils.html#'big,string proc `'big`(a: string): SomeType 164
nimgrp $ subdir/subdir_b/utils.html#$-procs-all proc 148
nimgrp fn11 subdir/subdir_b/utils.html#fN11-procs-all proc 85
nimgrp fn2 subdir/subdir_b/utils.html#fn2-procs-all proc 57
nimgrp f subdir/subdir_b/utils.html#f-procs-all proc 130
heading This is now a header subdir/subdir_b/utils.html#this-is-now-a-header This is now a header 0
heading Next header subdir/subdir_b/utils.html#this-is-now-a-header-next-header Next header 0
heading And so on subdir/subdir_b/utils.html#next-header-and-so-on And so on 0
heading More headers subdir/subdir_b/utils.html#more-headers More headers 0
heading Up to level 6 subdir/subdir_b/utils.html#more-headers-up-to-level-6 Up to level 6 0
heading Pandoc Markdown subdir/subdir_b/utils.html#pandoc-markdown Pandoc Markdown 0
heading Link name syntax subdir/subdir_b/utils.html#pandoc-markdown-link-name-syntax Link name syntax 0
heading Symbols documentation subdir/subdir_b/utils.html#pandoc-markdown-symbols-documentation Symbols documentation 0

View File

@@ -1,64 +1,67 @@
someVariable testproject.html#someVariable testproject: someVariable
C_A testproject.html#C_A testproject: C_A
C_B testproject.html#C_B testproject: C_B
C_C testproject.html#C_C testproject: C_C
C_D testproject.html#C_D testproject: C_D
bar testproject.html#bar,T,T testproject: bar[T](a, b: T): T
baz testproject.html#baz,T,T testproject: baz[T](a, b: T): T
buzz testproject.html#buzz,T,T testproject: buzz[T](a, b: T): T
FooBuzz testproject.html#FooBuzz testproject: FooBuzz
bar testproject.html#bar testproject: bar(f: FooBuzz)
aVariable testproject.html#aVariable testproject: aVariable
A testproject.html#A testproject: A
B testproject.html#B testproject: B
someFunc testproject.html#someFunc testproject: someFunc()
fromUtils1 testproject.html#fromUtils1.i testproject: fromUtils1(): int
fromUtils2 testproject.html#fromUtils2.t testproject: fromUtils2()
fromUtils3 testproject.html#fromUtils3 testproject: fromUtils3()
isValid testproject.html#isValid,T testproject: isValid[T](x: T): bool
enumValueA2 testproject.html#enumValueA2 Foo.enumValueA2
Foo testproject.html#Foo testproject: Foo
z1 testproject.html#z1 testproject: z1(): Foo
z2 testproject.html#z2 testproject: z2()
z3 testproject.html#z3 testproject: z3()
z4 testproject.html#z4 testproject: z4()
z5 testproject.html#z5 testproject: z5(): int
z6 testproject.html#z6 testproject: z6(): int
z6t testproject.html#z6t.t testproject: z6t(): int
z7 testproject.html#z7 testproject: z7(): int
z8 testproject.html#z8 testproject: z8(): int
z9 testproject.html#z9 testproject: z9()
z10 testproject.html#z10 testproject: z10()
z11 testproject.html#z11 testproject: z11()
z12 testproject.html#z12 testproject: z12(): int
z13 testproject.html#z13 testproject: z13()
baz testproject.html#baz testproject: baz()
z17 testproject.html#z17 testproject: z17()
p1 testproject.html#p1 testproject: p1()
addfBug14485 testproject.html#addfBug14485 testproject: addfBug14485()
c_printf testproject.html#c_printf,cstring testproject: c_printf(frmt: cstring): cint
c_nonexistent testproject.html#c_nonexistent,cstring testproject: c_nonexistent(frmt: cstring): cint
low testproject.html#low,T testproject: low[T: Ordinal | enum | range](x: T): T
low2 testproject.html#low2,T testproject: low2[T: Ordinal | enum | range](x: T): T
tripleStrLitTest testproject.html#tripleStrLitTest testproject: tripleStrLitTest()
method1 testproject.html#method1.e,Moo testproject: method1(self: Moo)
method2 testproject.html#method2.e,Moo testproject: method2(self: Moo): int
method3 testproject.html#method3.e,Moo testproject: method3(self: Moo): int
iter1 testproject.html#iter1.i,int testproject: iter1(n: int): int
iter2 testproject.html#iter2.i,int testproject: iter2(n: int): int
bar testproject.html#bar.m testproject: bar(): untyped
z16 testproject.html#z16.m testproject: z16()
z18 testproject.html#z18.m testproject: z18(): int
foo testproject.html#foo.t,SomeType,SomeType testproject: foo(a, b: SomeType)
myfn testproject.html#myfn.t testproject: myfn()
z14 testproject.html#z14.t testproject: z14()
z15 testproject.html#z15.t testproject: z15()
asyncFun1 testproject.html#asyncFun1 testproject: asyncFun1(): Future[int]
asyncFun2 testproject.html#asyncFun2 testproject: asyncFun2(): owned(Future[void])
asyncFun3 testproject.html#asyncFun3 testproject: asyncFun3(): owned(Future[void])
testNimDocTrailingExample testproject.html#testNimDocTrailingExample.t testproject: testNimDocTrailingExample()
Circle testproject.html#Circle Shapes.Circle
Triangle testproject.html#Triangle Shapes.Triangle
Rectangle testproject.html#Rectangle Shapes.Rectangle
Shapes testproject.html#Shapes testproject: Shapes
anything testproject.html#anything testproject: anything()
nimTitle testproject testproject.html module testproject 0
nim someVariable testproject.html#someVariable var someVariable 13
nim C_A testproject.html#C_A const C_A 26
nim C_B testproject.html#C_B const C_B 27
nim C_C testproject.html#C_C const C_C 28
nim C_D testproject.html#C_D const C_D 29
nim bar testproject.html#bar,T,T proc bar[T](a, b: T): T 31
nim baz testproject.html#baz,T,T proc baz[T](a, b: T): T 34
nim buzz testproject.html#buzz,T,T proc buzz[T](a, b: T): T 38
nim FooBuzz testproject.html#FooBuzz type FooBuzz 43
nim bar testproject.html#bar proc bar(f: FooBuzz) 47
nim aVariable testproject.html#aVariable var aVariable 52
nim A testproject.html#A enum A 92
nim B testproject.html#B enum B 97
nim someFunc testproject.html#someFunc proc someFunc() 56
nim fromUtils1 testproject.html#fromUtils1.i iterator fromUtils1(): int 112
nim fromUtils2 testproject.html#fromUtils2.t template fromUtils2() 119
nim fromUtils3 testproject.html#fromUtils3 proc fromUtils3() 57
nim isValid testproject.html#isValid,T proc isValid[T](x: T): bool 59
nim enumValueA2 testproject.html#enumValueA2 Foo.enumValueA2 66
nim Foo testproject.html#Foo enum Foo 66
nim z1 testproject.html#z1 proc z1(): Foo 69
nim z2 testproject.html#z2 proc z2() 73
nim z3 testproject.html#z3 proc z3() 78
nim z4 testproject.html#z4 proc z4() 81
nim z5 testproject.html#z5 proc z5(): int 87
nim z6 testproject.html#z6 proc z6(): int 91
nim z6t testproject.html#z6t.t template z6t(): int 95
nim z7 testproject.html#z7 proc z7(): int 99
nim z8 testproject.html#z8 proc z8(): int 103
nim z9 testproject.html#z9 proc z9() 111
nim z10 testproject.html#z10 proc z10() 114
nim z11 testproject.html#z11 proc z11() 119
nim z12 testproject.html#z12 proc z12(): int 124
nim z13 testproject.html#z13 proc z13() 129
nim baz testproject.html#baz proc baz() 134
nim z17 testproject.html#z17 proc z17() 144
nim p1 testproject.html#p1 proc p1() 156
nim addfBug14485 testproject.html#addfBug14485 proc addfBug14485() 177
nim c_printf testproject.html#c_printf,cstring proc c_printf(frmt: cstring): cint 193
nim c_nonexistent testproject.html#c_nonexistent,cstring proc c_nonexistent(frmt: cstring): cint 197
nim low testproject.html#low,T proc low[T: Ordinal | enum | range](x: T): T 200
nim low2 testproject.html#low2,T proc low2[T: Ordinal | enum | range](x: T): T 210
nim tripleStrLitTest testproject.html#tripleStrLitTest proc tripleStrLitTest() 223
nim method1 testproject.html#method1.e,Moo method method1(self: Moo) 264
nim method2 testproject.html#method2.e,Moo method method2(self: Moo): int 266
nim method3 testproject.html#method3.e,Moo method method3(self: Moo): int 269
nim iter1 testproject.html#iter1.i,int iterator iter1(n: int): int 274
nim iter2 testproject.html#iter2.i,int iterator iter2(n: int): int 278
nim bar testproject.html#bar.m macro bar(): untyped 285
nim z16 testproject.html#z16.m macro z16() 288
nim z18 testproject.html#z18.m macro z18(): int 297
nim foo testproject.html#foo.t,SomeType,SomeType template foo(a, b: SomeType) 302
nim myfn testproject.html#myfn.t template myfn() 307
nim z14 testproject.html#z14.t template z14() 328
nim z15 testproject.html#z15.t template z15() 333
nim asyncFun1 testproject.html#asyncFun1 proc asyncFun1(): Future[int] 358
nim asyncFun2 testproject.html#asyncFun2 proc asyncFun2(): owned(Future[void]) 361
nim asyncFun3 testproject.html#asyncFun3 proc asyncFun3(): owned(Future[void]) 362
nim testNimDocTrailingExample testproject.html#testNimDocTrailingExample.t template testNimDocTrailingExample() 371
nim Circle testproject.html#Circle Shapes.Circle 380
nim Triangle testproject.html#Triangle Shapes.Triangle 380
nim Rectangle testproject.html#Rectangle Shapes.Rectangle 380
nim Shapes testproject.html#Shapes enum Shapes 380
nim anything testproject.html#anything proc anything() 387
nimgrp bar testproject.html#bar-procs-all proc 31
nimgrp baz testproject.html#baz-procs-all proc 34

View File

@@ -24,377 +24,377 @@
Modules: <a href="subdir/subdir_b/utils.html">subdir/subdir_b/utils</a>, <a href="testproject.html">testproject</a>.<br/><p /><h2>API symbols</h2>
<dl><dt><a name="%60%24%60" href="#%60%24%60"><span>`$`:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="utils: `$`[T](a: G[T]): string" href="subdir/subdir_b/utils.html#%24%2CG%5BT%5D">utils: `$`[T](a: G[T]): string</a></li>
data-doc-search-tag="utils: proc `$`[T](a: G[T]): string" href="subdir/subdir_b/utils.html#%24%2CG%5BT%5D">utils: proc `$`[T](a: G[T]): string</a></li>
<li><a class="reference external"
data-doc-search-tag="utils: `$`[T](a: ref SomeType): string" href="subdir/subdir_b/utils.html#%24%2Cref.SomeType">utils: `$`[T](a: ref SomeType): string</a></li>
data-doc-search-tag="utils: proc `$`[T](a: ref SomeType): string" href="subdir/subdir_b/utils.html#%24%2Cref.SomeType">utils: proc `$`[T](a: ref SomeType): string</a></li>
</ul></dd>
<dt><a name="%60%27big%60" href="#%60%27big%60"><span>`'big`:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="utils: `&apos;big`(a: string): SomeType" href="subdir/subdir_b/utils.html#%27big%2Cstring">utils: `&apos;big`(a: string): SomeType</a></li>
data-doc-search-tag="utils: proc `'big`(a: string): SomeType" href="subdir/subdir_b/utils.html#%27big%2Cstring">utils: proc `'big`(a: string): SomeType</a></li>
</ul></dd>
<dt><a name="%60%5B%5D%3D%60" href="#%60%5B%5D%3D%60"><span>`[]=`:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="utils: `[]=`[T](a: var G[T]; index: int; value: T)" href="subdir/subdir_b/utils.html#%5B%5D%3D%2CG%5BT%5D%2Cint%2CT">utils: `[]=`[T](a: var G[T]; index: int; value: T)</a></li>
data-doc-search-tag="utils: proc `[]=`[T](a: var G[T]; index: int; value: T)" href="subdir/subdir_b/utils.html#%5B%5D%3D%2CG%5BT%5D%2Cint%2CT">utils: proc `[]=`[T](a: var G[T]; index: int; value: T)</a></li>
</ul></dd>
<dt><a name="%60%5B%5D%60" href="#%60%5B%5D%60"><span>`[]`:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="utils: `[]`[T](x: G[T]): T" href="subdir/subdir_b/utils.html#%5B%5D%2CG%5BT%5D">utils: `[]`[T](x: G[T]): T</a></li>
data-doc-search-tag="utils: proc `[]`[T](x: G[T]): T" href="subdir/subdir_b/utils.html#%5B%5D%2CG%5BT%5D">utils: proc `[]`[T](x: G[T]): T</a></li>
</ul></dd>
<dt><a name="A" href="#A"><span>A:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: A" href="testproject.html#A">testproject: A</a></li>
data-doc-search-tag="testproject: enum A" href="testproject.html#A">testproject: enum A</a></li>
</ul></dd>
<dt><a name="addfBug14485" href="#addfBug14485"><span>addfBug14485:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: addfBug14485()" href="testproject.html#addfBug14485">testproject: addfBug14485()</a></li>
data-doc-search-tag="testproject: proc addfBug14485()" href="testproject.html#addfBug14485">testproject: proc addfBug14485()</a></li>
</ul></dd>
<dt><a name="aEnum" href="#aEnum"><span>aEnum:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="utils: aEnum(): untyped" href="subdir/subdir_b/utils.html#aEnum.t">utils: aEnum(): untyped</a></li>
data-doc-search-tag="utils: template aEnum(): untyped" href="subdir/subdir_b/utils.html#aEnum.t">utils: template aEnum(): untyped</a></li>
</ul></dd>
<dt><a name="anything" href="#anything"><span>anything:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: anything()" href="testproject.html#anything">testproject: anything()</a></li>
data-doc-search-tag="testproject: proc anything()" href="testproject.html#anything">testproject: proc anything()</a></li>
</ul></dd>
<dt><a name="asyncFun1" href="#asyncFun1"><span>asyncFun1:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: asyncFun1(): Future[int]" href="testproject.html#asyncFun1">testproject: asyncFun1(): Future[int]</a></li>
data-doc-search-tag="testproject: proc asyncFun1(): Future[int]" href="testproject.html#asyncFun1">testproject: proc asyncFun1(): Future[int]</a></li>
</ul></dd>
<dt><a name="asyncFun2" href="#asyncFun2"><span>asyncFun2:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: asyncFun2(): owned(Future[void])" href="testproject.html#asyncFun2">testproject: asyncFun2(): owned(Future[void])</a></li>
data-doc-search-tag="testproject: proc asyncFun2(): owned(Future[void])" href="testproject.html#asyncFun2">testproject: proc asyncFun2(): owned(Future[void])</a></li>
</ul></dd>
<dt><a name="asyncFun3" href="#asyncFun3"><span>asyncFun3:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: asyncFun3(): owned(Future[void])" href="testproject.html#asyncFun3">testproject: asyncFun3(): owned(Future[void])</a></li>
data-doc-search-tag="testproject: proc asyncFun3(): owned(Future[void])" href="testproject.html#asyncFun3">testproject: proc asyncFun3(): owned(Future[void])</a></li>
</ul></dd>
<dt><a name="aVariable" href="#aVariable"><span>aVariable:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: aVariable" href="testproject.html#aVariable">testproject: aVariable</a></li>
data-doc-search-tag="testproject: var aVariable" href="testproject.html#aVariable">testproject: var aVariable</a></li>
</ul></dd>
<dt><a name="B" href="#B"><span>B:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: B" href="testproject.html#B">testproject: B</a></li>
data-doc-search-tag="testproject: enum B" href="testproject.html#B">testproject: enum B</a></li>
</ul></dd>
<dt><a name="bar" href="#bar"><span>bar:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: bar(f: FooBuzz)" href="testproject.html#bar">testproject: bar(f: FooBuzz)</a></li>
data-doc-search-tag="testproject: proc bar(f: FooBuzz)" href="testproject.html#bar">testproject: proc bar(f: FooBuzz)</a></li>
<li><a class="reference external"
data-doc-search-tag="testproject: bar[T](a, b: T): T" href="testproject.html#bar%2CT%2CT">testproject: bar[T](a, b: T): T</a></li>
data-doc-search-tag="testproject: proc bar[T](a, b: T): T" href="testproject.html#bar%2CT%2CT">testproject: proc bar[T](a, b: T): T</a></li>
<li><a class="reference external"
data-doc-search-tag="testproject: bar(): untyped" href="testproject.html#bar.m">testproject: bar(): untyped</a></li>
data-doc-search-tag="testproject: macro bar(): untyped" href="testproject.html#bar.m">testproject: macro bar(): untyped</a></li>
</ul></dd>
<dt><a name="baz" href="#baz"><span>baz:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: baz()" href="testproject.html#baz">testproject: baz()</a></li>
data-doc-search-tag="testproject: proc baz()" href="testproject.html#baz">testproject: proc baz()</a></li>
<li><a class="reference external"
data-doc-search-tag="testproject: baz[T](a, b: T): T" href="testproject.html#baz%2CT%2CT">testproject: baz[T](a, b: T): T</a></li>
data-doc-search-tag="testproject: proc baz[T](a, b: T): T" href="testproject.html#baz%2CT%2CT">testproject: proc baz[T](a, b: T): T</a></li>
</ul></dd>
<dt><a name="bEnum" href="#bEnum"><span>bEnum:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="utils: bEnum(): untyped" href="subdir/subdir_b/utils.html#bEnum.t">utils: bEnum(): untyped</a></li>
data-doc-search-tag="utils: template bEnum(): untyped" href="subdir/subdir_b/utils.html#bEnum.t">utils: template bEnum(): untyped</a></li>
</ul></dd>
<dt><a name="binarySearch" href="#binarySearch"><span>binarySearch:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="utils: binarySearch[T, K](a: openArray[T]; key: K;
cmp: proc (x: T; y: K): int {.closure.}): int" href="subdir/subdir_b/utils.html#binarySearch%2CopenArray%5BT%5D%2CK%2Cproc%28T%2CK%29">utils: binarySearch[T, K](a: openArray[T]; key: K;
data-doc-search-tag="utils: proc binarySearch[T, K](a: openArray[T]; key: K;
cmp: proc (x: T; y: K): int {.closure.}): int" href="subdir/subdir_b/utils.html#binarySearch%2CopenArray%5BT%5D%2CK%2Cproc%28T%2CK%29">utils: proc binarySearch[T, K](a: openArray[T]; key: K;
cmp: proc (x: T; y: K): int {.closure.}): int</a></li>
</ul></dd>
<dt><a name="buzz" href="#buzz"><span>buzz:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: buzz[T](a, b: T): T" href="testproject.html#buzz%2CT%2CT">testproject: buzz[T](a, b: T): T</a></li>
data-doc-search-tag="testproject: proc buzz[T](a, b: T): T" href="testproject.html#buzz%2CT%2CT">testproject: proc buzz[T](a, b: T): T</a></li>
</ul></dd>
<dt><a name="C_A" href="#C_A"><span>C_A:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: C_A" href="testproject.html#C_A">testproject: C_A</a></li>
data-doc-search-tag="testproject: const C_A" href="testproject.html#C_A">testproject: const C_A</a></li>
</ul></dd>
<dt><a name="C_B" href="#C_B"><span>C_B:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: C_B" href="testproject.html#C_B">testproject: C_B</a></li>
data-doc-search-tag="testproject: const C_B" href="testproject.html#C_B">testproject: const C_B</a></li>
</ul></dd>
<dt><a name="C_C" href="#C_C"><span>C_C:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: C_C" href="testproject.html#C_C">testproject: C_C</a></li>
data-doc-search-tag="testproject: const C_C" href="testproject.html#C_C">testproject: const C_C</a></li>
</ul></dd>
<dt><a name="C_D" href="#C_D"><span>C_D:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: C_D" href="testproject.html#C_D">testproject: C_D</a></li>
data-doc-search-tag="testproject: const C_D" href="testproject.html#C_D">testproject: const C_D</a></li>
</ul></dd>
<dt><a name="Circle" href="#Circle"><span>Circle:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="Shapes.Circle" href="testproject.html#Circle">Shapes.Circle</a></li>
data-doc-search-tag="testproject: Shapes.Circle" href="testproject.html#Circle">testproject: Shapes.Circle</a></li>
</ul></dd>
<dt><a name="c_nonexistent" href="#c_nonexistent"><span>c_nonexistent:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: c_nonexistent(frmt: cstring): cint" href="testproject.html#c_nonexistent%2Ccstring">testproject: c_nonexistent(frmt: cstring): cint</a></li>
data-doc-search-tag="testproject: proc c_nonexistent(frmt: cstring): cint" href="testproject.html#c_nonexistent%2Ccstring">testproject: proc c_nonexistent(frmt: cstring): cint</a></li>
</ul></dd>
<dt><a name="c_printf" href="#c_printf"><span>c_printf:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: c_printf(frmt: cstring): cint" href="testproject.html#c_printf%2Ccstring">testproject: c_printf(frmt: cstring): cint</a></li>
data-doc-search-tag="testproject: proc c_printf(frmt: cstring): cint" href="testproject.html#c_printf%2Ccstring">testproject: proc c_printf(frmt: cstring): cint</a></li>
</ul></dd>
<dt><a name="enumValueA" href="#enumValueA"><span>enumValueA:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="SomeType.enumValueA" href="subdir/subdir_b/utils.html#enumValueA">SomeType.enumValueA</a></li>
data-doc-search-tag="utils: SomeType.enumValueA" href="subdir/subdir_b/utils.html#enumValueA">utils: SomeType.enumValueA</a></li>
</ul></dd>
<dt><a name="enumValueA2" href="#enumValueA2"><span>enumValueA2:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="Foo.enumValueA2" href="testproject.html#enumValueA2">Foo.enumValueA2</a></li>
data-doc-search-tag="testproject: Foo.enumValueA2" href="testproject.html#enumValueA2">testproject: Foo.enumValueA2</a></li>
</ul></dd>
<dt><a name="enumValueB" href="#enumValueB"><span>enumValueB:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="SomeType.enumValueB" href="subdir/subdir_b/utils.html#enumValueB">SomeType.enumValueB</a></li>
data-doc-search-tag="utils: SomeType.enumValueB" href="subdir/subdir_b/utils.html#enumValueB">utils: SomeType.enumValueB</a></li>
</ul></dd>
<dt><a name="enumValueC" href="#enumValueC"><span>enumValueC:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="SomeType.enumValueC" href="subdir/subdir_b/utils.html#enumValueC">SomeType.enumValueC</a></li>
data-doc-search-tag="utils: SomeType.enumValueC" href="subdir/subdir_b/utils.html#enumValueC">utils: SomeType.enumValueC</a></li>
</ul></dd>
<dt><a name="f" href="#f"><span>f:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="utils: f(x: G[int])" href="subdir/subdir_b/utils.html#f%2CG%5Bint%5D">utils: f(x: G[int])</a></li>
data-doc-search-tag="utils: proc f(x: G[int])" href="subdir/subdir_b/utils.html#f%2CG%5Bint%5D">utils: proc f(x: G[int])</a></li>
<li><a class="reference external"
data-doc-search-tag="utils: f(x: G[string])" href="subdir/subdir_b/utils.html#f%2CG%5Bstring%5D">utils: f(x: G[string])</a></li>
data-doc-search-tag="utils: proc f(x: G[string])" href="subdir/subdir_b/utils.html#f%2CG%5Bstring%5D">utils: proc f(x: G[string])</a></li>
</ul></dd>
<dt><a name="fn" href="#fn"><span>fn:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="utils: fn[T; U, V: SomeFloat]()" href="subdir/subdir_b/utils.html#fn">utils: fn[T; U, V: SomeFloat]()</a></li>
data-doc-search-tag="utils: proc fn[T; U, V: SomeFloat]()" href="subdir/subdir_b/utils.html#fn">utils: proc fn[T; U, V: SomeFloat]()</a></li>
</ul></dd>
<dt><a name="fn10" href="#fn10"><span>fn10:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="utils: fn10(a: int): int" href="subdir/subdir_b/utils.html#fn10%2Cint">utils: fn10(a: int): int</a></li>
data-doc-search-tag="utils: proc fn10(a: int): int" href="subdir/subdir_b/utils.html#fn10%2Cint">utils: proc fn10(a: int): int</a></li>
</ul></dd>
<dt><a name="fN11" href="#fN11"><span>fN11:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="utils: fN11()" href="subdir/subdir_b/utils.html#fN11">utils: fN11()</a></li>
data-doc-search-tag="utils: proc fN11()" href="subdir/subdir_b/utils.html#fN11">utils: proc fN11()</a></li>
<li><a class="reference external"
data-doc-search-tag="utils: fN11(x: int)" href="subdir/subdir_b/utils.html#fN11%2Cint">utils: fN11(x: int)</a></li>
data-doc-search-tag="utils: proc fN11(x: int)" href="subdir/subdir_b/utils.html#fN11%2Cint">utils: proc fN11(x: int)</a></li>
</ul></dd>
<dt><a name="fn2" href="#fn2"><span>fn2:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="utils: fn2()" href="subdir/subdir_b/utils.html#fn2">utils: fn2()</a></li>
data-doc-search-tag="utils: proc fn2()" href="subdir/subdir_b/utils.html#fn2">utils: proc fn2()</a></li>
<li><a class="reference external"
data-doc-search-tag="utils: fn2(x: int)" href="subdir/subdir_b/utils.html#fn2%2Cint">utils: fn2(x: int)</a></li>
data-doc-search-tag="utils: proc fn2(x: int)" href="subdir/subdir_b/utils.html#fn2%2Cint">utils: proc fn2(x: int)</a></li>
<li><a class="reference external"
data-doc-search-tag="utils: fn2(x: int; y: float)" href="subdir/subdir_b/utils.html#fn2%2Cint%2Cfloat">utils: fn2(x: int; y: float)</a></li>
data-doc-search-tag="utils: proc fn2(x: int; y: float)" href="subdir/subdir_b/utils.html#fn2%2Cint%2Cfloat">utils: proc fn2(x: int; y: float)</a></li>
</ul></dd>
<dt><a name="fn3" href="#fn3"><span>fn3:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="utils: fn3(): auto" href="subdir/subdir_b/utils.html#fn3">utils: fn3(): auto</a></li>
data-doc-search-tag="utils: proc fn3(): auto" href="subdir/subdir_b/utils.html#fn3">utils: proc fn3(): auto</a></li>
</ul></dd>
<dt><a name="fn4" href="#fn4"><span>fn4:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="utils: fn4(): auto" href="subdir/subdir_b/utils.html#fn4">utils: fn4(): auto</a></li>
data-doc-search-tag="utils: proc fn4(): auto" href="subdir/subdir_b/utils.html#fn4">utils: proc fn4(): auto</a></li>
</ul></dd>
<dt><a name="fn5" href="#fn5"><span>fn5:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="utils: fn5()" href="subdir/subdir_b/utils.html#fn5">utils: fn5()</a></li>
data-doc-search-tag="utils: proc fn5()" href="subdir/subdir_b/utils.html#fn5">utils: proc fn5()</a></li>
</ul></dd>
<dt><a name="fn6" href="#fn6"><span>fn6:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="utils: fn6()" href="subdir/subdir_b/utils.html#fn6">utils: fn6()</a></li>
data-doc-search-tag="utils: proc fn6()" href="subdir/subdir_b/utils.html#fn6">utils: proc fn6()</a></li>
</ul></dd>
<dt><a name="fn7" href="#fn7"><span>fn7:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="utils: fn7()" href="subdir/subdir_b/utils.html#fn7">utils: fn7()</a></li>
data-doc-search-tag="utils: proc fn7()" href="subdir/subdir_b/utils.html#fn7">utils: proc fn7()</a></li>
</ul></dd>
<dt><a name="fn8" href="#fn8"><span>fn8:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="utils: fn8(): auto" href="subdir/subdir_b/utils.html#fn8">utils: fn8(): auto</a></li>
data-doc-search-tag="utils: proc fn8(): auto" href="subdir/subdir_b/utils.html#fn8">utils: proc fn8(): auto</a></li>
</ul></dd>
<dt><a name="fn9" href="#fn9"><span>fn9:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="utils: fn9(a: int): int" href="subdir/subdir_b/utils.html#fn9%2Cint">utils: fn9(a: int): int</a></li>
data-doc-search-tag="utils: proc fn9(a: int): int" href="subdir/subdir_b/utils.html#fn9%2Cint">utils: proc fn9(a: int): int</a></li>
</ul></dd>
<dt><a name="Foo" href="#Foo"><span>Foo:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: Foo" href="testproject.html#Foo">testproject: Foo</a></li>
data-doc-search-tag="testproject: enum Foo" href="testproject.html#Foo">testproject: enum Foo</a></li>
</ul></dd>
<dt><a name="foo" href="#foo"><span>foo:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: foo(a, b: SomeType)" href="testproject.html#foo.t%2CSomeType%2CSomeType">testproject: foo(a, b: SomeType)</a></li>
data-doc-search-tag="testproject: template foo(a, b: SomeType)" href="testproject.html#foo.t%2CSomeType%2CSomeType">testproject: template foo(a, b: SomeType)</a></li>
</ul></dd>
<dt><a name="fooBar" href="#fooBar"><span>fooBar:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="utils: fooBar(a: seq[SomeType]): int" href="subdir/subdir_b/utils.html#fooBar.i%2Cseq%5BSomeType%5D">utils: fooBar(a: seq[SomeType]): int</a></li>
data-doc-search-tag="utils: iterator fooBar(a: seq[SomeType]): int" href="subdir/subdir_b/utils.html#fooBar.i%2Cseq%5BSomeType%5D">utils: iterator fooBar(a: seq[SomeType]): int</a></li>
</ul></dd>
<dt><a name="FooBuzz" href="#FooBuzz"><span>FooBuzz:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: FooBuzz" href="testproject.html#FooBuzz">testproject: FooBuzz</a></li>
data-doc-search-tag="testproject: type FooBuzz" href="testproject.html#FooBuzz">testproject: type FooBuzz</a></li>
</ul></dd>
<dt><a name="fromUtils1" href="#fromUtils1"><span>fromUtils1:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: fromUtils1(): int" href="testproject.html#fromUtils1.i">testproject: fromUtils1(): int</a></li>
data-doc-search-tag="testproject: iterator fromUtils1(): int" href="testproject.html#fromUtils1.i">testproject: iterator fromUtils1(): int</a></li>
</ul></dd>
<dt><a name="fromUtils2" href="#fromUtils2"><span>fromUtils2:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: fromUtils2()" href="testproject.html#fromUtils2.t">testproject: fromUtils2()</a></li>
data-doc-search-tag="testproject: template fromUtils2()" href="testproject.html#fromUtils2.t">testproject: template fromUtils2()</a></li>
</ul></dd>
<dt><a name="fromUtils3" href="#fromUtils3"><span>fromUtils3:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: fromUtils3()" href="testproject.html#fromUtils3">testproject: fromUtils3()</a></li>
data-doc-search-tag="testproject: proc fromUtils3()" href="testproject.html#fromUtils3">testproject: proc fromUtils3()</a></li>
</ul></dd>
<dt><a name="fromUtilsGen" href="#fromUtilsGen"><span>fromUtilsGen:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="utils: fromUtilsGen(): untyped" href="subdir/subdir_b/utils.html#fromUtilsGen.t">utils: fromUtilsGen(): untyped</a></li>
data-doc-search-tag="utils: template fromUtilsGen(): untyped" href="subdir/subdir_b/utils.html#fromUtilsGen.t">utils: template fromUtilsGen(): untyped</a></li>
</ul></dd>
<dt><a name="funWithGenerics" href="#funWithGenerics"><span>funWithGenerics:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="utils: funWithGenerics[T, U: SomeFloat](a: T; b: U)" href="subdir/subdir_b/utils.html#funWithGenerics%2CT%2CU">utils: funWithGenerics[T, U: SomeFloat](a: T; b: U)</a></li>
data-doc-search-tag="utils: proc funWithGenerics[T, U: SomeFloat](a: T; b: U)" href="subdir/subdir_b/utils.html#funWithGenerics%2CT%2CU">utils: proc funWithGenerics[T, U: SomeFloat](a: T; b: U)</a></li>
</ul></dd>
<dt><a name="G" href="#G"><span>G:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="utils: G" href="subdir/subdir_b/utils.html#G">utils: G</a></li>
data-doc-search-tag="utils: object G" href="subdir/subdir_b/utils.html#G">utils: object G</a></li>
</ul></dd>
<dt><a name="isValid" href="#isValid"><span>isValid:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: isValid[T](x: T): bool" href="testproject.html#isValid%2CT">testproject: isValid[T](x: T): bool</a></li>
data-doc-search-tag="testproject: proc isValid[T](x: T): bool" href="testproject.html#isValid%2CT">testproject: proc isValid[T](x: T): bool</a></li>
</ul></dd>
<dt><a name="iter1" href="#iter1"><span>iter1:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: iter1(n: int): int" href="testproject.html#iter1.i%2Cint">testproject: iter1(n: int): int</a></li>
data-doc-search-tag="testproject: iterator iter1(n: int): int" href="testproject.html#iter1.i%2Cint">testproject: iterator iter1(n: int): int</a></li>
</ul></dd>
<dt><a name="iter2" href="#iter2"><span>iter2:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: iter2(n: int): int" href="testproject.html#iter2.i%2Cint">testproject: iter2(n: int): int</a></li>
data-doc-search-tag="testproject: iterator iter2(n: int): int" href="testproject.html#iter2.i%2Cint">testproject: iterator iter2(n: int): int</a></li>
</ul></dd>
<dt><a name="low" href="#low"><span>low:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: low[T: Ordinal | enum | range](x: T): T" href="testproject.html#low%2CT">testproject: low[T: Ordinal | enum | range](x: T): T</a></li>
data-doc-search-tag="testproject: proc low[T: Ordinal | enum | range](x: T): T" href="testproject.html#low%2CT">testproject: proc low[T: Ordinal | enum | range](x: T): T</a></li>
</ul></dd>
<dt><a name="low2" href="#low2"><span>low2:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: low2[T: Ordinal | enum | range](x: T): T" href="testproject.html#low2%2CT">testproject: low2[T: Ordinal | enum | range](x: T): T</a></li>
data-doc-search-tag="testproject: proc low2[T: Ordinal | enum | range](x: T): T" href="testproject.html#low2%2CT">testproject: proc low2[T: Ordinal | enum | range](x: T): T</a></li>
</ul></dd>
<dt><a name="method1" href="#method1"><span>method1:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: method1(self: Moo)" href="testproject.html#method1.e%2CMoo">testproject: method1(self: Moo)</a></li>
data-doc-search-tag="testproject: method method1(self: Moo)" href="testproject.html#method1.e%2CMoo">testproject: method method1(self: Moo)</a></li>
</ul></dd>
<dt><a name="method2" href="#method2"><span>method2:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: method2(self: Moo): int" href="testproject.html#method2.e%2CMoo">testproject: method2(self: Moo): int</a></li>
data-doc-search-tag="testproject: method method2(self: Moo): int" href="testproject.html#method2.e%2CMoo">testproject: method method2(self: Moo): int</a></li>
</ul></dd>
<dt><a name="method3" href="#method3"><span>method3:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: method3(self: Moo): int" href="testproject.html#method3.e%2CMoo">testproject: method3(self: Moo): int</a></li>
data-doc-search-tag="testproject: method method3(self: Moo): int" href="testproject.html#method3.e%2CMoo">testproject: method method3(self: Moo): int</a></li>
</ul></dd>
<dt><a name="myfn" href="#myfn"><span>myfn:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: myfn()" href="testproject.html#myfn.t">testproject: myfn()</a></li>
data-doc-search-tag="testproject: template myfn()" href="testproject.html#myfn.t">testproject: template myfn()</a></li>
</ul></dd>
<dt><a name="p1" href="#p1"><span>p1:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: p1()" href="testproject.html#p1">testproject: p1()</a></li>
data-doc-search-tag="testproject: proc p1()" href="testproject.html#p1">testproject: proc p1()</a></li>
</ul></dd>
<dt><a name="Rectangle" href="#Rectangle"><span>Rectangle:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="Shapes.Rectangle" href="testproject.html#Rectangle">Shapes.Rectangle</a></li>
data-doc-search-tag="testproject: Shapes.Rectangle" href="testproject.html#Rectangle">testproject: Shapes.Rectangle</a></li>
</ul></dd>
<dt><a name="Shapes" href="#Shapes"><span>Shapes:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: Shapes" href="testproject.html#Shapes">testproject: Shapes</a></li>
data-doc-search-tag="testproject: enum Shapes" href="testproject.html#Shapes">testproject: enum Shapes</a></li>
</ul></dd>
<dt><a name="someFunc" href="#someFunc"><span>someFunc:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: someFunc()" href="testproject.html#someFunc">testproject: someFunc()</a></li>
data-doc-search-tag="testproject: proc someFunc()" href="testproject.html#someFunc">testproject: proc someFunc()</a></li>
</ul></dd>
<dt><a name="SomeType" href="#SomeType"><span>SomeType:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="utils: SomeType" href="subdir/subdir_b/utils.html#SomeType">utils: SomeType</a></li>
data-doc-search-tag="utils: enum SomeType" href="subdir/subdir_b/utils.html#SomeType">utils: enum SomeType</a></li>
</ul></dd>
<dt><a name="someType" href="#someType"><span>someType:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="utils: someType(): SomeType" href="subdir/subdir_b/utils.html#someType_2">utils: someType(): SomeType</a></li>
data-doc-search-tag="utils: proc someType(): SomeType" href="subdir/subdir_b/utils.html#someType_2">utils: proc someType(): SomeType</a></li>
</ul></dd>
<dt><a name="someVariable" href="#someVariable"><span>someVariable:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: someVariable" href="testproject.html#someVariable">testproject: someVariable</a></li>
data-doc-search-tag="testproject: var someVariable" href="testproject.html#someVariable">testproject: var someVariable</a></li>
</ul></dd>
<dt><a name="testNimDocTrailingExample" href="#testNimDocTrailingExample"><span>testNimDocTrailingExample:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: testNimDocTrailingExample()" href="testproject.html#testNimDocTrailingExample.t">testproject: testNimDocTrailingExample()</a></li>
data-doc-search-tag="testproject: template testNimDocTrailingExample()" href="testproject.html#testNimDocTrailingExample.t">testproject: template testNimDocTrailingExample()</a></li>
</ul></dd>
<dt><a name="Triangle" href="#Triangle"><span>Triangle:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="Shapes.Triangle" href="testproject.html#Triangle">Shapes.Triangle</a></li>
data-doc-search-tag="testproject: Shapes.Triangle" href="testproject.html#Triangle">testproject: Shapes.Triangle</a></li>
</ul></dd>
<dt><a name="tripleStrLitTest" href="#tripleStrLitTest"><span>tripleStrLitTest:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: tripleStrLitTest()" href="testproject.html#tripleStrLitTest">testproject: tripleStrLitTest()</a></li>
data-doc-search-tag="testproject: proc tripleStrLitTest()" href="testproject.html#tripleStrLitTest">testproject: proc tripleStrLitTest()</a></li>
</ul></dd>
<dt><a name="z1" href="#z1"><span>z1:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: z1(): Foo" href="testproject.html#z1">testproject: z1(): Foo</a></li>
data-doc-search-tag="testproject: proc z1(): Foo" href="testproject.html#z1">testproject: proc z1(): Foo</a></li>
</ul></dd>
<dt><a name="z10" href="#z10"><span>z10:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: z10()" href="testproject.html#z10">testproject: z10()</a></li>
data-doc-search-tag="testproject: proc z10()" href="testproject.html#z10">testproject: proc z10()</a></li>
</ul></dd>
<dt><a name="z11" href="#z11"><span>z11:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: z11()" href="testproject.html#z11">testproject: z11()</a></li>
data-doc-search-tag="testproject: proc z11()" href="testproject.html#z11">testproject: proc z11()</a></li>
</ul></dd>
<dt><a name="z12" href="#z12"><span>z12:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: z12(): int" href="testproject.html#z12">testproject: z12(): int</a></li>
data-doc-search-tag="testproject: proc z12(): int" href="testproject.html#z12">testproject: proc z12(): int</a></li>
</ul></dd>
<dt><a name="z13" href="#z13"><span>z13:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: z13()" href="testproject.html#z13">testproject: z13()</a></li>
data-doc-search-tag="testproject: proc z13()" href="testproject.html#z13">testproject: proc z13()</a></li>
</ul></dd>
<dt><a name="z14" href="#z14"><span>z14:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: z14()" href="testproject.html#z14.t">testproject: z14()</a></li>
data-doc-search-tag="testproject: template z14()" href="testproject.html#z14.t">testproject: template z14()</a></li>
</ul></dd>
<dt><a name="z15" href="#z15"><span>z15:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: z15()" href="testproject.html#z15.t">testproject: z15()</a></li>
data-doc-search-tag="testproject: template z15()" href="testproject.html#z15.t">testproject: template z15()</a></li>
</ul></dd>
<dt><a name="z16" href="#z16"><span>z16:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: z16()" href="testproject.html#z16.m">testproject: z16()</a></li>
data-doc-search-tag="testproject: macro z16()" href="testproject.html#z16.m">testproject: macro z16()</a></li>
</ul></dd>
<dt><a name="z17" href="#z17"><span>z17:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: z17()" href="testproject.html#z17">testproject: z17()</a></li>
data-doc-search-tag="testproject: proc z17()" href="testproject.html#z17">testproject: proc z17()</a></li>
</ul></dd>
<dt><a name="z18" href="#z18"><span>z18:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: z18(): int" href="testproject.html#z18.m">testproject: z18(): int</a></li>
data-doc-search-tag="testproject: macro z18(): int" href="testproject.html#z18.m">testproject: macro z18(): int</a></li>
</ul></dd>
<dt><a name="z2" href="#z2"><span>z2:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: z2()" href="testproject.html#z2">testproject: z2()</a></li>
data-doc-search-tag="testproject: proc z2()" href="testproject.html#z2">testproject: proc z2()</a></li>
</ul></dd>
<dt><a name="z3" href="#z3"><span>z3:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: z3()" href="testproject.html#z3">testproject: z3()</a></li>
data-doc-search-tag="testproject: proc z3()" href="testproject.html#z3">testproject: proc z3()</a></li>
</ul></dd>
<dt><a name="z4" href="#z4"><span>z4:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: z4()" href="testproject.html#z4">testproject: z4()</a></li>
data-doc-search-tag="testproject: proc z4()" href="testproject.html#z4">testproject: proc z4()</a></li>
</ul></dd>
<dt><a name="z5" href="#z5"><span>z5:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: z5(): int" href="testproject.html#z5">testproject: z5(): int</a></li>
data-doc-search-tag="testproject: proc z5(): int" href="testproject.html#z5">testproject: proc z5(): int</a></li>
</ul></dd>
<dt><a name="z6" href="#z6"><span>z6:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: z6(): int" href="testproject.html#z6">testproject: z6(): int</a></li>
data-doc-search-tag="testproject: proc z6(): int" href="testproject.html#z6">testproject: proc z6(): int</a></li>
</ul></dd>
<dt><a name="z6t" href="#z6t"><span>z6t:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: z6t(): int" href="testproject.html#z6t.t">testproject: z6t(): int</a></li>
data-doc-search-tag="testproject: template z6t(): int" href="testproject.html#z6t.t">testproject: template z6t(): int</a></li>
</ul></dd>
<dt><a name="z7" href="#z7"><span>z7:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: z7(): int" href="testproject.html#z7">testproject: z7(): int</a></li>
data-doc-search-tag="testproject: proc z7(): int" href="testproject.html#z7">testproject: proc z7(): int</a></li>
</ul></dd>
<dt><a name="z8" href="#z8"><span>z8:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: z8(): int" href="testproject.html#z8">testproject: z8(): int</a></li>
data-doc-search-tag="testproject: proc z8(): int" href="testproject.html#z8">testproject: proc z8(): int</a></li>
</ul></dd>
<dt><a name="z9" href="#z9"><span>z9:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"
data-doc-search-tag="testproject: z9()" href="testproject.html#z9">testproject: z9()</a></li>
data-doc-search-tag="testproject: proc z9()" href="testproject.html#z9">testproject: proc z9()</a></li>
</ul></dd>
</dl>
<div class="twelve-columns footer">

View File

@@ -202,3 +202,19 @@ suite "Integration with Nim":
name: "Copyflag")
check inputRst.fromRst == expected
check inputMd.fromMd == expected
test "prefixed module":
let inputRst = "`module std / paths`_"
let inputMd = "[module std / paths]"
let expected = LangSymbol(symKind: "module",
name: "std/paths")
check inputRst.fromRst == expected
check inputMd.fromMd == expected
test "postfixed module":
let inputRst = "`std / paths module`_"
let inputMd = "[std / paths module]"
let expected = LangSymbol(symKind: "module",
name: "std/paths")
check inputRst.fromRst == expected
check inputMd.fromMd == expected

View File

@@ -60,7 +60,7 @@ proc toAst(input: string,
result = ""
var (rst, _, _) = rstParse(input, filen, line=LineRstInit, column=ColRstInit,
rstOptions, myFindFile, testMsgHandler)
rstOptions, myFindFile, nil, testMsgHandler)
result = treeRepr(rst)
except EParseError as e:
if e.msg != "":

View File

@@ -240,27 +240,28 @@ proc buildDocSamples(nimArgs, destPath: string) =
exec(findNim().quoteShell() & " doc $# -o:$# $#" %
[nimArgs, destPath / "docgen_sample.html", "doc" / "docgen_sample.nim"])
proc buildDocPackages(nimArgs, destPath: string) =
proc buildDocPackages(nimArgs, destPath: string, indexOnly: bool) =
# compiler docs; later, other packages (perhaps tools, testament etc)
let nim = findNim().quoteShell()
# to avoid broken links to manual from compiler dir, but a multi-package
# structure could be supported later
proc docProject(outdir, options, mainproj: string) =
exec("$nim doc --project --outdir:$outdir $nimArgs --git.url:$gitUrl $options $mainproj" % [
exec("$nim doc --project --outdir:$outdir $nimArgs --git.url:$gitUrl $index $options $mainproj" % [
"nim", nim,
"outdir", outdir,
"nimArgs", nimArgs,
"gitUrl", gitUrl,
"options", options,
"mainproj", mainproj,
"index", if indexOnly: "--index:only" else: ""
])
let extra = "-u:boot"
# xxx keep in sync with what's in $nim_prs_D/config/nimdoc.cfg, or, rather,
# start using nims instead of nimdoc.cfg
docProject(destPath/"compiler", extra, "compiler/index.nim")
proc buildDoc(nimArgs, destPath: string) =
proc buildDoc(nimArgs, destPath: string, indexOnly: bool) =
# call nim for the documentation:
let rst2html = getMd2html()
var
@@ -268,17 +269,19 @@ proc buildDoc(nimArgs, destPath: string) =
officialPackagesList.len + officialPackagesListWithoutIndex.len)
i = 0
let nim = findNim().quoteShell()
let index = if indexOnly: "--index:only" else: ""
for d in items(rst2html):
commands[i] = nim & " md2html $# --git.url:$# -o:$# --index:on $#" %
commands[i] = nim & " md2html $# --git.url:$# -o:$# $# $#" %
[nimArgs, gitUrl,
destPath / changeFileExt(splitFile(d).name, "html"), d]
destPath / changeFileExt(splitFile(d).name, "html"), index, d]
i.inc
for d in items(doc):
let extra = if isJsOnly(d): "--backend:js" else: ""
var nimArgs2 = nimArgs
if d.isRelativeTo("compiler"): doAssert false
commands[i] = nim & " doc $# $# --git.url:$# --outdir:$# --index:on $#" %
[extra, nimArgs2, gitUrl, destPath, d]
commands[i] = nim & " doc $# $# --git.url:$# --outdir:$# $# $#" %
[extra, nimArgs2, gitUrl, destPath, index, d]
i.inc
for d in items(withoutIndex):
commands[i] = nim & " doc $# --git.url:$# -o:$# $#" %
@@ -300,12 +303,6 @@ proc buildDoc(nimArgs, destPath: string) =
i.inc
mexec(commands)
exec(nim & " buildIndex -o:$1/theindex.html $1" % [destPath])
# caveat: this works so long it's called before `buildDocPackages` which
# populates `compiler/` with unrelated idx files that shouldn't be in index,
# so should work in CI but you may need to remove your generated html files
# locally after calling `./koch docs`. The clean fix would be for `idx` files
# to be transient with `--project` (eg all in memory).
proc nim2pdf(src: string, dst: string, nimArgs: string) =
# xxx expose as a `nim` command or in some other reusable way.
@@ -351,9 +348,23 @@ proc buildDocsDir*(args: string, dir: string) =
gitClonePackages(@["asyncftpclient", "punycode", "smtp", "db_connector"])
createDir(dir)
buildDocSamples(args, dir)
buildDoc(args, dir) # bottleneck
# generate `.idx` files and top-level `theindex.html`:
buildDoc(args, dir, indexOnly=true) # bottleneck
let nim = findNim().quoteShell()
exec(nim & " buildIndex -o:$1/theindex.html $1" % [dir])
# caveat: this works so long it's called before `buildDocPackages` which
# populates `compiler/` with unrelated idx files that shouldn't be in index,
# so should work in CI but you may need to remove your generated html files
# locally after calling `./koch docs`. The clean fix would be for `idx` files
# to be transient with `--project` (eg all in memory).
buildDocPackages(args, dir, indexOnly=true)
# generate HTML and package-level `theindex.html`:
buildDoc(args, dir, indexOnly=false) # bottleneck
buildDocPackages(args, dir, indexOnly=false)
copyFile(dir / "overview.html", dir / "index.html")
buildDocPackages(args, dir)
copyFile(docHackJsSource, dir / docHackJsSource.lastPathPart)
proc buildDocs*(args: string, localOnly = false, localOutDir = "") =