summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/aliases.nim7
-rw-r--r--compiler/nimpaths.nim2
-rw-r--r--doc/filters.md20
-rw-r--r--doc/idetools.md12
-rw-r--r--doc/intern.md4
-rw-r--r--doc/manual.md32
-rw-r--r--doc/nimsuggest.md8
-rw-r--r--lib/impure/nre.nim28
-rw-r--r--lib/packages/docutils/rst.nim92
-rw-r--r--lib/packages/docutils/rstast.nim2
-rw-r--r--lib/packages/docutils/rstgen.nim2
-rw-r--r--lib/pure/algorithm.nim8
-rw-r--r--lib/pure/strformat.nim6
-rw-r--r--lib/std/private/schubfach.nim4
-rw-r--r--tests/stdlib/trst.nim136
15 files changed, 266 insertions, 97 deletions
diff --git a/compiler/aliases.nim b/compiler/aliases.nim
index 9ec72faa4..4b50fdb28 100644
--- a/compiler/aliases.nim
+++ b/compiler/aliases.nim
@@ -77,24 +77,29 @@ proc isPartOf*(a, b: PNode): TAnalysisResult =
   ## cases:
   ##
   ## YES-cases:
+  ##  ```
   ##  x    <| x   # for general trees
   ##  x[]  <| x
   ##  x[i] <| x
   ##  x.f  <| x
+  ##  ```
   ##
   ## NO-cases:
+  ## ```
   ## x           !<| y    # depending on type and symbol kind
   ## x[constA]   !<| x[constB]
   ## x.f         !<| x.g
   ## x.f         !<| y.f  iff x !<= y
+  ## ```
   ##
   ## MAYBE-cases:
   ##
+  ##  ```
   ##  x[] ?<| y[]   iff compatible type
   ##
   ##
   ##  x[]  ?<| y  depending on type
-  ##
+  ##  ```
   if a.kind == b.kind:
     case a.kind
     of nkSym:
diff --git a/compiler/nimpaths.nim b/compiler/nimpaths.nim
index c6e188289..3756f956b 100644
--- a/compiler/nimpaths.nim
+++ b/compiler/nimpaths.nim
@@ -9,7 +9,7 @@ specialpaths is simpler because it doesn't need variables to be relocatable at
 runtime (eg for use in testament)
 
 interpolation variables:
-  $nimr: such that `$nimr/lib/system.nim` exists (avoids confusion with $nim binary)
+: $nimr: such that `$nimr/lib/system.nim` exists (avoids confusion with $nim binary)
          in compiler, it's obtainable via getPrefixDir(); for other tools (eg koch),
         this could be getCurrentDir() or getAppFilename().parentDir.parentDir,
         depending on use case
diff --git a/doc/filters.md b/doc/filters.md
index cf88724be..bf45788bc 100644
--- a/doc/filters.md
+++ b/doc/filters.md
@@ -72,10 +72,10 @@ The replace filter replaces substrings in each line.
 Parameters and their defaults:
 
 * `sub: string = ""`
-    the substring that is searched for
+  : the substring that is searched for
 
 * `by: string = ""`
-    the string the substring is replaced with
+  : the string the substring is replaced with
 
 
 Strip filter
@@ -87,14 +87,14 @@ each line.
 Parameters and their defaults:
 
 * `startswith: string = ""`
