-
Notifications
You must be signed in to change notification settings - Fork 42
Expand file tree
/
Copy pathupdate_index.py
More file actions
executable file
·169 lines (138 loc) · 5.7 KB
/
update_index.py
File metadata and controls
executable file
·169 lines (138 loc) · 5.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#!/usr/bin/env python
"""
This script generates the footers for all markdown files. Rerun the script
after adding new books or chapters in order to update the footer sections on
each page with links to the next and previous chapters.
The script works by recursively parsing "## Index" sections in files, starting
with README.md. The footer is marked with an HTML comment, `automatically
generated footer`. Any text after this comment is destroyed by the script, so
all edits should be made above that point.
"""
import sys,os,re
class TutorialIndex(object):
footermark = u"<!--automatically generated footer-->"
def __init__(self,link,chapter=None,title=None,parent=None):
"""Create a new TutorialIndex
:param link: A link to this page, relative to parent's link
:param chapter: The chapter number, e.g. "Chapter 5"
:param title: The chapter title, e.g. "Writing Docstrings"
:param parent: The TutorialIndex which references this one
"""
self.link = link
self.chapter = chapter
self.title = title
self.parent = parent
self.children = []
def parse(self):
"""Parse the index, add a footer, and do the same for each child
found in the '# Index' section (if any).
Caution, this method overwrites any existing footer sections on this
file and all children!
"""
#Recognise and parse "<CHAPTER>: (<TITLE>)[<LINK>]"
indexentry = re.compile("^(.*)[:-].*\[([^]]*)\]\(([^)]*)\).*$")
filename = self.rootlink()
with open(filename,"r+") as file:
line = file.readline()
had_footer=False
# Parse file for index, truncate prior footer, and append footermark
in_index = False
while line:
if line[0] == u"#": #That's a header, not a comment
if u"index" in line.lower():
in_index = True
else:
in_index = False
elif line.strip() == TutorialIndex.footermark: # Footer already!
had_footer=True
file.truncate()
break
elif in_index:
# look for 'Chapter 1: [Title](link)'
result = indexentry.match(line)
if result:
chapter,title,link = result.groups()
child = TutorialIndex(link,chapter,title,self)
self.children.append(child)
line = file.readline()
# Append footer
if not had_footer:
file.write(u"\n")
file.write(TutorialIndex.footermark)
file.write(u"\n")
footer = self.makefooter()
file.write(footer)
# Recurse to children
for child in self.children:
child.parse()
def rootlink(self):
"""Convert self.link to an absolute path relative to the root TutorialIndex
:return: The path to this TutorialIndex relative to the root index
"""
if self.parent is None:
return self.link
parentlink = self.parent.rootlink()
return os.path.join(os.path.dirname(parentlink),self.link)
def makefooter(self):
""" makefooter() -> str
Creates the footer text (everything below the "automatically generated
footer" line)
"""
# Don't include footer on main page
if self.parent is None:
return ""
lines = ["","---","","Navigation:"]
# Iterate over parents
p = self.parent
linkmd = [self.makename()] #reverse order (self to root)
while p is not None:
name = p.makename()
# Get a path to p relative to our own path
link = os.path.relpath(p.rootlink(),os.path.dirname(self.rootlink()))
linkmd.append("[{}]({})".format(name,link))
p = p.parent
linkmd.reverse()
lines.append("\n| ".join(linkmd))
lines.append("")
if self.parent is not None:
pos = self.parent.children.index(self) #Should always work
if pos > 0:
prev = self.parent.children[pos-1]
name = prev.makename()
link = os.path.relpath(prev.rootlink(),os.path.dirname(self.rootlink()))
lines.append("Prev: [{}]({})".format(name,link))
lines.append("")
if pos < len(self.parent.children)-1:
next = self.parent.children[pos+1]
name = next.makename()
link = os.path.relpath(next.rootlink(),os.path.dirname(self.rootlink()))
lines.append("Next: [{}]({})".format(name,link))
lines.append("")
#lines.append(self.makename()+", "+self.link)
return "\n".join(lines)
def makename(self):
""" Return a name, like "<CHAPTER>: <TITLE>"
"""
if self.chapter:
name = self.chapter
if self.title:
name += ": " + self.title
elif self.title:
name = self.title
else:
name = self.link #last resort
return name
def __repr__(self):
return "TutorialIndex({self.link!r},{self.chapter!r},{self.title!r},{parent!r})" \
.format(self=self,parent=self.parent.title if self.parent else None)
if __name__ == "__main__":
# Set root index
root = TutorialIndex("README.md",title="Home")
# Rewrite headers
root.parse()
# Output tree
def pr(node,indent=""):
print "{}{}".format(indent,node.link,node.rootlink())
for n in node.children:
pr(n,indent+" ")
pr(root)