Skip to content

Commit

Permalink
Merge pull request #39 from cmacmackin/lines-and-line-ranges
Browse files Browse the repository at this point in the history
Add support for specifying lines and line ranges
  • Loading branch information
ZedThree authored Nov 23, 2022
2 parents 692e499 + f5e754d commit 993e858
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 2 deletions.
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,30 @@ Markdown is being called. If you would like to change the directory relative to
which paths are evaluated, then this can be done by specifying the extension
setting ``base_path``.
### Line Ranges
You can also define specific lines or line ranges to include by specifying `lines`:

```Markdown
{!filename!lines=1 3 8-10 2}
```

`lines` takes a sequence of integers separated by spaces (one or more), or it can also
take line ranges specified with a start line and an end line separated by a dash (`-`).

In the example above, it would read the file called `filename` and include the lines
`1`, `3`, `8`, `9`, `10`, `2`.

Notice that line `9` was not explicitly set. But it was still included as part of the
range `8-10`.

Also, notice that line `2` is set *after* the range `8-10`. This means that the
line `2` in `filename` will be included *after* (below) the range `8-10`.

You can use this to include lines in a different order than the original file. But it
also means that if you want to preserve the original order, you have to pay attention
to the order in which you specify the lines.

## Configuration

The following settings can be specified when initialising the plugin.
Expand Down
44 changes: 42 additions & 2 deletions markdown_include/include.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
from markdown.extensions import Extension
from markdown.preprocessors import Preprocessor

INC_SYNTAX = re.compile(r'\{!\s*(.+?)\s*!\}')
INC_SYNTAX = re.compile(r'{!\s*(.+?)\s*!((\blines\b)=([0-9 -]+))?\}')
HEADING_SYNTAX = re.compile( '^#+' )


Expand Down Expand Up @@ -91,7 +91,7 @@ def run(self, lines):
)
try:
with open(filename, 'r', encoding=self.encoding) as r:
text = self.run(r.readlines())
original_text = self.run(r.readlines())

except Exception as e:
if not self.throwException:
Expand All @@ -101,6 +101,46 @@ def run(self, lines):
break
else:
raise e
if m.group(2) is None:
text = original_text
else:
lines_str = m.group(4)
lines_blocks = lines_str.split()
wanted_lines = []
for block in lines_blocks:
if "-" in block:
start, end = block.strip().split("-")
current_start = int(start)
current_end = int(end)
if not len(original_text) >= current_end:
current_end = len(original_text)
print(
f"Warning: line range: {block} ending in "
f"line: {end} is larger than file: {filename} "
f"using end: {current_end}"
)
if not current_start <= current_end:
current_start = max(current_end - 1, 1)
print(
f"Warning: in line range: {block} "
f"the start line: {start} is not "
f"smaller than the end line: {current_end} "
f"using start: {current_start}"
)

wanted_lines.extend(original_text[current_start-1:current_end])
else:
wanted_line = int(block.strip())
current_line = wanted_line
if current_line > len(original_text):
current_line = len(original_text)
print(
f"Warning: line: {wanted_line} is larger than "
f"file: {filename} using end: {current_line}"
)
wanted_lines.append(original_text[current_line-1])
text = wanted_lines


if len(text) == 0:
text.append('')
Expand Down
8 changes: 8 additions & 0 deletions tests/resources/longer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
This is line 1
This is line 2
This is line 3
This is line 4
This is line 5
This is line 6
This is line 7
This is line 8
48 changes: 48 additions & 0 deletions tests/test_include.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,3 +142,51 @@ def test_processor_lines():
result_lines = processor.run(source)

assert len(result_lines) == 9


def test_include_lines(markdown_include):
source = "{!resources/longer.md!lines=1 3}"
html = markdown.markdown(source, extensions=[markdown_include])

assert html == dedent(
"""\
<p>This is line 1
This is line 3</p>"""
)


def test_include_line_range(markdown_include):
source = "{!resources/longer.md!lines=3-5}"
html = markdown.markdown(source, extensions=[markdown_include])

assert html == dedent(
"""\
<p>This is line 3
This is line 4
This is line 5</p>"""
)


def test_include_lines_and_line_range(markdown_include):
source = "{!resources/longer.md!lines=1 3-5 8}"
html = markdown.markdown(source, extensions=[markdown_include])

assert html == dedent(
"""\
<p>This is line 1
This is line 3
This is line 4
This is line 5
This is line 8</p>"""
)


def test_include_lines_out_of_order(markdown_include):
source = "{!resources/longer.md!lines=3 1}"
html = markdown.markdown(source, extensions=[markdown_include])

assert html == dedent(
"""\
<p>This is line 3
This is line 1</p>"""
)

0 comments on commit 993e858

Please sign in to comment.