1
0
Fork 0
mirror of https://github.com/Oreolek/gamebookformat.git synced 2024-05-16 16:08:20 +03:00
gamebookformat/output.py
Pelle Nilsson 431357a85c Fixed problem with section used for missing.
It was handled at parse time, but must be done at
output time to be sure the section to use has been parsed.
2013-06-20 22:59:25 +02:00

179 lines
7.1 KiB
Python

import os
import os.path
import sys
COUNTER_CREATE_TAG = 'count'
COUNTER_USE_TAGS = set(['set', 'inc', 'dec', 'min',
'lessthan', 'morethan', 'atleast'])
class OutputFormat (object):
"Handles book output. Big FIXME required to make sense."
def __init__(self, templates, quote):
self.templates = templates
self.quote = quote
self.counter_names = {}
def format_begin(self, bookconfig):
# FIXME make sure book config is properly quoted
return self.format_with_template("begin", bookconfig)
def format_intro_sections(self, introsections, shuffled_sections):
res = ""
for s in introsections:
if not s.hastag('dummy'):
res += self.format_intro_section(s, shuffled_sections)
return res
def format_intro_section(self, section, shuffled_sections):
# FIXME some serious code-duplication here
refs = []
refsdict = ReferenceFormatter(section.nr,
shuffled_sections.name_to_nr,
shuffled_sections.missingto,
self.format_with_template("section_ref"),
self.quote)
formatted_text = self.format_section_body(section, refsdict)
return self.format_with_template("introsection", {
'name' : section.name,
'text' : formatted_text,
'refs' : '\n'.join(refsdict.getfound()) # hack for DOT output
})
def format_sections_begin(self, bookconfig):
return self.format_with_template("sections_begin",
bookconfig)
def format_shuffled_sections(self, shuffled_sections):
res = ""
for i, p in enumerate(shuffled_sections.as_list):
if p and not p.hastag('dummy'):
res += self.format_section(p, shuffled_sections)
elif i > 0:
res += self.format_empty_section(i)
return res
def format_section(self, section, shuffled_sections):
refs = []
refsdict = ReferenceFormatter(section.nr,
shuffled_sections.name_to_nr,
shuffled_sections.missingto,
self.format_with_template("section_ref"),
self.quote)
formatted_text = self.format_section_body(section, refsdict)
return self.format_with_template("section", {
'nr' : section.nr,
'name' : section.name,
'text' : formatted_text,
'refs' : '\n'.join(refsdict.getfound()) # hack for DOT output
})
def format_section_body(self, section, references):
i = 0
res = ""
# FIXME refactor for readability once good tests are in place
while i < len(section.text):
ref_start = section.text.find('[[', i)
tag_start = section.text.find('[', i)
if ref_start >= 0 and ref_start <= tag_start:
res += self.quote(section.text[i:ref_start])
ref_end = section.text.find(']]', ref_start)
if ref_end > ref_start:
ref = section.text[ref_start+2:ref_end]
splitref = ref.split()
if len(splitref) > 1:
for refmod in splitref[:-1]:
res += self.format_with_template(refmod,
references)
res += references[splitref[-1]]
i = ref_end + 2
else:
raise Exception('Mismatched ref start [[ in section %s' %
self.name)
elif tag_start >= 0:
res += self.quote(section.text[i:tag_start])
tag_end = section.text.find(']', tag_start)
if tag_end < 0:
raise Exception('Mismatched tag start [ in section %s' %
self.name)
tag = section.text[tag_start+1:tag_end].strip()
tagparts = tag.split()
tagname = tagparts[0]
end_tag_start = section.text.find('[', tag_end)
if (not end_tag_start > tag_end
and section.text[end_tag_start].startswith('[/' + tagname
+ ']')):
raise Exception('Bad format %s tag in %s.' % (
tag, self.name))
inner = section.text[tag_end+1:end_tag_start]
# FIXME this pollutes the mutable references object
references['inner'] = self.quote(inner)
for i, arg in enumerate(tagparts[1:]):
references['arg%d' % (i+1)] = self.quote(arg)
if tagname == COUNTER_CREATE_TAG and len(tagparts) > 1:
self.counter_names[tagparts[1]] = self.quote(inner)
references['counter'] = self.quote(inner)
elif tagname in COUNTER_USE_TAGS and len(tagparts) > 1:
if tagparts[1] in self.counter_names:
references['counter'] = self.counter_names[tagparts[1]]
f = self.format_with_template(tagname,
references)
if len(f) > 0:
res += f
else:
res += self.quote(inner)
i = section.text.find(']', end_tag_start) + 1
else:
res += self.quote(section.text[i:])
break
return res
def format_empty_section(self, nr):
return self.format_with_template("empty_section", {
'nr' : nr,
})
def format_end(self, bookconfig):
return self.format_with_template("end", bookconfig)
def format_with_template(self, name, values=None):
template = self.templates.get(name)
if values:
return template % values
else:
return template
class ReferenceFormatter (object):
"There is probably a better way, but this hack seems to work."
def __init__(self, from_nr, name_to_nr, missingto, ref_template, quote):
self.from_nr = from_nr
self.name_to_nr = name_to_nr
self.found = set()
self.ref_template = ref_template
self.items = {'nr' : from_nr}
self.quote = quote
self.missingto = missingto
def __getitem__(self, key):
if key in self.items:
return self.quote(self.items[key])
if key in self.name_to_nr:
to_nr = self.name_to_nr[key]
else:
to_nr = self.name_to_nr[self.missingto]
res = self.ref_template % {
'nr' : to_nr,
'from_nr' : self.from_nr
}
if key in self.name_to_nr:
self.found.add(res)
return res
def getfound(self):
return list(self.found)
def __setitem__(self, key, value):
self.items[key] = value
def __delitem__(self, key):
del self.items[key]