merge with 1.0

This commit is contained in:
Georg Brandl 2011-01-15 15:47:36 +01:00
commit bb7bf21c7e
18 changed files with 103 additions and 77 deletions

11
CHANGES
View File

@ -109,6 +109,15 @@ Release 1.1 (in development)
Release 1.0.7 (in development) Release 1.0.7 (in development)
============================== ==============================
* #347: Fix wrong generation of directives of static methods in
autosummary.
* #599: Import PIL as ``from PIL import Image``.
* #558: Fix longtables with captions in LaTeX output.
* Make token references work as hyperlinks again in LaTeX output.
* #572: Show warnings by default when reference labels cannot be * #572: Show warnings by default when reference labels cannot be
found. found.
@ -150,6 +159,8 @@ Release 1.0.7 (in development)
* Fix tracebacks occurring for duplicate C++ domain objects. * Fix tracebacks occurring for duplicate C++ domain objects.
* Fix JavaScript domain links to objects with ``$`` in their name.
Release 1.0.6 (Jan 04, 2011) Release 1.0.6 (Jan 04, 2011)
============================ ============================

View File

@ -27,6 +27,7 @@ Documentation using the default theme
* Google Wave API: http://wave-robot-python-client.googlecode.com/svn/trunk/pydocs/index.html * Google Wave API: http://wave-robot-python-client.googlecode.com/svn/trunk/pydocs/index.html
* GSL Shell: http://www.nongnu.org/gsl-shell/ * GSL Shell: http://www.nongnu.org/gsl-shell/
* Heapkeeper: http://heapkeeper.org/ * Heapkeeper: http://heapkeeper.org/
* Hands-on Python Tutorial: http://anh.cs.luc.edu/python/hands-on/3.1/handsonHtml/
* Hedge: http://documen.tician.de/hedge/ * Hedge: http://documen.tician.de/hedge/
* Kaa: http://doc.freevo.org/api/kaa/ * Kaa: http://doc.freevo.org/api/kaa/
* Leo: http://webpages.charter.net/edreamleo/front.html * Leo: http://webpages.charter.net/edreamleo/front.html
@ -79,6 +80,7 @@ Documentation using a customized version of the default theme
* simuPOP: http://simupop.sourceforge.net/manual_release/build/userGuide.html * simuPOP: http://simupop.sourceforge.net/manual_release/build/userGuide.html
* Sprox: http://sprox.org/ * Sprox: http://sprox.org/
* TurboGears: http://turbogears.org/2.0/docs/ * TurboGears: http://turbogears.org/2.0/docs/
* Zentyal: http://doc.zentyal.org/
* Zope: http://docs.zope.org/zope2/index.html * Zope: http://docs.zope.org/zope2/index.html
* zc.async: http://packages.python.org/zc.async/1.5.0/ * zc.async: http://packages.python.org/zc.async/1.5.0/
@ -140,6 +142,7 @@ Documentation using a custom theme/integrated in a site
* Open ERP: http://doc.openerp.com/ * Open ERP: http://doc.openerp.com/
* OpenLayers: http://docs.openlayers.org/ * OpenLayers: http://docs.openlayers.org/
* PyEphem: http://rhodesmill.org/pyephem/ * PyEphem: http://rhodesmill.org/pyephem/
* German Plone 4.0 user manual: http://www.hasecke.com/plone-benutzerhandbuch/4.0/
* Pylons: http://pylonshq.com/docs/en/0.9.7/ * Pylons: http://pylonshq.com/docs/en/0.9.7/
* PyMOTW: http://www.doughellmann.com/PyMOTW/ * PyMOTW: http://www.doughellmann.com/PyMOTW/
* qooxdoo: http://manual.qooxdoo.org/current * qooxdoo: http://manual.qooxdoo.org/current
@ -167,6 +170,13 @@ Homepages and other non-documentation sites
Books produced using Sphinx Books produced using Sphinx
--------------------------- ---------------------------
* The ``repoze.bfg`` Web Application Framework: * "The ``repoze.bfg`` Web Application Framework":
http://www.amazon.com/repoze-bfg-Web-Application-Framework-Version/dp/0615345379 http://www.amazon.com/repoze-bfg-Web-Application-Framework-Version/dp/0615345379
* A Theoretical Physics Reference book: http://theoretical-physics.net/ * A Theoretical Physics Reference book: http://theoretical-physics.net/
* "Simple and Steady Way of Learning for Software Engineering" (in Japanese):
http://www.amazon.co.jp/dp/477414259X/
* "Expert Python Programming" (Japanese translation):
http://www.amazon.co.jp/dp/4048686291/
* "Pomodoro Technique Illustrated" (Japanese translation):
http://www.amazon.co.jp/dp/4048689525/

