1import os 2 3from docutils import nodes 4from docutils.parsers.rst import Directive, directives 5from docutils.parsers.rst.directives.images import Image 6from sphinx.directives.code import LiteralInclude 7 8 9def excluded_list(argument): 10 return argument.split(',') 11 12 13 14 15class LvExample(Directive): 16 required_arguments = 1 17 option_spec = { 18 'excluded_languages': excluded_list, 19 'language': directives.unchanged, 20 'description': directives.unchanged 21 } 22 def get_example_code_path(self, example_path, language): 23 return os.path.abspath("../examples/" + example_path + "." + language) 24 def human_language_name(self, language): 25 if language == 'py': 26 return 'MicroPython' 27 elif language == 'c': 28 return 'C' 29 else: 30 return language 31 def github_path(self, example_path, language): 32 env = self.state.document.settings.env 33 return f"https://github.com/lvgl/lvgl/blob/{env.config.repo_commit_hash}/examples/{example_path}.{language}" 34 def embed_code(self, example_file, example_path, language, buttons={}): 35 toggle = nodes.container('', literal_block=False, classes=['toggle']) 36 header = nodes.container('', literal_block=False, classes=['header']) 37 toggle.append(header) 38 try: 39 with open(example_file) as f: 40 contents = f.read() 41 except FileNotFoundError: 42 contents = 'Error encountered while trying to open ' + example_file 43 literal_list = nodes.literal_block(contents, contents) 44 literal_list['language'] = language 45 toggle.append(literal_list) 46 paragraph_node = nodes.raw(text=f"<p>{self.human_language_name(language)} code </p>", format='html') 47 for text, url in buttons.items(): 48 paragraph_node.append(nodes.raw(text=f"<a class='lv-example-link-button' onclick=\"event.stopPropagation();\" href='{url}'>{text}</a>", format='html')) 49 header.append(paragraph_node) 50 return toggle 51 def run(self): 52 example_path = self.arguments[0] 53 example_name = os.path.split(example_path)[1] 54 excluded_languages = self.options.get('excluded_languages', []) 55 node_list = [] 56 57 env = self.state.document.settings.env 58 59 iframe_html = "" 60 61 c_path = self.get_example_code_path(example_path, 'c') 62 py_path = self.get_example_code_path(example_path, 'py') 63 64 c_code = self.embed_code(c_path, example_path, 'c', buttons={ 65 '<i class="fa fa-github"></i> GitHub': self.github_path(example_path, 'c') 66 }) 67 py_code = self.embed_code(py_path, example_path, 'py', buttons={ 68 '<i class="fa fa-github"></i> GitHub': self.github_path(example_path, 'py'), 69 '<i class="fa fa-play"></i> Simulator': f"https://sim.lvgl.io/v{env.config.version}/micropython/ports/javascript/index.html?script_startup=https://raw.githubusercontent.com/lvgl/lvgl/{env.config.repo_commit_hash}/examples/header.py&script=https://raw.githubusercontent.com/lvgl/lvgl/{env.config.repo_commit_hash}/examples/{example_path}.py" 70 }) 71 72 if not 'c' in excluded_languages: 73 if env.app.tags.has('html'): 74 iframe_html = f"<div class='lv-example' data-real-src='/{env.config.version}/_static/built_lv_examples/index.html?example={example_name}&w=320&h=240'></div>" 75 76 description_html = f"<div class='lv-example-description'>{self.options.get('description', '')}</div>" 77 layout_node = nodes.raw(text=f"<div class='lv-example-container'>{iframe_html}{description_html}</div>", format='html') 78 79 node_list.append(layout_node) 80 if not 'c' in excluded_languages: 81 node_list.append(c_code) 82 if not 'py' in excluded_languages: 83 node_list.append(py_code) 84 85 trailing_node = nodes.raw(text=f"<hr/>", format='html') 86 node_list.append(trailing_node) 87 88 return node_list 89 90def setup(app): 91 app.add_directive("lv_example", LvExample) 92 app.add_config_value("repo_commit_hash", "", "env") 93 94 return { 95 'version': '0.1', 96 'parallel_read_safe': True, 97 'parallel_write_safe': True, 98 } 99