]> rtime.felk.cvut.cz Git - pes-rpp/rpp-simulink.git/blob - rpp/blocks/scripts/doc_parse.py
759af56278a22279ea84cb15c44019c6fa601e23
[pes-rpp/rpp-simulink.git] / rpp / blocks / scripts / doc_parse.py
1 #!/usr/bin/env python3
2
3 # Copyright (C) 2013-2015, 2019 Czech Technical University in Prague
4 #
5 # Authors:
6 #     - Michal Sojka <sojkam1@fel.cvut.cz>
7 #
8 # This document contains proprietary information belonging to Czech
9 # Technical University in Prague. Passing on and copying of this
10 # document, and communication of its contents is not permitted
11 # without prior written authorization.
12 #
13 # File : doc_parse.py
14 # Abstract:
15
16 import yaml
17 import argparse
18 import Rx
19 import sys
20 import subprocess
21 import os
22 import os.path
23 from string import Template
24
25 parser = argparse.ArgumentParser()
26 parser.add_argument("file", help="file to process", nargs='+')
27 parser.add_argument("--html", help="output block description or help as HTML",
28                     action = 'store_true')
29 parser.add_argument("--latex", help="output block description as LaTeX",
30                     action = 'store_true')
31 parser.add_argument("--latex-table", help="output block status table as LaTeX",
32                     action = 'store_true')
33 parser.add_argument('--printdesc', help="output block description",
34                     action = 'store_true')
35 parser.add_argument('--printhelp', help="output block help",
36                     action = 'store_true')
37 parser.add_argument('--maskpromptstring', help="output prompt strings for Simulink mask",
38                     action = 'store_true')
39 parser.add_argument('--masktype', help="output mask type for Simulink mask",
40                     action = 'store_true')
41 parser.add_argument('--name', help="print block name",
42                     action = 'store_true')
43 args = parser.parse_args()
44
45 mydir = os.path.dirname(os.path.realpath(__file__))
46
47 def markdown_as(format, text):
48     sys.stdout.flush()
49     proc = subprocess.Popen(['pandoc', '-f', 'markdown-smart', '-t', format], stdin = subprocess.PIPE, stdout = subprocess.PIPE)
50     proc.stdin.write(bytes(text, 'UTF-8'))
51     (stdout, stderr) = proc.communicate()
52     proc.stdin.close()
53     if proc.returncode:
54         raise Exception("pandoc failed: %d" % proc.returncode)
55     return stdout.decode('utf-8').rstrip()
56
57 def print_markdown_as(format, text):
58     print(markdown_as(format, text))
59
60 def print_latex_desc(doc, filename):
61     def iodef_str(iodef):
62         if iodef is None: return "None"
63         str ='~\n\n\\smallskip\\noindent\\begin{tabularx}{\\textwidth}{|r|l|l|X|}\n'
64         str += '\\hline\n'
65         str += '~ & \\textbf{Name} & \\textbf{Type} & \\textbf{Range or notes} \\\\ \\hline \n'
66         i = 1
67         for io in iodef:
68             str += Template('%d. & $name & $type &' % i).substitute(io)
69             if 'range' in io:
70                 str += '  %s' % markdown_as('latex', io['range'])
71             if 'note' in io:
72                 str += '  %s' % markdown_as('latex', io['note'])
73             str += '\\\\ \\hline\n'
74             i += 1
75         return str +'\\end{tabularx}'
76
77     print("\\newpage\n")
78     print("\\subsection{%s}" % doc['Name'])
79     print("\\label{sec:block:%s}\n" % os.path.basename(filename))
80     print("\\paragraph{Inputs:}     %s\n" % iodef_str(doc['Inputs']))
81     print("\\paragraph{Outputs:}    %s\n" % iodef_str(doc['Outputs']))
82     print("\\paragraph{Parameters:} %s\n" % iodef_str(doc['Parameters']))
83     print("\\paragraph{Description:}\n")
84
85     print_markdown_as('latex', doc['Help'])
86
87     if doc.get('RPP API functions used', None) is not None:
88         print("\\paragraph{RPP API functions used:}")
89         print("\\begin{compactitem}")
90         print("\n".join(["\\item \\texttt{%s}" % i.replace('_', '\\_') for i in doc['RPP API functions used']]))
91         print("\\end{compactitem}")
92
93     if doc.get('Relevant demos', None) is not None:
94         print("\\paragraph{Relevant demos:}")
95         print("\\begin{compactitem}")
96         print("\n".join(["\\item %s" % i.replace('_', '\\_') for i in doc['Relevant demos']]))
97         print("\\end{compactitem}")
98
99 def process_file(f):
100     yaml_doc = None
101     for line in open(f, 'r'):
102         if yaml_doc:
103             yaml_doc += line
104         elif line.startswith("%YAML"):
105             yaml_doc = line
106         if line == '...\n':
107             break
108     if yaml_doc is None:
109         raise Exception("No line starting with '%%YAML' found in %s" % f)
110
111     doc = yaml.load(yaml_doc)
112     schema = yaml.load(open(mydir+'/schema.yaml', 'r'))
113
114     rx = Rx.Factory({ "register_core_types": True })
115     rpp_block_doc_schema = rx.make_schema(schema)
116     try:
117         rpp_block_doc_schema.check(doc)
118     except Rx.ValidationError as e:
119         raise Exception("Validation error in %s: %s" % (f, e))
120         #raise
121
122     fmt = 'html' if args.html else 'markdown'
123
124     if args.printdesc:
125         print_markdown_as(fmt, doc['Description'])
126     if args.printhelp:
127         print_markdown_as(fmt, doc['Help'])
128     if args.latex:
129         print_latex_desc(doc, f)
130     if args.latex_table:
131         global last_category
132         if last_category == doc['Category']: doc['Category']=''
133         doc['Header'] = doc['Header'].replace('_', '\\_')
134         print(Template("$Category & $Name & $Status & $Mnemonic & \\texttt{$Header} \\\\").substitute(doc))
135         if doc['Category']:
136             last_category = doc['Category']
137     if args.masktype:
138         print('RPP {name}'.format(name=doc['Name']))
139     if args.name:
140         print(doc['Name'])
141     if args.maskpromptstring and doc['Parameters'] != None:
142         print('|'.join(['{name}{range}{colon}'.format(name=par['name'],
143                                                       range=(' '+par['range'] if ('range' in par and (par['type'] in ['double'] or
144                                                                                                 'int' in par['type']))
145                                                              else ''),
146                                                       colon=':' if par['type'] != 'bool' else '')
147                         for par in doc['Parameters']]))
148
149 last_category = None
150 for f in args.file:
151     process_file(f)