Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
added ns3 wifi doc
[simgrid.git] / docs / source / _ext / showfile.py
1 # -*- coding: utf-8 -*-
2
3 # Useful doc: https://www.sphinx-doc.org/en/master/extdev/markupapi.html
4 # Example: https://www.sphinx-doc.org/en/master/development/tutorials/recipe.html
5
6 import os
7 from docutils.parsers.rst import Directive, directives
8 from docutils import nodes
9 from docutils.statemachine import StringList
10 from sphinx.util.osutil import copyfile
11 from sphinx.util import logging
12
13 CSS_FILE = 'showfile.css'
14 JS_FILE = 'showfile.js'
15
16 class ShowFileDirective(Directive):
17     """
18     Show a file or propose it to download.
19     """
20
21     has_content = False
22     optional_arguments = 1
23     option_spec = {
24         'language': directives.unchanged
25     }
26
27     def run(self):
28
29         filename = self.arguments[0]
30         language = "python"
31         if 'language' in self.options:
32             language = self.options['language']
33
34         logger = logging.getLogger(__name__)
35 #        logger.info('showfile {} in {}'.format(filename, language))
36
37         new_content = [
38           '.. toggle-header::',
39           '   :header: View {}'.format(filename),
40           '',
41           '   `Download {} <https://framagit.org/simgrid/simgrid/tree/{}>`_'.format(os.path.basename(filename), filename),
42           '',
43           '   .. literalinclude:: ../../{}'.format(filename),
44           '      :language: {}'.format(language),
45           ''
46         ]
47
48         for idx, line in enumerate(new_content):
49 #            logger.info('{} {}'.format(idx,line))
50             self.content.data.insert(idx, line)
51             self.content.items.insert(idx, (None, idx))
52
53         node = nodes.container()
54         self.state.nested_parse(self.content, self.content_offset, node)
55         return node.children
56
57 class ExampleTabDirective(Directive):
58     """
59     A group-tab for a given language, in the presentation of the examples.
60     """
61     has_content = True
62     optional_arguments = 0
63     mandatory_argument = 0
64
65     def run(self):
66         self.assert_has_content()
67
68         filename = self.content[0].strip()
69         self.content.trim_start(1)
70
71         (language, langcode) = (None, None)
72         if filename[-3:] == '.py':
73             language = 'Python'
74             langcode = 'py'
75         elif filename[-2:] == '.c':
76             language = 'C'
77             langcode = 'c'
78         elif filename[-4:] == '.cpp':
79             language = 'C++'
80             langcode = 'cpp'
81         elif filename[-4:] == '.xml':
82             language = 'XML'
83             langcode = 'xml'
84         else:
85             raise Exception("Unknown language '{}'. Please choose '.cpp', '.py', '.c' or '.xml'".format(language))
86
87         for idx, line in enumerate(self.content.data):
88             self.content.data[idx] = '   ' + line
89
90         for idx, line in enumerate([
91             '.. group-tab:: {}'.format(language),
92             '   ']):
93             self.content.data.insert(idx, line)
94             self.content.items.insert(idx, (None, idx))
95
96         for line in [
97             '',
98             '   .. showfile:: {}'.format(filename),
99             '      :language: {}'.format(langcode),
100             '']:
101             idx = len(self.content.data)
102             self.content.data.insert(idx, line)
103             self.content.items.insert(idx, (None, idx))
104
105 #        logger = logging.getLogger(__name__)
106 #        logger.info('------------------')
107 #        for line in self.content.data:
108 #            logger.info('{}'.format(line))
109
110         node = nodes.container()
111         self.state.nested_parse(self.content, self.content_offset, node)
112         return node.children
113
114 class ToggleDirective(Directive):
115     has_content = True
116     option_spec = {
117         'header': directives.unchanged,
118         'show': directives.flag
119     }
120     optional_arguments = 1
121
122     def run(self):
123         node = nodes.container()
124         node['classes'].append('toggle-content')
125         if "show" not in self.options:
126             # This :show: thing is not working, and I fail to see why.
127             # Only the hidden-content class gets a call to hide() in the Javascript,
128             # and :show:n block# still get hidden when I load the page.
129             # No idea what's going on (Mt)
130             node['classes'].append('hidden-content')
131
132         par = nodes.container()
133         par['classes'].append('toggle-header')
134         if self.arguments and self.arguments[0]:
135             par['classes'].append(self.arguments[0])
136
137         self.state.nested_parse(StringList([self.options["header"]]), self.content_offset, par)
138         self.state.nested_parse(self.content, self.content_offset, node)
139
140         return [par, node]
141
142 def add_assets(app):
143     app.add_stylesheet(CSS_FILE)
144     app.add_javascript(JS_FILE)
145
146
147 def copy_assets(app, exception):
148     if app.builder.name not in ['html', 'readthedocs'] or exception:
149         return
150     logger = logging.getLogger(__name__)
151     logger.info('Copying showfile stylesheet/javascript... ', nonl=True)
152     dest = os.path.join(app.builder.outdir, '_static', CSS_FILE)
153     source = os.path.join(os.path.abspath(os.path.dirname(__file__)), CSS_FILE)
154     copyfile(source, dest)
155     dest = os.path.join(app.builder.outdir, '_static', JS_FILE)
156     source = os.path.join(os.path.abspath(os.path.dirname(__file__)), JS_FILE)
157     copyfile(source, dest)
158     logger.info('done')
159
160 def setup(app):
161     app.add_directive('toggle-header', ToggleDirective)
162     app.add_directive('showfile', ShowFileDirective)
163     app.add_directive('example-tab', ExampleTabDirective)
164
165     app.connect('builder-inited', add_assets)
166     app.connect('build-finished', copy_assets)