View File

@ -377,6 +377,7 @@ documentation on :ref:`intl` for details.
* ``fr`` -- French * ``fr`` -- French
* ``hr`` -- Croatian * ``hr`` -- Croatian
* ``it`` -- Italian * ``it`` -- Italian
* ``ja`` -- Japanese
* ``lt`` -- Lithuanian * ``lt`` -- Lithuanian
* ``nl`` -- Dutch * ``nl`` -- Dutch
* ``pl`` -- Polish * ``pl`` -- Polish

View File

@ -179,7 +179,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
name = name.replace('<', '&lt;') name = name.replace('<', '&lt;')
name = name.replace('>', '&gt;') name = name.replace('>', '&gt;')
name = name.replace('"', '&quot;') name = name.replace('"', '&quot;')
name = name.replace('\'', '&apos;') name = name.replace('\'', '&#39;')
return name return name
def get_refnodes(self, doctree, result): def get_refnodes(self, doctree, result):
@ -408,6 +408,14 @@ class EpubBuilder(StandaloneHTMLBuilder):
spine.append(_spine_template % { spine.append(_spine_template % {
'idref': self.esc(self.make_id(item['refuri'])) 'idref': self.esc(self.make_id(item['refuri']))
}) })
for info in self.domain_indices:
spine.append(_spine_template % {
'idref': self.esc(self.make_id(info[0] + self.out_suffix))
})
if self.config.html_use_index:
spine.append(_spine_template % {
'idref': self.esc(self.make_id('genindex' + self.out_suffix))
})
# add the optional cover # add the optional cover
content_tmpl = _content_template content_tmpl = _content_template

View File

@ -46,10 +46,6 @@ class LaTeXBuilder(Builder):
return 'all documents' # for now return 'all documents' # for now
def get_target_uri(self, docname, typ=None): def get_target_uri(self, docname, typ=None):
if typ == 'token':
# token references are always inside production lists and must be
# replaced by \token{} in LaTeX
return '@token'
if docname not in self.docnames: if docname not in self.docnames:
raise NoUri raise NoUri
else: else:

View File

@ -96,7 +96,8 @@ class JSObject(ObjectDescription):
indextext = self.get_index_text(objectname, name_obj) indextext = self.get_index_text(objectname, name_obj)
if indextext: if indextext:
self.indexnode['entries'].append(('single', indextext, self.indexnode['entries'].append(('single', indextext,
fullname, '')) fullname.replace('$', '_S_'),
''))
def get_index_text(self, objectname, name_obj): def get_index_text(self, objectname, name_obj):
name, obj = name_obj name, obj = name_obj
@ -208,8 +209,10 @@ class JavaScriptDomain(Domain):
name, obj = self.find_obj(env, objectname, target, typ, searchorder) name, obj = self.find_obj(env, objectname, target, typ, searchorder)
if not obj: if not obj:
return None return None
return make_refnode(builder, fromdocname, obj[0], name, contnode, name) return make_refnode(builder, fromdocname, obj[0],
name.replace('$', '_S_'), contnode, name)
def get_objects(self): def get_objects(self):
for refname, (docname, type) in self.data['objects'].iteritems(): for refname, (docname, type) in self.data['objects'].iteritems():
yield refname, refname, type, docname, refname, 1 yield refname, refname, type, docname, \
refname.replace('$', '_S_'), 1

View File

