From: Angus Gratton Date: Tue, 20 Mar 2018 05:31:53 +0000 (+1100) Subject: doc: Use confgen.py to build docs from same code path as config generation X-Git-Tag: v3.1-rc2~9^2~38 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2a3e2b8eed79c2f755c7e57e97199792d72d3c18;p=esp-idf doc: Use confgen.py to build docs from same code path as config generation --- diff --git a/docs/conf_common.py b/docs/conf_common.py index e5dd9df6e0..16efc9d3c4 100644 --- a/docs/conf_common.py +++ b/docs/conf_common.py @@ -16,7 +16,7 @@ import sys, os import re -from subprocess import Popen, PIPE +import subprocess import shlex # Note: If extensions (or modules to document with autodoc) are in another directory, @@ -41,9 +41,21 @@ copy_if_modified('xml/', 'xml_in/') os.system('python ../gen-dxd.py') # Generate 'kconfig.inc' file from components' Kconfig files +print "Generating kconfig.inc from kconfig contents" kconfig_inc_path = '{}/inc/kconfig.inc'.format(builddir) -os.system('python ../gen-kconfig-doc.py > ' + kconfig_inc_path + '.in') -copy_if_modified(kconfig_inc_path + '.in', kconfig_inc_path) +temp_sdkconfig_path = '{}/sdkconfig.tmp'.format(builddir) +kconfigs = subprocess.check_output(["find", "../../components", "-name", "Kconfig"]) +kconfig_projbuilds = subprocess.check_output(["find", "../../components", "-name", "Kconfig.projbuild"]) +confgen_args = ["python", + "../../tools/kconfig_new/confgen.py", + "--kconfig", "../../Kconfig", + "--config", temp_sdkconfig_path, + "--create-config-if-missing", + "--env", "COMPONENT_KCONFIGS={}".format(kconfigs), + "--env", "COMPONENT_KCONFIGS_PROJBUILD={}".format(kconfig_projbuilds), + "--output", "docs", kconfig_inc_path +] +subprocess.check_call(confgen_args) # http://stackoverflow.com/questions/12772927/specifying-an-online-image-in-sphinx-restructuredtext-format # diff --git a/docs/gen-kconfig-doc.py b/docs/gen-kconfig-doc.py deleted file mode 100755 index a141641199..0000000000 --- a/docs/gen-kconfig-doc.py +++ /dev/null @@ -1,120 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# gen-kconfig-doc.py — generate Sphinx .rst file from Kconfig files -# -# This script iterates over Kconfig and Kconfig.projbuild files in -# ESP-IDF component directories, and outputs documentation for these options -# as ReST markup. -# For each option in Kconfig file (e.g. 'FOO'), CONFIG_FOO link target is -# generated, allowing options to be referenced in other documents -# (using :ref:`CONFIG_FOO`) -# -# This script uses kconfiglib library to do all the work of parsing Kconfig -# files: https://github.com/ulfalizer/Kconfiglib -# -# Copyright 2017 Espressif Systems (Shanghai) PTE LTD -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http:#www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import os -import kconfiglib - -# Indentation to be used in the generated file -INDENT = ' ' - -# Characters used when underlining section heading -HEADING_SYMBOLS = '#*=-^"+' - -# Keep the heading level in sync with api-reference/kconfig.rst -INITIAL_HEADING_LEVEL = 2 -MAX_HEADING_LEVEL = 5 -OPTION_HEADING_LEVEL = 6 - - -def print_menu_contents(title, items, heading_level, breadcrumbs): - if title: - print_section_heading(title, heading_level) - for entry in items: - if entry.is_menu(): - if len(breadcrumbs) > 0: - new_breadcrumbs = breadcrumbs + ' > ' + entry.get_title() - else: - new_breadcrumbs = entry.get_title() - - print_menu_contents(entry.get_title(), entry.get_items(), - min(heading_level + 1, MAX_HEADING_LEVEL), - new_breadcrumbs) - elif entry.is_choice(): - print_choice(entry, breadcrumbs) - else: - if len(entry.get_prompts()) == 0: - # Skip entries which can never be visible - continue - # Currently this does not handle 'menuconfig' entires in any special way, - # as Kconfglib offers no way of recognizing them automatically. - print_option(entry, breadcrumbs) - # Trailing newline after every option - print - -def print_choice(choice, breadcrumbs): - print_option(choice, breadcrumbs) - print - print '%sAvailable options:' % INDENT - for opt in choice.get_symbols(): - # Format available options as a list - print '%s- %s' % (INDENT * 2, opt.name) - -def print_section_heading(title, heading_level): - print title - print HEADING_SYMBOLS[heading_level] * len(title) - print - -def print_option(opt, breadcrumbs): - # add link target so we can use :ref:`CONFIG_FOO` - print '.. _CONFIG_%s:' % opt.name - print - print_section_heading(opt.name, OPTION_HEADING_LEVEL) - if len(opt.prompts) > 0: - print '%s%s' % (INDENT, opt.prompts[0][0]) - print - print '%s:emphasis:`Found in: %s`' % (INDENT, breadcrumbs) - print - if opt.get_help() is not None: - # Help text normally contains newlines, but spaces at the beginning of - # each line are stripped by kconfiglib. We need to re-indent the text - # to produce valid ReST. - print '%s%s' % (INDENT, opt.get_help().replace('\n', '\n%s' % INDENT)) - -def process_kconfig_file(kconfig_file, heading_level, breadcrumbs): - if os.path.exists(kconfig_file): - cfg = kconfiglib.Config(kconfig_file, print_warnings=True) - print_menu_contents(None, cfg.get_top_level_items(), heading_level, breadcrumbs) - -def print_all_components(): - heading_level = INITIAL_HEADING_LEVEL - # Currently this works only for IDF components. - # TODO: figure out if this can be re-used for documenting applications? - components_path = os.path.join(os.path.curdir, '../..', 'components') - for component_name in os.listdir(components_path): - if component_name.startswith('.'): - continue # skip system thumbnail folders - - kconfig_file_path = os.path.join(components_path, component_name, 'Kconfig') - - process_kconfig_file(kconfig_file_path, heading_level, 'Component config') - process_kconfig_file(kconfig_file_path + '.projbuild', heading_level, '') - -if __name__ == '__main__': - print_all_components() diff --git a/tools/kconfig_new/gen_kconfig_doc.py b/tools/kconfig_new/gen_kconfig_doc.py index 6614c54c33..e5e6968f18 100644 --- a/tools/kconfig_new/gen_kconfig_doc.py +++ b/tools/kconfig_new/gen_kconfig_doc.py @@ -7,7 +7,7 @@ # generated, allowing options to be referenced in other documents # (using :ref:`CONFIG_FOO`) # -# Copyright 2017 Espressif Systems (Shanghai) PTE LTD +# Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -30,12 +30,13 @@ INDENT = ' ' HEADING_SYMBOLS = '#*=-^"+' # Keep the heading level in sync with api-reference/kconfig.rst -INITIAL_HEADING_LEVEL = 2 -MAX_HEADING_LEVEL = 5 +INITIAL_HEADING_LEVEL = 3 +MAX_HEADING_LEVEL = len(HEADING_SYMBOLS)-1 def write_docs(config, filename): """ Note: writing .rst documentation ignores the current value - of any items. ie the --config option can be ignored. """ + of any items. ie the --config option can be ignored. + (However at time of writing it still needs to be set to something...) """ with open(filename, "w") as f: config.walk_menu(lambda node: write_menu_item(f, node)) @@ -61,6 +62,15 @@ def get_heading_level(node): node = node.parent return result +def format_rest_text(text, indent): + # Format an indented text block for use with ReST + text = indent + text.replace('\n', '\n' + indent) + # Escape some characters which are inline formatting in ReST + text = text.replace("*", "\\*") + text = text.replace("_", "\\_") + text += '\n' + return text + def write_menu_item(f, node): if not node.prompt: return # Don't do anything for invisible menu items @@ -87,12 +97,12 @@ def write_menu_item(f, node): title = node.prompt[0] # if no symbol name, use the prompt as the heading - if is_menu: + if True or is_menu: f.write('%s\n' % title) f.write(HEADING_SYMBOLS[get_heading_level(node)] * len(title)) f.write('\n\n') else: - f.write('**%s**\n\n\n % title') + f.write('**%s**\n\n\n' % title) if name: f.write('%s%s\n\n' % (INDENT, node.prompt[0])) @@ -103,7 +113,7 @@ def write_menu_item(f, node): # Help text normally contains newlines, but spaces at the beginning of # each line are stripped by kconfiglib. We need to re-indent the text # to produce valid ReST. - f.write('%s%s\n' % (INDENT, node.help.replace('\n', '\n%s' % INDENT))) + f.write(format_rest_text(node.help, INDENT)) except AttributeError: pass # No help @@ -115,8 +125,8 @@ def write_menu_item(f, node): f.write('%s- %-20s (%s)\n' % (INDENT * 2, choice_node.prompt[0], choice_node.item.name)) if choice_node.help: HELP_INDENT = INDENT * 2 - fmt_help = choice_node.help.replace('\n', '\n%s ' % HELP_INDENT) - f.write('%s \n%s %s\n' % (HELP_INDENT, HELP_INDENT, fmt_help)) + fmt_help = format_rest_text(choice_node.help, ' ' + HELP_INDENT) + f.write('%s \n%s\n' % (HELP_INDENT, fmt_help)) choice_node = choice_node.next f.write('\n\n')