summaryrefslogtreecommitdiff
path: root/sandbox/fwiemann/plugins/interface.py
diff options
context:
space:
mode:
Diffstat (limited to 'sandbox/fwiemann/plugins/interface.py')
-rw-r--r--sandbox/fwiemann/plugins/interface.py256
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], []