summaryrefslogtreecommitdiff
path: root/sandbox/cben/rolehack/rolehack.py
diff options
context:
space:
mode:
Diffstat (limited to 'sandbox/cben/rolehack/rolehack.py')
-rw-r--r--sandbox/cben/rolehack/rolehack.py192
1 files changed, 0 insertions, 192 deletions
diff --git a/sandbox/cben/rolehack/rolehack.py b/sandbox/cben/rolehack/rolehack.py
deleted file mode 100644
index 13895caa5..000000000
--- a/sandbox/cben/rolehack/rolehack.py
+++ /dev/null
@@ -1,192 +0,0 @@
-"""Preprocess reStructuredText roles to directives.
-
-This is a stop-gap hack for prototyping new syntaxes for reST, mainly useful
-when you find yourself using directives every 3 lines. In such cases an
-extension to docutils allowing some inline syntax is desired thing and such
-extensions most probably will take the form of new interpretted text roles.
-
-This module allows to easily prototype them by converting given interpretted
-text roles to directives. To make them inline, the uses of the roles are
-replaced with substitutions and all substitution definitions are appeneded at
-the end of the document (hint: use ``replace::`` if you don't want a
-directive).
-
-Since what's useful for inline syntaxes might also be useful outside of
-paragraphs, preprocessing simple directives (only an argument, no options or
-content) into other directives is also supported.
-
-I was too lazy to implement an elaborate command-line interface, so this is
-only a module. You should import it from a python script and call this module
-with specific role->template mappings to do the work.
-
-BUGS
-====
-
-There are too many. Most can't be fixed here, the right thing is to extend
-the docutils parser...
-
-- Backslashes are not interpretted in any way (except that backticks preceded
- by backslashes are won't be treated as start/end of interpretted text).
- This means backslashes are passed to the directive which probably won't stay
- this way if the role is accepted into docutils (only the double-backtick
- literal text syntax behaves this way).
-
- This bug is semi-intentional because it makes LaTeX generation easier...
-
-- Any number of lines is consumed in search for the closing backtick,
- disregarding indentation. The content is pasted into the directive as one
- line with normalized whitespace.
-
-- The width of the substitution references is not equal to the original, so
- you can't use it in tables.
-
-- Long parts of the document without empty lines might cause ``recursion limit
- exceeded`` errors.
-
-- Directives not recognized if preceded by non-whitespace (e.g. in a table).
-
-"""
-
-import re
-
-# Named groups are used to allow simultaneous replacement of all roles.
-
-_re_options = re.IGNORECASE | re.MULTILINE | re.DOTALL | re.VERBOSE
-
-def _role_re(group_name):
- return r'''
- # Start-string:
- (?:^|(?<=\s|[\'"([{<\-/:]))
- `
- (?=\S)
- # Content:
- (?P<%(group_name)s>
- (?:[^`]|\\.)+ # skip escaped chars
- )
- # End-string:
- (?<=\S)
- `
- (?=$|\s|[#\'")\]}>\-/:.,;!?\\])
- ''' % locals()
-
-_default_re = _role_re('_DEFAULT')
-
-def _role2regexp(role):
- """Return regexp for approximate recognition of `role`."""
- prefix_re = _role_re('prefix_' + role)
- postfix_re = _role_re('postfix_' + role)
- return r'''
- :%(role)s:
- %(prefix_re)s
- |
- %(postfix_re)s
- :%(role)s:
- ''' % locals()
-
-def _dir2regexp(dir):
- """Return regexp for approximate recognition of directive `dir`."""
- return r'''
- ^(?P<indent_%(dir)s> [ \t]* ) # record indentation
- \.\. \s+
- (?P<subst_%(dir)s>
- ## (?:|[^|]*|)? # optional substitution
- )
- \s*
- %(dir)s \s* ::
- (?P<argument_%(dir)s>
- [^\n]*
- (?:
- \n
- (?P=indent_%(dir)s) [ \t] # bigger indentation
- [^\n]+
- )*
- )
- ''' % locals()
-
-def process(doc, roles={}, default_role=None, directives={}):
- """Process `doc` replacing given `roles`.
-
- `doc` should be a single string containing the whole document. The
- `roles` dictionary maps from role names to replacement functions that
- should accept the role content and return the directive text, starting
- from the directive name, e.g.::
-
- def repl(text):
- return 'raw:: latex\n\n %s\n' % (text,)
-
- See `template()` for an easy way to create such trivial functions. The
- optional `default_role` argument specifies a replacement for the default
- role.
-
- The `directives` dictionary like `roles` but specifies directive names to
- handle. The directive can have only an argument; substitution definitions
- with these directives are also recognized. Indentation is adjusted
- properly for directives.
-
- """
- re_parts = []
- repls = {}
- if default_role:
- re_parts.append(_default_re)
- repls['_DEFAULT'] = default_role
- for role, repl in roles.items():
- re_parts.append(_role2regexp(role))
- repls['prefix_' + role] = repls['postfix_' + role] = repl
- for dir, repl in directives.items():
- re_parts.append(_dir2regexp(dir))
- repls['argument_' + dir] = repl
- full_re = '\n|'.join(re_parts)
- full_re = re.compile(full_re, _re_options)
-
- after_output = []
- def count(n=0):
- while True:
- yield n
- n += 1
- ids = count()
- def dispatch(match):
- groupname = match.lastgroup
- content = match.group(groupname)
- kind, name = groupname.split('_', 1)
- if kind == 'argument': # substitution
- indent = match.group('indent_' + name)
- subst = match.group('subst_' + name)
- repl = '\n.. %s %s' % (subst, repls[groupname](content))
- return indent + repl.replace('\n', '\n' + indent)
- else: # role
- id = ids.next()
- subst = '|rolehack_%d|' % (id,)
- repl = '.. %s %s' % (subst, repls[groupname](content))
- after_output.append(repl)
- return subst
-
- # Hack: process by chunks separated by blank lines, trying to avoid
- # "recursion limit exceeded" errors.
- empty_line_re = re.compile(r'\n[ \t]*\n')
- output = [full_re.sub(dispatch, chunk)
- for chunk in empty_line_re.split(doc)]
- return '\n\n'.join(output + after_output)
-
-def template(pre, post):
- """Make replacement function for wrapping content with two strings."""
- def repl(text):
- return ''.join((pre, text, post))
- return repl
-
-def main(*args, **kw_args):
- """Simple command-line interface."""
- import sys
- def parse_args(input='-', output='-'):
- if input == '-':
- input = sys.stdin
- else:
- input = file(input)
- if output == '-':
- output = sys.stdout
- else:
- output = file(output, 'w')
- output.write(process(input.read(), *args, **kw_args))
- parse_args(*sys.argv[1:])
-
-##main({'foo': template('foo::\n\n ', '\n')},
-## template('default::\n\n ', '\n'))