Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
allendowney
GitHub Repository: allendowney/thinkbayes2
Path: blob/master/book/Filist.py
1901 views
1
"""
2
3
A class for reading the contents of a file, modifying it in
4
memory, and writing it back.
5
6
A Filist is a list of strings that contains the contents of
7
a file. All the usual list operations can be applied to a Filist.
8
9
Because this class loads the entire file into memory, it uses
10
more space than it might need to, and it is limited to working with
11
files that fit into memory. The advantage is that it is easy to
12
implement algorithms that need random access to the contents of the
13
file, and it is convenient to debug because all the data is
14
available all the time.
15
16
Some of the methods I included are here because of specific
17
operations I was interested in.
18
19
Copyright 2012 Allen B. Downey
20
21
This program is free software; you can redistribute it and/or modify
22
it under the terms of the GNU General Public License as published by
23
the Free Software Foundation; either version 2 of the License, or
24
(at your option) any later version.
25
26
This program is distributed in the hope that it will be useful,
27
but WITHOUT ANY WARRANTY; without even the implied warranty of
28
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29
GNU General Public License for more details.
30
31
You should have received a copy of the GNU General Public License
32
along with this program; if not, see http://www.gnu.org/licenses/gpl.html
33
or write to the Free Software Foundation, Inc., 51 Franklin St,
34
Fifth Floor, Boston, MA 02110-1301 USA
35
36
"""
37
38
import sys
39
import re
40
41
class Filist(list):
42
def __init__(self, filename=None, t=None):
43
""" if a filename is provided, read the contents """
44
if filename:
45
self.filename = filename
46
lines = open(filename).readlines()
47
self.extend(lines)
48
# add any lines that are provided
49
if t:
50
self.extend(t)
51
52
def __str__(self):
53
return ''.join(self)
54
55
def join(self):
56
"""collapse the list of strings into a single long string"""
57
self[:] = [str(self)]
58
59
def search_lines(self, pattern):
60
"""traverse lines in order until one of them matches,
61
return the index and the match object
62
"""
63
pat = re.compile(pattern)
64
for i in range(0, len(self)):
65
match = pat.search(self[i])
66
if match:
67
return i, match
68
69
def sub_lines(self, pattern, replace, start=0):
70
"""
71
"""
72
pat = re.compile(pattern)
73
for i, line in enumerate(self):
74
if i < start:
75
continue
76
line, n = pat.subn(replace, self[i])
77
if n:
78
self[i] = line
79
80
def move_indexterms(self):
81
"""Moves index entries from section headings into a paragraph."""
82
i = 0
83
while i < len(self):
84
if not (self[i].startswith('\\section') or
85
self[i].startswith('\\subsection') or
86
self[i].startswith('\\begin{exercise}')):
87
i += 1
88
continue
89
90
i += 1
91
while self[i].startswith('\\label'):
92
i += 1
93
94
begin = i
95
96
while self[i].startswith('\\index'):
97
i += 1
98
99
end = i
100
101
if begin == end:
102
continue
103
104
# shift the lines
105
j = end
106
while j > begin:
107
self[j] = self[j-1]
108
j -= 1
109
110
self[begin] = '\n'
111
112
def decapitate(self, pattern='<BODY >\n'):
113
"""find the first line that matches the pattern;
114
remove it and all the previous lines
115
"""
116
i = self.index(pattern)
117
del self[:i+1]
118
119
def depeditate(self, pattern='</BODY>\n'):
120
"""find the first line that matches the pattern;
121
remove it and all the following lines
122
"""
123
i = self.index(pattern)
124
del self[i:]
125
126
def prefile(self, filename):
127
"""prepend the contents of the given file"""
128
ft = Filist(filename)
129
self.insert(0, ft)
130
131
def suffile(self, filename):
132
"""append the contents of the given file"""
133
ft = Filist(filename)
134
self.extend(ft)
135
136
def writeto(self, filename):
137
"""write the contents of the Filist to a file"""
138
fp = open(filename, 'w')
139
for line in self:
140
fp.write(line)
141
142
def writeback(self):
143
"""write the contents of the Filist back to the file it came from"""
144
self.writeto(self.filename)
145
146
def change_suffix(filename, suffix):
147
"""return a new filename that is the same as the given name
148
with the file extension replaced with the given suffix
149
"""
150
filename.split('.')
151
t[-1] = suffix
152
return '.'.join(t)
153
154
def cp(source, dest):
155
"""copy a file from source to destination, returning a Filist"""
156
ft = Filist(source)
157
ft.writeto(dest)
158
return ft
159
160
161