Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 361ee65

Browse files
committed
Utility to help create outline information for PDF.
1 parent 1546fc3 commit 361ee65

1 file changed

Lines changed: 115 additions & 0 deletions

File tree

Doc/tools/toc2bkm.py

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
#! /usr/bin/env python
2+
3+
"""Convert a LaTeX .toc file to some PDFTeX magic to create that neat outline.
4+
5+
The output file has an extension of '.bkm' instead of '.out', since hyperref
6+
already uses that extension. Let's avoid clashing.
7+
"""
8+
9+
import os
10+
import re
11+
import string
12+
import sys
13+
14+
15+
# Ench item in an entry is a tuple of:
16+
#
17+
# Section #, Title String, Page #, List of Sub-entries
18+
19+
cline_re = r"""^
20+
\\contentsline\ \{([a-z]*)} # type of section in $1
21+
\{(?:\\numberline\ \{([0-9.A-Z]+)})? # section number
22+
(.*)} # title string
23+
\{(\d+)}$""" # page number
24+
25+
cline_rx = re.compile(cline_re, re.VERBOSE)
26+
27+
OUTER_TO_INNER = -1
28+
29+
_transition_map = {
30+
('chapter', 'section'): OUTER_TO_INNER,
31+
('section', 'subsection'): OUTER_TO_INNER,
32+
('subsection', 'subsubsection'): OUTER_TO_INNER,
33+
('subsubsection', 'subsection'): 1,
34+
('subsection', 'section'): 1,
35+
('section', 'chapter'): 1,
36+
('subsection', 'chapter'): 2,
37+
('subsubsection', 'section'): 2,
38+
('subsubsection', 'chapter'): 3,
39+
}
40+
41+
def parse_toc(fp):
42+
toc = top = []
43+
stack = [toc]
44+
level = 'chapter'
45+
lineno = 0
46+
while 1:
47+
line = fp.readline()
48+
if not line:
49+
break
50+
lineno = lineno + 1
51+
m = cline_rx.match(line)
52+
if m:
53+
stype, snum, title, pageno = m.group(1, 2, 3, 4)
54+
title = clean_title(title)
55+
entry = (stype, snum, title, string.atoi(pageno), [])
56+
if stype == level:
57+
toc.append(entry)
58+
else:
59+
direction = _transition_map[(level, stype)]
60+
if direction == OUTER_TO_INNER:
61+
toc = toc[-1][-1]
62+
stack.insert(0, toc)
63+
toc.append(entry)
64+
else:
65+
for i in range(direction):
66+
del stack[0]
67+
toc = stack[0]
68+
toc.append(entry)
69+
level = stype
70+
else:
71+
sys.stderr.write("l.%s: " + line)
72+
return top
73+
74+
75+
hackscore_rx = re.compile(r"\\(hackscore|raisebox)\s*{[^}]*}")
76+
title_rx = re.compile(r"\\[a-zA-Z]+\s*")
77+
title_trans = string.maketrans("", "")
78+
79+
def clean_title(title):
80+
title = hackscore_rx.sub("_", title)
81+
while 1:
82+
m = title_rx.search(title)
83+
if m:
84+
title = title[:m.start()] + title[m.end():]
85+
else:
86+
break
87+
return string.translate(title, title_trans, "{}")
88+
89+
90+
def write_toc(toc, fp):
91+
for entry in toc:
92+
write_toc_entry(entry, fp, 0)
93+
94+
def write_toc_entry(entry, fp, layer):
95+
stype, snum, title, pageno, toc = entry
96+
s = "\\pdfoutline goto name{page.%d}" % pageno
97+
if toc:
98+
s = "%s count -%d" % (s, len(toc))
99+
if snum:
100+
title = "%s %s" % (snum, title)
101+
s = "%s {%s}\n" % (s, title)
102+
fp.write(s)
103+
for entry in toc:
104+
write_toc_entry(entry, fp, layer + 1)
105+
106+
107+
def main():
108+
base, ext = os.path.splitext(sys.argv[1])
109+
ext = ext or ".toc"
110+
toc = parse_toc(open(base + ext))
111+
write_toc(toc, open(base + ".bkm", "w"))
112+
113+
114+
if __name__ == "__main__":
115+
main()

0 commit comments

Comments
 (0)