From 4d0d74dc0a10e63e1372f925d0d2493cba351aa1 Mon Sep 17 00:00:00 2001 From: Ulf Magnusson Date: Tue, 1 May 2018 01:26:39 +0200 Subject: Rename examples/menuconfig.py to menuconfig_example.py To avoid confusing it with the new terminal menuconfig implementation. Clean up the README a bit at the same time, removing some stuff that's less essential now (e.g. the menuconfig_example.py "screenshot"). --- README.rst | 42 +----- examples/menuconfig.py | 335 ----------------------------------------- examples/menuconfig_example.py | 335 +++++++++++++++++++++++++++++++++++++++++ tests/reltest | 4 +- 4 files changed, 343 insertions(+), 373 deletions(-) delete mode 100644 examples/menuconfig.py create mode 100644 examples/menuconfig_example.py diff --git a/README.rst b/README.rst index 12fed27..070917e 100644 --- a/README.rst +++ b/README.rst @@ -75,7 +75,11 @@ Kconfiglib can do the following, among other things: from symbols depending on preceding symbols. This can be used e.g. to implement menuconfig-like functionality. - See the `menuconfig.py `_ example. + See `menuconfig.py + `_ and the + minimalistic `menuconfig_example.py + `_ + example. Here are some other features: @@ -302,41 +306,7 @@ The `examples/ `_ - `oldconfig.py `_ provides ``make oldconfig`` functionality, prompting the user for the values of new symbols to update an old ``.config`` file. -- `menuconfig.py `_ implements a configuration interface that uses notation similar to ``make menuconfig``. It's deliberately kept as simple as possible to demonstrate just the core concepts, and isn't something you'd actually want to use. Here's a screenshot: - -.. code-block:: - - ======== Example Kconfig configuration ======== - - [*] Enable loadable module support (MODULES) - Bool and tristate symbols - [*] Bool symbol (BOOL) - [ ] Dependent bool symbol (BOOL_DEP) - < > Dependent tristate symbol (TRI_DEP) - [ ] First prompt (TWO_MENU_NODES) - < > Tristate symbol (TRI) - [ ] Second prompt (TWO_MENU_NODES) - *** These are selected by TRI_DEP *** - < > Tristate selected by TRI_DEP (SELECTED_BY_TRI_DEP) - < > Tristate implied by TRI_DEP (IMPLIED_BY_TRI_DEP) - String, int, and hex symbols - (foo) String symbol (STRING) - (747) Int symbol (INT) - (0xABC) Hex symbol (HEX) - Various choices - -*- Bool choice (BOOL_CHOICE) - --> Bool choice sym 1 (BOOL_CHOICE_SYM_1) - Bool choice sym 2 (BOOL_CHOICE_SYM_2) - {M} Tristate choice (TRI_CHOICE) - < > Tristate choice sym 1 (TRI_CHOICE_SYM_1) - < > Tristate choice sym 2 (TRI_CHOICE_SYM_2) - [ ] Optional bool choice (OPT_BOOL_CHOICE) - - Enter a symbol/choice name, "load_config", or "write_config" (or press CTRL+D to exit): BOOL - Value for BOOL (available: n, y): n - ... - -See the `pymenuconfig `_ project for a real-world `menuconfig` implementation built on top of Kconfiglib. +- `menuconfig_example.py `_ implements a configuration interface that uses notation similar to ``make menuconfig``. It's deliberately kept as simple as possible to demonstrate just the core concepts. Real-world examples ~~~~~~~~~~~~~~~~~~~ diff --git a/examples/menuconfig.py b/examples/menuconfig.py deleted file mode 100644 index f026e74..0000000 --- a/examples/menuconfig.py +++ /dev/null @@ -1,335 +0,0 @@ -# Implements a simple configuration interface on top of Kconfiglib to -# demonstrate concepts for building a menuconfig-like. Emulates how the -# standard menuconfig prints menu entries. -# -# Always displays the entire Kconfig tree to keep things as simple as possible -# (all symbols, choices, menus, and comments). -# -# Usage: -# -# $ python(3) Kconfiglib/examples/menuconfig.py -# -# A sample Kconfig is available in Kconfiglib/examples/Kmenuconfig. -# -# Here's a notation guide. The notation matches the one used by menuconfig -# (scripts/kconfig/mconf): -# -# [ ] prompt - Bool -# < > prompt - Tristate -# {M} prompt - Tristate selected to m. Can only be set to m or y. -# -*- prompt - Bool/tristate selected to y, pinning it -# -M- prompt - Tristate selected to m that also has m visibility, -# pinning it to m -# (foo) prompt - String/int/hex symbol with value "foo" -# --> prompt - The selected symbol in a choice in y mode. This -# syntax is unique to this example. -# -# When modules are disabled, the .type attribute of TRISTATE symbols and -# choices automatically changes to BOOL. This trick is used by the C -# implementation as well, and gives the expected behavior without having to do -# anything extra here. The original type is available in .orig_type if needed. -# -# The Kconfiglib/examples/Kmenuconfig example uses named choices to be able to -# refer to choices by name. Named choices are supported in the C tools too, but -# I don't think I've ever seen them used in the wild. -# -# Sample session: -# -# $ python Kconfiglib/examples/menuconfig.py Kconfiglib/examples/Kmenuconfig -# -# ======== Example Kconfig configuration ======== -# -# [*] Enable loadable module support (MODULES) -# Bool and tristate symbols -# [*] Bool symbol (BOOL) -# [ ] Dependent bool symbol (BOOL_DEP) -# < > Dependent tristate symbol (TRI_DEP) -# [ ] First prompt (TWO_MENU_NODES) -# < > Tristate symbol (TRI) -# [ ] Second prompt (TWO_MENU_NODES) -# *** These are selected by TRI_DEP *** -# < > Tristate selected by TRI_DEP (SELECTED_BY_TRI_DEP) -# < > Tristate implied by TRI_DEP (IMPLIED_BY_TRI_DEP) -# String, int, and hex symbols -# (foo) String symbol (STRING) -# (747) Int symbol (INT) -# (0xABC) Hex symbol (HEX) -# Various choices -# -*- Bool choice (BOOL_CHOICE) -# --> Bool choice sym 1 (BOOL_CHOICE_SYM_1) -# Bool choice sym 2 (BOOL_CHOICE_SYM_2) -# {M} Tristate choice (TRI_CHOICE) -# < > Tristate choice sym 1 (TRI_CHOICE_SYM_1) -# < > Tristate choice sym 2 (TRI_CHOICE_SYM_2) -# [ ] Optional bool choice (OPT_BOOL_CHOICE) -# -# Enter a symbol/choice name, "load_config", or "write_config" (or press CTRL+D to exit): BOOL -# Value for BOOL (available: n, y): n -# -# ======== Example Kconfig configuration ======== -# -# [*] Enable loadable module support (MODULES) -# Bool and tristate symbols -# [ ] Bool symbol (BOOL) -# < > Tristate symbol (TRI) -# [ ] Second prompt (TWO_MENU_NODES) -# *** These are selected by TRI_DEP *** -# < > Tristate selected by TRI_DEP (SELECTED_BY_TRI_DEP) -# < > Tristate implied by TRI_DEP (IMPLIED_BY_TRI_DEP) -# String, int, and hex symbols -# (foo) String symbol (STRING) -# (747) Int symbol (INT) -# (0xABC) Hex symbol (HEX) -# Various choices -# -*- Bool choice (BOOL_CHOICE) -# --> Bool choice sym 1 (BOOL_CHOICE_SYM_1) -# Bool choice sym 2 (BOOL_CHOICE_SYM_2) -# {M} Tristate choice (TRI_CHOICE) -# < > Tristate choice sym 1 (TRI_CHOICE_SYM_1) -# < > Tristate choice sym 2 (TRI_CHOICE_SYM_2) -# [ ] Optional bool choice (OPT_BOOL_CHOICE) -# -# Enter a symbol/choice name, "load_config", or "write_config" (or press CTRL+D to exit): MODULES -# Value for MODULES (available: n, y): n -# -# ======== Example Kconfig configuration ======== -# -# [ ] Enable loadable module support (MODULES) -# Bool and tristate symbols -# [ ] Bool symbol (BOOL) -# [ ] Tristate symbol (TRI) -# [ ] Second prompt (TWO_MENU_NODES) -# *** These are selected by TRI_DEP *** -# [ ] Tristate selected by TRI_DEP (SELECTED_BY_TRI_DEP) -# [ ] Tristate implied by TRI_DEP (IMPLIED_BY_TRI_DEP) -# String, int, and hex symbols -# (foo) String symbol (STRING) -# (747) Int symbol (INT) -# (0xABC) Hex symbol (HEX) -# Various choices -# -*- Bool choice (BOOL_CHOICE) -# --> Bool choice sym 1 (BOOL_CHOICE_SYM_1) -# Bool choice sym 2 (BOOL_CHOICE_SYM_2) -# -*- Tristate choice (TRI_CHOICE) -# --> Tristate choice sym 1 (TRI_CHOICE_SYM_1) -# Tristate choice sym 2 (TRI_CHOICE_SYM_2) -# [ ] Optional bool choice (OPT_BOOL_CHOICE) -# -# Enter a symbol/choice name, "load_config", or "write_config" (or press CTRL+D to exit): ^D - -from kconfiglib import Kconfig, \ - Symbol, Choice, MENU, COMMENT, \ - BOOL, TRISTATE, STRING, INT, HEX, UNKNOWN, \ - expr_value, \ - TRI_TO_STR -import readline -import sys - -# Python 2/3 compatibility hack -if sys.version_info[0] < 3: - input = raw_input - -def indent_print(s, indent): - print(" "*indent + s) - -def value_str(sc): - """ - Returns the value part ("[*]", "", "(foo)" etc.) of a menu entry. - - sc: Symbol or Choice. - """ - if sc.type in (STRING, INT, HEX): - return "({})".format(sc.str_value) - - # BOOL or TRISTATE - - # The choice mode is an upper bound on the visibility of choice symbols, so - # we can check the choice symbols' own visibility to see if the choice is - # in y mode - if isinstance(sc, Symbol) and sc.choice and sc.visibility == 2: - # For choices in y mode, print '-->' next to the selected symbol - return "-->" if sc.choice.selection is sc else " " - - tri_val_str = (" ", "M", "*")[sc.tri_value] - - if len(sc.assignable) == 1: - # Pinned to a single value - return "-{}-".format(tri_val_str) - - if sc.type == BOOL: - return "[{}]".format(tri_val_str) - - if sc.type == TRISTATE: - if sc.assignable == (1, 2): - # m and y available - return "{" + tri_val_str + "}" # Gets a bit confusing with .format() - return "<{}>".format(tri_val_str) - -def node_str(node): - """ - Returns the complete menu entry text for a menu node, or "" for invisible - menu nodes. Invisible menu nodes are those that lack a prompt or that do - not have a satisfied prompt condition. - - Example return value: "[*] Bool symbol (BOOL)" - - The symbol name is printed in parentheses to the right of the prompt. This - is so that symbols can easily be referred to in the configuration - interface. - """ - if not node.prompt: - return "" - - # Even for menu nodes for symbols and choices, it's wrong to check - # Symbol.visibility / Choice.visibility here. The reason is that a symbol - # (and a choice, in theory) can be defined in multiple locations, giving it - # multiple menu nodes, which do not necessarily all have the same prompt - # visibility. Symbol.visibility / Choice.visibility is calculated as the OR - # of the visibility of all the prompts. - prompt, prompt_cond = node.prompt - if not expr_value(prompt_cond): - return "" - - if node.item == MENU: - return " " + prompt - - if node.item == COMMENT: - return " *** {} ***".format(prompt) - - # Symbol or Choice - - sc = node.item - - if sc.type == UNKNOWN: - # Skip symbols defined without a type (these are obscure and generate - # a warning) - return "" - - # {:3} sets the field width to three. Gives nice alignment for empty string - # values. - res = "{:3} {}".format(value_str(sc), prompt) - - # Don't print the name for unnamed choices (the normal kind) - if sc.name is not None: - res += " ({})".format(sc.name) - - return res - -def print_menuconfig_nodes(node, indent): - """ - Prints a tree with all the menu entries rooted at 'node'. Child menu - entries are indented. - """ - while node: - string = node_str(node) - if string: - indent_print(string, indent) - - if node.list: - print_menuconfig_nodes(node.list, indent + 8) - - node = node.next - -def print_menuconfig(kconf): - """ - Prints all menu entries for the configuration. - """ - # Print the expanded mainmenu text at the top. This is the same as - # kconf.top_node.prompt[0], but with variable references expanded. - print("\n======== {} ========\n".format(kconf.mainmenu_text)) - - print_menuconfig_nodes(kconf.top_node.list, 0) - print("") - -def get_value_from_user(sc): - """ - Prompts the user for a value for the symbol or choice 'sc'. For - bool/tristate symbols and choices, provides a list of all the assignable - values. - """ - if not sc.visibility: - print(sc.name + " is not currently visible") - return False - - prompt = "Value for {}".format(sc.name) - if sc.type in (BOOL, TRISTATE): - prompt += " (available: {})" \ - .format(", ".join(TRI_TO_STR[val] for val in sc.assignable)) - prompt += ": " - - val = input(prompt) - - # Automatically add a "0x" prefix for hex symbols, like the menuconfig - # interface does. This isn't done when loading .config files, hence why - # set_value() doesn't do it automatically. - if sc.type == HEX and not val.startswith(("0x", "0X")): - val = "0x" + val - - # Let Kconfiglib itself print a warning here if the value is invalid. We - # could also disable warnings temporarily with - # kconf.disable_warnings() / kconf.enable_warnings() and print our own - # warning. - return sc.set_value(val) - -if __name__ == "__main__": - if len(sys.argv) != 2: - sys.exit("usage: menuconfig.py ") - - # Load Kconfig configuration files - kconf = Kconfig(sys.argv[1]) - - # Print the initial configuration tree - print_menuconfig(kconf) - - while True: - try: - cmd = input('Enter a symbol/choice name, "load_config", or "write_config" (or press CTRL+D to exit): ') \ - .strip() - except EOFError: - print("") - break - - if cmd == "load_config": - config_filename = input(".config file to load: ") - - try: - kconf.load_config(config_filename) - except IOError as e: - # Print the (spammy) error from Kconfiglib itself - print(e.message + "\n") - else: - print("Configuration loaded from " + config_filename) - - print_menuconfig(kconf) - continue - - if cmd == "write_config": - config_filename = input("To this file: ") - - try: - kconf.write_config(config_filename) - except IOError as e: - print(e.message) - else: - print("Configuration written to " + config_filename) - - continue - - # Assume 'cmd' is the name of a symbol or choice if it isn't one of the - # commands above, prompt the user for a value for it, and print the new - # configuration tree - - if cmd in kconf.syms: - if get_value_from_user(kconf.syms[cmd]): - print_menuconfig(kconf) - - continue - - if cmd in kconf.named_choices: - if get_value_from_user(kconf.named_choices[cmd]): - print_menuconfig(kconf) - - continue - - print("No symbol/choice named '{}' in the configuration" - .format(cmd)) diff --git a/examples/menuconfig_example.py b/examples/menuconfig_example.py new file mode 100644 index 0000000..f026e74 --- /dev/null +++ b/examples/menuconfig_example.py @@ -0,0 +1,335 @@ +# Implements a simple configuration interface on top of Kconfiglib to +# demonstrate concepts for building a menuconfig-like. Emulates how the +# standard menuconfig prints menu entries. +# +# Always displays the entire Kconfig tree to keep things as simple as possible +# (all symbols, choices, menus, and comments). +# +# Usage: +# +# $ python(3) Kconfiglib/examples/menuconfig.py +# +# A sample Kconfig is available in Kconfiglib/examples/Kmenuconfig. +# +# Here's a notation guide. The notation matches the one used by menuconfig +# (scripts/kconfig/mconf): +# +# [ ] prompt - Bool +# < > prompt - Tristate +# {M} prompt - Tristate selected to m. Can only be set to m or y. +# -*- prompt - Bool/tristate selected to y, pinning it +# -M- prompt - Tristate selected to m that also has m visibility, +# pinning it to m +# (foo) prompt - String/int/hex symbol with value "foo" +# --> prompt - The selected symbol in a choice in y mode. This +# syntax is unique to this example. +# +# When modules are disabled, the .type attribute of TRISTATE symbols and +# choices automatically changes to BOOL. This trick is used by the C +# implementation as well, and gives the expected behavior without having to do +# anything extra here. The original type is available in .orig_type if needed. +# +# The Kconfiglib/examples/Kmenuconfig example uses named choices to be able to +# refer to choices by name. Named choices are supported in the C tools too, but +# I don't think I've ever seen them used in the wild. +# +# Sample session: +# +# $ python Kconfiglib/examples/menuconfig.py Kconfiglib/examples/Kmenuconfig +# +# ======== Example Kconfig configuration ======== +# +# [*] Enable loadable module support (MODULES) +# Bool and tristate symbols +# [*] Bool symbol (BOOL) +# [ ] Dependent bool symbol (BOOL_DEP) +# < > Dependent tristate symbol (TRI_DEP) +# [ ] First prompt (TWO_MENU_NODES) +# < > Tristate symbol (TRI) +# [ ] Second prompt (TWO_MENU_NODES) +# *** These are selected by TRI_DEP *** +# < > Tristate selected by TRI_DEP (SELECTED_BY_TRI_DEP) +# < > Tristate implied by TRI_DEP (IMPLIED_BY_TRI_DEP) +# String, int, and hex symbols +# (foo) String symbol (STRING) +# (747) Int symbol (INT) +# (0xABC) Hex symbol (HEX) +# Various choices +# -*- Bool choice (BOOL_CHOICE) +# --> Bool choice sym 1 (BOOL_CHOICE_SYM_1) +# Bool choice sym 2 (BOOL_CHOICE_SYM_2) +# {M} Tristate choice (TRI_CHOICE) +# < > Tristate choice sym 1 (TRI_CHOICE_SYM_1) +# < > Tristate choice sym 2 (TRI_CHOICE_SYM_2) +# [ ] Optional bool choice (OPT_BOOL_CHOICE) +# +# Enter a symbol/choice name, "load_config", or "write_config" (or press CTRL+D to exit): BOOL +# Value for BOOL (available: n, y): n +# +# ======== Example Kconfig configuration ======== +# +# [*] Enable loadable module support (MODULES) +# Bool and tristate symbols +# [ ] Bool symbol (BOOL) +# < > Tristate symbol (TRI) +# [ ] Second prompt (TWO_MENU_NODES) +# *** These are selected by TRI_DEP *** +# < > Tristate selected by TRI_DEP (SELECTED_BY_TRI_DEP) +# < > Tristate implied by TRI_DEP (IMPLIED_BY_TRI_DEP) +# String, int, and hex symbols +# (foo) String symbol (STRING) +# (747) Int symbol (INT) +# (0xABC) Hex symbol (HEX) +# Various choices +# -*- Bool choice (BOOL_CHOICE) +# --> Bool choice sym 1 (BOOL_CHOICE_SYM_1) +# Bool choice sym 2 (BOOL_CHOICE_SYM_2) +# {M} Tristate choice (TRI_CHOICE) +# < > Tristate choice sym 1 (TRI_CHOICE_SYM_1) +# < > Tristate choice sym 2 (TRI_CHOICE_SYM_2) +# [ ] Optional bool choice (OPT_BOOL_CHOICE) +# +# Enter a symbol/choice name, "load_config", or "write_config" (or press CTRL+D to exit): MODULES +# Value for MODULES (available: n, y): n +# +# ======== Example Kconfig configuration ======== +# +# [ ] Enable loadable module support (MODULES) +# Bool and tristate symbols +# [ ] Bool symbol (BOOL) +# [ ] Tristate symbol (TRI) +# [ ] Second prompt (TWO_MENU_NODES) +# *** These are selected by TRI_DEP *** +# [ ] Tristate selected by TRI_DEP (SELECTED_BY_TRI_DEP) +# [ ] Tristate implied by TRI_DEP (IMPLIED_BY_TRI_DEP) +# String, int, and hex symbols +# (foo) String symbol (STRING) +# (747) Int symbol (INT) +# (0xABC) Hex symbol (HEX) +# Various choices +# -*- Bool choice (BOOL_CHOICE) +# --> Bool choice sym 1 (BOOL_CHOICE_SYM_1) +# Bool choice sym 2 (BOOL_CHOICE_SYM_2) +# -*- Tristate choice (TRI_CHOICE) +# --> Tristate choice sym 1 (TRI_CHOICE_SYM_1) +# Tristate choice sym 2 (TRI_CHOICE_SYM_2) +# [ ] Optional bool choice (OPT_BOOL_CHOICE) +# +# Enter a symbol/choice name, "load_config", or "write_config" (or press CTRL+D to exit): ^D + +from kconfiglib import Kconfig, \ + Symbol, Choice, MENU, COMMENT, \ + BOOL, TRISTATE, STRING, INT, HEX, UNKNOWN, \ + expr_value, \ + TRI_TO_STR +import readline +import sys + +# Python 2/3 compatibility hack +if sys.version_info[0] < 3: + input = raw_input + +def indent_print(s, indent): + print(" "*indent + s) + +def value_str(sc): + """ + Returns the value part ("[*]", "", "(foo)" etc.) of a menu entry. + + sc: Symbol or Choice. + """ + if sc.type in (STRING, INT, HEX): + return "({})".format(sc.str_value) + + # BOOL or TRISTATE + + # The choice mode is an upper bound on the visibility of choice symbols, so + # we can check the choice symbols' own visibility to see if the choice is + # in y mode + if isinstance(sc, Symbol) and sc.choice and sc.visibility == 2: + # For choices in y mode, print '-->' next to the selected symbol + return "-->" if sc.choice.selection is sc else " " + + tri_val_str = (" ", "M", "*")[sc.tri_value] + + if len(sc.assignable) == 1: + # Pinned to a single value + return "-{}-".format(tri_val_str) + + if sc.type == BOOL: + return "[{}]".format(tri_val_str) + + if sc.type == TRISTATE: + if sc.assignable == (1, 2): + # m and y available + return "{" + tri_val_str + "}" # Gets a bit confusing with .format() + return "<{}>".format(tri_val_str) + +def node_str(node): + """ + Returns the complete menu entry text for a menu node, or "" for invisible + menu nodes. Invisible menu nodes are those that lack a prompt or that do + not have a satisfied prompt condition. + + Example return value: "[*] Bool symbol (BOOL)" + + The symbol name is printed in parentheses to the right of the prompt. This + is so that symbols can easily be referred to in the configuration + interface. + """ + if not node.prompt: + return "" + + # Even for menu nodes for symbols and choices, it's wrong to check + # Symbol.visibility / Choice.visibility here. The reason is that a symbol + # (and a choice, in theory) can be defined in multiple locations, giving it + # multiple menu nodes, which do not necessarily all have the same prompt + # visibility. Symbol.visibility / Choice.visibility is calculated as the OR + # of the visibility of all the prompts. + prompt, prompt_cond = node.prompt + if not expr_value(prompt_cond): + return "" + + if node.item == MENU: + return " " + prompt + + if node.item == COMMENT: + return " *** {} ***".format(prompt) + + # Symbol or Choice + + sc = node.item + + if sc.type == UNKNOWN: + # Skip symbols defined without a type (these are obscure and generate + # a warning) + return "" + + # {:3} sets the field width to three. Gives nice alignment for empty string + # values. + res = "{:3} {}".format(value_str(sc), prompt) + + # Don't print the name for unnamed choices (the normal kind) + if sc.name is not None: + res += " ({})".format(sc.name) + + return res + +def print_menuconfig_nodes(node, indent): + """ + Prints a tree with all the menu entries rooted at 'node'. Child menu + entries are indented. + """ + while node: + string = node_str(node) + if string: + indent_print(string, indent) + + if node.list: + print_menuconfig_nodes(node.list, indent + 8) + + node = node.next + +def print_menuconfig(kconf): + """ + Prints all menu entries for the configuration. + """ + # Print the expanded mainmenu text at the top. This is the same as + # kconf.top_node.prompt[0], but with variable references expanded. + print("\n======== {} ========\n".format(kconf.mainmenu_text)) + + print_menuconfig_nodes(kconf.top_node.list, 0) + print("") + +def get_value_from_user(sc): + """ + Prompts the user for a value for the symbol or choice 'sc'. For + bool/tristate symbols and choices, provides a list of all the assignable + values. + """ + if not sc.visibility: + print(sc.name + " is not currently visible") + return False + + prompt = "Value for {}".format(sc.name) + if sc.type in (BOOL, TRISTATE): + prompt += " (available: {})" \ + .format(", ".join(TRI_TO_STR[val] for val in sc.assignable)) + prompt += ": " + + val = input(prompt) + + # Automatically add a "0x" prefix for hex symbols, like the menuconfig + # interface does. This isn't done when loading .config files, hence why + # set_value() doesn't do it automatically. + if sc.type == HEX and not val.startswith(("0x", "0X")): + val = "0x" + val + + # Let Kconfiglib itself print a warning here if the value is invalid. We + # could also disable warnings temporarily with + # kconf.disable_warnings() / kconf.enable_warnings() and print our own + # warning. + return sc.set_value(val) + +if __name__ == "__main__": + if len(sys.argv) != 2: + sys.exit("usage: menuconfig.py ") + + # Load Kconfig configuration files + kconf = Kconfig(sys.argv[1]) + + # Print the initial configuration tree + print_menuconfig(kconf) + + while True: + try: + cmd = input('Enter a symbol/choice name, "load_config", or "write_config" (or press CTRL+D to exit): ') \ + .strip() + except EOFError: + print("") + break + + if cmd == "load_config": + config_filename = input(".config file to load: ") + + try: + kconf.load_config(config_filename) + except IOError as e: + # Print the (spammy) error from Kconfiglib itself + print(e.message + "\n") + else: + print("Configuration loaded from " + config_filename) + + print_menuconfig(kconf) + continue + + if cmd == "write_config": + config_filename = input("To this file: ") + + try: + kconf.write_config(config_filename) + except IOError as e: + print(e.message) + else: + print("Configuration written to " + config_filename) + + continue + + # Assume 'cmd' is the name of a symbol or choice if it isn't one of the + # commands above, prompt the user for a value for it, and print the new + # configuration tree + + if cmd in kconf.syms: + if get_value_from_user(kconf.syms[cmd]): + print_menuconfig(kconf) + + continue + + if cmd in kconf.named_choices: + if get_value_from_user(kconf.named_choices[cmd]): + print_menuconfig(kconf) + + continue + + print("No symbol/choice named '{}' in the configuration" + .format(cmd)) diff --git a/tests/reltest b/tests/reltest index dea0137..cd31711 100755 --- a/tests/reltest +++ b/tests/reltest @@ -39,12 +39,12 @@ for py in python2 python3; do test_script Kconfiglib/examples/print_sym_info.py MODULES test_script Kconfiglib/examples/print_tree.py - $py Kconfiglib/examples/menuconfig.py Kconfiglib/examples/Kmenuconfig <