Add make_refnode() utility function.

This commit is contained in:
Georg Brandl 2009-07-13 18:27:34 +02:00
parent d4f957da8c
commit db8395f9e1
3 changed files with 58 additions and 69 deletions

View File

@ -15,6 +15,7 @@ import re
from sphinx import addnodes
from sphinx.roles import XRefRole
from sphinx.directives import DescDirective
from sphinx.util import make_refnode
class Domain(object):
@ -50,7 +51,7 @@ class Domain(object):
inliner, options, content)
self._role_cache[name] = role_adapter
return role_adapter
def directive(self, name):
"""
Return a directive adapter class that always gives the registered
@ -384,8 +385,10 @@ class PythonDomain(Domain):
}
def find_desc(self, env, modname, classname, name, type, searchorder=0):
"""Find a description node matching "name", perhaps using
the given module and/or classname."""
"""
Find a Python object description for "name", perhaps using the given
module and/or classname.
"""
# skip parens
if name[-2:] == '()':
name = name[:-2]
@ -393,14 +396,6 @@ class PythonDomain(Domain):
if not name:
return None, None
# don't add module and class names for C things
if type[0] == 'c' and type not in ('class', 'const'):
# skip trailing star and whitespace
name = name.rstrip(' *')
if name in env.descrefs and env.descrefs[name][1][0] == 'c':
return name, env.descrefs[name]
return None, None
newname = None
if searchorder == 1:
if modname and classname and \
@ -432,28 +427,22 @@ class PythonDomain(Domain):
def resolve_xref(self, env, fromdocname, builder,
typ, target, node, contnode):
if typ == 'mod' or \
typ == 'obj' and target in env.modules:
if (typ == 'mod' or
typ == 'obj' and target in env.modules):
docname, synopsis, platform, deprecated = \
env.modules.get(target, ('','','', ''))
if not docname:
newnode = builder.app.emit_firstresult(
'missing-reference', env, node, contnode)
if not newnode:
newnode = contnode
return None
elif docname == fromdocname:
# don't link to self
newnode = contnode
return contnode
else:
newnode = nodes.reference('', '')
newnode['refuri'] = builder.get_relative_uri(
fromdocname, docname) + '#module-' + target
newnode['reftitle'] = '%s%s%s' % (
(platform and '(%s) ' % platform),
synopsis, (deprecated and ' (deprecated)' or ''))
newnode.append(contnode)
elif typ in env.descroles:
title = '%s%s%s' % ((platform and '(%s) ' % platform),
synopsis,
(deprecated and ' (deprecated)' or ''))
return make_refnode(builder, fromdocname, docname,
'module-' + target, contnode, title)
else:
# "descrefs"
modname = node['modname']
clsname = node['classname']
@ -461,20 +450,10 @@ class PythonDomain(Domain):
name, desc = self.find_desc(env, modname, clsname,
target, typ, searchorder)
if not desc:
newnode = builder.app.emit_firstresult(
'missing-reference', env, node, contnode)
if not newnode:
newnode = contnode
return None
else:
newnode = nodes.reference('', '')
if desc[0] == fromdocname:
newnode['refid'] = name
else:
newnode['refuri'] = (
builder.get_relative_uri(fromdocname, desc[0])
+ '#' + name)
newnode['reftitle'] = name
newnode.append(contnode)
return make_refnode(builder, fromdocname, desc[0], name,
contnode, name)
@ -620,6 +599,16 @@ class CDomain(Domain):
'type': XRefRole(),
}
def resolve_xref(self, env, fromdocname, builder,
typ, target, node, contnode):
# strip pointer asterisk
target = target.rstrip(' *')
# XXX descrefs
if target not in env.descrefs:
return None
desc = env.descrefs[target]
return make_refnode(builder, fromdocname, desc[0], contnode, target)
# this contains all registered domains
all_domains = {

View File

@ -43,7 +43,7 @@ from docutils.transforms.parts import ContentsFilter
from sphinx import addnodes
from sphinx.util import movefile, get_matching_docs, SEP, ustrftime, \
docname_join, FilenameUniqDict, url_re
docname_join, FilenameUniqDict, url_re, make_refnode
from sphinx.errors import SphinxError
from sphinx.directives import additional_xref_types
@ -1199,10 +1199,6 @@ class BuildEnvironment:
docname, refnode['refuri']) + refnode['anchorname']
return newnode
descroles = frozenset(('data', 'exc', 'func', 'class', 'const',
'attr', 'obj', 'meth', 'cfunc', 'cmember',
'cdata', 'ctype', 'cmacro'))
def resolve_references(self, doctree, fromdocname, builder):
# XXX remove this
reftarget_roles = set(('token', 'term', 'citation'))
@ -1218,7 +1214,7 @@ class BuildEnvironment:
try:
if node.has_key('refdomain'):
# let the domain resolve the reference
# let the domain try to resolve the reference
try:
domain = builder.app.domains[node['refdomain']]
except KeyError:
@ -1290,13 +1286,8 @@ class BuildEnvironment:
#self.warn(fromdocname, 'unknown keyword: %s' % target)
newnode = contnode
else:
newnode = nodes.reference('', '')
if docname == fromdocname:
newnode['refid'] = labelid
else:
newnode['refuri'] = builder.get_relative_uri(
fromdocname, docname) + '#' + labelid
newnode.append(contnode)
newnode = make_refnode(builder, fromdocname, docname,
labelid, contnode)
elif typ == 'option':
progname = node['refprogram']
docname, labelid = self.progoptions.get((progname, target),
@ -1304,13 +1295,8 @@ class BuildEnvironment:
if not docname:
newnode = contnode
else:
newnode = nodes.reference('', '')
if docname == fromdocname:
newnode['refid'] = labelid
else:
newnode['refuri'] = builder.get_relative_uri(
fromdocname, docname) + '#' + labelid
newnode.append(contnode)
newnode = make_refnode(builder, fromdocname, docname,
labelid, contnode)
elif typ in reftarget_roles:
docname, labelid = self.reftargets.get((typ, target),
('', ''))
@ -1325,20 +1311,19 @@ class BuildEnvironment:
node.line)
newnode = contnode
else:
newnode = nodes.reference('', '')
if docname == fromdocname:
newnode['refid'] = labelid
else:
newnode['refuri'] = builder.get_relative_uri(
fromdocname, docname, typ) + '#' + labelid
newnode.append(contnode)
newnode = make_refnode(builder, fromdocname, docname,
labelid, contnode)
else:
raise RuntimeError('unknown xfileref node encountered: %s'
% node)
# no new node found? try the missing-reference event
if newnode is None:
newnode = builder.app.emit_firstresult(
'missing-reference', env, node, contnode)
except NoUri:
newnode = contnode
if newnode:
node.replace_self(newnode)
node.replace_self(newnode or contnode)
for node in doctree.traverse(addnodes.only):
try:

View File

@ -435,6 +435,21 @@ def split_explicit_title(text):
else:
return False, text, text
def make_refnode(builder, fromdocname, todocname, targetid, child, title=None):
"""Shortcut to create a reference node."""
node = nodes.reference('', '')
if fromdocname == todocname:
node['refid'] = targetid
else:
node['refuri'] = (builder.get_relative_uri(fromdocname, todocname)
+ '#' + targetid)
if title:
node['reftitle'] = title
node.append(child)
return node
# monkey-patch Node.traverse to get more speed
# traverse() is called so many times during a build that it saves
# on average 20-25% overall build time!