summaryrefslogtreecommitdiff
path: root/sandbox/py-rest-doc/sphinx/roles.py
blob: fa194c76af6c9e700f8e3fbe3a9e3ac21762d772 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# -*- 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)