Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
showfile: adapt to recent sphinx
[simgrid.git] / docs / source / _ext / showfile.py
index a75fb17..7894d6d 100644 (file)
@@ -1,5 +1,8 @@
 # -*- coding: utf-8 -*-
 
+# Useful doc: https://www.sphinx-doc.org/en/master/extdev/markupapi.html
+# Example: https://www.sphinx-doc.org/en/master/development/tutorials/recipe.html
+
 import os
 from docutils.parsers.rst import Directive, directives
 from docutils import nodes
@@ -7,6 +10,9 @@ from docutils.statemachine import StringList
 from sphinx.util.osutil import copyfile
 from sphinx.util import logging
 
+CSS_FILE = 'showfile.css'
+JS_FILE = 'showfile.js'
+
 class ShowFileDirective(Directive):
     """
     Show a file or propose it to download.
@@ -15,11 +21,10 @@ class ShowFileDirective(Directive):
     has_content = False
     optional_arguments = 1
     option_spec = {
-      'language': directives.unchanged
+        'language': directives.unchanged
     }
 
     def run(self):
-#        self.assert_has_content()
 
         filename = self.arguments[0]
         language = "python"
@@ -49,5 +54,113 @@ class ShowFileDirective(Directive):
         self.state.nested_parse(self.content, self.content_offset, node)
         return node.children
 
+class ExampleTabDirective(Directive):
+    """
+    A group-tab for a given language, in the presentation of the examples.
+    """
+    has_content = True
+    optional_arguments = 0
+    mandatory_argument = 0
+
+    def run(self):
+        self.assert_has_content()
+
+        filename = self.content[0].strip()
+        self.content.trim_start(1)
+
+        (language, langcode) = (None, None)
+        if filename[-3:] == '.py':
+            language = 'Python'
+            langcode = 'py'
+        elif filename[-2:] == '.c':
+            language = 'C'
+            langcode = 'c'
+        elif filename[-4:] == '.cpp':
+            language = 'C++'
+            langcode = 'cpp'
+        elif filename[-4:] == '.xml':
+            language = 'XML'
+            langcode = 'xml'
+        else:
+            raise Exception("Unknown language '{}'. Please choose '.cpp', '.py', '.c' or '.xml'".format(language))
+
+        for idx, line in enumerate(self.content.data):
+            self.content.data[idx] = '   ' + line
+
+        for idx, line in enumerate([
+            '.. group-tab:: {}'.format(language),
+            '   ']):
+            self.content.data.insert(idx, line)
+            self.content.items.insert(idx, (None, idx))
+
+        for line in [
+            '',
+            '   .. showfile:: {}'.format(filename),
+            '      :language: {}'.format(langcode),
+            '']:
+            idx = len(self.content.data)
+            self.content.data.insert(idx, line)
+            self.content.items.insert(idx, (None, idx))
+
+#        logger = logging.getLogger(__name__)
+#        logger.info('------------------')
+#        for line in self.content.data:
+#            logger.info('{}'.format(line))
+
+        node = nodes.container()
+        self.state.nested_parse(self.content, self.content_offset, node)
+        return node.children
+
+class ToggleDirective(Directive):
+    has_content = True
+    option_spec = {
+        'header': directives.unchanged,
+        'show': directives.flag
+    }
+    optional_arguments = 1
+
+    def run(self):
+        node = nodes.container()
+        node['classes'].append('toggle-content')
+        if "show" not in self.options:
+            # This :show: thing is not working, and I fail to see why.
+            # Only the hidden-content class gets a call to hide() in the Javascript,
+            # and :show:n block# still get hidden when I load the page.
+            # No idea what's going on (Mt)
+            node['classes'].append('hidden-content')
+
+        par = nodes.container()
+        par['classes'].append('toggle-header')
+        if self.arguments and self.arguments[0]:
+            par['classes'].append(self.arguments[0])
+
+        self.state.nested_parse(StringList([self.options["header"]]), self.content_offset, par)
+        self.state.nested_parse(self.content, self.content_offset, node)
+
+        return [par, node]
+
+def add_assets(app):
+    app.add_css_file(CSS_FILE)
+    app.add_js_file(JS_FILE)
+
+
+def copy_assets(app, exception):
+    if app.builder.name not in ['html', 'readthedocs'] or exception:
+        return
+    logger = logging.getLogger(__name__)
+    logger.info('Copying showfile stylesheet/javascript... ', nonl=True)
+    dest = os.path.join(app.builder.outdir, '_static', CSS_FILE)
+    source = os.path.join(os.path.abspath(os.path.dirname(__file__)), CSS_FILE)
+    copyfile(source, dest)
+    dest = os.path.join(app.builder.outdir, '_static', JS_FILE)
+    source = os.path.join(os.path.abspath(os.path.dirname(__file__)), JS_FILE)
+    copyfile(source, dest)
+    logger.info('done')
+
 def setup(app):
+    app.add_directive('toggle-header', ToggleDirective)
     app.add_directive('showfile', ShowFileDirective)
+    app.add_directive('example-tab', ExampleTabDirective)
+
+    app.connect('builder-inited', add_assets)
+    app.connect('build-finished', copy_assets)