Skip to content

Commit

Permalink
Rst parser respect :start-after: and :end-before: in include di…
Browse files Browse the repository at this point in the history
…rective (#12972)

* [FEATURE] rst parser respect :start-after: in include

Rst parser now respects `:start-after:` and `:end-before:` attributes
for `include` directive.

* [DOC] include directive parsing proc update

* [TEST] Added unit tests for include rst directive in `rst` module
  • Loading branch information
haxscramper authored and Araq committed Jan 5, 2020
1 parent ae68ff9 commit 9a5aaad
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 10 deletions.
49 changes: 39 additions & 10 deletions lib/packages/docutils/rst.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1558,15 +1558,20 @@ proc parseDirBody(p: var RstParser, contentParser: SectionParser): PRstNode =
popInd(p)

proc dirInclude(p: var RstParser): PRstNode =
#
#The following options are recognized:
#
#start-after : text to find in the external data file
# Only the content after the first occurrence of the specified text will
# be included.
#end-before : text to find in the external data file
# Only the content before the first occurrence of the specified text
# (but after any after text) will be included.
##
## The following options are recognized:
##
## :start-after: text to find in the external data file
##
## Only the content after the first occurrence of the specified
## text will be included. If text is not found inclusion will
## start from beginning of the file
##
## :end-before: text to find in the external data file
##
## Only the content before the first occurrence of the specified
## text (but after any after text) will be included. If text is
## not found inclusion will happen until the end of the file.
#literal : flag (empty)
# The entire included text is inserted into the document as a single
# literal block (useful for program listings).
Expand All @@ -1586,10 +1591,34 @@ proc dirInclude(p: var RstParser): PRstNode =
result = newRstNode(rnLiteralBlock)
add(result, newRstNode(rnLeaf, readFile(path)))
else:
let inputString = readFile(path).string()
let startPosition =
block:
let searchFor = n.getFieldValue("start-after").strip()
if searchFor != "":
let pos = inputString.find(searchFor)
if pos != -1: pos + searchFor.len()
else: 0
else:
0

let endPosition =
block:
let searchFor = n.getFieldValue("end-before").strip()
if searchFor != "":
let pos = inputString.find(searchFor, start = startPosition)
if pos != -1: pos - 1
else: 0
else:
inputString.len - 1

var q: RstParser
initParser(q, p.s)
q.filename = path
q.col += getTokens(readFile(path), false, q.tok)
q.col += getTokens(
inputString[startPosition..endPosition].strip(),
false,
q.tok)
# workaround a GCC bug; more like the interior pointer bug?
#if find(q.tok[high(q.tok)].symbol, "\0\x01\x02") > 0:
# InternalError("Too many binary zeros in include file")
Expand Down
79 changes: 79 additions & 0 deletions tests/stdlib/trst.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# tests for rst module

import ../../lib/packages/docutils/rstgen
import ../../lib/packages/docutils/rst
import unittest
import os

suite "RST include directive":
test "Include whole":
"other.rst".writeFile("**test1**")
let input = ".. include:: other.rst"
assert "<strong>test1</strong>" == rstTohtml(input, {}, defaultConfig())
removeFile("other.rst")

test "Include starting from":
"other.rst".writeFile("""
And this should **NOT** be visible in `docs.html`
OtherStart
*Visible*
""")

let input = """
.. include:: other.rst
:start-after: OtherStart
"""
assert "<em>Visible</em>" == rstTohtml(input, {}, defaultConfig())
removeFile("other.rst")

test "Include everything before":
"other.rst".writeFile("""
*Visible*
OtherEnd
And this should **NOT** be visible in `docs.html`
""")

let input = """
.. include:: other.rst
:end-before: OtherEnd
"""
assert "<em>Visible</em>" == rstTohtml(input, {}, defaultConfig())
removeFile("other.rst")


test "Include everything between":
"other.rst".writeFile("""
And this should **NOT** be visible in `docs.html`
OtherStart
*Visible*
OtherEnd
And this should **NOT** be visible in `docs.html`
""")

let input = """
.. include:: other.rst
:start-after: OtherStart
:end-before: OtherEnd
"""
assert "<em>Visible</em>" == rstTohtml(input, {}, defaultConfig())
removeFile("other.rst")


test "Ignore premature ending string":
"other.rst".writeFile("""
OtherEnd
And this should **NOT** be visible in `docs.html`
OtherStart
*Visible*
OtherEnd
And this should **NOT** be visible in `docs.html`
""")

let input = """
.. include:: other.rst
:start-after: OtherStart
:end-before: OtherEnd
"""
assert "<em>Visible</em>" == rstTohtml(input, {}, defaultConfig())
removeFile("other.rst")

0 comments on commit 9a5aaad

Please sign in to comment.