import sys, re from .tokens import * def placeholder(txt): return '<<<%s>>>' % (txt,) class BaseFormat(object): text_based = True SPACES_PAT = re.compile(r'[\n ]+') class Format(BaseFormat): """The base format implements a lossy plaintext display format that serves as reasonable default behavior. Formats are stateful, so currently you construct a new one each time you parse something. I'm not sure I like those semantics, though.""" def __init__(self): self.start_of_list = False self.start_of_table = False self.link_text = None self.eat_nl = True def text(self, text): """Escape special characters in text, intended to be plain text, as necessary.""" if self.eat_nl: text = text.lstrip('\n') self.eat_nl = False text = SPACES_PAT.sub(' ', text) # TODO(xavid): I'm not sure I like this hack. if self.link_text is not None: self.link_text += text yield text def tag(self, t, arg=None): if t == BOLD: return u'*' elif t == ITALIC: return u'/' elif t == MONOSPACE: return u'' elif t == SUPERSCRIPT: return u'^' elif t == SUBSCRIPT: return u',' elif t == UNDERLINE: return u'_' elif t == STRIKE: return u'-' elif t == CODEBLOCK: return u'' else: # Default to doing nothing, it's pretty safe. return u'' LIST_MAP = {ORDERED_ITEM: '#', UNORDERED_ITEM: '*'} def start(self, t, arg=None): if t in (ORDERED, UNORDERED, BLOCKQUOTE): if arg == 1: print 'sol!' self.start_of_list = True yield '' elif t in self.LIST_MAP: if self.start_of_list: start = u'' else: start = u'\n' self.start_of_list = False print 'sol.' yield start + u' ' * arg + self.LIST_MAP[t] + u' ' elif t == BLOCKQUOTE_LINE: if self.start_of_list: start = u'' else: start = u'\n' self.start_of_list = False yield start + u'>' * arg + u' ' elif t == PARAGRAPH: yield '' elif t == LINK: self.link_text = '' yield '' elif t == IMAGE: yield '[' elif t == HEADING: yield '%s ' % (u'=' * arg) elif t == TABLE: self.start_of_table = True yield u'' elif t == TABLE_CELL: yield u'\t' elif t == TABLE_HEADING: yield u'\t* ' elif t == TABLE_ROW: if self.start_of_table: self.start_of_table = False yield u'' else: yield u'\n' self.eat_nl = True else: yield self.tag(t, arg) def end(self, t, arg=None): if t in (ORDERED, UNORDERED): yield '' elif t in (ORDERED_ITEM, UNORDERED_ITEM, BLOCKQUOTE_LINE): yield '' elif t == PARAGRAPH: yield '' elif t == LINK: implicit = arg['url'] == self.link_text and '://' in arg['url'] self.link_text = None if implicit: yield u'' else: yield u'@<%s>' % arg['url'] elif t == IMAGE: yield u']' elif t == HEADING: yield ' %s' % (u'=' * arg) elif t == TABLE: yield u'' elif t == TABLE_CELL: yield u'' elif t == TABLE_HEADING: yield u' *' elif t == TABLE_ROW: yield u'' else: yield self.tag(t, arg) def entity(self, t, arg=None): if t == HRULE: yield u'%s' % (u'-' * 70) self.eat_nl = True elif t == LINEBREAK: yield u'\n' self.eat_nl = True elif t == ENV_BREAK: yield u'\n\n' self.eat_nl = True elif t == ERROR: yield u'!! %s !!' % arg elif t == NOINDENT: yield u'' elif t == REF: yield placeholder(arg) else: assert False, t