Generate command line options for sphinx docs (#6555)
authorGereon Kremer <nafur42@gmail.com>
Wed, 19 May 2021 05:55:53 +0000 (07:55 +0200)
committerGitHub <noreply@github.com>
Wed, 19 May 2021 05:55:53 +0000 (05:55 +0000)
This PR adds documentation about the command line options to the sphinx documentation. It is mostly a reformatted version of what --help would print.

25 files changed:
docs/CMakeLists.txt
docs/_static/custom.css
docs/conf.py.in
docs/ext/include_build_file.py [new file with mode: 0644]
docs/index.rst
docs/options.rst [new file with mode: 0644]
src/options/CMakeLists.txt
src/options/arith_options.toml
src/options/arrays_options.toml
src/options/booleans_options.toml
src/options/builtin_options.toml
src/options/bv_options.toml
src/options/datatypes_options.toml
src/options/decision_options.toml
src/options/expr_options.toml
src/options/fp_options.toml
src/options/mkoptions.py
src/options/prop_options.toml
src/options/resource_manager_options.toml
src/options/sep_options.toml
src/options/sets_options.toml
src/options/smt_options.toml
src/options/strings_options.toml
src/options/theory_options.toml
src/options/uf_options.toml

index 4c5d9aa6c4b595636bc0ffa3973e09d37fef821f..99c4f3ab3a875d9c4556b7d4aa93d44cb8c8a7c1 100644 (file)
@@ -26,7 +26,7 @@ set(SPHINX_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/sphinx)
 configure_file(conf.py.in ${CMAKE_CURRENT_BINARY_DIR}/conf.py)
 
 add_custom_target(docs ALL
-                  DEPENDS docs-cpp docs-python
+                  DEPENDS docs-cpp docs-python gen-options
                   COMMAND
                     ${SPHINX_EXECUTABLE} -b html
                     -c ${CMAKE_CURRENT_BINARY_DIR}
index a0348f9edd58bb1ddaef238e4dff2216bb26d3c8..f657196ed7116f65477a6f1aa379b2f32587ec45 100644 (file)
@@ -20,6 +20,7 @@ code.xref {
 
 .rst-content code {
     padding: 1px !important;
+    background: unset !important;
 }
 
 a {
index f6e75b9b5cd00c97506a99d188bb64b460dadd5c..07a4d8a76d82d4ebf0c62e7f1f577cbc32206095 100644 (file)
@@ -43,6 +43,7 @@ extensions = [
         'sphinxcontrib.bibtex',
         'sphinx_tabs.tabs',
         'examples',
+        'include_build_file',
 ]
 
 bibtex_bibfiles = ['references.bib']
@@ -69,3 +70,6 @@ html_css_files = ['custom.css']
 # -- Breathe configuration ---------------------------------------------------
 breathe_default_project = "cvc5"
 breathe_domain_by_extension = {"h" : "cpp"}
+
+# where to look for include-build-file
+ibf_folders = ['${CMAKE_CURRENT_BINARY_DIR}']
diff --git a/docs/ext/include_build_file.py b/docs/ext/include_build_file.py
new file mode 100644 (file)
index 0000000..02da604
--- /dev/null
@@ -0,0 +1,44 @@
+import os
+
+from docutils import nodes
+from docutils.parsers.rst import Directive
+from docutils.statemachine import StringList
+from sphinx.util.docutils import SphinxDirective
+from sphinx.util.nodes import nested_parse_with_titles
+
+class IncludeBuildFile(SphinxDirective):
+    """Add directive `include-build-file` to be used as follows:
+
+        .. include-build-file:: <filename>
+
+    The argument should be a filename of an rst files within one of the
+    folders given by the `ibf_folders` config option.
+    """
+
+    # The "arguments" are actually the content of the directive
+    has_content = True
+
+    def run(self):
+        filename = ''.join(self.content)
+        for folder in self.env.config.ibf_folders:
+            candidate = os.path.join(folder, filename)
+            if os.path.isfile(candidate):
+                filename = candidate
+                break
+        content = open(filename).readlines()
+        content = [line.rstrip('\n') for line in content]
+        # parse the string list
+        node = nodes.Element()
+        nested_parse_with_titles(self.state, StringList(content), node)
+        self.state.document.settings.env.note_dependency(filename)
+        return node.children
+
+
+def setup(app):
+    app.add_config_value('ibf_folders', [], 'env')
+    app.add_directive('include-build-file', IncludeBuildFile)
+    return {
+        'version': '0.1',
+        'parallel_read_safe': True,
+        'parallel_write_safe': True,
+    }
index 14adad0fc6f088c3eb4a86f0ce66bef7d267292b..8d77790fb4a1e66335454ae68ba025393d6dc65c 100644 (file)
@@ -19,3 +19,4 @@ cvc5 API Documentation
    python/python
    references
    examples/examples
+   options
diff --git a/docs/options.rst b/docs/options.rst
new file mode 100644 (file)
index 0000000..6f9c613
--- /dev/null
@@ -0,0 +1,5 @@
+Commandline Options
+===================
+
+.. include-build-file:: options_generated.rst
+
index 078c2ad3183950b65b6f6b22950f1fb2aba49b55..997c6850a8e3938f983d5894a980f99b3642946c 100644 (file)
@@ -74,10 +74,12 @@ add_custom_command(
     OUTPUT
       options.h options.cpp
       ${options_gen_cpp_files} ${options_gen_h_files}
+      ${CMAKE_BINARY_DIR}/docs/options_generated.rst
     COMMAND
       ${PYTHON_EXECUTABLE}
       ${CMAKE_CURRENT_LIST_DIR}/mkoptions.py
       ${CMAKE_CURRENT_LIST_DIR}
+      ${CMAKE_BINARY_DIR}
       ${CMAKE_CURRENT_BINARY_DIR}
       ${abs_toml_files}
     DEPENDS
index a52f2144eb2bf392fc8b36728cc4adb173ad6f40..472657274a30b023eb6b1e82d192354e5b80b5f0 100644 (file)
@@ -1,5 +1,5 @@
 id     = "ARITH"
-name   = "Arithmetic theory"
+name   = "Arithmetic Theory"
 
 [[option]]
   name       = "arithUnateLemmaMode"
index 6017edfd55406d671826309eaf2349111c969631..4cb6dda1d9b488065d8ce53b95ad996edc9ed1a9 100644 (file)
@@ -1,5 +1,5 @@
 id     = "ARRAYS"
-name   = "Arrays theory"
+name   = "Arrays Theory"
 
 [[option]]
   name       = "arraysOptimizeLinear"
index 52725bb8e60fd8f4af204849cbbfe1aae2d7f04a..4aa46cfa2df0f0a589512a43e77d03cb7f5d6201 100644 (file)
@@ -1,3 +1,3 @@
 id     = "BOOLEANS"
-name   = "Boolean theory"
+name   = "Boolean Theory"
 
index b5f2ed593d6aaa2ba4ca0a69302c081def1585b0..e4d4296fa3ff7fa94c859468beef5313b7b5dda9 100644 (file)
@@ -1,3 +1,3 @@
 id     = "BUILTIN"
-name   = "Builtin theory"
+name   = "Builtin Theory"
 
index 6cbf9cf37d72f8434da1ec6a4461e5408cb82041..e5b96b54ae7b02ca700a89134329b14cadd58965 100644 (file)
@@ -1,5 +1,5 @@
 id     = "BV"
-name   = "Bitvector theory"
+name   = "Bitvector Theory"
 
 [[option]]
   name       = "bvSatSolver"
index 7c6a550952c93d2c151f81711e483faed2d6285f..80dedfb70fdec5545c301b29ed6b3e9378aaf2d0 100644 (file)
@@ -1,5 +1,5 @@
 id     = "DATATYPES"
-name   = "Datatypes theory"
+name   = "Datatypes Theory"
 
 # How to handle selectors applied to incorrect constructors.  If this option is set,
 # then we do not rewrite such a selector term to an arbitrary ground term.  
index b3d18aebff368a720db73f7b5965a0d2cf91285c..b6f5a5c1bac53f08a54de48039ef5400c3c92a2d 100644 (file)
@@ -1,5 +1,5 @@
 id     = "DECISION"
-name   = "Decision heuristics"
+name   = "Decision Heuristics"
 
 [[option]]
   name       = "decisionMode"
index 94a9db05b3614f611f6936f9a4b163a9f3e5d53d..ecd0bcf95ddb743acd64de0debd63029f33dea1b 100644 (file)
@@ -1,5 +1,5 @@
 id     = "EXPR"
-name   = "Expression package"
+name   = "Expression"
 
 [[option]]
   name       = "defaultExprDepth"
index d726cec3b2451613802e64cbad903644d5ddad63..6fd632a7c0a5fb229242b3bcbb30b10ae722c5f1 100644 (file)
@@ -1,5 +1,5 @@
 id     = "FP"
-name   = "Fp"
+name   = "Floating-Point"
 
 [[option]]
   name       = "fpExp"
index 4c3524456d2438d81d62ce58c50085516904a42a..4cc814a61f90cb0608310ae8be38e23798e43492 100644 (file)
@@ -298,6 +298,104 @@ class Option(object):
                 self.long_opt = r[1]
 
 
+class SphinxGenerator:
+    def __init__(self):
+        self.common = []
+        self.others = {}
+
+    def add(self, module, option):
+        if option.category == 'undocumented':
+            return
+        if not option.long and not option.short:
+            return
+        names = []
+        if option.long:
+            if option.long_opt:
+                names.append('--{}={}'.format(option.long_name, option.long_opt))
+            else:
+                names.append('--{}'.format(option.long_name))
+        
+        if option.alias:
+            if option.long_opt:
+                names.extend(['--{}={}'.format(a, option.long_opt) for a in option.alias])
+            else:
+                names.extend(['--{}'.format(a) for a in option.alias])
+
+        if option.short:
+            if option.long_opt:
+                names.append('-{} {}'.format(option.short, option.long_opt))
+            else:
+                names.append('-{}'.format(option.short))
+        
+        modes = None
+        if option.mode:
+            modes = {}
+            for _, data in option.mode.items():
+                assert len(data) == 1
+                data = data[0]
+                modes[data['name']] = data.get('help', '')
+
+        data = {
+            'name': names,
+            'help': option.help,
+            'expert': option.category == 'expert',
+            'alternate': option.type == 'bool' and option.alternate,
+            'help_mode': option.help_mode,
+            'modes': modes,
+        }
+
+        if option.category == 'common':
+            self.common.append(data)
+        else:
+            if module.name not in self.others:
+                self.others[module.name] = []
+            self.others[module.name].append(data)
+    
+    def __render_option(self, res, opt):
+        desc = '``{}``'
+        val = '    {}'
+        if opt['expert']:
+            res.append('.. admonition:: This option is intended for Experts only!')
+            res.append('    ')
+            desc = '    ' + desc
+            val = '    ' + val
+
+        if opt['alternate']:
+            desc += ' (also ``--no-*``)'
+        res.append(desc.format(' | '.join(opt['name'])))
+        res.append(val.format(opt['help']))
+
+        if opt['modes']:
+            print(opt['modes'])
+            res.append(val.format(''))
+            res.append(val.format(opt['help_mode']))
+            res.append(val.format(''))
+            for k, v in opt['modes'].items():
+                res.append(val.format(':{}: {}'.format(k, v)))
+        res.append('    ')
+
+
+    def render(self, dstdir, filename):
+        res = []
+
+        res.append('Most Commonly-Used cvc5 Options')
+        res.append('===============================')
+        for opt in self.common:
+            self.__render_option(res, opt)
+
+        res.append('')
+        res.append('Additional cvc5 Options')
+        res.append('=======================')
+        for module in self.others:
+            res.append('')
+            res.append('{} Module'.format(module))
+            res.append('-' * (len(module) + 8))
+            for opt in self.others[module]:
+                self.__render_option(res, opt)
+
+        write_file(dstdir, filename, '\n'.join(res))
+
+
 def die(msg):
     sys.exit('[error] {}'.format(msg))
 
@@ -626,7 +724,7 @@ def add_getopt_long(long_name, argument_req, getopt_long):
             'required' if argument_req else 'no', value))
 
 
-def codegen_all_modules(modules, dst_dir, tpl_options_h, tpl_options_cpp):
+def codegen_all_modules(modules, build_dir, dst_dir, tpl_options_h, tpl_options_cpp):
     """
     Generate code for all option modules (options.cpp, options_holder.h).
     """
@@ -645,6 +743,8 @@ def codegen_all_modules(modules, dst_dir, tpl_options_h, tpl_options_cpp):
     setoption_handlers = []  # handlers for set-option command
     getoption_handlers = []  # handlers for get-option command
 
+    sphinxgen = SphinxGenerator()
+
     for module in modules:
         headers_module.append(format_include(module.header))
 
@@ -660,6 +760,8 @@ def codegen_all_modules(modules, dst_dir, tpl_options_h, tpl_options_cpp):
 
             docgen_option(option, help_common, help_others)
 
+            sphinxgen.add(module, option)
+
             # Generate handler call
             handler = None
             if option.handler:
@@ -885,6 +987,8 @@ def codegen_all_modules(modules, dst_dir, tpl_options_h, tpl_options_cpp):
         getoption_handlers='\n'.join(getoption_handlers)
     ))
 
+    if os.path.isdir('{}/docs/'.format(build_dir)):
+        sphinxgen.render('{}/docs/'.format(build_dir), 'options_generated.rst')
 
 def lstrip(prefix, s):
     """
@@ -1010,8 +1114,9 @@ def mkoptions_main():
         die('missing arguments')
 
     src_dir = sys.argv[1]
-    dst_dir = sys.argv[2]
-    filenames = sys.argv[3:]
+    build_dir = sys.argv[2]
+    dst_dir = sys.argv[3]
+    filenames = sys.argv[4:]
 
     # Check if given directories exist.
     for d in [src_dir, dst_dir]:
@@ -1052,7 +1157,7 @@ def mkoptions_main():
         codegen_module(module, dst_dir, tpl_module_h, tpl_module_cpp)
 
     # Create options.cpp and options_holder.h in destination directory
-    codegen_all_modules(modules, dst_dir, tpl_options_h, tpl_options_cpp)
+    codegen_all_modules(modules, build_dir, dst_dir, tpl_options_h, tpl_options_cpp)
 
 
 
index 69dad8d63a77f3e6f26a7af189c01a035286b1c5..26d7a451bda4f94fb0f8b951b82a46592c18303f 100644 (file)
@@ -1,5 +1,5 @@
 id     = "PROP"
-name   = "SAT layer"
+name   = "SAT Layer"
 
 [[option]]
   name       = "satRandomFreq"
index 88bacce1b76522f30e0733b01e21247d63ef506d..6d5c4d4cf2663dac6fb17e2d07ee1bb0b910dd45 100644 (file)
@@ -1,5 +1,5 @@
 id     = "RESMAN"
-name   = "Resource Manager options"
+name   = "Resource Manager"
 
 [[option]]
   name       = "cumulativeMillisecondLimit"
index f45e78c980c029d205f1b97e20e65dd2e6b643c5..7185a35df9ca885be880b6d7b27908c46c371ee3 100644 (file)
@@ -1,5 +1,5 @@
 id     = "SEP"
-name   = "Sep"
+name   = "Separation Logic Theory"
 
 [[option]]
   name       = "sepCheckNeg"
index db9cfa480329ef6d4e693760101008ac21424693..dee134ae4d4f86f3a88c544656f26aee0b5ba39e 100644 (file)
@@ -1,5 +1,5 @@
 id     = "SETS"
-name   = "Sets"
+name   = "Sets Theory"
 
 [[option]]
   name       = "setsProxyLemmas"
index 22d05f6f718164956560b909320519c9a85b6dbb..733c2239cea90d382d75d58904bdf16aa9e2d576 100644 (file)
@@ -1,5 +1,5 @@
 id     = "SMT"
-name   = "SMT layer"
+name   = "SMT Layer"
 
 [[option]]
   name       = "dumpModeString"
index 44c9c191fe3b835f4c21cff2f3d02a9ca76b45c2..958136494276c153f77423dff5da7f9b42f0b7da 100644 (file)
@@ -1,5 +1,5 @@
 id     = "STRINGS"
-name   = "Strings theory"
+name   = "Strings Theory"
 
 [[option]]
   name       = "stringExp"
index ec11d17ec9e9e757471e5ef4fa11309de9cf2d71..f4790768309601176c4ea40d93fe2b6293bd7ac0 100644 (file)
@@ -1,5 +1,5 @@
 id     = "THEORY"
-name   = "Theory layer"
+name   = "Theory Layer"
 
 [[option]]
   name       = "theoryOfMode"
index 81b119964ff5f5a59e9e8333b71fee7fb6c0aafe..058d8be277c34cfc249e317a8fc56bdaa6316fc2 100644 (file)
@@ -1,5 +1,5 @@
 id     = "UF"
-name   = "Uninterpreted functions theory"
+name   = "Uninterpreted Functions Theory"
 
 [[option]]
   name       = "ufSymmetryBreaker"