-    strip only the lines that start with *startswith* (ignoring leading
+  : strip only the lines that start with *startswith* (ignoring leading
     whitespace). If empty every line is stripped.
 
 * `leading: bool = true`
-    strip leading whitespace
+  : strip leading whitespace
 
 * `trailing: bool = true`
-    strip trailing whitespace
+  : strip trailing whitespace
 
 
 StdTmpl filter
@@ -109,19 +109,19 @@ statements need `end X` delimiters.
 Parameters and their defaults:
 
 * `metaChar: char = '#'`
-    prefix for a line that contains Nim code
+  : prefix for a line that contains Nim code
 
 * `subsChar: char = '$'`
-    prefix for a Nim expression within a template line
+  : prefix for a Nim expression within a template line
 
 * `conc: string = " & "`
-    the operation for concatenation
+  : the operation for concatenation
 
 * `emit: string = "result.add"`
-    the operation to emit a string literal
+  : the operation to emit a string literal
 
 * `toString: string = "$"`
-    the operation that is applied to each expression
+  : the operation that is applied to each expression
 
 Example::
 
diff --git a/doc/idetools.md b/doc/idetools.md
index 5bfa59442..7c69232e3 100644
--- a/doc/idetools.md
+++ b/doc/idetools.md
@@ -45,30 +45,30 @@ Or::
     nim idetools --trackDirty:DIRTY_FILE,FILE,LINE,COL <switches> proj.nim
 
 `proj.nim`
-    This is the main *project* filename. Most of the time you will
+:   This is the main *project* filename. Most of the time you will
     pass in the same as **FILE**, but for bigger projects this is
     the file which is used as main entry point for the program, the
     one which users compile to generate a final binary.
 
 `<switches>`
-    This would be any of the other idetools available options, like
+:   This would be any of the other idetools available options, like
     `--def` or `--suggest` explained in the following sections.
 
 `COL`
-    An integer with the column you are going to query. For the
+:   An integer with the column you are going to query. For the
     compiler columns start at zero, so the first column will be
     **0** and the last in an 80 column terminal will be **79**.
 
 `LINE`
-    An integer with the line you are going to query. For the compiler
+:   An integer with the line you are going to query. For the compiler
     lines start at **1**.
 
 `FILE`
-    The file you want to perform the query on. Usually you will
+:   The file you want to perform the query on. Usually you will
     pass in the same value as **proj.nim**.
 
 `DIRTY_FILE`
-    The **FILE** parameter is enough for static analysis, but IDEs
+:   The **FILE** parameter is enough for static analysis, but IDEs
     tend to have *unsaved buffers* where the user may still be in
     the middle of typing a line. In such situations the IDE can
     save the current contents to a temporary file and then use the
diff --git a/doc/intern.md b/doc/intern.md
index 08de0edd6..71d695e7d 100644
--- a/doc/intern.md
+++ b/doc/intern.md
@@ -398,11 +398,11 @@ Runtime type information
 programming language:
 
 Garbage collection
-  The old GCs use the RTTI for traversing arbitrary Nim types, but usually
+: The old GCs use the RTTI for traversing arbitrary Nim types, but usually
   only the `marker` field which contains a proc that does the traversal.
 
 Complex assignments
-  Sequences and strings are implemented as
+: Sequences and strings are implemented as
   pointers to resizable buffers, but Nim requires copying for
   assignments. Apart from RTTI the compiler also generates copy procedures
   as a specialization.
diff --git a/doc/manual.md b/doc/manual.md
index 3034bc65f..e236132b0 100644
--- a/doc/manual.md
+++ b/doc/manual.md
@@ -1023,24 +1023,24 @@ Pre-defined integer types
 These integer types are pre-defined:
 
 `int`
-  the generic signed integer type; its size is platform-dependent and has the
+: the generic signed integer type; its size is platform-dependent and has the
   same size as a pointer. This type should be used in general. An integer
   literal that has no type suffix is of this type if it is in the range
   `low(int32)..high(int32)` otherwise the literal's type is `int64`.
 
 `int`\ XX
-  additional signed integer types of XX bits use this naming scheme
+: additional signed integer types of XX bits use this naming scheme
   (example: int16 is a 16-bit wide integer).
   The current implementation supports `int8`, `int16`, `int32`, `int64`.
   Literals of these types have the suffix 'iXX.
 
 `uint`
-  the generic `unsigned integer`:idx: type; its size is platform-dependent and
+: the generic `unsigned integer`:idx: type; its size is platform-dependent and
   has the same size as a pointer. An integer literal with the type
   suffix `'u` is of this type.
 
 `uint`\ XX
-  additional unsigned integer types of XX bits use this naming scheme
+: additional unsigned integer types of XX bits use this naming scheme
   (example: uint16 is a 16-bit wide unsigned integer).
   The current implementation supports `uint8`, `uint16`, `uint32`,
   `uint64`. Literals of these types have the suffix 'uXX.
@@ -1135,12 +1135,12 @@ Pre-defined floating-point types
 The following floating-point types are pre-defined:
 
 `float`
-  the generic floating-point type; its size used to be platform-dependent,
+: the generic floating-point type; its size used to be platform-dependent,
   but now it is always mapped to `float64`.
   This type should be used in general.
 
 `float`\ XX
-  an implementation may define additional floating-point types of XX bits using
+: an implementation may define additional floating-point types of XX bits using
   this naming scheme (example: `float64` is a 64-bit wide float). The current
   implementation supports `float32` and `float64`. Literals of these types
   have the suffix 'fXX.
@@ -2092,52 +2092,52 @@ that expects a proc of the calling convention `closure`.
 Nim supports these `calling conventions`:idx:\:
 
 `nimcall`:idx:
-    is the default convention used for a Nim **proc**. It is the
+:   is the default convention used for a Nim **proc**. It is the
     same as `fastcall`, but only for C compilers that support `fastcall`.
 
 `closure`:idx:
-    is the default calling convention for a **procedural type** that lacks
+:   is the default calling convention for a **procedural type** that lacks
     any pragma annotations. It indicates that the procedure has a hidden
     implicit parameter (an *environment*). Proc vars that have the calling
     convention `closure` take up two machine words: One for the proc pointer
     and another one for the pointer to implicitly passed environment.
 
 `stdcall`:idx:
-    This is the stdcall convention as specified by Microsoft. The generated C
+:   This is the stdcall convention as specified by Microsoft. The generated C
     procedure is declared with the `__stdcall` keyword.
 
 `cdecl`:idx:
-    The cdecl convention means that a procedure shall use the same convention
+:   The cdecl convention means that a procedure shall use the same convention
     as the C compiler. Under Windows the generated C procedure is declared with
     the `__cdecl` keyword.
 
 `safecall`:idx:
-    This is the safecall convention as specified by Microsoft. The generated C
+:   This is the safecall convention as specified by Microsoft. The generated C
     procedure is declared with the `__safecall` keyword. The word *safe*
     refers to the fact that all hardware registers shall be pushed to the
     hardware stack.
 
 `inline`:idx:
-    The inline convention means the caller should not call the procedure,
+:   The inline convention means the caller should not call the procedure,
     but inline its code directly. Note that Nim does not inline, but leaves
     this to the C compiler; it generates `__inline` procedures. This is
     only a hint for the compiler: it may completely ignore it, and
     it may inline procedures that are not marked as `inline`.
 
 `fastcall`:idx:
-    Fastcall means different things to different C compilers. One gets whatever
+:   Fastcall means different things to different C compilers. One gets whatever
     the C `__fastcall` means.
 
 `thiscall`:idx:
-    This is the thiscall calling convention as specified by Microsoft, used on
+:   This is the thiscall calling convention as specified by Microsoft, used on
     C++ class member functions on the x86 architecture.
 
 `syscall`:idx:
-    The syscall convention is the same as `__syscall`:c: in C. It is used for
+:   The syscall convention is the same as `__syscall`:c: in C. It is used for
     interrupts.
 
 `noconv`:idx:
-    The generated C code will not have any explicit calling convention and thus
+:   The generated C code will not have any explicit calling convention and thus
     use the C compiler's default calling convention. This is needed because
     Nim's default calling convention for procedures is `fastcall` to
     improve speed.
diff --git a/doc/nimsuggest.md b/doc/nimsuggest.md
index f542cab19..bfa423707 100644
--- a/doc/nimsuggest.md
+++ b/doc/nimsuggest.md
@@ -63,10 +63,10 @@ a location. A query location consists of:
 
 
 ``file.nim``
-    This is the name of the module or include file the query refers to.
+:   This is the name of the module or include file the query refers to.
 
 ``dirtyfile.nim``
-    This is optional.
+:   This is optional.
 
     The `file` parameter is enough for static analysis, but IDEs
     tend to have *unsaved buffers* where the user may still be in
@@ -77,11 +77,11 @@ a location. A query location consists of:
 
 
 ``line``
-    An integer with the line you are going to query. For the compiler
+:   An integer with the line you are going to query. For the compiler
     lines start at **1**.
 
 ``col``
-    An integer with the column you are going to query. For the
+:   An integer with the column you are going to query. For the
     compiler columns start at **0**.
 
 
diff --git a/lib/impure/nre.nim b/lib/impure/nre.nim
index 1012c7c36..738fc39cf 100644
--- a/lib/impure/nre.nim
+++ b/lib/impure/nre.nim
@@ -75,16 +75,16 @@ type
     ## comment".`
     ##
     ## `pattern: string`
-    ##     the string that was used to create the pattern. For details on how
+    ## :   the string that was used to create the pattern. For details on how
     ##     to write a pattern, please see `the official PCRE pattern
     ##     documentation.
     ##     <https://www.pcre.org/original/doc/html/pcrepattern.html>`_
     ##
     ## `captureCount: int`
-    ##     the number of captures that the pattern has.
+    ## :   the number of captures that the pattern has.
     ##
     ## `captureNameId: Table[string, int]`
-    ##     a table from the capture names to their numeric id.
+    ## :   a table from the capture names to their numeric id.
     ##
     ##
     ## Options
@@ -151,36 +151,36 @@ type
     ## execution. On failure, it is none, on success, it is some.
     ##
     ## `pattern: Regex`
-    ##     the pattern that is being matched
+    ## :   the pattern that is being matched
     ##
     ## `str: string`
-    ##     the string that was matched against
+    ## :   the string that was matched against
     ##
     ## `captures[]: string`
-    ##     the string value of whatever was captured at that id. If the value
+    ## :   the string value of whatever was captured at that id. If the value
     ##     is invalid, then behavior is undefined. If the id is `-1`, then
     ##     the whole match is returned. If the given capture was not matched,
     ##     `nil` is returned. See examples for `match`.
     ##
     ## `captureBounds[]: HSlice[int, int]`
-    ##     gets the bounds of the given capture according to the same rules as
+    ## :   gets the bounds of the given capture according to the same rules as
     ##     the above. If the capture is not filled, then `None` is returned.
     ##     The bounds are both inclusive.  See examples for `match`.
     ##
     ## `match: string`
-    ##     the full text of the match.
+    ## :   the full text of the match.
     ##
     ## `matchBounds: HSlice[int, int]`
-    ##     the bounds of the match, as in `captureBounds[]`
+    ## :   the bounds of the match, as in `captureBounds[]`
     ##
     ## `(captureBounds|captures).toTable`
-    ##     returns a table with each named capture as a key.
+    ## :   returns a table with each named capture as a key.
     ##
     ## `(captureBounds|captures).toSeq`
-    ##     returns all the captures by their number.
+    ## :   returns all the captures by their number.
     ##
     ## `$: string`
-    ##     same as `match`
+    ## :   same as `match`
     pattern*: Regex  ## The regex doing the matching.
                      ## Not nil.
     str*: string  ## The string that was matched against.
@@ -583,11 +583,11 @@ proc find*(str: string, pattern: Regex, start = 0, endpos = int.high): Option[Re
   ## positions.
   ##
   ## `start`
-  ##     The start point at which to start matching. `|abc` is `0`;
+  ## :   The start point at which to start matching. `|abc` is `0`;
   ##     `a|bc` is `1`
   ##
   ## `endpos`
-  ##     The maximum index for a match; `int.high` means the end of the
+  ## :   The maximum index for a match; `int.high` means the end of the
   ##     string, otherwise it’s an inclusive upper bound.
   return str.matchImpl(pattern, start, endpos, 0)
 
diff --git a/lib/packages/docutils/rst.nim b/lib/packages/docutils/rst.nim
index 0a997ecba..629245b4b 100644
--- a/lib/packages/docutils/rst.nim
+++ b/lib/packages/docutils/rst.nim
@@ -2064,7 +2064,22 @@ proc getWrappableIndent(p: RstParser): int =
     elif nextIndent >= currentTok(p).col: # may be a definition list [case.2]
       result = currentTok(p).col
     else:
-      result = nextIndent                 #                          [case.3]
+      result = nextIndent                 # allow parsing next lines [case.3]
+
+proc getMdBlockIndent(p: RstParser): int =
+  ## Markdown version of `getWrappableIndent`.
+  if currentTok(p).kind == tkIndent:
+    result = currentTok(p).ival
+  else:
+    var nextIndent = p.tok[tokenAfterNewline(p)-1].ival
+    # TODO: Markdown-compliant definition should allow nextIndent == currInd(p):
+    if nextIndent <= currInd(p):           # parse only this line
+      result = currentTok(p).col
+    else:
+      result = nextIndent                 # allow parsing next lines [case.3]
+
+template isRst(p: RstParser): bool = roPreferMarkdown notin p.s.options
+template isMd(p: RstParser): bool = roPreferMarkdown in p.s.options
 
 proc parseField(p: var RstParser): PRstNode =
   ## Returns a parsed rnField node.
@@ -2309,6 +2324,39 @@ proc isDefList(p: RstParser): bool =
       p.tok[j].kind in {tkWord, tkOther, tkPunct} and
       p.tok[j - 2].symbol != "::"
 
+proc `$`(t: Token): string =  # for debugging only
+  result = "(" & $t.kind & " line=" & $t.line & " col=" & $t.col
+  if t.kind == tkIndent: result = result & " ival=" & $t.ival & ")"
+  else: result = result & " symbol=" & t.symbol & ")"
+
+proc skipNewlines(p: RstParser, j: int): int =
+  result = j
+  while p.tok[result].kind != tkEof and p.tok[result].kind == tkIndent:
+    inc result  # skip blank lines
+
+proc skipNewlines(p: var RstParser) =
+  p.idx = skipNewlines(p, p.idx)
+
+const maxMdRelInd = 3  ## In Markdown: maximum indentation that does not yet
+                       ## make the indented block a code
+
+proc isMdRelInd(outerInd, nestedInd: int): bool =
+  result = outerInd <= nestedInd and nestedInd <= outerInd + maxMdRelInd
+
+proc isMdDefBody(p: RstParser, j: int, termCol: int): bool =
+  let defCol = p.tok[j].col
+  result = p.tok[j].symbol == ":" and
+    isMdRelInd(termCol, defCol) and
+    p.tok[j+1].kind == tkWhite and
+    p.tok[j+2].kind in {tkWord, tkOther, tkPunct}
+
+proc isMdDefListItem(p: RstParser, idx: int): bool =
+  var j = tokenAfterNewline(p, idx)
+  j = skipNewlines(p, j)
+  let termCol = p.tok[j].col
+  result = isMdRelInd(currInd(p), termCol) and
+      isMdDefBody(p, j, termCol)
+
 proc isOptionList(p: RstParser): bool =
   result = match(p, p.idx, "-w") or match(p, p.idx, "--w") or
            match(p, p.idx, "/w") or match(p, p.idx, "//w")
@@ -2381,8 +2429,10 @@ proc whichSection(p: RstParser): RstNodeKind =
       result = rnEnumList
     elif isOptionList(p):
       result = rnOptionList
-    elif isDefList(p):
+    elif isRst(p) and isDefList(p):
       result = rnDefList
+    elif isMd(p) and isMdDefListItem(p, p.idx):
+      result = rnMdDefList
     else:
       result = rnParagraph
   of tkWord, tkOther, tkWhite:
@@ -2391,7 +2441,9 @@ proc whichSection(p: RstParser): RstNodeKind =
       if isAdornmentHeadline(p, tokIdx): result = rnHeadline
       else: result = rnParagraph
     elif match(p, p.idx, "e) ") or match(p, p.idx, "e. "): result = rnEnumList
-    elif isDefList(p): result = rnDefList
+    elif isRst(p) and isDefList(p): result = rnDefList
+    elif isMd(p) and isMdDefListItem(p, p.idx):
+      result = rnMdDefList
     else: result = rnParagraph
   else: result = rnLeaf
 
@@ -2921,6 +2973,36 @@ proc parseOptionList(p: var RstParser): PRstNode =
       if currentTok(p).kind != tkEof: dec p.idx  # back to tkIndent
       break
 
+proc parseMdDefinitionList(p: var RstParser): PRstNode =
+  ## Parses (Pandoc/kramdown/PHPextra) Mardkown definition lists.
+  result = newRstNodeA(p, rnMdDefList)
+  let termCol = currentTok(p).col
+  while true:
+    var item = newRstNode(rnDefItem)
+    var term = newRstNode(rnDefName)
+    parseLine(p, term)
+    skipNewlines(p)
+    inc p.idx, 2  # skip ":" and space
+    item.add(term)
+    while true:
+      var def = newRstNode(rnDefBody)
+      let indent = getMdBlockIndent(p)
+      pushInd(p, indent)
+      parseSection(p, def)
+      popInd(p)
+      item.add(def)
+      let j = skipNewlines(p, p.idx)
+      if isMdDefBody(p, j, termCol):  # parse next definition body
+        p.idx = j + 2  # skip ":" and space
+      else:
+        break
+    result.add(item)
+    let j = skipNewlines(p, p.idx)
+    if p.tok[j].col == termCol and isMdDefListItem(p, j):
+      p.idx = j  # parse next item
+    else:
+      break
+
 proc parseDefinitionList(p: var RstParser): PRstNode =
   result = nil
   var j = tokenAfterNewline(p) - 1
@@ -3094,6 +3176,7 @@ proc parseSection(p: var RstParser, result: PRstNode) =
     of rnLeaf: rstMessage(p, meNewSectionExpected, "(syntax error)")
     of rnParagraph: discard
     of rnDefList: a = parseDefinitionList(p)
+    of rnMdDefList: a = parseMdDefinitionList(p)
     of rnFieldList:
       if p.idx > 0: dec p.idx
       a = parseFields(p)
@@ -3120,9 +3203,6 @@ proc parseSectionWrapper(p: var RstParser): PRstNode =
   while result.kind == rnInner and result.len == 1:
     result = result.sons[0]
 
-proc `$`(t: Token): string =
-  result = $t.kind & ' ' & t.symbol
-
 proc parseDoc(p: var RstParser): PRstNode =
   result = parseSectionWrapper(p)
   if currentTok(p).kind != tkEof:
diff --git a/lib/packages/docutils/rstast.nim b/lib/packages/docutils/rstast.nim
index 05e4ec39e..e85bbfb98 100644
--- a/lib/packages/docutils/rstast.nim
+++ b/lib/packages/docutils/rstast.nim
@@ -27,7 +27,7 @@ type
     rnBulletItem,             # a bullet item
     rnEnumList,               # an enumerated list
     rnEnumItem,               # an enumerated item
-    rnDefList,                # a definition list
+    rnDefList, rnMdDefList,   # a definition list (RST/Markdown)
     rnDefItem,                # an item of a definition list consisting of ...
     rnDefName,                # ... a name part ...
     rnDefBody,                # ... and a body part ...
diff --git a/lib/packages/docutils/rstgen.nim b/lib/packages/docutils/rstgen.nim
index 1b5f9e78c..f5ff9aa03 100644
--- a/lib/packages/docutils/rstgen.nim
+++ b/lib/packages/docutils/rstgen.nim
@@ -1212,7 +1212,7 @@ proc renderRstToOut(d: PDoc, n: PRstNode, result: var string) =
   of rnBulletItem, rnEnumItem:
     renderAux(d, n, "<li$2>$1</li>\n", "\\item $2$1\n", result)
   of rnEnumList: renderEnumList(d, n, result)
-  of rnDefList:
+  of rnDefList, rnMdDefList:
     renderAux(d, n, "<dl$2 class=\"docutils\">$1</dl>\n",
                     "\\begin{description}\n$2\n$1\\end{description}\n", result)
   of rnDefItem: renderAux(d, n, result)
diff --git a/lib/pure/algorithm.nim b/lib/pure/algorithm.nim
index c43545f78..fc0eceac3 100644
--- a/lib/pure/algorithm.nim
+++ b/lib/pure/algorithm.nim
@@ -825,10 +825,10 @@ proc rotateLeft*[T](arg: var openArray[T]; slice: HSlice[int, int];
   ## If an invalid range (`HSlice`) is passed, it raises `IndexDefect`.
   ##
   ## `slice`
-  ##   The indices of the element range that should be rotated.
+  ## : The indices of the element range that should be rotated.
   ##
   ## `dist`
-  ##   The distance in amount of elements that the data should be rotated.
+  ## : The distance in amount of elements that the data should be rotated.
   ##   Can be negative, can be any number.
   ##
   ## **See also:**
@@ -876,10 +876,10 @@ proc rotatedLeft*[T](arg: openArray[T]; slice: HSlice[int, int],
   ## If an invalid range (`HSlice`) is passed, it raises `IndexDefect`.
   ##
   ## `slice`
-  ##   The indices of the element range that should be rotated.
+  ## : The indices of the element range that should be rotated.
   ##
   ## `dist`
-  ##   The distance in amount of elements that the data should be rotated.
+  ## : The distance in amount of elements that the data should be rotated.
   ##   Can be negative, can be any number.
   ##
   ## **See also:**
diff --git a/lib/pure/strformat.nim b/lib/pure/strformat.nim
index 247d0a296..fe3cfdab0 100644
--- a/lib/pure/strformat.nim
+++ b/lib/pure/strformat.nim
@@ -180,15 +180,15 @@ The square brackets `[]` indicate an optional element.
 The optional `align` flag can be one of the following:
 
 `<`
-    Forces the field to be left-aligned within the available
+:   Forces the field to be left-aligned within the available
     space. (This is the default for strings.)
 
 `>`
-    Forces the field to be right-aligned within the available space.
+:   Forces the field to be right-aligned within the available space.
     (This is the default for numbers.)
 
 `^`
-    Forces the field to be centered within the available space.
+:   Forces the field to be centered within the available space.
 
 Note that unless a minimum field width is defined, the field width
 will always be the same size as the data to fill it, so that the alignment
diff --git a/lib/std/private/schubfach.nim b/lib/std/private/schubfach.nim
index 206153a68..872317ebf 100644
--- a/lib/std/private/schubfach.nim
+++ b/lib/std/private/schubfach.nim
@@ -78,19 +78,23 @@ proc floorDivPow2(x: int32; n: int32): int32 {.inline.} =
   return x shr n
 
 ##  Returns floor(log_10(2^e))
+##  ```c
 ##  static inline int32_t FloorLog10Pow2(int32_t e)
 ##  {
 ##      SF_ASSERT(e >= -1500);
 ##      SF_ASSERT(e <=  1500);
 ##      return FloorDivPow2(e * 1262611, 22);
 ##  }
+##  ```
 ##  Returns floor(log_10(3/4 2^e))
+##  ```c
 ##  static inline int32_t FloorLog10ThreeQuartersPow2(int32_t e)
 ##  {
 ##      SF_ASSERT(e >= -1500);
 ##      SF_ASSERT(e <=  1500);
 ##      return FloorDivPow2(e * 1262611 - 524031, 22);
 ##  }
+##  ```
 ##  Returns floor(log_2(10^e))
 
 proc floorLog2Pow10(e: int32): int32 {.inline.} =
diff --git a/tests/stdlib/trst.nim b/tests/stdlib/trst.nim
index f9150e02d..a92ab2daa 100644
--- a/tests/stdlib/trst.nim
+++ b/tests/stdlib/trst.nim
@@ -423,21 +423,21 @@ suite "RST parsing":
         .. Note:: deflist:
                     >> quote
                     continuation
-        """.toAst == expected)
+        """.toAst(rstOptions = preferRst) == expected)
 
     check(dedent"""
         .. Note::
            deflist:
              >> quote
              continuation
-        """.toAst == expected)
+        """.toAst(rstOptions = preferRst) == expected)
 
     check(dedent"""
         .. Note::
            deflist:
              >> quote
              >> continuation
-        """.toAst == expected)
+        """.toAst(rstOptions = preferRst) == expected)
 
     # spaces are not significant between `>`:
     check(dedent"""
@@ -445,7 +445,7 @@ suite "RST parsing":
            deflist:
              > > quote
              > > continuation
-        """.toAst == expected)
+        """.toAst(rstOptions = preferRst) == expected)
 
   test "Markdown quoted blocks: de-indent handled well":
     check(dedent"""
@@ -616,27 +616,28 @@ suite "RST parsing":
     check inputTilde.toAst == expected
 
   test "option list has priority over definition list":
-    check(dedent"""
-        --defusages
-                      file
-        -o            set
-        """.toAst ==
-      dedent"""
-        rnOptionList
-          rnOptionListItem  order=1
-            rnOptionGroup
-              rnLeaf  '--'
-              rnLeaf  'defusages'
-            rnDescription
-              rnInner
-                rnLeaf  'file'
-          rnOptionListItem  order=2
-            rnOptionGroup
-              rnLeaf  '-'
-              rnLeaf  'o'
-            rnDescription
-              rnLeaf  'set'
-        """)
+    for opt in [preferMarkdown, preferRst]:
+      check(dedent"""
+          --defusages
+                        file
+          -o            set
+          """.toAst(rstOptions = opt) ==
+        dedent"""
+          rnOptionList
+            rnOptionListItem  order=1
+              rnOptionGroup
+                rnLeaf  '--'
+                rnLeaf  'defusages'
+              rnDescription
+                rnInner
+                  rnLeaf  'file'
+            rnOptionListItem  order=2
+              rnOptionGroup
+                rnLeaf  '-'
+                rnLeaf  'o'
+              rnDescription
+                rnLeaf  'set'
+          """)
 
   test "items of 1 option list can be separated by blank lines":
     check(dedent"""
@@ -660,13 +661,13 @@ suite "RST parsing":
               rnLeaf  'desc2'
       """)
 
-  test "option list has priority over definition list":
+  test "definition list does not gobble up the following blocks":
     check(dedent"""
         defName
             defBody
 
         -b  desc2
-        """.toAst ==
+        """.toAst(rstOptions = preferRst) ==
       dedent"""
         rnInner
           rnDefList
@@ -1054,7 +1055,7 @@ suite "RST indentation":
          term2
            Definition2
     """
-    check(input.toAst == dedent"""
+    check(input.toAst(rstOptions = preferRst) == dedent"""
       rnEnumList  labelFmt=1)
         rnEnumItem
           rnAdmonition  adType=hint
@@ -1157,6 +1158,85 @@ suite "RST indentation":
     # "template..." should be parsed as a definition list attached to ":test:":
     check inputWrong.toAst != ast
 
+  test "Markdown definition lists work in conjunction with bullet lists":
+    check(dedent"""
+        * some term
+          : the definition
+
+        Paragraph.""".toAst ==
+      dedent"""
+        rnInner
+          rnBulletList
+            rnBulletItem
+              rnMdDefList
+                rnDefItem
+                  rnDefName
+                    rnLeaf  'some'
+                    rnLeaf  ' '
+                    rnLeaf  'term'
+                  rnDefBody
+                    rnInner
+                      rnLeaf  'the'
+                      rnLeaf  ' '
+                      rnLeaf  'definition'
+          rnParagraph
+            rnLeaf  'Paragraph'
+            rnLeaf  '.'
+      """)
+
+  test "Markdown definition lists work with blank lines and extra paragraphs":
+    check(dedent"""
+        Term1
+
+        :   Definition1
+
+        Term2 *inline markup*
+
+        :   Definition2
+
+            Paragraph2
+
+        Term3
+        : * point1
+          * point2
+        : term3definition2
+      """.toAst == dedent"""
+        rnMdDefList
+          rnDefItem
+            rnDefName
+              rnLeaf  'Term1'
+            rnDefBody
+              rnInner
+                rnLeaf  'Definition1'
+          rnDefItem
+            rnDefName
+              rnLeaf  'Term2'
+              rnLeaf  ' '
+              rnEmphasis
+                rnLeaf  'inline'
+                rnLeaf  ' '
+                rnLeaf  'markup'
+            rnDefBody
+              rnParagraph
+                rnLeaf  'Definition2'
+              rnParagraph
+                rnLeaf  'Paragraph2'
+          rnDefItem
+            rnDefName
+              rnLeaf  'Term3'
+            rnDefBody
+              rnBulletList
+                rnBulletItem
+                  rnInner
+                    rnLeaf  'point1'
+                rnBulletItem
+                  rnInner
+                    rnLeaf  'point2'
+            rnDefBody
+              rnInner
+                rnLeaf  'term3definition2'
+      """)
+
 suite "Warnings":
   test "warnings for broken footnotes/links/substitutions":
     let input = dedent"""