@ -133,27 +133,19 @@ except AttributeError:
return False return False
isgetsetdescriptor = ismemberdescriptor isgetsetdescriptor = ismemberdescriptor
def get_documenter(obj): def get_documenter(obj, parent):
"""Get an autodoc.Documenter class suitable for documenting the given """Get an autodoc.Documenter class suitable for documenting the given
object. object.
""" """
import sphinx.ext.autodoc as autodoc from sphinx.ext.autodoc import AutoDirective, DataDocumenter
if inspect.isclass(obj): classes = [cls for cls in AutoDirective._registry.values()
if issubclass(obj, Exception): if cls.can_document_member(obj, '', False, parent)]
return autodoc.ExceptionDocumenter if classes:
return autodoc.ClassDocumenter classes.sort(key=lambda cls: cls.priority)
elif inspect.ismodule(obj): return classes[-1]
return autodoc.ModuleDocumenter
elif inspect.ismethod(obj) or inspect.ismethoddescriptor(obj):
return autodoc.MethodDocumenter
elif (ismemberdescriptor(obj) or isgetsetdescriptor(obj)
or inspect.isdatadescriptor(obj)):
return autodoc.AttributeDocumenter
elif inspect.isroutine(obj):
return autodoc.FunctionDocumenter
else: else:
return autodoc.DataDocumenter return DataDocumenter
# -- .. autosummary:: ---------------------------------------------------------- # -- .. autosummary:: ----------------------------------------------------------
@ -238,7 +230,7 @@ class Autosummary(Directive):
display_name = name.split('.')[-1] display_name = name.split('.')[-1]
try: try:
obj, real_name = import_by_name(name, prefixes=prefixes) real_name, obj, parent = import_by_name(name, prefixes=prefixes)
except ImportError: except ImportError:
self.warn('failed to import %s' % name) self.warn('failed to import %s' % name)
items.append((name, '', '', name)) items.append((name, '', '', name))
@ -246,7 +238,7 @@ class Autosummary(Directive):
# NB. using real_name here is important, since Documenters # NB. using real_name here is important, since Documenters
# handle module prefixes slightly differently # handle module prefixes slightly differently
documenter = get_documenter(obj)(self, real_name) documenter = get_documenter(obj, parent)(self, real_name)
if not documenter.parse_name(): if not documenter.parse_name():
self.warn('failed to parse name %s' % real_name) self.warn('failed to parse name %s' % real_name)
items.append((display_name, '', '', real_name)) items.append((display_name, '', '', real_name))
@ -383,7 +375,8 @@ def import_by_name(name, prefixes=[None]):
prefixed_name = '.'.join([prefix, name]) prefixed_name = '.'.join([prefix, name])
else: else:
prefixed_name = name prefixed_name = name
return _import_by_name(prefixed_name), prefixed_name obj, parent = _import_by_name(prefixed_name)
return prefixed_name, obj, parent
except ImportError: except ImportError:
tried.append(prefixed_name) tried.append(prefixed_name)
raise ImportError('no module named %s' % ' or '.join(tried)) raise ImportError('no module named %s' % ' or '.join(tried))
@ -398,7 +391,8 @@ def _import_by_name(name):
if modname: if modname:
try: try:
__import__(modname) __import__(modname)
return getattr(sys.modules[modname], name_parts[-1]) mod = sys.modules[modname]
return getattr(mod, name_parts[-1]), mod
except (ImportError, IndexError, AttributeError): except (ImportError, IndexError, AttributeError):
pass pass
@ -416,12 +410,14 @@ def _import_by_name(name):
break break
if last_j < len(name_parts): if last_j < len(name_parts):
parent = None
obj = sys.modules[modname] obj = sys.modules[modname]
for obj_name in name_parts[last_j:]: for obj_name in name_parts[last_j:]:
parent = obj
obj = getattr(obj, obj_name) obj = getattr(obj, obj_name)
return obj return obj, parent
else: else:
return sys.modules[modname] return sys.modules[modname], None
except (ValueError, ImportError, AttributeError, KeyError), e: except (ValueError, ImportError, AttributeError, KeyError), e:
raise ImportError(*e.args) raise ImportError(*e.args)
@ -443,7 +439,7 @@ def autolink_role(typ, rawtext, etext, lineno, inliner,
prefixes = [None] prefixes = [None]
#prefixes.insert(0, inliner.document.settings.env.currmodule) #prefixes.insert(0, inliner.document.settings.env.currmodule)
try: try:
obj, name = import_by_name(pnode['reftarget'], prefixes) name, obj, parent = import_by_name(pnode['reftarget'], prefixes)
except ImportError: except ImportError:
content = pnode[0] content = pnode[0]
r[0][0] = nodes.emphasis(rawtext, content[0].astext(), r[0][0] = nodes.emphasis(rawtext, content[0].astext(),

View File

@ -108,7 +108,7 @@ def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
ensuredir(path) ensuredir(path)
try: try:
obj, name = import_by_name(name) name, obj, parent = import_by_name(name)
except ImportError, e: except ImportError, e:
warn('[autosummary] failed to import %r: %s' % (name, e)) warn('[autosummary] failed to import %r: %s' % (name, e))
continue continue
@ -124,7 +124,7 @@ def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
f = open(fn, 'w') f = open(fn, 'w')
try: try:
doc = get_documenter(obj) doc = get_documenter(obj, parent)
if template_name is not None: if template_name is not None:
template = template_env.get_template(template_name) template = template_env.get_template(template_name)
@ -138,7 +138,7 @@ def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
def get_members(obj, typ, include_public=[]): def get_members(obj, typ, include_public=[]):
items = [ items = [
name for name in dir(obj) name for name in dir(obj)
if get_documenter(getattr(obj, name)).objtype == typ if get_documenter(getattr(obj, name), obj).objtype == typ
] ]
public = [x for x in items public = [x for x in items
if x in include_public or not x.startswith('_')] if x in include_public or not x.startswith('_')]
@ -212,7 +212,7 @@ def find_autosummary_in_docstring(name, module=None, filename=None):
See `find_autosummary_in_lines`. See `find_autosummary_in_lines`.
""" """
try: try:
obj, real_name = import_by_name(name) real_name, obj, parent = import_by_name(name)
lines = pydoc.getdoc(obj).splitlines() lines = pydoc.getdoc(obj).splitlines()
return find_autosummary_in_lines(lines, module=name, filename=filename) return find_autosummary_in_lines(lines, module=name, filename=filename)
except AttributeError: except AttributeError:

View File

@ -85,7 +85,7 @@ class InheritanceGraph(object):
"""Import a class using its fully-qualified *name*.""" """Import a class using its fully-qualified *name*."""
try: try:
path, base = class_sig_re.match(name).groups() path, base = class_sig_re.match(name).groups()
except ValueError: except (AttributeError, ValueError):
raise InheritanceException('Invalid class or module %r specified ' raise InheritanceException('Invalid class or module %r specified '
'for inheritance diagram' % name) 'for inheritance diagram' % name)

View File

@ -71,7 +71,8 @@ class MathDirective(Directive):
node['docname'] = self.state.document.settings.env.docname node['docname'] = self.state.document.settings.env.docname
ret = [node] ret = [node]
node.line = self.lineno node.line = self.lineno
node.source = self.src if hasattr(self, 'src'):
node.source = self.src
if node['label']: if node['label']:
tnode = nodes.target('', '', ids=['equation-' + node['label']]) tnode = nodes.target('', '', ids=['equation-' + node['label']])
self.state.document.note_explicit_target(tnode) self.state.document.note_explicit_target(tnode)

View File

@ -41,6 +41,15 @@ def accesskey(context, key):
return 'accesskey="%s"' % key return 'accesskey="%s"' % key
return '' return ''
class idgen(object):
def __init__(self):
self.id = 0
def current(self):
return self.id
def next(self):
self.id += 1
return self.id
class SphinxFileSystemLoader(FileSystemLoader): class SphinxFileSystemLoader(FileSystemLoader):
""" """
@ -109,6 +118,7 @@ class BuiltinTemplateLoader(TemplateBridge, BaseLoader):
self.environment.filters['toint'] = _toint self.environment.filters['toint'] = _toint
self.environment.globals['debug'] = contextfunction(pformat) self.environment.globals['debug'] = contextfunction(pformat)
self.environment.globals['accesskey'] = contextfunction(accesskey) self.environment.globals['accesskey'] = contextfunction(accesskey)
self.environment.globals['idgen'] = idgen
if use_i18n: if use_i18n:
self.environment.install_gettext_translations( self.environment.install_gettext_translations(
builder.app.translator) builder.app.translator)

View File

@ -220,21 +220,12 @@
\addtolength{\py@argswidth}{\linewidth}% \addtolength{\py@argswidth}{\linewidth}%
\item[#1\code{(}\py@sigparams{#2}{#3}]} \item[#1\code{(}\py@sigparams{#2}{#3}]}
% This version is being checked in for the historical record; it shows % Production lists
% how I've managed to get some aspects of this to work. It will not
% be used in practice, so a subsequent revision will change things
% again. This version has problems, but shows how to do something
% that proved more tedious than I'd expected, so I don't want to lose
% the example completely.
% %
\newcommand{\grammartoken}[1]{\texttt{#1}} \newenvironment{productionlist}{
\newenvironment{productionlist}[1][\@undefined]{ % \def\optional##1{{\Large[}##1{\Large]}}
\def\optional##1{{\Large[}##1{\Large]}} \def\production##1##2{\\\code{##1}&::=&\code{##2}}
\def\production##1##2{\hypertarget{grammar-token-##1}{}% \def\productioncont##1{\\& &\code{##1}}
\code{##1}&::=&\code{##2}\\}
\def\productioncont##1{& &\code{##1}\\}
\def\token##1{##1}
\let\grammartoken=\token
\parindent=2em \parindent=2em
\indent \indent
\begin{tabular}{lcl} \begin{tabular}{lcl}

View File

@ -19,7 +19,7 @@
{% endblock %} {% endblock %}
{% block body %} {% block body %}
{%- set curr_group = 0 %} {%- set groupid = idgen() %}
<h1>{{ indextitle }}</h1> <h1>{{ indextitle }}</h1>
@ -33,15 +33,14 @@
<table class="indextable modindextable" cellspacing="0" cellpadding="2"> <table class="indextable modindextable" cellspacing="0" cellpadding="2">
{%- for letter, entries in content %} {%- for letter, entries in content %}
<tr class="pcap"><td></td><td>&nbsp;</td><td></td></tr> <tr class="pcap"><td></td><td>&nbsp;</td><td></td></tr>
<tr class="cap"><td></td><td><a name="cap-{{ letter }}"> <tr class="cap" id="cap-{{ letter }}"><td></td><td>
<strong>{{ letter }}</strong></a></td><td></td></tr> <strong>{{ letter }}</strong></td><td></td></tr>
{%- for (name, grouptype, page, anchor, extra, qualifier, description) {%- for (name, grouptype, page, anchor, extra, qualifier, description)
in entries %} in entries %}
{%- if grouptype == 1 %}{% set curr_group = curr_group + 1 %}{% endif %} <tr{% if grouptype == 2 %} class="cg-{{ groupid.current() }}"{% endif %}>
<tr{% if grouptype == 2 %} class="cg-{{ curr_group }}"{% endif %}>
<td>{% if grouptype == 1 -%} <td>{% if grouptype == 1 -%}
<img src="{{ pathto('_static/minus.png', 1) }}" id="toggle-{{ curr_group }}" <img src="{{ pathto('_static/minus.png', 1) }}" class="toggler"
class="toggler" style="display: none" alt="-" /> id="toggle-{{ groupid.next() }}" style="display: none" alt="-" />
{%- endif %}</td> {%- endif %}</td>
<td>{% if grouptype == 2 %}&nbsp;&nbsp;&nbsp;{% endif %} <td>{% if grouptype == 2 %}&nbsp;&nbsp;&nbsp;{% endif %}
{% if page %}<a href="{{ pathto(page) }}#{{ anchor }}">{% endif -%} {% if page %}<a href="{{ pathto(page) }}#{{ anchor }}">{% endif -%}

View File

@ -34,9 +34,9 @@
<h1 id="index">{% trans key=key %}Index &ndash; {{ key }}{% endtrans %}</h1> <h1 id="index">{% trans key=key %}Index &ndash; {{ key }}{% endtrans %}</h1>
<table width="100%" class="indextable"><tr> <table style="width: 100%" class="indextable"><tr>
{%- for column in entries|slice(2) if column %} {%- for column in entries|slice(2) if column %}
<td width="33%" valign="top"><dl> <td style="width: 33%" valign="top"><dl>
{%- for entryname, (links, subitems) in column %} {%- for entryname, (links, subitems) in column %}
{{ indexentries(entryname, links) }} {{ indexentries(entryname, links) }}
{%- if subitems %} {%- if subitems %}

View File

@ -43,9 +43,9 @@
{%- for key, entries in genindexentries %} {%- for key, entries in genindexentries %}
<h2 id="{{ key }}">{{ key }}</h2> <h2 id="{{ key }}">{{ key }}</h2>
<table width="100%" class="indextable genindextable"><tr> <table style="width: 100%" class="indextable genindextable"><tr>
{%- for column in entries|slice(2) if column %} {%- for column in entries|slice(2) if column %}
<td width="33%" valign="top"><dl> <td style="width: 33%" valign="top"><dl>
{%- for entryname, (links, subitems) in column %} {%- for entryname, (links, subitems) in column %}
{{ indexentries(entryname, links) }} {{ indexentries(entryname, links) }}
{%- if subitems %} {%- if subitems %}

View File

@ -413,7 +413,7 @@ dl.glossary dt {
} }
.footnote:target { .footnote:target {
background-color: #ffa background-color: #ffa;
} }
.line-block { .line-block {

View File

@ -21,7 +21,7 @@ from sphinx.locale import admonitionlabels, versionlabels, _
from sphinx.util.smartypants import sphinx_smarty_pants from sphinx.util.smartypants import sphinx_smarty_pants
try: try:
import Image # check for the Python Imaging Library from PIL import Image # check for the Python Imaging Library
except ImportError: except ImportError:
Image = None Image = None
@ -249,6 +249,12 @@ class HTMLTranslator(BaseTranslator):
def visit_doctest_block(self, node): def visit_doctest_block(self, node):
self.visit_literal_block(node) self.visit_literal_block(node)
# overwritten to add the <div> (for XHTML compliance)
def visit_block_quote(self, node):
self.body.append(self.starttag(node, 'blockquote') + '<div>')
def depart_block_quote(self, node):
self.body.append('</div></blockquote>\n')
# overwritten # overwritten
def visit_literal(self, node): def visit_literal(self, node):
self.body.append(self.starttag(node, 'tt', '', self.body.append(self.starttag(node, 'tt', '',

View File

@ -267,10 +267,10 @@ class LaTeXTranslator(nodes.NodeVisitor):
'\\label{%s}' % self.idescape(id) '\\label{%s}' % self.idescape(id)
def hyperlink(self, id): def hyperlink(self, id):
return '{\\hyperref[%s]{' % (self.idescape(id)) return '{\\hyperref[%s]{' % self.idescape(id)
def hyperpageref(self, id): def hyperpageref(self, id):
return '\\autopageref*{%s}' % (self.idescape(id)) return '\\autopageref*{%s}' % self.idescape(id)
def idescape(self, id): def idescape(self, id):
return str(unicode(id).translate(tex_replace_map)) return str(unicode(id).translate(tex_replace_map))
@ -423,8 +423,9 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_production(self, node): def visit_production(self, node):
if node['tokenname']: if node['tokenname']:
self.body.append('\\production{%s}{' % tn = node['tokenname']
self.encode(node['tokenname'])) self.body.append(self.hypertarget('grammar-token-' + tn))
self.body.append('\\production{%s}{' % self.encode(tn))
else: else:
self.body.append('\\productioncont{') self.body.append('\\productioncont{')
def depart_production(self, node): def depart_production(self, node):
@ -658,8 +659,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
else: else:
self.body.append('{|' + ('L|' * self.table.colcount) + '}\n') self.body.append('{|' + ('L|' * self.table.colcount) + '}\n')
if self.table.longtable and self.table.caption is not None: if self.table.longtable and self.table.caption is not None:
self.body.append(u'\\capstart\\caption{%s} \\\\\n' % self.body.append(u'\\caption{%s} \\\\\n' % self.table.caption)
self.table.caption)
if self.table.caption is not None: if self.table.caption is not None:
for id in self.next_table_ids: for id in self.next_table_ids:
self.body.append(self.hypertarget(id, anchor=False)) self.body.append(self.hypertarget(id, anchor=False))
@ -1151,12 +1151,6 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.context.append('}} (%s)' % self.hyperpageref(id)) self.context.append('}} (%s)' % self.hyperpageref(id))
else: else:
self.context.append('}}') self.context.append('}}')
elif uri.startswith('@token'):
if self.in_production_list:
self.body.append('\\token{')
else:
self.body.append('\\grammartoken{')
self.context.append('}')
else: else:
self.builder.warn('unusable reference target found: %s' % uri, self.builder.warn('unusable reference target found: %s' % uri,
(self.curfilestack[-1], node.line)) (self.curfilestack[-1], node.line))