]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - doc/macro2rst.py
Documentation fixup: made filenames more descriptive, switched parsing utility to...
[bcachefs-tools-debian] / doc / macro2rst.py
diff --git a/doc/macro2rst.py b/doc/macro2rst.py
new file mode 100755 (executable)
index 0000000..e80f7ed
--- /dev/null
@@ -0,0 +1,85 @@
+#!/usr/bin/env python3
+'''
+A utility script for generating documentation.
+
+Preprocessor macro output from opts_macro.h is parsed and combined with
+bcachefs.5.rst.tmpl to generate bcachefs.5.rst.
+
+>=python3.6
+'''
+
+import sys
+import re
+
+INDENT = '       '
+TEMPLATE = './doc/bcachefs.5.rst.tmpl'
+RST_FILE= './doc/bcachefs.5.rst'
+SANITIZE_CHARS = [
+            '\\\\n',
+            '\\n',
+            '  ',
+            '"',
+            '\\',
+        ]
+
+def sanitize(text):
+    '''
+    Parses opts_macro.h preprocessor output
+    :param text: text to sanitize
+    :type text: str
+    :returns: a list of options
+    :rtype: list
+    '''
+
+    args = []
+    reg = re.search('FMT_START_SECTION(.*)FMT_END_SECTION', text,
+            flags=re.DOTALL)
+    if not reg:
+        raise re.error('no text found')
+
+    # decoding would probably be better, but this works
+    for char in SANITIZE_CHARS:
+        text = text.replace(char, '')
+
+    text = re.split(r'FMT_END_LINE', text)
+
+    # this seemed easier than getting preprocessor macros to play nice
+    # with python's builtin csv module
+    for line in text:
+        vals = line.split(';')
+        if not vals:
+            continue
+        if len(vals) != 4:
+            continue
+        vals = list(map(str.strip, vals))
+        name, is_bool, desc, arg_name = vals
+
+        # this macro value from opts.h indicates that no values are passed
+        if is_bool == 'OPT_BOOL()':
+            args.append(f'--{name}\n{INDENT}{desc}')
+        else:
+            args.append(f'--{name} <{arg_name}>\n{INDENT}{desc}')
+    if not args:
+        raise re.error('no args found, likely parsing error')
+
+    return args
+
+
+def main():
+    ''' Transform stdin to option list and write templated output to new file '''
+    out = ''
+
+    stdin = sys.stdin.read()
+    opts = sanitize(stdin)
+    opts = '\n'.join(opts)
+
+    # Insert into template
+    with open(TEMPLATE, 'r') as in_handle:
+        in_handle = in_handle.read()
+    out = in_handle.replace('OPTIONS_TABLE', opts)
+    with open(RST_FILE, 'w') as out_handle:
+        out_handle.write(out)
+
+
+if __name__ == '__main__':
+    main()