nnnotes/parse/inject.py

237 lines
4.8 KiB
Python
Raw Normal View History

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():
if int(i) < ppnbr:
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])
emit_quotes(rest)
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:
i = q.pop()
if i['pp'] in out.keys():
out[i['pp']].append(i)
else:
out[i['pp']] = [i]
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-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