├── deveal ├── __init__.py ├── skeleton │ ├── deveal.css │ ├── sections │ │ ├── title.html │ │ ├── part1.html │ │ └── part2.html │ ├── deveal.yaml │ └── deveal-index.html ├── about.py └── __main__.py ├── tests ├── __init__.py └── test_main.py ├── requirements.txt ├── TODO ├── LICENSE ├── .gitignore ├── setup.py ├── .github └── workflows │ └── CI.yaml └── README.rst /deveal/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /deveal/skeleton/deveal.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | jinja2 2 | watchdog 3 | pyyaml 4 | -------------------------------------------------------------------------------- /deveal/skeleton/sections/title.html: -------------------------------------------------------------------------------- 1 |
2 |

My presentation

3 |
-------------------------------------------------------------------------------- /deveal/skeleton/sections/part1.html: -------------------------------------------------------------------------------- 1 |
2 |

Part 1

3 |

Slide A

4 |
-------------------------------------------------------------------------------- /deveal/about.py: -------------------------------------------------------------------------------- 1 | __license__ = "GPLv3" 2 | __author__ = "Jean-Christophe Fabre " 3 | 4 | __version__ = "1.3.0" 5 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | TODO Add better handling of template exceptions 2 | TODO Refactor source code to match PEP8 recommendations 3 | TODO Add integrated tests 4 | TODO Add deployment process in README.md file -------------------------------------------------------------------------------- /deveal/skeleton/deveal.yaml: -------------------------------------------------------------------------------- 1 | 2 | reveal_path : "https://cdn.jsdelivr.net/npm/reveal.js@4.1.0" 3 | reveal_theme : "black" 4 | 5 | custom_css : "deveal.css" 6 | 7 | content_files : ["sections/title.html","sections/part1.html","sections/part2.html"] -------------------------------------------------------------------------------- /deveal/skeleton/sections/part2.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Part 2

4 |
5 |
6 |

Slide J

7 |
8 |
9 |

Slide K

10 |
11 |
12 |

Slide L

