summaryrefslogtreecommitdiff
path: root/examples/menuconfig.py
diff options
context:
space:
mode:
Diffstat (limited to 'examples/menuconfig.py')
-rw-r--r--examples/menuconfig.py335
1 files changed, 0 insertions, 335 deletions
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 <Kconfig file>
-#
-# 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 ("[*]", "<M>", "(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 <Kconfig file>")
-
- # 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))