2014-08-25 12:54:27 +02:00
|
|
|
#!/usr/bin/env python
|
|
|
|
|
from statemachine import StateMachine
|
2014-08-25 19:23:13 +02:00
|
|
|
import sys, os, string, json, shutil, codecs, traceback
|
2014-08-25 12:54:27 +02:00
|
|
|
|
|
|
|
|
quote_nbr = sys.maxint
|
|
|
|
|
fileout = ''
|
|
|
|
|
fileref = ''
|
|
|
|
|
notes = []
|
|
|
|
|
quotes = []
|
2014-08-25 17:57:34 +02:00
|
|
|
notes_cnt = 0
|
2014-08-25 12:54:27 +02:00
|
|
|
|
|
|
|
|
def error(c):
|
|
|
|
|
fp, l = c
|
|
|
|
|
sys.stderr.write('Unidentifiable line:\n'+ l)
|
|
|
|
|
|
|
|
|
|
def eof(c):
|
|
|
|
|
print "eof"
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
def parse(c):
|
|
|
|
|
fp, l = c
|
|
|
|
|
while 1:
|
|
|
|
|
line = fp.readline()
|
|
|
|
|
if not line: return eof, (fp, line)
|
|
|
|
|
if line[:2] == '##': return section(line), (fp, line)
|
|
|
|
|
else:
|
|
|
|
|
emit_line(line)
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
def QUOTES(c):
|
|
|
|
|
fp, l = c
|
|
|
|
|
while 1:
|
|
|
|
|
line = fp.readline()
|
|
|
|
|
if not line:
|
|
|
|
|
emit_remaining_quotes()
|
|
|
|
|
return eof, (fp, line)
|
2014-08-25 17:57:34 +02:00
|
|
|
elif is_quote_identifier(line): return process_quote, (fp, line)
|
2014-08-25 12:54:27 +02:00
|
|
|
elif line[:2] == '##':
|
|
|
|
|
emit_remaining_quotes()
|
|
|
|
|
return section(line), (fp, line)
|
|
|
|
|
else:
|
|
|
|
|
emit_line(line)
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
def NOTES(c):
|
|
|
|
|
fp, l = c
|
|
|
|
|
while 1:
|
|
|
|
|
line = fp.readline()
|
|
|
|
|
if not line:
|
|
|
|
|
emit_line('\n')
|
|
|
|
|
emit_remaining_notes()
|
|
|
|
|
return eof, (fp, line)
|
2014-08-25 17:57:34 +02:00
|
|
|
elif is_note_identifier(line): return process_note, (fp, line)
|
2014-08-25 12:54:27 +02:00
|
|
|
elif line[:2] == '##':
|
|
|
|
|
emit_line('\n')
|
|
|
|
|
emit_remaining_notes()
|
|
|
|
|
return section(line), (fp, line)
|
|
|
|
|
else:
|
|
|
|
|
emit_line(line)
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
def process_quote(c):
|
|
|
|
|
fp, l = c
|
2014-08-25 17:57:34 +02:00
|
|
|
ppnbr = int(extract_identifier(l))
|
2014-08-25 12:54:27 +02:00
|
|
|
for i in quotes.keys():
|
2014-09-01 10:35:11 +02:00
|
|
|
if i < ppnbr:
|
2014-08-25 12:54:27 +02:00
|
|
|
emit_quotes(quotes[i])
|
|
|
|
|
emit_line(l)
|
|
|
|
|
return QUOTES(c)
|
|
|
|
|
|
|
|
|
|
def process_note(c):
|
2014-08-25 17:57:34 +02:00
|
|
|
global notes_cnt
|
2014-08-25 12:54:27 +02:00
|
|
|
fp, l = c
|
2014-08-25 17:57:34 +02:00
|
|
|
cnt = int(extract_identifier(l))
|
|
|
|
|
if(cnt > notes_cnt):
|
|
|
|
|
notes_cnt = cnt
|
2014-08-25 12:54:27 +02:00
|
|
|
emit_line(l)
|
|
|
|
|
return NOTES(c)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
####################
|
|
|
|
|
|
|
|
|
|
def section(line):
|
|
|
|
|
emit_line(line)
|
|
|
|
|
line = string.upper(line)
|
|
|
|
|
if string.find(line, 'NOTES') >= 0:
|
|
|
|
|
if not notes:
|
|
|
|
|
return parse
|
|
|
|
|
return NOTES
|
|
|
|
|
elif string.find(line, 'QUOTES') >= 0:
|
|
|
|
|
if not quotes:
|
|
|
|
|
return parse
|
|
|
|
|
return QUOTES
|
|
|
|
|
elif string.find(line, 'REFERENCE') >= 0: return parse
|
|
|
|
|
else: return parse
|
|
|
|
|
|
2014-08-25 17:57:34 +02:00
|
|
|
def is_quote_identifier(line):
|
|
|
|
|
l = line.strip().upper()
|
|
|
|
|
return l.startswith("<!--") and l.find("PAGE") >= 0
|
|
|
|
|
|
|
|
|
|
def is_note_identifier(line):
|
|
|
|
|
l = line.strip().upper()
|
|
|
|
|
return l.startswith("<!--") and l.find("NOTE") >= 0
|
|
|
|
|
|
|
|
|
|
def extract_identifier(line):
|
|
|
|
|
t = line.strip().replace('<!--', '').replace('-->', '')
|
|
|
|
|
return t.strip().rsplit()[-1]
|
|
|
|
|
|
2014-08-25 12:54:27 +02:00
|
|
|
def emit_remaining_quotes():
|
|
|
|
|
rest = []
|
|
|
|
|
for i in quotes:
|
|
|
|
|
rest.extend(quotes[i])
|
2014-09-01 10:35:11 +02:00
|
|
|
for j in rest:
|
|
|
|
|
emit_quote(j)
|
|
|
|
|
#emit_quotes(rest)
|
2014-08-25 12:54:27 +02:00
|
|
|
|
|
|
|
|
def emit_quotes(list):
|
|
|
|
|
while list:
|
|
|
|
|
emit_quote(list.pop())
|
|
|
|
|
|
|
|
|
|
def emit_quote(data):
|
2014-08-25 17:57:34 +02:00
|
|
|
emit_line("<!--page " + data['pp'] + "-->\n\n")
|
|
|
|
|
emit_line(">\"" + data['quote'] + "\" pp." + data['pp'] + "\n")
|
2014-08-25 12:54:27 +02:00
|
|
|
emit_line('\n')
|
|
|
|
|
|
|
|
|
|
def emit_remaining_notes():
|
|
|
|
|
rest = []
|
|
|
|
|
for i in notes:
|
|
|
|
|
rest.extend(notes[i])
|
|
|
|
|
for j in rest:
|
|
|
|
|
emit_note(j)
|
|
|
|
|
|
|
|
|
|
def emit_note(data):
|
2014-08-25 17:57:34 +02:00
|
|
|
global notes_cnt
|
|
|
|
|
notes_cnt += 1
|
|
|
|
|
emit_line("<!--note " + str(notes_cnt) + "-->\n\n")
|
|
|
|
|
emit_line(str(notes_cnt) + ". " + data['note'] + "\n\n" )
|
2014-08-25 12:54:27 +02:00
|
|
|
|
|
|
|
|
def emit_line(l):
|
|
|
|
|
#l = l.encode('utf-8')
|
|
|
|
|
fileout.write(l)
|
|
|
|
|
|
|
|
|
|
def reoder(q):
|
|
|
|
|
out = {}
|
|
|
|
|
while q:
|
2014-09-01 10:35:11 +02:00
|
|
|
ip = q.pop()
|
|
|
|
|
i = int(ip['pp'])
|
|
|
|
|
if i in out.keys():
|
|
|
|
|
out[i].append(ip)
|
2014-08-25 12:54:27 +02:00
|
|
|
else:
|
2014-09-01 10:35:11 +02:00
|
|
|
out[i] = [ip]
|
2014-08-25 12:54:27 +02:00
|
|
|
return out
|
|
|
|
|
|
|
|
|
|
def open_file(p):
|
|
|
|
|
if not os.path.exists(p):
|
|
|
|
|
sys.exit('File %s does not exists... Aborting.' % p)
|
|
|
|
|
return codecs.open(p, 'rb', 'utf-8')
|
|
|
|
|
|
|
|
|
|
def open_fileoutput(p):
|
|
|
|
|
if not os.path.exists(p):
|
|
|
|
|
sys.exit('File %s does not exists... Aborting.' % p)
|
|
|
|
|
return codecs.open(p, 'r+', 'utf-8')
|
|
|
|
|
|
|
|
|
|
def backupfile(p):
|
|
|
|
|
if not os.path.exists(p):
|
|
|
|
|
sys.exit('File %s does not exists... Aborting.' % p)
|
|
|
|
|
bak = p + '.bak'
|
|
|
|
|
shutil.copy2(p, bak)
|
|
|
|
|
return codecs.open(bak, 'r', 'utf-8')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
if len(sys.argv) < 2:
|
|
|
|
|
sys.exit('No input file... Aborting.')
|
|
|
|
|
# fp1 should be the incoming .mmd file
|
2014-08-25 19:23:13 +02:00
|
|
|
try:
|
|
|
|
|
fileref = backupfile(sys.argv[1])
|
|
|
|
|
fileout = open_fileoutput(sys.argv[1])
|
|
|
|
|
fileout.seek(0)
|
|
|
|
|
except:
|
|
|
|
|
sys.exit("Can't open file " + sys.argv[1] + ". Aborting.")
|
|
|
|
|
|
2014-08-25 12:54:27 +02:00
|
|
|
if len(sys.argv) < 3:
|
|
|
|
|
fp2 = sys.stdin
|
|
|
|
|
else:
|
2014-08-25 19:23:13 +02:00
|
|
|
try:
|
|
|
|
|
fp2 = open_file(sys.argv[2])
|
|
|
|
|
except:
|
|
|
|
|
sys.exit("Can't open file " + sys.argv[2] + ". Aborting.")
|
2014-08-25 12:54:27 +02:00
|
|
|
|
|
|
|
|
# fp2 should be the incoming (json) data to inject in fp1
|
2014-08-25 19:23:13 +02:00
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
sdata = fp2.read()
|
|
|
|
|
data = json.loads(sdata)
|
|
|
|
|
except:
|
|
|
|
|
e = "<inject> Error loading data. Aborting\n"
|
|
|
|
|
if sdata:
|
|
|
|
|
e += "Traceback: " + sdata
|
|
|
|
|
fileout.close()
|
|
|
|
|
fileref.close()
|
|
|
|
|
sys.exit(e)
|
|
|
|
|
finally:
|
|
|
|
|
fp2.close()
|
2014-08-25 12:54:27 +02:00
|
|
|
|
|
|
|
|
if not data['QUOTES'] and not data['NOTES']:
|
|
|
|
|
print "Document up-to-date."
|
|
|
|
|
fileout.close()
|
|
|
|
|
sys.exit(0)
|
|
|
|
|
|
|
|
|
|
quotes = reoder(data['QUOTES'])
|
|
|
|
|
notes = reoder(data['NOTES'])
|
|
|
|
|
|
2014-09-01 10:35:11 +02:00
|
|
|
print quotes
|
|
|
|
|
|
2014-08-25 17:57:34 +02:00
|
|
|
notes_cnt = 0
|
|
|
|
|
|
2014-08-25 19:23:13 +02:00
|
|
|
try:
|
|
|
|
|
m = StateMachine();
|
|
|
|
|
m.add_state(parse)
|
|
|
|
|
m.add_state(NOTES)
|
|
|
|
|
m.add_state(QUOTES)
|
|
|
|
|
m.add_state(process_quote)
|
|
|
|
|
m.add_state(process_note)
|
|
|
|
|
m.add_state(error, end_state=1)
|
|
|
|
|
m.add_state(eof, end_state=1)
|
|
|
|
|
m.set_start(parse)
|
|
|
|
|
m.run((fileref, ''))
|
|
|
|
|
except:
|
|
|
|
|
trace = "Error injecting.\n\nTrace: \n"
|
|
|
|
|
trace += traceback.format_exc()
|
|
|
|
|
else:
|
|
|
|
|
trace = "Done injection."
|
|
|
|
|
finally:
|
|
|
|
|
fileout.close()
|
|
|
|
|
fileref.close()
|
|
|
|
|
sys.exit(trace)
|
|
|
|
|
|
|
|
|
|
|
2014-08-25 12:54:27 +02:00
|
|
|
|
|
|
|
|
|