5
# Copyright: Srinath Avadhanula
7
# This file implements a simple outline creation for latex documents.
15
def getFileContents(argin, ext=''):
16
if type(argin) is str:
19
fname = argin.group(3) + ext
21
# This longish thing is to make sure that all files are converted into
23
contents = '\n'.join(open(fname).read().splitlines())
25
# TODO what are all the ways in which a tex file can include another?
26
pat = re.compile(r'^\\(@?)(include|input){(.*?)}', re.M)
27
contents = re.sub(pat, lambda input: getFileContents(input, ext), contents)
29
return ('%%==== FILENAME: %s' % fname) + '\n' + contents
33
def stripComments(contents):
34
# remove all comments except those of the form
35
# %%==== FILENAME: <filename.tex>
36
uncomm = [re.sub('%(?!==== FILENAME: ).*', '', line) for line in contents.splitlines()]
37
# also remove all only-whitespace lines.
38
nonempty = [line for line in uncomm if line.strip()]
42
# addFileNameAndNumber {{{
43
def addFileNameAndNumber(lines):
47
if re.match('%==== FILENAME: ', line):
48
filename = line.split('%==== FILENAME: ')[1]
50
retval += '<%s>%s\n' % (filename, line)
54
# getSectionLabels_Root {{{
55
def getSectionLabels_Root(lineinfo, section_prefix, label_prefix):
59
outstr = StringIO.StringIO('')
60
pres_depth = len(section_prefix)
62
#print '+getSectionLabels_Root: lineinfo = [%s]' % lineinfo
63
for line in lineinfo.splitlines():
67
# throw away leading white-space
68
m = re.search('<(.*?)>(.*)', line)
71
line = m.group(2).lstrip()
74
m = re.search(r'\\label{(%s.*?)}' % label_prefix, line)
76
# add the current line (except the \label command) to the text
77
# which will be displayed below this label
78
prev_txt += re.search(r'(^.*?)\\label{', line).group(1)
80
# for the figure environment however, just display the caption.
81
# instead of everything since the \begin command.
82
if prev_env == 'figure':
83
cm = re.search(r'\caption(\[.*?\]\s*)?{(.*?)}', prev_txt)
85
prev_txt = cm.group(2)
87
# print a nice formatted text entry like so
92
# Use the current "section depth" for the leading indentation.
93
print >>outstr, '>%s%s\t\t<%s>' % (' '*(2*pres_depth+2),
95
print >>outstr, ':%s%s' % (' '*(2*pres_depth+4), prev_txt)
98
# If we just encoutered the start or end of an environment or a
99
# label, then do not remember this line.
100
# NOTE: This assumes that there is no equation text on the same
101
# line as the \begin or \end command. The text on the same line as
102
# the \label was already handled.
103
if re.search(r'\\begin{(equation|eqnarray|align|figure)', line):
105
prev_env = re.search(r'\\begin{(.*?)}', line).group(1)
108
elif re.search(r'\\label', line):
111
elif re.search(r'\\end{(equation|eqnarray|align|figure)', line):
116
# If we are inside an environment, then the text displayed with
117
# the label is the complete text within the environment,
118
# otherwise its just the previous line.
124
return outstr.getvalue()
127
# getSectionLabels {{{
128
def getSectionLabels(lineinfo,
129
sectypes=['chapter', 'section', 'subsection', 'subsubsection'],
130
section_prefix='', label_prefix=''):
133
return getSectionLabels_Root(lineinfo, section_prefix, label_prefix)
135
##print 'sectypes[0] = %s, section_prefix = [%s], lineinfo = [%s]' % (
136
## sectypes[0], section_prefix, lineinfo)
138
sections = re.split(r'(<.*?>\\%s{.*})' % sectypes[0], lineinfo)
140
# there will 1+2n sections, the first containing the "preamble" and the
141
# others containing the child sections as paris of [section_name,
144
rettext = getSectionLabels(sections[0], sectypes[1:], section_prefix, label_prefix)
146
for i in range(1,len(sections),2):
148
section_name = re.search(r'\\%s{(.*?)}' % sectypes[0], sections[i]).group(1)
149
section_label_text = getSectionLabels(sections[i] + sections[i+1], sectypes[1:],
150
section_prefix+('%d.' % sec_num), label_prefix)
152
if section_label_text:
153
sec_heading = 2*' '*len(section_prefix) + section_prefix
154
sec_heading += '%d. %s' % (sec_num, section_name)
155
sec_heading += '<<<%d\n' % (len(section_prefix)/2+1)
157
rettext += sec_heading + section_label_text
164
def main(fname, label_prefix):
165
[head, tail] = os.path.split(fname)
169
[root, ext] = os.path.splitext(tail)
170
contents = getFileContents(root, ext)
171
nonempty = stripComments(contents)
172
lineinfo = addFileNameAndNumber(nonempty)
174
return getSectionLabels(lineinfo, label_prefix=label_prefix)
177
if __name__ == "__main__":
178
if len(sys.argv) > 2:
183
print main(sys.argv[1], prefix)