13 |
14 |
-------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This program is free software: you can redistribute it and/or modify 2 | it under the terms of the GNU General Public License as published by 3 | the Free Software Foundation, either version 3 of the License, or 4 | (at your option) any later version. 5 | 6 | This program is distributed in the hope that it will be useful, 7 | but WITHOUT ANY WARRANTY; without even the implied warranty of 8 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 9 | GNU General Public License for more details. 10 | 11 | You should have received a copy of the GNU General Public License 12 | along with this program. If not, see . -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # Unit test / coverage reports 30 | htmlcov/ 31 | .tox/ 32 | .nox/ 33 | .coverage 34 | .coverage.* 35 | .cache 36 | nosetests.xml 37 | coverage.xml 38 | *.cover 39 | *.py,cover 40 | .hypothesis/ 41 | .pytest_cache/ 42 | cover/ 43 | 44 | # Sphinx documentation 45 | docs/_build/ 46 | 47 | # Environments 48 | .env 49 | .venv 50 | env/ 51 | venv/ 52 | ENV/ 53 | env.bak/ 54 | venv.bak/ 55 | 56 | 57 | # Other 58 | .DS_Store 59 | .vscode 60 | _exec/ -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | 4 | def readme(): 5 | with open('README.rst') as f: 6 | return f.read() 7 | 8 | 9 | def version(): 10 | about_file = "deveal/about.py" 11 | with open(about_file) as f: 12 | exec(compile(f.read(), about_file, "exec")) 13 | return locals()["__version__"] 14 | 15 | 16 | setup( 17 | name='deveal', 18 | version=version(), 19 | description='A reveal.js helper tool', 20 | long_description=readme(), 21 | author='Jean-Christophe Fabre', 22 | author_email='jctophe.fabre@gmail.com', 23 | url='https://github.com/jctophefabre/deveal', 24 | license='GPLv3', 25 | packages=['deveal'], 26 | package_data={ 27 | 'deveal': ['skeleton/*', 'skeleton/sections/*'] 28 | }, 29 | entry_points={ 30 | 'console_scripts': [ 31 | 'deveal = deveal.__main__:main' 32 | ] 33 | }, 34 | install_requires=[ 35 | 'argparse', 36 | 'jinja2 >= 2.7', 37 | 'PyYAML', 38 | 'watchdog', 39 | 'livereload' 40 | ], 41 | python_requires='~=3.5', 42 | ) 43 | -------------------------------------------------------------------------------- /.github/workflows/CI.yaml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | 4 | on: [push, pull_request] 5 | 6 | 7 | jobs: 8 | deveal-tests: 9 | 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v2 13 | - name: Set up Python 14 | uses: actions/setup-python@v2 15 | with: 16 | python-version: '3.x' 17 | - name: Install dependencies 18 | run: | 19 | python -m pip install --upgrade pip setuptools wheel 20 | python -m pip install -r requirements.txt 21 | python -m pip install -U pytest 22 | - name: Run tests 23 | run: | 24 | pytest -v 25 | 26 | 27 | deveal-install: 28 | 29 | runs-on: ubuntu-latest 30 | steps: 31 | - uses: actions/checkout@v2 32 | - name: Set up Python 33 | uses: actions/setup-python@v2 34 | with: 35 | python-version: '3.x' 36 | - name: Install dependencies 37 | run: | 38 | python -m pip install --upgrade pip setuptools wheel 39 | pip install -r requirements.txt 40 | - name: Install deveal 41 | run: | 42 | python -m pip install -e . 43 | - name: Show deveal version 44 | run: | 45 | deveal version -------------------------------------------------------------------------------- /deveal/skeleton/deveal-index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {% if title %} 8 | {{ title }} 9 | {% endif %} 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | {% if custom_css %} 23 | {%- if custom_css is string -%} 24 | 25 | {% else %} 26 | {%- for css in custom_css -%} 27 | 28 | {% endfor %} 29 | {% endif %} 30 | {% endif %} 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
40 | 41 | 42 |
43 | 44 | {% for f in content_files %} 45 | {% include "%s" % f %} 46 | {% endfor %} 47 | 48 | 49 |
50 | 51 |
52 | 53 | 54 | 55 | 56 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ############################### 2 | Deveal, a reveal.js helper tool 3 | ############################### 4 | 5 | 6 | Deveal is an helper tool for using the marvelous `reveal.js presentation framework `_. 7 | 8 | It provides the ability to 9 | 10 | * create a new presentation 11 | * split presentation into multiple files 12 | * easily parameterize the presentation (title, theme, custom css, ...) 13 | * build presentation into a single index.html file 14 | * watch for presentation updates while editing the source files 15 | 16 | 17 | Deveal is developped in Python 3 and mainly relies on the wonderful 18 | `Jinja2 `_, `PyYaml `_ and `watchdog `_ packages. 19 | 20 | 21 | 22 | Installation 23 | ============ 24 | 25 | Use the pip installation tool 26 | 27 | .. code-block:: shell 28 | 29 | pip install deveal 30 | 31 | The dependencies will be automatically installed. 32 | 33 | 34 | Usage 35 | ===== 36 | 37 | Deveal is a command line tool. It must be used from within a terminal. 38 | 39 | Run the following command to get help 40 | 41 | .. code-block:: shell 42 | 43 | deveal --help 44 | 45 | 46 | deveal new 47 | ---------- 48 | 49 | The ``deveal new`` command creates a new presentation. 50 | As it creates the presentation directory itself, the command must be run in the upper directory where the new presentation will be created 51 | 52 | (example below for creating a new presentation named "mynewslideshow") 53 | 54 | .. code-block:: shell 55 | 56 | deveal new mynewslideshow 57 | 58 | 59 | This command creates the minimal required files in the presentation directory 60 | 61 | * the **deveal-index.html** template file 62 | * the **deveal.yaml** configuration file 63 | 64 | A **deveal.css** file for optional custom styles and a **sections** directory with an example presentation are also created 65 | 66 | The deveal-index.html file is the template for the presentation. 67 | It a Jinja2 template rendered throught the ``deveal build`` command, using the variables contained in the deveal.yaml file. 68 | Unless you want to modify the reveal.js configuration, you should not have to modify this template. 69 | 70 | The deveal.yaml file contains the configuration for the presentation. It should contains the folling expected variables: 71 | 72 | * reveal_path : The path or URL to the installed reveal.js framework (default is "https://cdn.jsdelivr.net/npm/reveal.js@4.1.0") 73 | * reveal_theme : The theme to use for (default is "black") 74 | * content_files : The ordered array of files containing the parts of the presentation 75 | * custom_css : The path to custom css files if any 76 | 77 | Any other variable defined in this file is made available as a variable for the template file. 78 | This may be useful to customize the base template. 79 | 80 | 81 | 82 | deveal build 83 | ------------ 84 | 85 | The ``deveal build`` command builds the presentation as a single **index.html** file using the deveal-index.html and deveal.yaml files 86 | 87 | .. code-block:: shell 88 | 89 | deveal build 90 | 91 | The obtained index.html file is the presentation itself that can be open throught a web browser. 92 | 93 | 94 | deveal watch 95 | ------------ 96 | 97 | The ``deveal watch`` command watches for files changes in the presentation directory and subdirectories. 98 | If a change is detected, a build is automatically triggered. Type ``Ctrl+C`` to stop watching. 99 | 100 | .. code-block:: shell 101 | 102 | deveal watch 103 | 104 | 105 | Tips 106 | ---- 107 | 108 | * For an easier writing and maintenance of the presentation, it is encouraged to split the presentation into multiple files (for example title.html, part1.html, part2.html, ...) 109 | * it is encouraged to put the graphics used in the presentation in a dedicated subdirectory (named "graphics" for example) 110 | 111 | 112 | Authors 113 | ======= 114 | 115 | Deveal is developed by `Jean-Christophe Fabre `_ 116 | -------------------------------------------------------------------------------- /tests/test_main.py: -------------------------------------------------------------------------------- 1 | __license__ = "GPLv3" 2 | __author__ = "Jean-Christophe Fabre " 3 | 4 | from unittest import TestCase 5 | 6 | import os 7 | import shutil 8 | import tempfile 9 | 10 | from deveal import about 11 | from deveal.__main__ import Deveal 12 | 13 | 14 | EXEC_DIR = os.path.join(tempfile.gettempdir(), "deveal_tests_exec") 15 | 16 | 17 | class DevealTests(TestCase): 18 | 19 | @classmethod 20 | def setUpClass(cls): 21 | print("Execution directory: {}".format(EXEC_DIR)) 22 | shutil.rmtree(EXEC_DIR, ignore_errors=True) 23 | os.makedirs(EXEC_DIR) 24 | 25 | # check version string is available 26 | def test_001_version(self): 27 | print(about.__version__) 28 | self.assertTrue(len(about.__version__) > 0) 29 | 30 | # check creation of a new slideshow 31 | def test_010_new(self): 32 | dvl = Deveal() 33 | os.chdir(EXEC_DIR) 34 | args = {"path": "slides"} 35 | self.assertEqual(dvl.run_new(args), 0) 36 | slides_dir = os.path.join(EXEC_DIR, "slides") 37 | self.assertTrue(os.path.isfile(os.path.join(slides_dir, "deveal.yaml"))) 38 | self.assertTrue(os.path.isfile(os.path.join(slides_dir, "deveal-index.html"))) 39 | self.assertTrue(os.path.isfile(os.path.join(slides_dir, "deveal.css"))) 40 | self.assertTrue(os.path.isdir(os.path.join(slides_dir, "sections"))) 41 | 42 | # check creation of a new slideshow with cloning of reveal.js 43 | def test_011_new_withreveal(self): 44 | dvl = Deveal() 45 | os.chdir(EXEC_DIR) 46 | args = {"path": "slideswithreveal", "with_reveal": True} 47 | self.assertEqual(dvl.run_new(args), 0) 48 | slides_dir = os.path.join(EXEC_DIR, "slideswithreveal") 49 | self.assertTrue(os.path.isdir(slides_dir)) 50 | self.assertTrue(os.path.isdir(os.path.join(slides_dir, "reveal.js"))) 51 | 52 | # check detection of existing slideshow when attempting to create one with the same name 53 | def test_012_new_alreadyexists(self): 54 | dvl = Deveal() 55 | os.chdir(EXEC_DIR) 56 | args = {"path": "slides"} 57 | self.assertNotEqual(dvl.run_new(args), 0) 58 | 59 | # check build of a slideshow 60 | def test_020_build(self): 61 | dvl = Deveal() 62 | slides_dir = os.path.join(EXEC_DIR, "slides") 63 | os.chdir(slides_dir) 64 | args = {} 65 | self.assertEqual(dvl.run_build(args), 0) 66 | self.assertTrue(os.path.isfile(os.path.join(slides_dir, "index.html"))) 67 | 68 | # check management of missing main template 69 | def test_021_build_templateerror_missingindex(self): 70 | dvl = Deveal() 71 | os.chdir(EXEC_DIR) 72 | args = {"path": "slidestplindex"} 73 | self.assertEqual(dvl.run_new(args), 0) 74 | slides_dir = os.path.join(EXEC_DIR, "slidestplindex") 75 | os.remove(os.path.join(slides_dir, "deveal-index.html")) 76 | os.chdir(slides_dir) 77 | args = {} 78 | self.assertEqual(dvl.run_build(args), 127) 79 | self.assertFalse(os.path.isfile(os.path.join(slides_dir, "deveal-index.html"))) 80 | 81 | # check management of missing included template 82 | def test_022_build_templateerror_missingsections(self): 83 | dvl = Deveal() 84 | os.chdir(EXEC_DIR) 85 | args = {"path": "slidestplsections"} 86 | self.assertEqual(dvl.run_new(args), 0) 87 | slides_dir = os.path.join(EXEC_DIR, "slidestplsections") 88 | shutil.rmtree(os.path.join(slides_dir, "sections")) 89 | os.chdir(slides_dir) 90 | args = {} 91 | self.assertEqual(dvl.run_build(args), 127) 92 | self.assertFalse(os.path.isdir(os.path.join(slides_dir, "sections"))) 93 | 94 | # check cloning of reveal.js in an existing slideshow 95 | def test_030_clonereveal(self): 96 | dvl = Deveal() 97 | slides_dir = os.path.join(EXEC_DIR, "slides") 98 | os.chdir(slides_dir) 99 | args = {} 100 | self.assertFalse(os.path.exists(os.path.join(slides_dir, "reveal.js"))) 101 | self.assertEqual(dvl.run_reveal(args), 0) 102 | self.assertTrue(os.path.isdir(os.path.join(slides_dir, "reveal.js"))) 103 | -------------------------------------------------------------------------------- /deveal/__main__.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | 3 | __license__ = "GPLv3" 4 | __author__ = "Jean-Christophe Fabre " 5 | 6 | 7 | import sys 8 | 9 | if sys.version_info[0] < 3: 10 | raise Exception("Python 3 or a more recent version is required.") 11 | 12 | 13 | import os 14 | import argparse 15 | import shutil 16 | import time 17 | import subprocess 18 | import yaml 19 | import jinja2 20 | from watchdog.observers import Observer 21 | from watchdog.events import FileSystemEventHandler 22 | 23 | from .about import __version__ 24 | 25 | 26 | ############################################################################## 27 | 28 | 29 | BASE_DIR = os.path.dirname(os.path.abspath(__file__)) 30 | SKELETON_DIR = os.path.join(BASE_DIR, "skeleton") 31 | 32 | DEFAULT_CONFIG = { 33 | "reveal_theme": "black", 34 | "reveal_path": "https://cdn.jsdelivr.net/npm/reveal.js@4.1.0" 35 | } 36 | 37 | REVEAL_CLONE_DIR = 'reveal.js' 38 | 39 | 40 | ############################################################################## 41 | 42 | 43 | class Deveal(FileSystemEventHandler): 44 | 45 | def __init__(self): 46 | pass 47 | 48 | @staticmethod 49 | def __print_error(msg): 50 | print("[ERROR] {}".format(msg)) 51 | 52 | @staticmethod 53 | def __print_warning(msg): 54 | print("[WARNING] {}".format(msg)) 55 | 56 | def __build_vars(self): 57 | vars = dict() 58 | 59 | if not os.path.isfile("deveal.yaml"): 60 | Deveal.__print_warning("File deveal.yaml not found. Config file ignored.") 61 | else: 62 | with open(os.path.join(os.getcwd(), "deveal.yaml"), 'r') as yaml_file: 63 | try: 64 | vars = yaml.load(yaml_file, Loader=yaml.FullLoader) 65 | except yaml.YAMLError as E: 66 | mark = E.problem_mark 67 | Deveal.__print_warning( 68 | "Problem reading deveal.yaml file at line {}, column {}. Config file ignored." 69 | .format(mark.line+1, mark.column+1) 70 | ) 71 | 72 | for (key, value) in DEFAULT_CONFIG.items(): 73 | if key not in vars: 74 | vars[key] = value 75 | Deveal.__print_warning( 76 | "Missing parameter {} in configuration, using defaullt value \"{}\".".format(key, value) 77 | ) 78 | 79 | return vars 80 | 81 | def run_new(self, args): 82 | dest_dir = os.path.join(os.getcwd(), args['path']) 83 | 84 | if os.path.exists(dest_dir): 85 | Deveal.__print_error("{} already exists.".format(dest_dir)) 86 | return 1 87 | 88 | print("Creating new slideshow in {}...".format(dest_dir)) 89 | shutil.copytree(SKELETON_DIR, dest_dir) 90 | print("Done") 91 | 92 | if "with_reveal" in args and args["with_reveal"]: 93 | ret = self.run_reveal(args) 94 | if ret == 0: 95 | # rewrite config file to used cloned reveal repository 96 | yamlfile_path = os.path.join(dest_dir, 'deveal.yaml') 97 | with open(yamlfile_path) as yaml_file: 98 | vars = yaml.load(yaml_file, Loader=yaml.FullLoader) 99 | vars['reveal_path'] = REVEAL_CLONE_DIR 100 | with open(yamlfile_path, 'w') as yaml_file: 101 | yaml.dump(vars, yaml_file) 102 | else: 103 | return ret 104 | 105 | return 0 106 | 107 | def run_reveal(self, args): 108 | work_path = os.getcwd() 109 | if 'path' in args: 110 | work_path = args['path'] 111 | 112 | if not os.path.isdir(work_path): 113 | Deveal.__print_error("Directory {} not found".format(work_path)) 114 | return 127 115 | 116 | try: 117 | subprocess.run(["git", "--version"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 118 | except subprocess.SubprocessError: 119 | Deveal.__print_error("Git not found") 120 | return 127 121 | 122 | is_git_workdir = True 123 | try: 124 | subprocess.run(["git", "status"], cwd=work_path, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 125 | except subprocess.SubprocessError: 126 | is_git_workdir = False 127 | 128 | if is_git_workdir: 129 | print("Adding reveal.js as git submodule") 130 | try: 131 | subprocess.run( 132 | ['git', 'submodule', 'add', 'https://github.com/hakimel/reveal.js.git', REVEAL_CLONE_DIR], 133 | cwd=work_path 134 | ) 135 | except subprocess.SubprocessError: 136 | return 127 137 | else: 138 | print("Cloning reveal.js in subdirectory") 139 | try: 140 | subprocess.run( 141 | ['git', 'clone', 'https://github.com/hakimel/reveal.js.git', REVEAL_CLONE_DIR], 142 | cwd=work_path 143 | ) 144 | except subprocess.SubprocessError: 145 | return 127 146 | 147 | return 0 148 | 149 | def run_build(self, args): 150 | vars = self.__build_vars() 151 | 152 | try: 153 | tpl_filename = "deveal-index.html" 154 | generated_content = jinja2.Environment( 155 | loader=jinja2.FileSystemLoader(os.getcwd()) 156 | ).get_template(tpl_filename).render(**vars) 157 | except jinja2.TemplateSyntaxError as e: 158 | Deveal.__print_error("Template problem : {} (file {}, line {})".format(e.message, e.filename, e.lineno)) 159 | return 127 160 | except jinja2.TemplateNotFound: 161 | Deveal.__print_error("Template not found") 162 | return 127 163 | except jinja2.TemplateError: 164 | Deveal.__print_error("Unknown template problem") 165 | return 127 166 | 167 | outFile = open(os.path.join(os.getcwd(), "index.html"), "w") 168 | outFile.write(generated_content) 169 | outFile.close() 170 | print("Build on {}".format(time.strftime("%Y-%d-%m %H:%M:%S"))) 171 | 172 | return 0 173 | 174 | def on_any_event(self, event): 175 | if event.src_path != os.path.join(os.getcwd(), "index.html"): 176 | print("{} is {}".format(os.path.relpath(event.src_path), event.event_type)) 177 | self.run_build(dict()) 178 | 179 | def run_watch(self, args): 180 | print("Watching {} ...".format(os.getcwd())) 181 | obs = Observer(timeout=0.1) 182 | obs.schedule(self, path=os.getcwd(), recursive=True) 183 | obs.start() 184 | 185 | try: 186 | while True: 187 | time.sleep(1) 188 | except KeyboardInterrupt: 189 | print("") 190 | print("Interrupted by keyboard...") 191 | obs.stop() 192 | 193 | obs.join() 194 | print("Done") 195 | 196 | return 0 197 | 198 | 199 | ############################################################################## 200 | 201 | 202 | def main(): 203 | 204 | parser = argparse.ArgumentParser( 205 | description="Helper tool for creation and management of reveal.js slideshows") 206 | 207 | subparsers = parser.add_subparsers(dest="command_name") 208 | 209 | parser_new = subparsers.add_parser("new", help="create new reveal.js slideshow") 210 | parser_new.add_argument("path", type=str) 211 | parser_new.add_argument("--with-reveal", action="store_true", 212 | help="donwloads the reveal repository in a subdirectory (requires git)") 213 | subparsers.add_parser("build", help="build reveal.js slideshow") 214 | subparsers.add_parser("watch", help="watch for changes and build reveal.js slideshow") 215 | subparsers.add_parser("reveal", help="donwload the reveal repository in a subdirectory (requires git)") 216 | subparsers.add_parser("version", help="show deveal version") 217 | 218 | cmd_args = vars(parser.parse_args()) 219 | 220 | dvl = Deveal() 221 | 222 | if cmd_args["command_name"] == "new": 223 | return dvl.run_new(cmd_args) 224 | elif cmd_args["command_name"] == "reveal": 225 | return dvl.run_reveal(cmd_args) 226 | elif cmd_args["command_name"] == "build": 227 | return dvl.run_build(cmd_args) 228 | elif cmd_args["command_name"] == "watch": 229 | return dvl.run_watch(cmd_args) 230 | elif cmd_args["command_name"] == "version": 231 | print(__version__) 232 | else: 233 | parser.print_help() 234 | --------------------------------------------------------------------------------