I've been trying to fix MoinMoin's text_plain formatter to produce
readable output. It's almost correct, except I don't understand why I
can't get the LF-adding rules correct. Either there are too many LFs or
too few. And whenever I change something, something else breaks.. It's
getting pretty annoying.

So if anyone else wants to try getting it fixed that'd be great. :)
Attached the current version that I have.

For testing you'll need your own MoinMoin installation. Then replace the
included text_plain.py with the attached version. Then test it with for
example:

http://localhost/wiki/SomePage?action=format;mimetype=text/plain

# -*- coding: iso-8859-1 -*-
"""
    MoinMoin - "text/plain" Formatter

    @copyright: 2000, 2001, 2002 by Jürgen Hermann <[EMAIL PROTECTED]>
    @license: GNU GPL, see COPYING for details.
"""

from MoinMoin.formatter.base import FormatterBase

class Formatter(FormatterBase):
    """
        Send plain text data.
    """

    hardspace = u' '

    def __init__(self, request, **kw):
        apply(FormatterBase.__init__, (self, request), kw)
        self._in_code_area = 0
        self._in_code_line = 0
        self._code_area_state = [0, -1, -1, 0]
        self._lists = []
        self._url = None
        self._text = None # XXX does not work with links in headings!!!!!
	self._textbuf = ''
	self._indent = 0
	self._end_indent = -1
	self._para_begin = True
	self._listitem_on = []
	self._last_lf = True
	self._empty_line_count = 2

    def startDocument(self, pagename):
        line = u"*" * (len(pagename) + 2) + u'\n'
        return self.wrap(u"%s %s \n%s" % (line, pagename, line))

    def endDocument(self):
        return self.flush(True)

    def sysmsg(self, on, **kw):
        return self.wrap((u'\n\n*** ', u' ***\n\n')[not on])

    def pagelink(self, on, pagename='', page=None, **kw):
        apply(FormatterBase.pagelink, (self, on, pagename, page), kw)
	if on:
	    self._text = []
	    return self.wrap(u"<")
	else:
	    if "".join(self._text) == pagename:
                self._text = None
		return self.wrap(u">")
	    else:
                self._text = None
	        return self.wrap(u"> [%s]" % (pagename))

    def interwikilink(self, on, interwiki='', pagename='', **kw):
        if on:
            self._url = u"%s:%s" % (interwiki, pagename)
            self._text = []
            return u''
        else:
            if "".join(self._text) == self._url:
                self._url = None
                self._text = None
                return ''
            else:
                self._url = None
                self._text = None
                return self.wrap(u' [%s]' % (self._url))
            
    def url(self, on, url='', css=None, **kw):
        if on:
            self._url = url
            self._text = []
            return u''
        else:
            if "".join(self._text) == self._url:
                self._url = None
                self._text = None
                return ''
            else:
                self._text = None
                return self.wrap(u' [%s]' % (self._url))

    def attachment_link(self, url, text, **kw):
        return self.wrap("[%s]" % text)

    def attachment_image(self, url, **kw):
        title = ''
        for a in (u'title', u'html__title', u'alt', u'html_alt'):
            if kw.has_key(a):
                title = ':' + kw[a]
        return self.wrap("[image:%s%s]" % (url, title))

    def attachment_drawing(self, url, text, **kw):
        return self.wrap("[drawing:%s]" % text)
    
    def text(self, text, **kw):
        if self._text is not None:
            self._text.append(text)
        return self.wrap(text)

    def rule(self, size=0, **kw):
        size = min(size, 10)
        ch = u"---~=*+#####"[size]
        return self.wrap((ch * 79) + u'\n')

    def strong(self, on, **kw):
        return self.wrap(u'*')

    def emphasis(self, on, **kw):
        return self.wrap(u'/')

    def highlight(self, on, **kw):
        return u''

    def number_list(self, on, type=None, start=None, **kw):
        if on:
	    self._para_begin = False
	    result = self.start_para()
	    self._lists.append(0)
	    self._listitem_on.append(False)
        else:
	    result = self.flush(False)
	    num = self._lists.pop(-1)
	    listitem_on = self._listitem_on.pop(-1)
	    if listitem_on:
                result += self.wrap('\n')
	        prefix = ' %d. ' % (num)
	        self._indent -= len(prefix)
            result += self.end_para()
	    self._end_indent = self._indent
        return result

    def bullet_list(self, on, **kw):
	if on:
	    self._para_begin = False
	    result = self.start_para()
	    self._lists.append(-1)
	    self._listitem_on.append(False)
        else:
	    result = self.flush(False)
	    self._lists.pop(-1)
	    listitem_on = self._listitem_on.pop(-1)
	    if listitem_on:
                result += self.wrap('\n')
	        self._indent -= 3
	    result += self.end_para()
	    self._end_indent = self._indent
        return result

    def listitem(self, on, **kw):
	if not on:
	    return ''

	result = ''
	num = self._lists.pop(-1)
	listitem_on = self._listitem_on.pop(-1)
	if listitem_on and on:
	    # we didn't receive on=False for previous listitem
	    if num >= 0:
	        prefix = ' %d. ' % (num)
	        self._indent -= len(prefix)
	    else:
	        self._indent -= 3
            result += self.wrap('\n')
	self._listitem_on.append(on)

	if num >= 0:
	    if on:
	        num += 1
	    prefix = ' %d. ' % (num)
	else:
	    prefix = ' * '
	self._lists.append(num)

	if on:
	    self._para_begin = True
	    result += self.wrap(prefix)
	    self._indent += len(prefix)
	else:
	    self._indent -= len(prefix)
	    result += self.wrap('\n')
	self._end_indent = -1
        return result;
        
    def sup(self, on, **kw):
	if on:
	    return self.wrap(u'^')
	else:
	    return ''

    def sub(self, on, **kw):
        return self.wrap(u'_')

    def strike(self, on, **kw):
        return self.wrap(u'__')

    def code(self, on, **kw):
        #return [unichr(0x60), unichr(0xb4)][not on]
        return self.wrap(u"'") # avoid high-ascii

    def preformatted(self, on, **kw):
        FormatterBase.preformatted(self, on)
        snip = u'---%<'
        snip = snip + (u'-' * (78 - len(snip)))
        if on:
	    self._text = []
	    return self.wrap(u'\n' + snip + u'\n')
        else:
	    if not "".join(self._text).endswith(u'\n'):
		snip = u'\n' + snip;
            self._text = None
	    return self.wrap(snip + u'\n')

    def small(self, on, **kw):
        return u''

    def big(self, on, **kw):
        return u''

    def code_area(self, on, code_id, code_type='code', show=0, start=-1, step=-1):
        snip = u'---CodeArea'
        snip = snip + (u'-' * (78 - len(snip)))
        if on:
            self._in_code_area = 1
            self._in_code_line = 0
            self._code_area_state = [show, start, step, start]
            return self.wrap(u'\n' + snip + u'\n')
        else:
            if self._in_code_line:
                return self.wrap(self.code_line(0) + snip + u'\n')
            return self.wrap(snip + u'\n')

    def code_line(self, on):
        res = u''
        if not on or (on and self._in_code_line):
            res += u'\n'
        if on:
            if self._code_area_state[0] > 0:
                res += u' %4d  ' % self._code_area_state[3]
                self._code_area_state[3] += self._code_area_state[2]
        self._in_code_line = on != 0
        return self.wrap(res)

    def code_token(self, on, tok_type):
        return ""

    def paragraph(self, on, **kw):
        FormatterBase.paragraph(self, on)
        if on:
	    result = self.start_para()
	else:
	    result = self.end_para()
	return result

    def linebreak(self, preformatted=1):
        return self.wrap(u'\n')

    def smiley(self, text):
        return self.wrap(text)

    def heading(self, on, depth, **kw):
        if on:
	    result = self.start_para()
	    self._text = []
        else:
            result =  u'\n%s\n\n' % (u'=' * len("".join(self._text)))
            self._text = None
            result = self.wrap(result)
	    result += self.end_para()
	return result;

    def table(self, on, attrs={}, **kw):
        return u''

    def table_row(self, on, attrs={}, **kw):
        return u''

    def table_cell(self, on, attrs={}, **kw):
        return u''

    def underline(self, on, **kw):
        return self.wrap(u'_')

    def definition_list(self, on, **kw):
        return u''

    def definition_term(self, on, compact=0, **kw):
        result = u''
        #if not compact:
        #    result = result + u'\n'
        if not on:
            result = result + u':\n'
        return self.wrap(result)

    def definition_desc(self, on, **kw):
        return self.wrap([u'    ', u'\n'][not on])

    def image(self, src=None, **kw):
        for a in (u'title', u'html__title', u'alt', u'html_alt'):
            if kw.has_key(a):
                return self.wrap(kw[a])
        return u''

    def lang(self, on, lang_name):
        return ''

    def wrap(self, text):
	if len(text) == 0:
	    return ''

	prefix = ''
	if len(self._textbuf) == 0 and self._last_lf:
	    prefix = self.check_para_begin(1)
	    text = ' ' * self._indent + text
	lines = text.split('\n')
	text = prefix
	while len(lines) > 0:
	    self._textbuf += lines.pop(0)
	    if len(lines) > 0:
	        # LFs found
		#text += 'lf<' + self.flush(True) + '>'
		text += self.flush(True)
	    if len(self._textbuf) > 80 and self._textbuf.find(' ') != -1:
	        # wrap time
		text += self.flush(True, False)
	return text

    def start_para(self):
	result = ''
	if not self._para_begin:
	    if len(self._textbuf) > 0:
	        #result += 'start_para<' + self.flush(True) + '>'
	        result += self.flush(True)
	    self._para_begin = True
	return result

    def end_para(self):
	if len(self._textbuf) > 0:
	    #return 'end_para<' + self.flush(True) + '>'
	    return self.flush(True)
	else:
	    return ''

    def check_para_begin(self, foo=0):
	if self._para_begin:
	    self._para_begin = False
	    self._empty_line_count += 1
	    if self._end_indent == self._indent and self._empty_line_count == 1:
		#return 'i{' + str(self._indent) + '}' + '\n'
		return '\n'
	return ''

    def flush(self, addlf, full_flush=True):
	result = ''
	if len(self._textbuf) > 0:
	    result += self.check_para_begin()
	#result = 'n{' + str(self._indent) + '}'

	while len(self._textbuf) >= 80:
	    # need to wrap
	    last_space = self._textbuf.rfind(' ', self._indent, 80)
	    if last_space == -1:
		# a long line. split at the next possible space
		last_space = self._textbuf.find(' ', self._indent)
		if last_space == -1:
		    break
	    result += self._textbuf[:last_space] + '\n'
	    self._empty_line_count = 0
	    self._textbuf = ' ' * self._indent + self._textbuf[last_space+1:]
	    self._end_indent = self._indent
	if not full_flush:
	    self._para_begin = False
	    self._last_lf = result[-1] == '\n'
	    return result

	# strip trailing whitespace
	while len(self._textbuf) > 0 and self._textbuf[-1] == ' ':
	    self._textbuf = self._textbuf[:-1]
	if len(self._textbuf) == 0:
	    if not addlf:
		return result
	    self._empty_line_count += 1
	    if self._empty_line_count >= 2:
		return result
	else:
	    self._empty_line_count = 0

	result += self._textbuf
	if addlf:
	    result += '\n'
	self._textbuf = ''
	self._para_begin = False
	self._last_lf = result[-1] == '\n'
	return result

Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to