From f82a4a4eab1b45ccf99a0b8c928553d4a59ab80d Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Tue, 30 Jun 2009 15:16:33 +0100 Subject: [PATCH 1/4] Makefile and .hgignore ignore a virtualenv called "env" in this folder by default now. --- .hgignore | 1 + Makefile | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.hgignore b/.hgignore index f617875e8..dcfd914ed 100644 --- a/.hgignore +++ b/.hgignore @@ -9,3 +9,4 @@ Sphinx.egg-info/ doc/_build/ TAGS \.ropeproject/ +^env/ diff --git a/Makefile b/Makefile index dbe7c36e2..f405fddca 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ all: clean-pyc check test check: @$(PYTHON) utils/check_sources.py -i sphinx/style/jquery.js \ -i sphinx/pycode/pgen2 -i sphinx/util/smartypants.py \ - -i doc/_build -i ez_setup.py -i tests/path.py -i tests/coverage.py . + -i doc/_build -i ez_setup.py -i tests/path.py -i tests/coverage.py -i env . clean: clean-pyc clean-patchfiles From 957be3bfa05d7d524456442f326d82826f7c0b5e Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Tue, 30 Jun 2009 15:16:46 +0100 Subject: [PATCH 2/4] Refactored role registrations. --- sphinx/application.py | 12 +- sphinx/domains.py | 1 + sphinx/roles.py | 263 +++++++++++++++++++++++------------------- 3 files changed, 150 insertions(+), 126 deletions(-) diff --git a/sphinx/application.py b/sphinx/application.py index cfe37745b..9b6cf36f7 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -20,7 +20,7 @@ from docutils import nodes from docutils.parsers.rst import directives, roles import sphinx -from sphinx.roles import xfileref_role, innernodetypes +from sphinx.roles import make_xref_role, simple_link_func from sphinx.config import Config from sphinx.errors import SphinxError, SphinxWarning, ExtensionError from sphinx.domains import domains @@ -310,17 +310,15 @@ class Sphinx(object): parse_node) directives.register_directive(directivename, directive_dwim(GenericDesc)) - roles.register_local_role(rolename, xfileref_role) - if ref_nodeclass is not None: - innernodetypes[rolename] = ref_nodeclass + role_func = make_xref_role(simple_link_func, innernodeclass=ref_nodeclass) + roles.register_local_role(rolename, role_func) def add_crossref_type(self, directivename, rolename, indextemplate='', ref_nodeclass=None): additional_xref_types[directivename] = (rolename, indextemplate, None) directives.register_directive(directivename, directive_dwim(Target)) - roles.register_local_role(rolename, xfileref_role) - if ref_nodeclass is not None: - innernodetypes[rolename] = ref_nodeclass + role_func = make_xref_role(simple_link_func, innernodeclass=ref_nodeclass) + roles.register_local_role(rolename, role_func) def add_transform(self, transform): SphinxStandaloneReader.transforms.append(transform) diff --git a/sphinx/domains.py b/sphinx/domains.py index aab31e236..6845496c5 100644 --- a/sphinx/domains.py +++ b/sphinx/domains.py @@ -13,6 +13,7 @@ class Domain(object): name = '' directives = {} + roles = {} label = '' domains = {} diff --git a/sphinx/roles.py b/sphinx/roles.py index af574b98c..1a587cf26 100644 --- a/sphinx/roles.py +++ b/sphinx/roles.py @@ -94,106 +94,40 @@ roles.register_local_role('pep', indexmarkup_role) roles.register_local_role('rfc', indexmarkup_role) -# default is `literal` -innernodetypes = { - 'ref': nodes.emphasis, - 'term': nodes.emphasis, - 'token': nodes.strong, - 'envvar': nodes.strong, - 'download': nodes.strong, - 'option': addnodes.literal_emphasis, -} +def make_xref_role(link_func, nodeclass=None, innernodeclass=None): + if nodeclass is None: + nodeclass = addnodes.pending_xref + if innernodeclass is None: + innernodeclass = nodes.literal -def _fix_parens(typ, text, env): - if typ in ('func', 'meth', 'cfunc'): - if text.endswith('()'): - # remove parentheses - text = text[:-2] - if env.config.add_function_parentheses: - # add them back to all occurrences if configured - text += '()' - return text + def func(typ, rawtext, text, lineno, inliner, options={}, content=[]): + env = inliner.document.settings.env + if not typ: + typ = env.config.default_role + else: + typ = typ.lower() + text = utils.unescape(text) + # if the first character is a bang, don't cross-reference at all + if text[0:1] == '!': + text = _fix_parens(typ, text[1:], env) + return [innernodeclass(rawtext, text, classes=['xref'])], [] + # we want a cross-reference, create the reference node + pnode = nodeclass(rawtext, reftype=typ, refcaption=False, + modname=env.currmodule, classname=env.currclass) + # we may need the line number for warnings + pnode.line = lineno + target, title = link_func(env, text, pnode) + pnode['reftarget'] = target + pnode += innernodeclass(rawtext, title, classes=['xref']) + return [pnode], [] + return func -def xfileref_role(typ, rawtext, text, lineno, inliner, options={}, content=[]): - env = inliner.document.settings.env - if not typ: - typ = env.config.default_role - else: - typ = typ.lower() - text = utils.unescape(text) - # if the first character is a bang, don't cross-reference at all - if text[0:1] == '!': - text = _fix_parens(typ, text[1:], env) - return [innernodetypes.get(typ, nodes.literal)( - rawtext, text, classes=['xref'])], [] - # we want a cross-reference, create the reference node - nodeclass = (typ == 'download') and addnodes.download_reference or \ - addnodes.pending_xref - pnode = nodeclass(rawtext, reftype=typ, refcaption=False, - modname=env.currmodule, classname=env.currclass) - # we may need the line number for warnings - pnode.line = lineno - # look if explicit title and target are given with `foo ` syntax - has_explicit_title, title, target = split_explicit_title(text) - if has_explicit_title: - pnode['refcaption'] = True - # special target for Python object cross-references - if typ in ('data', 'exc', 'func', 'class', 'const', 'attr', - 'meth', 'mod', 'obj'): - # fix-up parentheses in link title - if not has_explicit_title: - title = title.lstrip('.') # only has a meaning for the target - target = target.lstrip('~') # only has a meaning for the title - title = _fix_parens(typ, title, env) - # if the first character is a tilde, don't display the module/class - # parts of the contents - if title[0:1] == '~': - title = title[1:] - dot = title.rfind('.') - if dot != -1: - title = title[dot+1:] - # remove parentheses from the target too - if target.endswith('()'): - target = target[:-2] - # if the first character is a dot, search more specific namespaces first - # else search builtins first - if target[0:1] == '.': - target = target[1:] - pnode['refspecific'] = True - # some other special cases for the target - elif typ == 'option': - program = env.currprogram - if not has_explicit_title: - if ' ' in title and not (title.startswith('/') or - title.startswith('-')): - program, target = re.split(' (?=-|--|/)', title, 1) - program = ws_re.sub('-', program) - target = target.strip() - elif ' ' in target: - program, target = re.split(' (?=-|--|/)', target, 1) - program = ws_re.sub('-', program) - pnode['refprogram'] = program - elif typ == 'term': - # normalize whitespace in definition terms (if the term reference is - # broken over a line, a newline will be in target) - target = ws_re.sub(' ', target).lower() - elif typ == 'ref': - # reST label names are always lowercased - target = ws_re.sub('', target).lower() - elif typ == 'cfunc': - # fix-up parens for C functions too - if not has_explicit_title: - title = _fix_parens(typ, title, env) - # remove parentheses from the target too - if target.endswith('()'): - target = target[:-2] - else: - # remove all whitespace to avoid referencing problems - target = ws_re.sub('', target) - pnode['reftarget'] = target - pnode += innernodetypes.get(typ, nodes.literal)(rawtext, title, - classes=['xref']) - return [pnode], [] + +def menusel_role(typ, rawtext, text, lineno, inliner, options={}, content=[]): + return [nodes.emphasis( + rawtext, + utils.unescape(text).replace('-->', u'\N{TRIANGULAR BULLET}'))], [] + return role def menusel_role(typ, rawtext, text, lineno, inliner, options={}, content=[]): @@ -232,30 +166,121 @@ def abbr_role(typ, rawtext, text, lineno, inliner, options={}, content=[]): return [addnodes.abbreviation(abbr, abbr, explanation=expl)], [] +def normalize_func_parens(env, target, title): + if title.endswith('()'): + # remove parentheses + title = title[:-2] + if env.config.add_function_parentheses: + # add them back to all occurrences if configured + title += '()' + # remove parentheses from the target too + if target.endswith('()'): + target = target[:-2] + return target, title + + +def generic_link_func(env, text, pnode): + has_explicit_title, title, target = split_explicit_title(text) + if has_explicit_title: + pnode['refcaption'] = True + return target, title + + +def pyref_link_func(env, text, pnode): + has_explicit_title, title, target = split_explicit_title(text) + if has_explicit_title: + pnode['refcaption'] = True + # fix-up parentheses in link title + if not has_explicit_title: + title = title.lstrip('.') # only has a meaning for the target + target = target.lstrip('~') # only has a meaning for the title + # if the first character is a tilde, don't display the module/class + # parts of the contents + if title[0:1] == '~': + title = title[1:] + dot = title.rfind('.') + if dot != -1: + title = title[dot+1:] + # if the first character is a dot, search more specific namespaces first + # else search builtins first + if target[0:1] == '.': + target = target[1:] + pnode['refspecific'] = True + return target, title + + +def pyref_callable_link_func(env, text, pnode): + target, title = pyref_link_func(env, text, pnode) + target, title = normalize_func_parens(env, target, title) + return target, title + + +def option_link_func(env, text, pnode): + has_explicit_title, title, target = split_explicit_title(text) + program = env.currprogram + if not has_explicit_title: + if ' ' in title and not (title.startswith('/') or + title.startswith('-')): + program, target = re.split(' (?=-|--|/)', title, 1) + program = ws_re.sub('-', program) + target = target.strip() + elif ' ' in target: + program, target = re.split(' (?=-|--|/)', target, 1) + program = ws_re.sub('-', program) + pnode['refprogram'] = program + return target, title + + +def simple_link_func(env, text, pnode): + # normalize all whitespace to avoid referencing problems + has_explicit_title, title, target = split_explicit_title(text) + target = ws_re.sub(' ', target) + return target, title + + +def lowercase_link_func(env, text, pnode): + target, title = simple_link_func(env, text, pnode) + return target.lower(), title + + +def cfunc_link_func(env, text, pnode): + has_explicit_title, title, target = split_explicit_title(text) + if not has_explicit_title: + target, title = normalize_func_parens(env, target, title) + # remove parentheses from the target too + if target.endswith('()'): + target = target[:-2] + return target, title + + +generic_pyref_role = make_xref_role(pyref_link_func) +callable_pyref_role = make_xref_role(pyref_callable_link_func) +simple_xref_role = make_xref_role(simple_link_func) + specific_docroles = { - 'data': xfileref_role, - 'exc': xfileref_role, - 'func': xfileref_role, - 'class': xfileref_role, - 'const': xfileref_role, - 'attr': xfileref_role, - 'meth': xfileref_role, - 'obj': xfileref_role, - 'cfunc' : xfileref_role, - 'cmember': xfileref_role, - 'cdata': xfileref_role, - 'ctype': xfileref_role, - 'cmacro': xfileref_role, + 'data': generic_pyref_role, + 'exc': generic_pyref_role, + 'func': callable_pyref_role, + 'class': generic_pyref_role, + 'const': generic_pyref_role, + 'attr': generic_pyref_role, + 'meth': callable_pyref_role, + 'mod': generic_pyref_role, + 'obj': generic_pyref_role, - 'mod': xfileref_role, + 'keyword': simple_xref_role, + 'ref': make_xref_role(lowercase_link_func, None, nodes.emphasis), + 'token': simple_xref_role, + 'term': make_xref_role(lowercase_link_func, None, nodes.emphasis), + 'option': make_xref_role(option_link_func, None, addnodes.literal_emphasis), + 'doc': simple_xref_role, + 'download': make_xref_role(simple_link_func, addnodes.download_reference), - 'keyword': xfileref_role, - 'ref': xfileref_role, - 'token': xfileref_role, - 'term': xfileref_role, - 'option': xfileref_role, - 'doc': xfileref_role, - 'download': xfileref_role, + 'cmember': simple_xref_role, + 'cmacro': simple_xref_role, + 'cfunc' : make_xref_role(cfunc_link_func), + 'cdata': simple_xref_role, + 'ctype': simple_xref_role, 'menuselection': menusel_role, 'file': emph_literal_role, From 09d234df20d9fd93d05a703576ab95c7f6e9f49d Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Tue, 30 Jun 2009 18:11:57 +0200 Subject: [PATCH 3/4] Fix duplicate code. --- sphinx/roles.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/sphinx/roles.py b/sphinx/roles.py index 1a587cf26..fce349632 100644 --- a/sphinx/roles.py +++ b/sphinx/roles.py @@ -130,12 +130,6 @@ def menusel_role(typ, rawtext, text, lineno, inliner, options={}, content=[]): return role -def menusel_role(typ, rawtext, text, lineno, inliner, options={}, content=[]): - return [nodes.emphasis( - rawtext, - utils.unescape(text).replace('-->', u'\N{TRIANGULAR BULLET}'))], [] - - _litvar_re = re.compile('{([^}]+)}') def emph_literal_role(typ, rawtext, text, lineno, inliner, @@ -247,9 +241,6 @@ def cfunc_link_func(env, text, pnode): has_explicit_title, title, target = split_explicit_title(text) if not has_explicit_title: target, title = normalize_func_parens(env, target, title) - # remove parentheses from the target too - if target.endswith('()'): - target = target[:-2] return target, title From 22f3fbb388c549652238f9662f9b6871e20d627f Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Tue, 30 Jun 2009 18:59:36 +0200 Subject: [PATCH 4/4] Refactor a bit to fix b/w compat of cfunc role. --- sphinx/roles.py | 49 ++++++++++++++++++++++--------------------------- 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/sphinx/roles.py b/sphinx/roles.py index fce349632..7b96c73ab 100644 --- a/sphinx/roles.py +++ b/sphinx/roles.py @@ -116,7 +116,8 @@ def make_xref_role(link_func, nodeclass=None, innernodeclass=None): modname=env.currmodule, classname=env.currclass) # we may need the line number for warnings pnode.line = lineno - target, title = link_func(env, text, pnode) + has_explicit_title, title, target = split_explicit_title(text) + target, title = link_func(env, pnode, has_explicit_title, title, target) pnode['reftarget'] = target pnode += innernodeclass(rawtext, title, classes=['xref']) return [pnode], [] @@ -160,32 +161,31 @@ def abbr_role(typ, rawtext, text, lineno, inliner, options={}, content=[]): return [addnodes.abbreviation(abbr, abbr, explanation=expl)], [] -def normalize_func_parens(env, target, title): - if title.endswith('()'): - # remove parentheses - title = title[:-2] - if env.config.add_function_parentheses: - # add them back to all occurrences if configured - title += '()' +def normalize_func_parens(env, has_explicit_title, target, title): + if has_explicit_title: + if title.endswith('()'): + # remove parentheses + title = title[:-2] + if env.config.add_function_parentheses: + # add them back to all occurrences if configured + title += '()' # remove parentheses from the target too if target.endswith('()'): target = target[:-2] return target, title -def generic_link_func(env, text, pnode): - has_explicit_title, title, target = split_explicit_title(text) +def generic_link_func(env, pnode, has_explicit_title, title, target): if has_explicit_title: pnode['refcaption'] = True return target, title -def pyref_link_func(env, text, pnode): - has_explicit_title, title, target = split_explicit_title(text) +def pyref_link_func(env, pnode, has_explicit_title, title, target): if has_explicit_title: pnode['refcaption'] = True # fix-up parentheses in link title - if not has_explicit_title: + else: title = title.lstrip('.') # only has a meaning for the target target = target.lstrip('~') # only has a meaning for the title # if the first character is a tilde, don't display the module/class @@ -203,14 +203,13 @@ def pyref_link_func(env, text, pnode): return target, title -def pyref_callable_link_func(env, text, pnode): - target, title = pyref_link_func(env, text, pnode) - target, title = normalize_func_parens(env, target, title) +def pyref_callable_link_func(env, pnode, has_explicit_title, title, target): + target, title = pyref_link_func(env, pnode, has_explicit_title, title, target) + target, title = normalize_func_parens(env, has_explicit_title, target, title) return target, title -def option_link_func(env, text, pnode): - has_explicit_title, title, target = split_explicit_title(text) +def option_link_func(env, pnode, has_explicit_title, title, target): program = env.currprogram if not has_explicit_title: if ' ' in title and not (title.startswith('/') or @@ -225,23 +224,19 @@ def option_link_func(env, text, pnode): return target, title -def simple_link_func(env, text, pnode): +def simple_link_func(env, pnode, has_explicit_title, title, target): # normalize all whitespace to avoid referencing problems - has_explicit_title, title, target = split_explicit_title(text) target = ws_re.sub(' ', target) return target, title -def lowercase_link_func(env, text, pnode): - target, title = simple_link_func(env, text, pnode) +def lowercase_link_func(env, pnode, has_explicit_title, title, target): + target, title = simple_link_func(env, pnode, has_explicit_title, title, target) return target.lower(), title -def cfunc_link_func(env, text, pnode): - has_explicit_title, title, target = split_explicit_title(text) - if not has_explicit_title: - target, title = normalize_func_parens(env, target, title) - return target, title +def cfunc_link_func(env, pnode, has_explicit_title, title, target): + return normalize_func_parens(env, has_explicit_title, target, title) generic_pyref_role = make_xref_role(pyref_link_func)