1 # -*- coding: utf-8 -*-
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
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
13 CSS_FILE = 'showfile.css'
14 JS_FILE = 'showfile.js'
16 class ShowFileDirective(Directive):
18 Show a file or propose it to download.
22 optional_arguments = 1
24 'language': directives.unchanged
29 filename = self.arguments[0]
31 if 'language' in self.options:
32 language = self.options['language']
34 logger = logging.getLogger(__name__)
35 # logger.info('showfile {} in {}'.format(filename, language))
39 ' :header: View {}'.format(filename),
41 ' `Download {} <https://framagit.org/simgrid/simgrid/tree/master/{}>`_'.format(os.path.basename(filename), filename),
43 ' .. literalinclude:: ../../{}'.format(filename),
44 ' :language: {}'.format(language),
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))
53 node = nodes.container()
54 self.state.nested_parse(self.content, self.content_offset, node)
57 class ExampleTabDirective(Directive):
59 A group-tab for a given language, in the presentation of the examples.
62 optional_arguments = 0
63 mandatory_argument = 0
66 self.assert_has_content()
68 filename = self.content[0].strip()
69 self.content.trim_start(1)
71 (language, langcode) = (None, None)
72 if filename[-3:] == '.py':
75 elif filename[-2:] == '.c':
78 elif filename[-4:] == '.cpp':
81 elif filename[-4:] == '.xml':
85 raise Exception("Unknown language '{}'. Please choose '.cpp', '.py', '.c' or '.xml'".format(language))
87 for idx, line in enumerate(self.content.data):
88 self.content.data[idx] = ' ' + line
90 for idx, line in enumerate([
91 '.. group-tab:: {}'.format(language),
93 self.content.data.insert(idx, line)
94 self.content.items.insert(idx, (None, idx))
98 ' .. showfile:: {}'.format(filename),
99 ' :language: {}'.format(langcode),
101 idx = len(self.content.data)
102 self.content.data.insert(idx, line)
103 self.content.items.insert(idx, (None, idx))
105 # logger = logging.getLogger(__name__)
106 # logger.info('------------------')
107 # for line in self.content.data:
108 # logger.info('{}'.format(line))
110 node = nodes.container()
111 self.state.nested_parse(self.content, self.content_offset, node)
114 class ToggleDirective(Directive):
117 'header': directives.unchanged,
118 'show': directives.flag
120 optional_arguments = 1
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')
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])
137 self.state.nested_parse(StringList([self.options["header"]]), self.content_offset, par)
138 self.state.nested_parse(self.content, self.content_offset, node)
143 app.add_css_file(CSS_FILE)
144 app.add_js_file(JS_FILE)
147 def copy_assets(app, exception):
148 if app.builder.name not in ['html', 'readthedocs'] or exception:
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)
161 app.add_directive('toggle-header', ToggleDirective)
162 app.add_directive('showfile', ShowFileDirective)
163 app.add_directive('example-tab', ExampleTabDirective)
165 app.connect('builder-inited', add_assets)
166 app.connect('build-finished', copy_assets)