/usr/share/uicilibris/expand.py is in uicilibris 1.13-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 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 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 | #!/usr/bin/env python
# $Id: expand.py 19 2011-08-09 16:09:53Z georgesk $
#
# expand.py is part of the package uicilibris
#
# uicilibris is based on wiki2beamer's code, which was authored by
# Michael Rentzsch and Kai Dietrich
#
# (c) 2007-2008 Michael Rentzsch (http://www.repc.de)
# (c) 2009-2010 Michael Rentzsch (http://www.repc.de)
# Kai Dietrich (mail@cleeus.de)
# (c) 2011 Georges Khaznadar (georgesk@ofset.org)
#
# Create high-level parseable code from a wiki-like code, like LaTeX
#
#
# This file is part of uicilibris.
# uicilibris is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# uicilibris is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with uicilibris. If not, see <http://www.gnu.org/licenses/>.
import random, re, string, hashlib, sys
def syntax_error(message, code):
print >>sys.stderr, 'syntax error in [expand]: %s' % message
print >>sys.stderr, '\tcode:\n%s' % code
sys.exit(-3)
def md5hex(string):
return hashlib.md5(string).hexdigest()
def expand_code_make_defverb(content, name):
return "\\defverbatim[colored]\\%s{\n%s\n}" % (name, content)
def expand_code_make_lstlisting(content, options):
return "\\begin{lstlisting}%s%s\\end{lstlisting}" % (options, content)
def expand_code_search_escape_sequences(code):
open = '1'
close = '2'
while code.find(open) != -1 or code.find(close) != -1:
open = open + chr(random.randint(48,57))
close = close + chr(random.randint(48,57))
return (open,close)
def expand_code_tokenize_anims(code):
#escape
(esc_open, esc_close) = expand_code_search_escape_sequences(code)
code = code.replace('\\[', esc_open)
code = code.replace('\\]', esc_close)
p = re.compile(r'\[\[(?:.|\s)*?\]\]|\[(?:.|\s)*?\]')
non_anim = p.split(code)
anim = p.findall(code)
#unescape
anim = map(lambda s: s.replace(esc_open, '\\[').replace(esc_close, '\\]'), anim)
non_anim = map(lambda s: s.replace(esc_open, '[').replace(esc_close, ']'), non_anim)
return (anim, non_anim)
def expand_code_parse_overlayspec(overlayspec):
overlays = []
groups = overlayspec.split(',')
for group in groups:
group = group.strip()
if group.find('-')!=-1:
nums = group.split('-')
if len(nums)<2:
syntax_error('overlay specs must be of the form <(%d-%d)|(%d), ...>', overlayspec)
else:
try:
start = int(nums[0])
stop = int(nums[1])
except ValueError:
syntax_error('not an int, overlay specs must be of the form <(%d-%d)|(%d), ...>', overlayspec)
overlays.extend(range(start,stop+1))
else:
try:
num = int(group)
except ValueError:
syntax_error('not an int, overlay specs must be of the form <(%d-%d)|(%d), ...>', overlayspec)
overlays.append(num)
#make unique
overlays = list(set(overlays))
return overlays
def expand_code_parse_simpleanimspec(animspec):
#escape
(esc_open, esc_close) = expand_code_search_escape_sequences(animspec)
animspec = animspec.replace('\\[', esc_open)
animspec = animspec.replace('\\]', esc_close)
p = re.compile(r'^\[<([0-9,\-]+)>((?:.|\s)*)\]$')
m = p.match(animspec)
if m != None:
overlays = expand_code_parse_overlayspec(m.group(1))
code = m.group(2)
else:
syntax_error('specification does not match [<%d>%s]', animspec)
#unescape code
code = code.replace(esc_open, '[').replace(esc_close, ']')
return [(overlay, code) for overlay in overlays]
def expand_code_parse_animspec(animspec):
if len(animspec)<4 or not animspec.startswith('[['):
return ('simple', expand_code_parse_simpleanimspec(animspec))
#escape
(esc_open, esc_close) = expand_code_search_escape_sequences(animspec)
animspec = animspec.replace('\\[', esc_open)
animspec = animspec.replace('\\]', esc_close)
p = re.compile(r'\[|\]\[|\]')
simple_specs = map(lambda s: '[%s]'%s, filter(lambda s: len(s.strip())>0, p.split(animspec)))
#unescape
simple_specs = map(lambda s: s.replace(esc_open, '\\[').replace(esc_close, '\\]'), simple_specs)
parsed_simple_specs = map(expand_code_parse_simpleanimspec, simple_specs)
#print parsed_simple_specs
unified_pss = []
for pss in parsed_simple_specs:
unified_pss.extend(pss)
#print unified_pss
return ('double', unified_pss)
def expand_code_getmaxoverlay(parsed_anims):
max_overlay = 0
for anim in parsed_anims:
for spec in anim:
if spec[0] > max_overlay:
max_overlay = spec[0]
return max_overlay
def expand_code_getminoverlay(parsed_anims):
min_overlay = sys.maxint
for anim in parsed_anims:
for spec in anim:
if spec[0] < min_overlay:
min_overlay = spec[0]
if min_overlay == sys.maxint:
min_overlay = 0
return min_overlay
def expand_code_genanims(parsed_animspec, minoverlay, maxoverlay, type):
#get maximum length of code
maxlen=0
if type=='double':
for simple_animspec in parsed_animspec:
if maxlen < len(simple_animspec[1]):
maxlen = len(simple_animspec[1])
out = []
fill = ''.join([' ' for i in xrange(0, maxlen)])
for x in xrange(minoverlay,maxoverlay+1):
out.append(fill[:])
for simple_animspec in parsed_animspec:
out[simple_animspec[0]-minoverlay] = simple_animspec[1]
return out
def expand_code_getname(code):
asciihextable = string.maketrans('0123456789abcdef',\
'abcdefghijklmnop')
d = md5hex(code).translate(asciihextable)
return d
def expand_code_makeoverprint(names, minoverlay):
out = ['\\begin{overprint}\n']
for (index, name) in enumerate(names):
out.append(' \\onslide<%d>\\%s\n' % (index+minoverlay, name))
out.append('\\end{overprint}\n')
return ''.join(out)
def expand_code_get_unique_name(defverbs, code, lstparams):
"""generate a collision free entry in the defverbs-map and names-list"""
name = expand_code_getname(code)
expanded_code = expand_code_make_defverb(expand_code_make_lstlisting(code, lstparams), name)
rehash = ''
while name in defverbs and defverbs[name] != expanded_code:
rehash += char(random.randint(65,90)) #append a character from A-Z to rehash value
name = expanded_code_getname(code + rehash)
expanded_code = expand_code_make_defverb(expand_code_make_lstlisting(code, lstparams), name)
return (name, expanded_code)
def expand_code_segment(result, codebuffer, state):
#treat first line as params for lstlistings
lstparams = codebuffer[0]
codebuffer[0] = ''
#join lines into one string
code = ''.join(codebuffer)
#print code
#tokenize code into anim and non_anim parts
(anim, non_anim) = expand_code_tokenize_anims(code)
#print anim
#print non_anim
if len(anim)>0:
#generate multiple versions of the anim parts
parsed_anims = map(expand_code_parse_animspec, anim)
#print parsed_anims
max_overlay = expand_code_getmaxoverlay(map(lambda x: x[1], parsed_anims))
#if there is unanimated code, use 0 as the starting overlay
if len(non_anim)>0:
min_overlay = 1
else:
min_overlay = expand_code_getminoverlay(map(lambda x: x[1], parsed_anims))
#print min_overlay
#print max_overlay
gen_anims = map(lambda x: expand_code_genanims(x[1], min_overlay, max_overlay, x[0]), parsed_anims)
#print gen_anims
anim_map = {}
for i in xrange(0,max_overlay-min_overlay+1):
anim_map[i+min_overlay] = map(lambda x: x[i], gen_anims)
#print anim_map
names = []
for overlay in sorted(anim_map.keys()):
#combine non_anim and anim parts
anim_map[overlay].append('')
zipped = zip(non_anim, anim_map[overlay])
mapped = map(lambda x: x[0] + x[1], zipped)
code = ''.join(mapped)
#generate a collision free entry in the defverbs-map and names-list
(name, expanded_code) = expand_code_get_unique_name(state.defverbs, code, lstparams)
#now we have a collision free entry, append it
names.append(name)
state.defverbs[name] = expanded_code
#append overprint area to result
overprint = expand_code_makeoverprint(names, min_overlay)
result.append(overprint)
else:
#we have no animations and can just put the defverbatim in
#remove escapings
code = code.replace('\\[', '[').replace('\\]', ']')
(name, expanded_code) = expand_code_get_unique_name(state.defverbs, code, lstparams)
state.defverbs[name] = expanded_code
result.append('\n\\%s\n' % name)
#print '----'
return
def expand_code_defverbs(result, state):
result[state.code_pos] = result[state.code_pos] + '\n'.join(state.defverbs.values()) + '\n'
state.defverbs={}
|