diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt
index 309e3e3f258..2e5afebb5ff 100644
--- a/doc/CMakeLists.txt
+++ b/doc/CMakeLists.txt
@@ -35,4 +35,4 @@ GENERATE_DOXYGEN_HTML(Doxyfile_en.in pages html insert_examples.py)
GENERATE_DOXYGEN_HTML(Doxyfile_cn.in pages_cn html_cn insert_examples_cn.py)
add_subdirectory(sphinx)
-add_custom_target(doc DEPENDS examples documented_example shogun_sphinx_doc ${DOC_DEPENDENCIES})
+add_custom_target(doc DEPENDS examples documented_examples shogun_sphinx_doc ${DOC_DEPENDENCIES})
diff --git a/doc/sphinx/extensions/sgexample.py b/doc/sphinx/extensions/sgexample.py
new file mode 100644
index 00000000000..7b78c375535
--- /dev/null
+++ b/doc/sphinx/extensions/sgexample.py
@@ -0,0 +1,136 @@
+from sphinx.directives.code import LiteralInclude
+from docutils import nodes
+import os
+import uuid
+import sys
+
+def setup(app):
+ app.add_config_value('target_languages', None, True)
+ app.add_config_value('generated_examples_path', None, True)
+
+ # register functions called upon node-visiting
+ app.add_node(sgexample,
+ html=(visit_sgexample_node, depart_sgexample_node))
+ app.add_node(tabpanel,
+ html=(visit_tabpanel_node, depart_tabpanel_node))
+ app.add_node(navtabs,
+ html=(visit_navtabs_node, depart_navtabs_node))
+ app.add_node(navtab,
+ html=(visit_navtab_node, depart_navtab_node))
+ app.add_node(fluid_tab_content,
+ html=(visit_fluid_tab_content, depart_fluid_tab_content))
+
+ app.add_directive('sgexample', ShogunExample)
+ app.connect('builder-inited', setup_parameters)
+
+ return {'version': '0.1'}
+
+class LocalContext(object):
+ pass
+
+context = LocalContext()
+
+def setup_parameters(app):
+ context.target_languages = app.config.target_languages
+ context.generated_examples_path = app.config.generated_examples_path
+
+class sgexample(nodes.Element):
+ pass
+class fluid_tab_content(nodes.Element):
+ pass
+class tabpanel(nodes.Element):
+ pass
+class navtabs(nodes.Element):
+ pass
+class navtab(nodes.Element):
+ pass
+
+def visit_tabpanel_node(self, node):
+ self.body.append('
')
+def depart_tabpanel_node(self, node):
+ self.body.append('
')
+
+def visit_navtabs_node(self, node):
+ self.body.append('' % node.uid)
+def depart_navtabs_node(self, node):
+ self.body.append('
')
+
+def visit_navtab_node(self, node):
+ cls = ""
+ if node.index is 0:
+ cls = 'class="active"'
+ self.body.append('' % (node.language, cls, node.language, node.language))
+def depart_navtab_node(self, node):
+ self.body.append('')
+
+def visit_fluid_tab_content(self, node):
+ self.body.append('')
+def depart_fluid_tab_content(self, node):
+ self.body.append('
')
+
+def visit_sgexample_node(self, node):
+ cls = ""
+ if node.index is 0:
+ cls = 'active'
+ self.body.append('' % (cls, node.language))
+def depart_sgexample_node(self, node):
+ self.body.append('
')
+
+class ShogunExample(LiteralInclude):
+ def element_id(self, target, uid):
+ return '%s-code-%s' % (target, uid)
+ def resolve_path(self, name):
+ return self.state.document.settings.env.relfn2path(name)
+
+ def run(self):
+
+ section = self.arguments[0].split(':')[1]
+ if section == 'begin':
+ self.options['end-before'] = section
+ elif section == 'end':
+ self.options['start-after'] = section
+ else:
+ self.options['start-after'] = section
+ self.options['end-before'] = section
+ uid = str(uuid.uuid1())[:6]
+ result = tabpanel()
+ nvtbs = navtabs()
+ nvtbs.uid = uid
+ for i, (target, _) in enumerate(context.target_languages):
+ nvtb = navtab()
+ nvtb.language = self.element_id(target, uid)
+ nvtb.index = i
+ nvtbs += nvtb
+
+ result += nvtbs
+
+ # save original node
+ fname = self.arguments[0].split(':')[0].strip()
+ fname = [context.generated_examples_path] + self.resolve_path(fname)[0].split(os.sep)[1:]
+
+ tbcntnt = fluid_tab_content()
+
+ # create nodes with parsed listings
+ for i, (target, extension) in enumerate(context.target_languages):
+ target_fname = list(fname)
+ target_fname.insert(1, target)
+ target_fname[-1] = os.path.splitext(target_fname[-1])[0]+'.'+extension
+ target_fname = os.path.join(*target_fname)
+ if not os.path.exists(target_fname):
+ raise IOError('Generated listing %s not found, it is expected to be created from the corresponding meta-example' % (os.path.abspath(target_fname)))
+
+ relative_target_fname = os.path.relpath(target_fname, self.state.document.settings.env.srcdir)
+ self.arguments[0] = '/' + relative_target_fname
+ self.options['language'] = target
+ # call base class, returns list
+ include_container = sgexample()
+ include_container.language = self.element_id(target, uid)
+ include_container.index = i
+ include_container += LiteralInclude.run(self)
+ tbcntnt += include_container
+ result += tbcntnt
+
+ return [result]
+
+def meta_convert(fname):
+ pass
diff --git a/doc/sphinx/source/conf.py b/doc/sphinx/source/conf.py
index e9b7ab8d980..8253c55b764 100644
--- a/doc/sphinx/source/conf.py
+++ b/doc/sphinx/source/conf.py
@@ -187,6 +187,8 @@
('java', 'java')
)
+generated_examples_path = None
+
html_context = {
'target_languages':
[x[0] for x in target_languages]