/usr/share/pyshared/doconce/expand_newcommands.py is in doconce 0.7.3-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 | #!/usr/bin/env python
# NOTE: all newcommands can only span *one line*!
# (necessary requirement since a findall with re.DOTALL will
# not catch the final } of a command, real parsing is then neeeded)
import shutil, re, sys, os
def process_newcommand(line):
line = line.replace('renewcommand', 'newcommand') # make syntax uniform
# newcommand without arguments:
pattern1 = r'\\newcommand\{(.+)\}\s*\{(.*)\}'
found = False
m = re.search(pattern1, line)
if m:
# for a newcommand \x we can have many appearances:
# \x |{\x}|\x{}|(\x)|\x, and replacing \x in \xpoint must
# but avoided - the idea is to use the regex (\x)([^A-Za-z])
end_pattern = r'([^A-Za-z])'
pattern = m.group(1) + end_pattern
replacement = m.group(2) + r'\g<1>' # \g<1> is the end_pattern
# could also use a lookahead pattern: (?=[^A-Za-z]), not tested
#pattern = m.group(1) + r'(?=[^A-Za-z])'
#replacement = m.group(2)
found = True
# newcommand with arguments:
pattern2 = r'\\newcommand\{(.+)\}\[(\d)\]\{(.*)\}'
m = re.search(pattern2, line)
if m:
nargs = int(m.group(2))
args = r'\{(.+?)\}'*nargs
pattern = m.group(1) + args
replacement = m.group(3)
for i in range(1, nargs+1):
replacement = replacement.replace('#%d' % i, r'\g<%d>' % i)
found = True
if found:
# fix \x, \b, \r... etc in strings
from latex import fix_latex_command_regex as fix
pattern = fix(pattern, 'match')
replacement = fix(replacement, 'replacement')
return pattern, replacement
def parse_newcommands(filename):
f = open(filename, 'r')
lines = f.readlines()
f.close()
newcommands = []
for line in lines:
line = line.strip()
if line.startswith('%') or line == '':
continue
elif line.startswith(r'\newcommand') or \
line.startswith(r'\renewcommand'):
pattern, replacement = process_newcommand(line)
newcommands.append((pattern, replacement))
else:
raise SyntaxError('Illegal line\n %s\nline' % line + \
'must start with %% or ' + r'\newcommand')
return newcommands
def substitute(source, newcommands):
"""
Expand all newcommands in the list 'newcommands' of
(pattern, replacement) pairs. source can be a filename
or just a string with text. If source is a filename, a backup
file with extension .old~ is first made and then the original
file is overwritten by the new text with expanded commands.
"""
if os.path.isfile(source):
shutil.copy(source, source + '.old~')
f = open(source, 'r')
text = f.read()
f.close()
else:
text = source
for pattern, replacement in newcommands:
m = re.search(pattern, text)
#if m:
# print 'matching', pattern, 'groups:',m.groups()
text, n = re.subn(pattern, replacement, text)
#print 'replacing', repr(pattern), 'with', repr(replacement), n, 'times'
# newcommands can be nested, let's repeat
depth = 2
for i in range(depth):
for pattern, replacement in newcommands:
m = re.search(pattern, text)
#if m:
# print 'matching', pattern, 'groups:',m.groups()
text, n = re.subn(pattern, replacement, text)
#print 'replacing', repr(pattern), 'with', repr(replacement), n, 'times'
if os.path.isfile(source):
f = open(source, 'w')
f.write(text)
f.close()
else:
return text
def expand_newcommands(newcommands_files, source):
if isinstance(newcommands_files, basestring):
newcommands_files = [newcommands_files] # always list
newcommands = []
for filename in newcommands_files:
if os.path.isfile(filename):
newcommands.extend(parse_newcommands(filename))
#import pprint; pprint.pprint(newcommands)
return substitute(source, newcommands)
if __name__ == '__main__':
if len(sys.argv) < 3:
print 'Usage: expand_newcommands.py newcommands_file source_file1 source_file2 ...'
sys.exit(1)
newcommands_file = sys.argv[1]
for source_file in sys.argv[2:]:
print 'expanding newcommands in', source_file
expand_newcommands(newcommands_file, source_file)
|