Skip to content

Commit 9a5c93a

Browse files
committed
add: native reStructuredText support
test: added AsciiDoc and reStructuredText tests
1 parent 2b96ab3 commit 9a5c93a

File tree

9 files changed

+165
-49
lines changed

9 files changed

+165
-49
lines changed

CHANGELOG.md

Lines changed: 12 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,22 @@
1-
<!--
2-
// ┌───────────────────────────────────────────────────────────────┐
3-
// │ Contents of CHANGELOG.md │
4-
// ├───────────────────────────────────────────────────────────────┘
5-
// │
6-
// ├──┐Changelog - toc
7-
// │ ├──┐[2.4.0] - 2024-02-07
8-
// │ │ ├── Added
9-
// │ │ ├── Changed
10-
// │ │ ├── Documentation
11-
// │ │ ├── Performance
12-
// │ │ └── Testing
13-
// │ ├──┐[2.3.0] - 2024-02-02
14-
// │ │ ├── Added
15-
// │ │ ├── Documentation
16-
// │ │ ├── Fixed
17-
// │ │ ├── Performance
18-
// │ │ └── Testing
19-
// │ ├──┐[2.2.0] - 2024-01-29
20-
// │ │ ├── Added
21-
// │ │ ├── Documentation
22-
// │ │ ├── Fixed
23-
// │ │ └── Testing
24-
// │ ├──┐[2.1.0] - 2024-01-22
25-
// │ │ ├── Added
26-
// │ │ └── Documentation
27-
// │ ├── [2.0.0] - 2024-01-21
28-
// │ └── [1.0.0] - 2023-11-03
29-
// │
30-
// └───────────────────────────────────────────────────────────────
31-
-->
32-
331
# Changelog - toc
342

3+
## [2.5.0] - 2024-02-23
4+
### Added
5+
6+
- Native reStructuredText support
7+
- Native AsciiDoc support
8+
9+
### Testing
10+
11+
- Added AsciiDoc and reStructuredText tests
12+
3513
## [2.4.0] - 2024-02-07
3614
### Added
3715

3816
- Native man pages support
3917
- Line numbers to HTML toc
40-
- Stdin support with `-` argument
41-
- Set an arbitrary extension with `-e`, useful for stdin
18+
- Stdin support with "-" argument
19+
- Set an arbitrary extension with "-e", useful for stdin
4220
- Native HTML support
4321

4422
### Changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ If you are using Arch or Manjaro Linux, you can install [toc](https://aur.archli
6666

6767
You should now be able to run `toc -h` to display a list of parameter you can use.
6868

69-
See [USAGE.md](./USAGE.md) for step-by-step explanations of the different features, and languages that don't need comments (e.g. Markdown) or needs special attention (e.g. CSS)
69+
See [USAGE.md](./USAGE.md) for step-by-step explanations of different features, and a list of languages supported natively (e.g. Markdown, AsciiDoc, reStructuredText) or that need special attention (e.g. CSS)
7070

7171
See <https://regex101.com/r/ngzZXN/1> for examples of valid and invalid comments.
7272

USAGE.md

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
// │ │ ├── HTML
2222
// │ │ ├── Man pages
2323
// │ │ ├── Markdown
24-
// │ │ └── Perl
24+
// │ │ ├── Perl
25+
// │ │ └── reStructuredText
2526
// │ ├──┐Wrap around comments needed
2627
// │ │ ├── CSS
2728
// │ │ └── OCaml
@@ -40,7 +41,7 @@ The scenarios below show different features of `toc`
4041
### Read the table of contents
4142

4243
Let's say you want to structure your javascript file "example.js".
43-
Single line comments in this language start with `//`.
44+
Single-line comments in this language start with `//`.
4445
You open your file and add these comments where you need them:
4546

4647
```js
@@ -344,7 +345,6 @@ For [AsciiDoc](https://raw.githubusercontent.com/apple/pkl/main/CONTRIBUTING.ado
344345
===== Level 4 Section Title
345346

346347
====== Level 5 Section Title
347-
348348
```
349349

