1import os.path as path
2import subprocess
3import shlex
4from sphinx.util import logging
5from docutils import nodes
6logger = logging.getLogger(__name__)
7
8
9# use an old git trick, to get the top-level, could have used ../ etc.. but
10# this will be fine..
11top = subprocess.check_output(shlex.split(
12    "git rev-parse --show-toplevel")).strip().decode("utf-8")
13
14
15def make_ref(text):
16    """ Make hyperlink to Github """
17    full_path = path.join(top, text)
18    if path.isfile(full_path):
19        ref = "https://www.github.com/numba/numba/blob/master/" + text
20    elif path.isdir(full_path):
21        ref = "https://www.github.com/numba/numba/tree/master/" + text
22    else:
23        logger.warn("Failed to find file in repomap: " + text)
24        ref = "https://www.github.com/numba/numba"
25    return ref
26
27
28def intersperse(lst, item):
29    """ Insert item between each item in lst.
30
31    Copied under CC-BY-SA from stackoverflow at:
32
33    https://stackoverflow.com/questions/5920643/
34    add-an-item-between-each-item-already-in-the-list
35
36    """
37    result = [item] * (len(lst) * 2 - 1)
38    result[0::2] = lst
39    return result
40
41
42def ghfile_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
43    """ Emit hyperlink nodes for a given file in repomap. """
44    my_nodes = []
45    if "{" in text:  # myfile.{c,h} - make two nodes
46        # could have used regexes, but this will be fine..
47        base = text[:text.find(".") + 1]
48        exts = text[text.find("{") + 1:text.find("}")].split(",")
49        for e in exts:
50            node = nodes.reference(rawtext,
51                                   base + e,
52                                   refuri=make_ref(base + e),
53                                   **options)
54            my_nodes.append(node)
55    elif "*" in text:  # path/*_files.py - link to directory
56        # Could have used something from os.path, but this will be fine..
57        ref = path.dirname(text) + path.sep
58        node = nodes.reference(rawtext, text, refuri=make_ref(ref), **options)
59        my_nodes.append(node)
60    else:  # everything else is taken verbatim
61        node = nodes.reference(rawtext, text, refuri=make_ref(text), **options)
62        my_nodes.append(node)
63
64    # insert seperators if needed
65    if len(my_nodes) > 1:
66        my_nodes = intersperse(my_nodes, nodes.Text(" | "))
67    return my_nodes, []
68
69
70def setup(app):
71    logger.info('Initializing ghfiles plugin')
72    app.add_role('ghfile', ghfile_role)
73
74    metadata = {'parallel_read_safe': True, 'parallel_write_safe': True}
75    return metadata
76