autonumber.py 2.38 KB
Newer Older
peastman's avatar
peastman committed
1
from docutils.parsers.rst import roles
2
from docutils.nodes import Text, reference, section, label
peastman's avatar
peastman committed
3
from sphinx.roles import XRefRole
4
5

class autonumber(label):
peastman's avatar
peastman committed
6
    pass
7

peastman's avatar
peastman committed
8
9
10
11
class autonumber_ref(reference):
    pass

def autonumber_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
12
    return ([autonumber(text=text)], [])
peastman's avatar
peastman committed
13
14
15
16
17
18

def doctree_resolved(app, doctree, docname):
    index = {};
    refTable = {}
    if app.config.autonumber_by_chapter:
        # Record the number of each chapter
19

peastman's avatar
peastman committed
20
21
22
23
24
25
26
        env = app.builder.env
        sectionNumbers = {}
        for doc in env.toc_secnumbers:
            sections = env.toc_secnumbers[doc]
            for sectionId in sections:
                sectionNumbers[sectionId[1:]] = sections[sectionId]
        lastChapter = -1
27

peastman's avatar
peastman committed
28
    # Assign numbers to all the autonumbered objects.
29

peastman's avatar
peastman committed
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
    for node in doctree.traverse(autonumber):
        category = node.astext().split(',')[0]
        if category in index:
            nextNumber = index[category]+1
        else:
            nextNumber = 1
        if app.config.autonumber_by_chapter:
            parent = node.parent
            chapter = None
            while chapter is None:
                if isinstance(parent, section):
                    chapter = parent
                parent = parent.parent
            chapter = sectionNumbers[chapter.attributes['ids'][0]][0]
            if chapter != lastChapter:
                index = {}
peastman's avatar
peastman committed
46
                nextNumber = 1
peastman's avatar
peastman committed
47
48
49
            newNode = Text('%s %d-%d' % (category, chapter, nextNumber))
            lastChapter = chapter
        else:
50
            newNode = Text('%s %d' % (category, nextNumber))
peastman's avatar
peastman committed
51
52
53
        index[category] = nextNumber
        refTable[node.astext()] = newNode
        node.parent.replace(node, newNode)
54

peastman's avatar
peastman committed
55
    # Replace references with the name of the referenced object
56

peastman's avatar
peastman committed
57
58
59
60
61
62
63
64
65
66
67
    for ref_info in doctree.traverse(autonumber_ref):
        target = ref_info['reftarget']
        if target not in refTable:
            raise ValueError('Unknown target for autonumber reference: '+target)
        ref_info.replace_self(Text(refTable[target].astext()))

def setup(app):
    app.add_config_value('autonumber_by_chapter', True, False)
    roles.register_local_role('autonumber', autonumber_role)
    app.add_node(autonumber)
    app.add_node(autonumber_ref)
68
    app.add_role('autonumref', XRefRole(nodeclass=autonumber_ref))
peastman's avatar
peastman committed
69
70
    app.connect('doctree-resolved', doctree_resolved)