350350
#### Beancount
@@ -416,9 +416,27 @@ Text
416416
=cut
417417
```
418418

419+
#### reStructuredText
420+
421+
For [ReStructured Text](https://raw.githubusercontent.com/sphinx-doc/sphinx/master/doc/usage/restructuredtext/basics.rst) files, just use the [conventional heading format](https://devguide.python.org/documentation/markup/#sections):
422+
423+
```rst
424+
*******
425+
Chapter
426+
*******
427+
428+
=======
429+
Section
430+
=======
431+
432+
----------
433+
Subsection
434+
----------
435+
```
436+
419437
### Wrap around comments needed
420438

421-
These languages do not support single line comments, and thus every comment should be wrapped by a multi line comment separator
439+
These languages do not support single-line comments, and thus every comment should be wrapped by a multi-line comment separator
422440

423441
#### CSS
424442

@@ -471,7 +489,7 @@ void main() { exit(0);}
471489
#### RStudio
472490
473491
If you are using RStudio, you may want to end your comments with at least 4 `-`, `=` or `#`.
474-
This marks the comment as a foldable sections:
492+
This marks the comment as a foldable section:
475493
476494
```r
477495
# ################################################################ Foldable section 1 ####
@@ -486,5 +504,5 @@ print("Collapse me!")
486504

487505

488506
[^1]: No, not really, it's just a match-case statement using the file extension, defaulting to "#"
489-
[^2]: Not even, it's just a bunch of if-else and try-excepts statement that may prevent catastrophic damage
490-
[^3]: The outdated toc to be replaced is defined as the the first match of a non-greedy regex
507+
[^2]: Not even, it's just a bunch of if-else and try-excepts statements that may prevent catastrophic damage
508+
[^3]: The outdated toc to be replaced is defined as the first match of a non-greedy regex

tests/input/asciidoc_simple.adoc

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
= Document Title (Level 0)
2+
3+
== Level 1 Section Title
4+
5+
= Level 0 Section Title (Part)
6+
7+
== Level 1 Section Title
8+
9+
=== Level 2 Section Title
10+
11+
==== Level 3 Section Title
12+
13+
===== Level 4 Section Title
14+
15+
====== Level 5 Section Title
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
*******
2+
Chapter
3+
*******
4+
5+
Section
6+
=======
7+
8+
----------
9+
Subsection
10+
----------
11+
^^^^^^^^^^^^^^
12+
Subsubsections
13+
^^^^^^^^^^^^^^
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// ┌───────────────────────────────────────────────────────────────┐
2+
// │ Contents of asciidoc_simple.adoc │
3+
// ├───────────────────────────────────────────────────────────────┘
4+
// │
5+
// ├──┐Document Title (Level 0)
6+
// │ └── Level 1 Section Title
7+
// ├──┐Level 0 Section Title (Part)
8+
// │ └──┐Level 1 Section Title
9+
// │ └──┐Level 2 Section Title
10+
// │ └──┐Level 3 Section Title
11+
// │ └──┐Level 4 Section Title
12+
// │ └── Level 5 Section Title
13+
// │
14+
// └───────────────────────────────────────────────────────────────
15+
16+
= Document Title (Level 0)
17+
18+
== Level 1 Section Title
19+
20+
= Level 0 Section Title (Part)
21+
22+
== Level 1 Section Title
23+
24+
=== Level 2 Section Title
25+
26+
==== Level 3 Section Title
27+
28+
===== Level 4 Section Title
29+
30+
====== Level 5 Section Title
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
.. ┌───────────────────────────────────────────────────────────────┐
2+
.. │ Contents of restructuredtext_simple.rst │
3+
.. ├───────────────────────────────────────────────────────────────┘
4+
..
5+
.. │ └──┐Chapter
6+
.. │ └──┐Section
7+
.. │ └──┐Subsection
8+
.. │ └── Subsubsections
9+
..
10+
.. └───────────────────────────────────────────────────────────────
11+
12+
*******
13+
Chapter
14+
*******
15+
16+
Section
17+
=======
18+
19+
----------
20+
Subsection
21+
----------
22+
^^^^^^^^^^^^^^
23+
Subsubsections
24+
^^^^^^^^^^^^^^

toc/__version__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
#!/usr/bin/env python
22

3-
__version__ = "2.4.0"
3+
__version__ = "2.5.0"

toc/toc.py

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
# │ │ └──┐BODY
2323
# │ │ ├── ASCIIDOC, BEANCOUNT AND MARKDOWN
2424
# │ │ ├── HTML
25+
# │ │ ├── RESTRUCTUREDTEXT
2526
# │ │ ├── MAN PAGES
2627
# │ │ ├── PERL
2728
# │ │ ├── GENERIC
@@ -54,6 +55,7 @@ def __init__(self, inputFile: str = "", outputFile=None, lineNumbers: bool = Fal
5455
self.innerTocTitle = None
5556
self.innerTocEnd = None
5657
self.pattern = None
58+
# n=2**(7−l), l=7−math.log(n,2)
5759
self.levels = {
5860
64: 1,
5961
32: 2,
@@ -81,10 +83,6 @@ def set_character(self):
8183
# https://www.gnu.org/software/groff/manual/, https://manpages.bsd.lv/mdoc.html
8284
case "1" | "1m" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "n":
8385
self.character = '.\\"'
84-
case "ml" | "mli":
85-
self.character = "*"
86-
case "vb" | "vba" | "vbs":
87-
self.character = "'"
8886
case "apl":
8987
self.character = "⍝"
9088
# https://www.gavilan.edu/csis/languages/comments.html#_Toc53710123
@@ -93,13 +91,19 @@ def set_character(self):
9391
# https://stackoverflow.com/a/17665688
9492
case "cbl" | "cob":
9593
self.character = " *>"
96-
case "f" | "for":
97-
self.character = "C"
9894
# https://github.com/textmate/fortran.tmbundle/issues/10#issuecomment-22660333
9995
case "f90" | "f95" | "f03" | "f08" | "f15" | "f18":
10096
self.character = "!"
97+
case "f" | "for":
98+
self.character = "C"
10199
case "j":
102100
self.character = "NB."
101+
case "ml" | "mli":
102+
self.character = "*"
103+
case "rst":
104+
self.character = ".."
105+
case "vb" | "vba" | "vbs":
106+
self.character = "'"
103107
# jl mojo pl pm ps1 py r rb sh, yml, and anything else
104108
case _:
105109
self.character = "#"
@@ -346,6 +350,8 @@ def _toc_body(self):
346350
_newtoc = self._process_man(_lines)
347351
case "pl" | "pm" | "pod":
348352
_newtoc = self._process_perl(_lines)
353+
case "rst":
354+
_newtoc = self._process_restructuredtext(_data)
349355
case _:
350356
_newtoc = self._process_generic(_lines)
351357
_tocBody = self._prettify_connectors(_newtoc)
@@ -410,6 +416,38 @@ def _process_html(self, data):
410416
_newtoc.append(self._add_heading(_heading_level, _heading_text))
411417
return _newtoc
412418

419+
# #### RESTRUCTUREDTEXT
420+
421+
def _process_restructuredtext(self, data):
422+
_newtoc = []
423+
# match the line above a streak of "#" (chapters), "*" (sections), etc., avoiding '"""' heredocs (min 4)
424+
_pattern = re.compile(r'(?:[#\*=\-\^~]{2,}|[\"]{4,}|\n)[ \t]*(?!\.\.)(.+)\n[ \t]*([#\*=\-\^~]{2,}|[\"]{4,})\n', re.MULTILINE)
425+
_fromLastMatch = 0
426+
n = 1
427+
# https://devguide.python.org/documentation/markup/#sections
428+
_levels = {
429+
'#': 1,
430+
'*': 2,
431+
'=': 3,
432+
'-': 4,
433+
'~': 5,
434+
'^': 5,
435+
'"': 6
436+
}
437+
for _match in _pattern.finditer(data):
438+
_heading_text = _match.group(1)
439+
_symbol = _match.group(2)[:1]
440+
_heading_level = _levels[_symbol]
441+
if self.lineNumbers:
442+
# start counting from _heading_text, not optional overline
443+
_untilCurrentMatch = _match.start(1)
444+
n = n + data.count("\n", _fromLastMatch, _untilCurrentMatch)
445+
_heading_text = _heading_text + " " + str(n)
446+
# update with the position of the current match
447+
_fromLastMatch = _untilCurrentMatch
448+
_newtoc.append(self._add_heading(_heading_level, _heading_text))
449+
return _newtoc
450+
413451
# #### MAN PAGES
414452

415453
def _process_man(self, lines):

0 commit comments

Comments
 (0)