# -*- coding: utf-8 -*-
"""
sphinx.roles
~~~~~~~~~~~~
Handlers for additional ReST roles.
:copyright: 2007 by Georg Brandl.
:license: Python license.
"""
import re
from docutils import nodes, utils
from docutils.parsers.rst import roles
from . import addnodes
ws_re = re.compile(r'\s+')
generic_docroles = {
'command' : nodes.strong,
'dfn' : nodes.emphasis,
'file' : nodes.emphasis,
'filenq' : nodes.emphasis,
'filevar' : nodes.emphasis,
'guilabel' : nodes.strong,
'kbd' : nodes.literal,
'keyword' : nodes.literal,
'mailheader' : nodes.emphasis,
'makevar' : nodes.Text,
'manpage' : nodes.emphasis,
'mimetype' : nodes.emphasis,
'newsgroup' : nodes.emphasis,
'option' : nodes.emphasis,
'program' : nodes.strong,
'regexp' : nodes.literal,
}
for rolename, nodeclass in generic_docroles.iteritems():
roles.register_generic_role(rolename, nodeclass)
def indexmarkup_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
env = inliner.document.settings.env
text = utils.unescape(text)
targetid = 'index-%s' % env.index_num
env.index_num += 1
targetnode = nodes.target('', '', ids=[targetid])
inliner.document.note_explicit_target(targetnode)
if typ == 'envvar':
env.note_index_entry('single', '%s' % text,
targetid, text)
env.note_index_entry('single', 'environment variables!%s' % text,
targetid, text)
textnode = nodes.strong(text, text)
return [targetnode, textnode], []
elif typ == 'pep':
env.note_index_entry('single', 'Python Enhancement Proposals!PEP %s' % text,
targetid, 'PEP %s' % text)
try:
pepnum = int(text)
except ValueError:
msg = inliner.reporter.error('invalid PEP number %s' % text, line=lineno)
prb = inliner.problematic(rawtext, rawtext, msg)
return [prb], [msg]
ref = inliner.document.settings.pep_base_url + 'pep-%04d' % pepnum
sn = nodes.strong('PEP '+text, 'PEP '+text)
rn = nodes.reference('', '', refuri=ref)
rn += sn
return [targetnode, rn], []
elif typ == 'rfc':
env.note_index_entry('single', 'RFC!RFC %s' % text,
targetid, 'RFC %s' % text)
try:
rfcnum = int(text)
except ValueError:
msg = inliner.reporter.error('invalid RFC number %s' % text, line=lineno)
prb = inliner.problematic(rawtext, rawtext, msg)
return [prb], [msg]
ref = inliner.document.settings.rfc_base_url + inliner.rfc_url % rfcnum
sn = nodes.strong('RFC '+text, 'RFC '+text)
rn = nodes.reference('', '', refuri=ref)
rn += sn
return [targetnode, rn], []
roles.register_canonical_role('envvar', indexmarkup_role)
roles.register_local_role('pep', indexmarkup_role)
roles.register_local_role('rfc', indexmarkup_role)
# default is `literal`
innernodetypes = {
'ref': nodes.emphasis,
'token': nodes.strong,
}
def xfileref_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
env = inliner.document.settings.env
text = utils.unescape(text)
# 'token' is the default role inside 'productionlist' directives
if typ == '':
typ = 'token'
if env.config.get('strip_trailing_parentheses', False):
if text[-2:] == '()':
text = text[:-2]
pnode = addnodes.pending_xref(rawtext)
pnode['reftype'] = typ
pnode['reftarget'] = ws_re.sub('', text)
pnode['modname'] = env.currmodule
pnode['classname'] = env.currclass
pnode += innernodetypes.get(typ, nodes.literal)(rawtext, text, classes=['xref'])
return [pnode], []
def menusel_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
return [nodes.emphasis(rawtext, text.replace('-->', u'\N{TRIANGULAR BULLET}'))], []
specific_docroles = {
'data': xfileref_role,
'exc': xfileref_role,
'func': xfileref_role,
'class': xfileref_role,
'const': xfileref_role,
'attr': xfileref_role,
'meth': xfileref_role,
'cfunc' : xfileref_role,
'cdata' : xfileref_role,
'ctype' : xfileref_role,
'cmacro' : xfileref_role,
'mod' : xfileref_role,
'ref': xfileref_role,
'token' : xfileref_role,
'menuselection' : menusel_role,
}
for rolename, func in specific_docroles.iteritems():
roles.register_canonical_role(rolename, func)