diff options
author | wiemann <wiemann@929543f6-e4f2-0310-98a6-ba3bd3dd1d04> | 2006-01-09 20:44:25 +0000 |
---|---|---|
committer | wiemann <wiemann@929543f6-e4f2-0310-98a6-ba3bd3dd1d04> | 2006-01-09 20:44:25 +0000 |
commit | d77fdfef70e08114f57cbef5d91707df8717ea9f (patch) | |
tree | 49444e3486c0c333cb7b33dfa721296c08ee4ece /sandbox/fwiemann/plugins/interface.py | |
parent | 53cd16ca6ca5f638cbe5956988e88f9339e355cf (diff) | |
parent | 3993c4097756e9885bcfbd07cb1cc1e4e95e50e4 (diff) | |
download | docutils-0.4.tar.gz |
Release 0.4: tagging released revisiondocutils-0.4
git-svn-id: http://svn.code.sf.net/p/docutils/code/tags/docutils-0.4@4268 929543f6-e4f2-0310-98a6-ba3bd3dd1d04
Diffstat (limited to 'sandbox/fwiemann/plugins/interface.py')
-rw-r--r-- | sandbox/fwiemann/plugins/interface.py | 256 |
1 files changed, 0 insertions, 256 deletions
diff --git a/sandbox/fwiemann/plugins/interface.py b/sandbox/fwiemann/plugins/interface.py deleted file mode 100644 index 17e5d0a71..000000000 --- a/sandbox/fwiemann/plugins/interface.py +++ /dev/null @@ -1,256 +0,0 @@ -""" -Designing the urgently-needed plugin support... - -This module doesn't work, it's just there for showing the design, from -a plugin's point of view. (Kind of test-first. The required -interfaces will be implemented in Docutils later.) - -Let's implement an extension for rendering keys: - -reST source: - :key:`Ctrl+C` -Node tree: - <KeyNode> - Ctrl - + - <KeyNode> - C -HTML rendering: - <html><body><span style="border: 1px solid black;">Ctrl</span>+<span style="border: 1px solid black;">C</span></body></html> - -That isn't a particularly challenging task, but it's probably best to -stick to something simple first. (Later we could try to make a plugin -out of a math patch, but that will to require more code.) - -Things not (yet) covered here: - -* Adding a Component (this may require a generic frontend). -* Adding a directive (will require more complicated code than for - roles, because of arguments and options). -* Extending the parser by modifying a parser instance. (Do we *want* - to support that? It's powerful, but a little bit hackish.) -* Adding a transform. (Do we need that?) -* Writing a test case for an extension. -""" - - -class KeyNode(nodes.Inline, nodes.TextElement): - - """ - This is the node which stores the key texts (like "Ctrl" or "C"). - """ - - def __init__(self, key): - self += nodes.Text(key, key) - - -def html_visit_keynode(visitor, node): - """ - This is a visit_ method which looks like any normal Visitor - method. - - It is referenced from the writer support class below. - """ - if visitor.settings['key_html_tt']: - # Now insert a string into the writer's data stream. There is - # visitor.body.append(...) for the HTML visitor, but why not - # just return the string? That's much easier. The visitor - # should know where to put it. - return visitor.starttag('tt', - style='border: 1px solid black', - CLASS='key') - else: - return visitor.starttag('span', - style='border: 1px solid black', - CLASS='key') - -def html_depart_keynode(visitor, node): - """ - Now this is the depart method. - """ - if visitor.settings['key_html_tt']: - return '</tt>' - else: - return '</span>' - - -class KeyNodeHTMLSupport(docutils.WriterExtension): - - """ - This class describes HTML writer handling for the KeyNode, i.e. it - provides visit_ and depart_ methods. (By the way, is there any - term for visit_/depart_ methods?) - """ - - extends = 'html4css1' - """The writer this extension extends.""" - - handlers = {'KeyNode': (html_visit_keynode, html_depart_keynode)} - """ - Dictionary mapping node names to pairs of visit and departure - functions. - """ - - name = 'DefaultKeyHTMLSupport' - """ - Name of this extension. - - This is needed when there are several extensions proving support - for the same node, because in this case the user would have to - specify the name of the preferred extension (probably using an - option). - - For convenience, maybe we shouldn't require setting a name - attribute and have a default name of 'default' (or - self.__class__?). - """ - - settings_spec = (('Render key buttons in <tt> tags in HTML.', - ['--key-html-tt'], - {'default': 0, 'action': 'store_true'}), - ('Render key buttons in <span> tags in HTML.', - ['--key-html-span'], - {'dest': 'key_html_tt', 'action': 'store_false'},)) - """ - Sequence of settings. - """ - - -class KeyNodeLaTeXSupport(docutils.WriterExtension): - - """Support for the LaTeX writer. See KeyNodeHTMLSupport.""" - - extends = 'latex2e' - - handlers = {'KeyNode': ('\\fbox{', '}')} - """ - Here we have strings instead of functions. They are simply - inserted into the data stream; the visitor should know how to do - this. - - This is shorter and simpler than using lambdas, e.g. ``(lambda: - '\\fbox{', lambda: '}')``. - """ - - name = 'DefaultKeyLaTeXSupport' - - -class KeyRole(docutils.ParserExtension): - - """ - This is the role implementation for the reST parser. - - It is only registered at the parser if the parser requests it. - - The reST parser, for example, issues a request when it encounters - ".. require:: something". The request procedure might look like - this: - - Let's say the reST parser encounters a ".. require:: key". Then - it calls docutils.register_extension_by_id(self, 'key'). The - register function determines that the first parameter (self) is a - component instance of type Parser (so it only considers - ParserExtensions) and that its name is 'restructuredtext' (so it - only considers extensions whose `extends` attribute is - 'restructuredtext'). - - For all matching extensions, the register function then looks at - the `id` attribute. If the second parameter ('key' in this - example) matches `id`, the extension is registered at the - component instance passed as first parameter. - """ - - extends = 'restructuredtext' - """The component this extension extends.""" - - id = 'key' - """ - The id under which this extension is known. - - In this case, it's used for ".. require:: key" in reST. - - The presence of an `id` attribute means that the extension isn't - loaded automatically but only on request. (Is that too much - magic?) - """ - - type = 'role' - """ - The type of this extension. - - Might also be 'directive', for example. This attribute is read by - the reST parser. - """ - - # The rest of this class definition is specific to reST roles: - - role_name = 'key' - """ - Name of this role. - - This means we can write :key:`Ctrl+C`. - - There is no i18n support yet, because using a dictionary like - {'en': 'key'} seems a little bit too complex (since translations - usually aren't necessary) and the current i18n system needs a - redesign anyway. - """ - - raw = 1 - """ - If we pass pre-parsed contents to the role as proposed in - <http://article.gmane.org/gmane.text.docutils.user/1727>, we need - this ``raw`` attribute for the following purpose: - - The run() method wants to get a raw string, so we set raw to 1. - (Backslashes aren't interpreted then, but that isn't important in - the case of our key role.) - - If ``raw`` were 0, the run() method would get a list with one - Text node. Backslashes would be interpreted, and if there - were nested-inline-markup support, the list might contain any - Inline elements. - - If the role handler processes the role contents itself as proposed - in <http://article.gmane.org/gmane.text.docutils.user/1729>, we - don't need the ``raw`` attribute. - """ - - def run(self, contents): - """ - For the source text ":key:`Ctrl+C`", this method is called as - keyrole_instance.run('Ctrl+C'). - - lineno, inliner etc. aren't passed as parameters but they can - be grabbed from instance variables if needed (like - self.lineno). This avoids long useless copy'n'paste parameter - lists. - - Return value is a tuple of a node list and a system-message - list. - """ - - if (not contents or - contents.startswith('+') or contents.endswith('+') - or ' ' in contents): - # Not a valid key combination. - # Now we want to throw an error, but that isn't easy. - # Theoretically, we could do: - #msg = self.inliner.reporter.error( - # 'Invalid key string: %s' % contents, lineno=self.lineno) - #prb = self.inliner.problematic(contents, contents, msg) - #return [prb], [msg] - # But this causes a lot of redundancy, given that it's - # such a common case. It would be better to have a - # shortcut like this instead: - raise self.parser.RoleError('Invalid key string') - # which does the same as the three lines above. - - # Now comes our highly sophisticated key combination parsing - # algorithm. - keys = contents.split('+') - nodes = [KeyNode(keys[0])] - for i in keys[1:]: - nodes.append(nodes.Text('+')) - nodes.append(KeyNode(i)) - return [nodes], [] |