]> rtime.felk.cvut.cz Git - pes-rpp/rpp-simulink.git/blob - rpp/blocks/scripts/doc_parse.py
doc: Update mode parameters of block Mask automatically
[pes-rpp/rpp-simulink.git] / rpp / blocks / scripts / doc_parse.py
1 #!/usr/bin/env python3
2
3 import yaml
4 import argparse
5 import Rx
6 import sys
7 import subprocess
8 import os
9 from string import Template
10
11 parser = argparse.ArgumentParser()
12 parser.add_argument("file", help="file to process", nargs='+')
13 parser.add_argument("--html", help="output block description as HTML",
14                     action = 'store_true')
15 parser.add_argument("--latex", help="output block description as LaTeX",
16                     action = 'store_true')
17 parser.add_argument("--latex-table", help="output block status table as LaTeX",
18                     action = 'store_true')
19 parser.add_argument('--maskpromptstring', help="output prompt strings for Simulink mask",
20                     action = 'store_true')
21 parser.add_argument('--masktype', help="output mask type for Simulink mask",
22                     action = 'store_true')
23 args = parser.parse_args()
24
25 mydir = os.path.dirname(os.path.realpath(__file__))
26
27 def print_markdown_as(format, text):
28     sys.stdout.flush()
29     proc = subprocess.Popen(['pandoc', '-f', 'markdown', '-t', format], stdin = subprocess.PIPE)
30     proc.stdin.write(bytes(text, 'UTF-8'))
31     proc.communicate()
32     proc.stdin.close()
33     if proc.returncode:
34         raise Exception("pandoc failed: %d" % proc.returncode)
35
36 def print_latex_desc(doc):
37     def iodef_str(iodef):
38         if iodef is None: return "None"
39         str='%d\n\\begin{enumerate}\n' % len(iodef)
40         for io in iodef:
41             str += Template('\\item {\\bf $name} $type').substitute(io)
42             if 'range' in io:
43                 str += '  %s' % io['range']
44             str += '\n'
45         return str +'\end{enumerate}'
46
47     print("\\newpage\n")
48     print("\\subsubsection{%s}\n" % doc['Name'])
49     print("\\begin{description}\n")
50     print("\\item[Inputs:]     %s\n" % iodef_str(doc['Inputs']))
51     print("\\item[Outputs:]    %s\n" % iodef_str(doc['Outputs']))
52     print("\\item[Parameters:] %s\n" % iodef_str(doc['Parameters']))
53     print("\\end{description}\n")
54
55     print_markdown_as('latex', doc['Description'])
56
57     print("\n\\textbf{Status:}")
58     print("\\begin{multicols}{3}")
59     if doc['Status']['Tested']:
60         print("\\begin{compactitem}")
61         print("\\item \\textbf{Tested}:")
62         print(" \\begin{compactitem}")
63         print("\n".join(["\\item %s" % i.replace('_', '\\_') for i in doc['Status']['Tested']]))
64         print(" \\end{compactitem}")
65         print("\\end{compactitem}")
66     else:
67         print("\\ ")
68
69     print("\\vfill\\columnbreak")
70
71     if doc['Status']['Untested']:
72         print("\\begin{compactitem}")
73         print("\\item \\textbf{Untested}:")
74         print(" \\begin{compactitem}")
75         print("\n".join(["\\item %s" % i.replace('_', '\\_') for i in doc['Status']['Untested']]))
76         print(" \\end{compactitem}")
77         print("\\end{compactitem}")
78     else:
79         print("\\ ")
80
81     print("\\vfill\\columnbreak")
82
83     if doc['Status']['Not working']:
84         print("\\begin{compactitem}")
85         print("\\item \\textbf{Not working}:")
86         print(" \\begin{compactitem}")
87         print("\n".join(["\\item %s" % i.replace('_', '\\_') for i in doc['Status']['Not working']]))
88         print(" \\end{compactitem}")
89         print("\\end{compactitem}")
90     else:
91         print("\\ ")
92
93     print("\\end{multicols}\n")
94
95     if doc.get('RPP API functions used', None) is not None:
96         print("\\textbf{RPP API functions used:}")
97         print("\\begin{compactitem}")
98         print("\n".join(["\\item \\texttt{%s}" % i.replace('_', '\\_') for i in doc['RPP API functions used']]))
99         print("\\end{compactitem}")
100
101     if doc.get('Relevant demos', None) is not None:
102         print("\\textbf{Relevant demos:}")
103         print("\\begin{compactitem}")
104         print("\n".join(["\\item %s" % i.replace('_', '\\_') for i in doc['Relevant demos']]))
105         print("\\end{compactitem}")
106
107 def process_file(f):
108     yaml_doc = None
109     for line in open(f, 'r'):
110         if yaml_doc:
111             yaml_doc += line
112         elif line.startswith("%YAML"):
113             yaml_doc = line
114         if line == '...\n':
115             break
116     if yaml_doc is None:
117         raise Exception("No line starting with '%%YAML' found in %s" % f)
118
119     doc = yaml.load(yaml_doc)
120     schema = yaml.load(open(mydir+'/schema.yaml', 'r'))
121
122     rx = Rx.Factory({ "register_core_types": True })
123     rpp_block_doc_schema = rx.make_schema(schema)
124     try:
125         rpp_block_doc_schema.check(doc)
126     except Rx.ValidationError as e:
127         raise Exception("Validation error in %s: %s" % (f, e))
128         #raise
129
130     if args.html:
131         print_markdown_as('html', doc['Description'])
132     if args.latex:
133         print_latex_desc(doc)
134     if args.latex_table:
135         global last_category
136         if last_category == doc['Category']: doc['Category']=''
137         doc['Header'] = doc['Header'].replace('_', '\\_')
138         if   doc['Status']['Not working']: doc['ShortStatus'] = '$\\alpha$'
139         elif doc['Status']['Untested']:    doc['ShortStatus'] = '$\\beta$'
140         elif not doc['Status']['Tested']:  doc['ShortStatus'] = '$\\beta$'
141         else:                              doc['ShortStatus'] = 'Stable'
142         print(Template("$Category & $Name & $ShortStatus & $Mnemonic & \\texttt{$Header} \\\\").substitute(doc))
143         if doc['Category']:
144             last_category = doc['Category']
145     if args.masktype:
146         print('RPP {name}'.format(name=doc['Name']))
147     if args.maskpromptstring and doc['Parameters'] != None:
148         print('|'.join(['{name}{range}:'.format(name=par['name'],
149                                                 range=(' '+par['range'] if ('range' in par and (par['type'] in ['double'] or
150                                                                                                 'int' in par['type']))
151                                                        else ''))
152                         for par in doc['Parameters']]))
153
154 last_category = None
155 for f in args.file:
156     process_file(f)