Merge branch 'bugfix/update_menuconfig' into 'master'
Update kconfiglib from v12.14.0 to v13.3.2 See merge request espressif/esp-idf!6816
This commit is contained in:
commit
af382a1b8e
|
@ -554,7 +554,7 @@ from glob import iglob
|
|||
from os.path import dirname, exists, expandvars, islink, join, realpath
|
||||
|
||||
|
||||
VERSION = (12, 14, 0)
|
||||
VERSION = (13, 3, 2)
|
||||
|
||||
|
||||
# File layout:
|
||||
|
@ -773,8 +773,8 @@ class Kconfig(object):
|
|||
See Kconfig.load_config() as well.
|
||||
|
||||
srctree:
|
||||
The value of the $srctree environment variable when the configuration was
|
||||
loaded, or the empty string if $srctree wasn't set. This gives nice
|
||||
The value the $srctree environment variable had when the Kconfig instance
|
||||
was created, or the empty string if $srctree wasn't set. This gives nice
|
||||
behavior with os.path.join(), which treats "" as the current directory,
|
||||
without adding "./".
|
||||
|
||||
|
@ -789,13 +789,22 @@ class Kconfig(object):
|
|||
if multiple configurations are loaded with different values for $srctree.
|
||||
|
||||
config_prefix:
|
||||
The value of the $CONFIG_ environment variable when the configuration was
|
||||
loaded. This is the prefix used (and expected) on symbol names in .config
|
||||
files and C headers. Defaults to "CONFIG_". Used in the same way in the C
|
||||
tools.
|
||||
The value the CONFIG_ environment variable had when the Kconfig instance
|
||||
was created, or "CONFIG_" if CONFIG_ wasn't set. This is the prefix used
|
||||
(and expected) on symbol names in .config files and C headers. Used in
|
||||
the same way in the C tools.
|
||||
|
||||
Like for srctree, only the value of $CONFIG_ when the configuration is
|
||||
loaded matters.
|
||||
config_header:
|
||||
The value the KCONFIG_CONFIG_HEADER environment variable had when the
|
||||
Kconfig instance was created, or the empty string if
|
||||
KCONFIG_CONFIG_HEADER wasn't set. This string is inserted verbatim at the
|
||||
beginning of configuration files. See write_config().
|
||||
|
||||
header_header:
|
||||
The value the KCONFIG_AUTOHEADER_HEADER environment variable had when the
|
||||
Kconfig instance was created, or the empty string if
|
||||
KCONFIG_AUTOHEADER_HEADER wasn't set. This string is inserted verbatim at
|
||||
the beginning of header files. See write_autoconf().
|
||||
|
||||
filename/linenr:
|
||||
The current parsing location, for use in Python preprocessor functions.
|
||||
|
@ -810,11 +819,13 @@ class Kconfig(object):
|
|||
"_warn_assign_no_prompt",
|
||||
"choices",
|
||||
"comments",
|
||||
"config_header",
|
||||
"config_prefix",
|
||||
"const_syms",
|
||||
"defconfig_list",
|
||||
"defined_syms",
|
||||
"env_vars",
|
||||
"header_header",
|
||||
"kconfig_filenames",
|
||||
"m",
|
||||
"menus",
|
||||
|
@ -943,6 +954,9 @@ class Kconfig(object):
|
|||
self._unset_match = _re_match(r"# {}([^ ]+) is not set".format(
|
||||
self.config_prefix))
|
||||
|
||||
self.config_header = os.getenv("KCONFIG_CONFIG_HEADER", "")
|
||||
self.header_header = os.getenv("KCONFIG_AUTOHEADER_HEADER", "")
|
||||
|
||||
self.syms = {}
|
||||
self.const_syms = {}
|
||||
self.defined_syms = []
|
||||
|
@ -1245,7 +1259,7 @@ class Kconfig(object):
|
|||
self._warn("'{}' is not a valid value for the {} "
|
||||
"symbol {}. Assignment ignored."
|
||||
.format(val, TYPE_TO_STR[sym.orig_type],
|
||||
_name_and_loc(sym)),
|
||||
sym.name_and_loc),
|
||||
filename, linenr)
|
||||
continue
|
||||
|
||||
|
@ -1272,7 +1286,7 @@ class Kconfig(object):
|
|||
if not match:
|
||||
self._warn("malformed string literal in "
|
||||
"assignment to {}. Assignment ignored."
|
||||
.format(_name_and_loc(sym)),
|
||||
.format(sym.name_and_loc),
|
||||
filename, linenr)
|
||||
continue
|
||||
|
||||
|
@ -1341,7 +1355,7 @@ class Kconfig(object):
|
|||
user_val = sym.user_value
|
||||
|
||||
msg = '{} set more than once. Old value "{}", new value "{}".'.format(
|
||||
_name_and_loc(sym), user_val, new_val)
|
||||
sym.name_and_loc, user_val, new_val)
|
||||
|
||||
if user_val == new_val:
|
||||
if self.warn_assign_redun:
|
||||
|
@ -1349,8 +1363,7 @@ class Kconfig(object):
|
|||
elif self.warn_assign_override:
|
||||
self._warn(msg, filename, linenr)
|
||||
|
||||
def write_autoconf(self, filename,
|
||||
header="/* Generated by Kconfiglib (https://github.com/ulfalizer/Kconfiglib) */\n"):
|
||||
def write_autoconf(self, filename=None, header=None):
|
||||
r"""
|
||||
Writes out symbol values as a C header file, matching the format used
|
||||
by include/generated/autoconf.h in the kernel.
|
||||
|
@ -1364,22 +1377,37 @@ class Kconfig(object):
|
|||
like the modification time and possibly triggering redundant work in
|
||||
build tools.
|
||||
|
||||
filename:
|
||||
Self-explanatory.
|
||||
filename (default: None):
|
||||
Path to write header to.
|
||||
|
||||
header (default: "/* Generated by Kconfiglib (https://github.com/ulfalizer/Kconfiglib) */\n"):
|
||||
Text that will be inserted verbatim at the beginning of the file. You
|
||||
would usually want it enclosed in '/* */' to make it a C comment,
|
||||
and include a final terminating newline.
|
||||
If None (the default), the path in the environment variable
|
||||
KCONFIG_AUTOHEADER is used if set, and "include/generated/autoconf.h"
|
||||
otherwise. This is compatible with the C tools.
|
||||
|
||||
header (default: None):
|
||||
Text inserted verbatim at the beginning of the file. You would
|
||||
usually want it enclosed in '/* */' to make it a C comment, and
|
||||
include a trailing newline.
|
||||
|
||||
If None (the default), the value of the environment variable
|
||||
KCONFIG_AUTOHEADER_HEADER had when the Kconfig instance was created
|
||||
will be used if it was set, and no header otherwise. See the
|
||||
Kconfig.header_header attribute.
|
||||
"""
|
||||
if filename is None:
|
||||
filename = os.getenv("KCONFIG_AUTOHEADER",
|
||||
"include/generated/autoconf.h")
|
||||
|
||||
self._write_if_changed(filename, self._autoconf_contents(header))
|
||||
|
||||
def _autoconf_contents(self, header):
|
||||
# write_autoconf() helper. Returns the contents to write as a string,
|
||||
# with 'header' at the beginning.
|
||||
# with 'header' or KCONFIG_AUTOHEADER_HEADER at the beginning.
|
||||
|
||||
# "".join()ed later
|
||||
chunks = [header]
|
||||
if header is None:
|
||||
header = self.header_header
|
||||
|
||||
chunks = [header] # "".join()ed later
|
||||
add = chunks.append
|
||||
|
||||
for sym in self.unique_defined_syms:
|
||||
|
@ -1415,9 +1443,8 @@ class Kconfig(object):
|
|||
|
||||
return "".join(chunks)
|
||||
|
||||
def write_config(self, filename=None,
|
||||
header="# Generated by Kconfiglib (https://github.com/ulfalizer/Kconfiglib)\n",
|
||||
save_old=True, verbose=None):
|
||||
def write_config(self, filename=None, header=None, save_old=True,
|
||||
verbose=None):
|
||||
r"""
|
||||
Writes out symbol values in the .config format. The format matches the
|
||||
C implementation, including ordering.
|
||||
|
@ -1439,16 +1466,21 @@ class Kconfig(object):
|
|||
(OSError/IOError). KconfigError is never raised here.
|
||||
|
||||
filename (default: None):
|
||||
Filename to save configuration to (a string).
|
||||
Path to write configuration to (a string).
|
||||
|
||||
If None (the default), the filename in the environment variable
|
||||
If None (the default), the path in the environment variable
|
||||
KCONFIG_CONFIG is used if set, and ".config" otherwise. See
|
||||
standard_config_filename().
|
||||
|
||||
header (default: "# Generated by Kconfiglib (https://github.com/ulfalizer/Kconfiglib)\n"):
|
||||
Text that will be inserted verbatim at the beginning of the file. You
|
||||
would usually want each line to start with '#' to make it a comment,
|
||||
and include a final terminating newline.
|
||||
header (default: None):
|
||||
Text inserted verbatim at the beginning of the file. You would
|
||||
usually want each line to start with '#' to make it a comment, and
|
||||
include a trailing newline.
|
||||
|
||||
if None (the default), the value of the environment variable
|
||||
KCONFIG_CONFIG_HEADER had when the Kconfig instance was created will
|
||||
be used if it was set, and no header otherwise. See the
|
||||
Kconfig.config_header attribute.
|
||||
|
||||
save_old (default: True):
|
||||
If True and <filename> already exists, a copy of it will be saved to
|
||||
|
@ -1493,7 +1525,7 @@ class Kconfig(object):
|
|||
|
||||
def _config_contents(self, header):
|
||||
# write_config() helper. Returns the contents to write as a string,
|
||||
# with 'header' at the beginning.
|
||||
# with 'header' or KCONFIG_CONFIG_HEADER at the beginning.
|
||||
#
|
||||
# More memory friendly would be to 'yield' the strings and
|
||||
# "".join(_config_contents()), but it was a bit slower on my system.
|
||||
|
@ -1505,13 +1537,15 @@ class Kconfig(object):
|
|||
for sym in self.unique_defined_syms:
|
||||
sym._visited = False
|
||||
|
||||
if header is None:
|
||||
header = self.config_header
|
||||
|
||||
chunks = [header] # "".join()ed later
|
||||
add = chunks.append
|
||||
|
||||
# Did we just print an '# end of ...' comment?
|
||||
after_end_comment = False
|
||||
|
||||
# "".join()ed later
|
||||
chunks = [header]
|
||||
add = chunks.append
|
||||
|
||||
node = self.top_node
|
||||
while 1:
|
||||
# Jump to the next node with an iterative tree walk
|
||||
|
@ -1564,8 +1598,7 @@ class Kconfig(object):
|
|||
add("\n#\n# {}\n#\n".format(node.prompt[0]))
|
||||
after_end_comment = False
|
||||
|
||||
def write_min_config(self, filename,
|
||||
header="# Generated by Kconfiglib (https://github.com/ulfalizer/Kconfiglib)\n"):
|
||||
def write_min_config(self, filename, header=None):
|
||||
"""
|
||||
Writes out a "minimal" configuration file, omitting symbols whose value
|
||||
matches their default value. The format matches the one produced by
|
||||
|
@ -1581,12 +1614,17 @@ class Kconfig(object):
|
|||
(OSError/IOError). KconfigError is never raised here.
|
||||
|
||||
filename:
|
||||
Self-explanatory.
|
||||
Path to write minimal configuration to.
|
||||
|
||||
header (default: "# Generated by Kconfiglib (https://github.com/ulfalizer/Kconfiglib)\n"):
|
||||
Text that will be inserted verbatim at the beginning of the file. You
|
||||
would usually want each line to start with '#' to make it a comment,
|
||||
and include a final terminating newline.
|
||||
header (default: None):
|
||||
Text inserted verbatim at the beginning of the file. You would
|
||||
usually want each line to start with '#' to make it a comment, and
|
||||
include a final terminating newline.
|
||||
|
||||
if None (the default), the value of the environment variable
|
||||
KCONFIG_CONFIG_HEADER had when the Kconfig instance was created will
|
||||
be used if it was set, and no header otherwise. See the
|
||||
Kconfig.config_header attribute.
|
||||
|
||||
Returns a string with a message saying which file got saved. This is
|
||||
meant to reduce boilerplate in tools, which can do e.g.
|
||||
|
@ -1603,9 +1641,12 @@ class Kconfig(object):
|
|||
|
||||
def _min_config_contents(self, header):
|
||||
# write_min_config() helper. Returns the contents to write as a string,
|
||||
# with 'header' at the beginning.
|
||||
# with 'header' or KCONFIG_CONFIG_HEADER at the beginning.
|
||||
|
||||
chunks = [header]
|
||||
if header is None:
|
||||
header = self.config_header
|
||||
|
||||
chunks = [header] # "".join()ed later
|
||||
add = chunks.append
|
||||
|
||||
for sym in self.unique_defined_syms:
|
||||
|
@ -2603,10 +2644,9 @@ class Kconfig(object):
|
|||
while 1:
|
||||
match = _name_special_search(s, i)
|
||||
|
||||
if match.group() == "$(":
|
||||
s, i = self._expand_macro(s, match.start(), ())
|
||||
else:
|
||||
if match.group() != "$(":
|
||||
return (s, match.start())
|
||||
s, i = self._expand_macro(s, match.start(), ())
|
||||
|
||||
def _expand_str(self, s, i):
|
||||
# Expands a quoted string starting at index 'i' in 's'. Handles both
|
||||
|
@ -2649,14 +2689,12 @@ class Kconfig(object):
|
|||
# Returns the expanded 's' (including the part before the macro) and
|
||||
# the index of the first character after the expanded macro in 's'.
|
||||
|
||||
start = i
|
||||
res = s[:i]
|
||||
i += 2 # Skip over "$("
|
||||
|
||||
# Start of current macro argument
|
||||
arg_start = i
|
||||
|
||||
# Arguments of this macro call
|
||||
new_args = []
|
||||
arg_start = i # Start of current macro argument
|
||||
new_args = [] # Arguments of this macro call
|
||||
nesting = 0 # Current parentheses nesting level
|
||||
|
||||
while 1:
|
||||
match = _macro_special_search(s, i)
|
||||
|
@ -2664,32 +2702,42 @@ class Kconfig(object):
|
|||
self._parse_error("missing end parenthesis in macro expansion")
|
||||
|
||||
|
||||
if match.group() == ")":
|
||||
if match.group() == "(":
|
||||
nesting += 1
|
||||
i = match.end()
|
||||
|
||||
elif match.group() == ")":
|
||||
if nesting:
|
||||
nesting -= 1
|
||||
i = match.end()
|
||||
continue
|
||||
|
||||
# Found the end of the macro
|
||||
|
||||
new_args.append(s[arg_start:match.start()])
|
||||
|
||||
prefix = s[:start]
|
||||
|
||||
# $(1) is replaced by the first argument to the function, etc.,
|
||||
# provided at least that many arguments were passed
|
||||
|
||||
try:
|
||||
# Does the macro look like an integer, with a corresponding
|
||||
# argument? If so, expand it to the value of the argument.
|
||||
prefix += args[int(new_args[0])]
|
||||
res += args[int(new_args[0])]
|
||||
except (ValueError, IndexError):
|
||||
# Regular variables are just functions without arguments,
|
||||
# and also go through the function value path
|
||||
prefix += self._fn_val(new_args)
|
||||
res += self._fn_val(new_args)
|
||||
|
||||
return (prefix + s[match.end():],
|
||||
len(prefix))
|
||||
return (res + s[match.end():], len(res))
|
||||
|
||||
elif match.group() == ",":
|
||||
i = match.end()
|
||||
if nesting:
|
||||
continue
|
||||
|
||||
# Found the end of a macro argument
|
||||
new_args.append(s[arg_start:match.start()])
|
||||
arg_start = i = match.end()
|
||||
arg_start = i
|
||||
|
||||
else: # match.group() == "$("
|
||||
# A nested macro call within the macro
|
||||
|
@ -2836,7 +2884,7 @@ class Kconfig(object):
|
|||
|
||||
if node.is_menuconfig and not node.prompt:
|
||||
self._warn("the menuconfig symbol {} has no prompt"
|
||||
.format(_name_and_loc(sym)))
|
||||
.format(sym.name_and_loc))
|
||||
|
||||
# Equivalent to
|
||||
#
|
||||
|
@ -3173,8 +3221,7 @@ class Kconfig(object):
|
|||
# UNKNOWN is falsy
|
||||
if node.item.orig_type and node.item.orig_type is not new_type:
|
||||
self._warn("{} defined with multiple types, {} will be used"
|
||||
.format(_name_and_loc(node.item),
|
||||
TYPE_TO_STR[new_type]))
|
||||
.format(node.item.name_and_loc, TYPE_TO_STR[new_type]))
|
||||
|
||||
node.item.orig_type = new_type
|
||||
|
||||
|
@ -3184,7 +3231,7 @@ class Kconfig(object):
|
|||
# multiple times
|
||||
|
||||
if node.prompt:
|
||||
self._warn(_name_and_loc(node.item) +
|
||||
self._warn(node.item.name_and_loc +
|
||||
" defined with multiple prompts in single location")
|
||||
|
||||
prompt = self._tokens[1]
|
||||
|
@ -3194,7 +3241,7 @@ class Kconfig(object):
|
|||
self._parse_error("expected prompt string")
|
||||
|
||||
if prompt != prompt.strip():
|
||||
self._warn(_name_and_loc(node.item) +
|
||||
self._warn(node.item.name_and_loc +
|
||||
" has leading or trailing whitespace in its prompt")
|
||||
|
||||
# This avoid issues for e.g. reStructuredText documentation, where
|
||||
|
@ -3205,7 +3252,7 @@ class Kconfig(object):
|
|||
|
||||
def _parse_help(self, node):
|
||||
if node.help is not None:
|
||||
self._warn(_name_and_loc(node.item) + " defined with more than "
|
||||
self._warn(node.item.name_and_loc + " defined with more than "
|
||||
"one help text -- only the last one will be used")
|
||||
|
||||
# Micro-optimization. This code is pretty hot.
|
||||
|
@ -3261,7 +3308,7 @@ class Kconfig(object):
|
|||
self._line_after_help(line)
|
||||
|
||||
def _empty_help(self, node, line):
|
||||
self._warn(_name_and_loc(node.item) +
|
||||
self._warn(node.item.name_and_loc +
|
||||
" has 'help' but empty help text")
|
||||
node.help = ""
|
||||
if line:
|
||||
|
@ -3641,26 +3688,26 @@ class Kconfig(object):
|
|||
if target_sym.orig_type not in _BOOL_TRISTATE_UNKNOWN:
|
||||
self._warn("{} selects the {} symbol {}, which is not "
|
||||
"bool or tristate"
|
||||
.format(_name_and_loc(sym),
|
||||
.format(sym.name_and_loc,
|
||||
TYPE_TO_STR[target_sym.orig_type],
|
||||
_name_and_loc(target_sym)))
|
||||
target_sym.name_and_loc))
|
||||
|
||||
for target_sym, _ in sym.implies:
|
||||
if target_sym.orig_type not in _BOOL_TRISTATE_UNKNOWN:
|
||||
self._warn("{} implies the {} symbol {}, which is not "
|
||||
"bool or tristate"
|
||||
.format(_name_and_loc(sym),
|
||||
.format(sym.name_and_loc,
|
||||
TYPE_TO_STR[target_sym.orig_type],
|
||||
_name_and_loc(target_sym)))
|
||||
target_sym.name_and_loc))
|
||||
|
||||
elif sym.orig_type: # STRING/INT/HEX
|
||||
for default, _ in sym.defaults:
|
||||
if default.__class__ is not Symbol:
|
||||
raise KconfigError(
|
||||
"the {} symbol {} has a malformed default {} -- expected "
|
||||
"a single symbol"
|
||||
.format(TYPE_TO_STR[sym.orig_type], _name_and_loc(sym),
|
||||
expr_str(default)))
|
||||
"the {} symbol {} has a malformed default {} -- "
|
||||
"expected a single symbol"
|
||||
.format(TYPE_TO_STR[sym.orig_type],
|
||||
sym.name_and_loc, expr_str(default)))
|
||||
|
||||
if sym.orig_type is STRING:
|
||||
if not default.is_constant and not default.nodes and \
|
||||
|
@ -3671,22 +3718,22 @@ class Kconfig(object):
|
|||
# (and no symbol named 'foo' exists).
|
||||
self._warn("style: quotes recommended around "
|
||||
"default value for string symbol "
|
||||
+ _name_and_loc(sym))
|
||||
+ sym.name_and_loc)
|
||||
|
||||
elif not num_ok(default, sym.orig_type): # INT/HEX
|
||||
self._warn("the {0} symbol {1} has a non-{0} default {2}"
|
||||
.format(TYPE_TO_STR[sym.orig_type],
|
||||
_name_and_loc(sym),
|
||||
_name_and_loc(default)))
|
||||
sym.name_and_loc,
|
||||
default.name_and_loc))
|
||||
|
||||
if sym.selects or sym.implies:
|
||||
self._warn("the {} symbol {} has selects or implies"
|
||||
.format(TYPE_TO_STR[sym.orig_type],
|
||||
_name_and_loc(sym)))
|
||||
sym.name_and_loc))
|
||||
|
||||
else: # UNKNOWN
|
||||
self._warn("{} defined without a type"
|
||||
.format(_name_and_loc(sym)))
|
||||
.format(sym.name_and_loc))
|
||||
|
||||
|
||||
if sym.ranges:
|
||||
|
@ -3694,7 +3741,7 @@ class Kconfig(object):
|
|||
self._warn(
|
||||
"the {} symbol {} has ranges, but is not int or hex"
|
||||
.format(TYPE_TO_STR[sym.orig_type],
|
||||
_name_and_loc(sym)))
|
||||
sym.name_and_loc))
|
||||
else:
|
||||
for low, high, _ in sym.ranges:
|
||||
if not num_ok(low, sym.orig_type) or \
|
||||
|
@ -3703,9 +3750,9 @@ class Kconfig(object):
|
|||
self._warn("the {0} symbol {1} has a non-{0} "
|
||||
"range [{2}, {3}]"
|
||||
.format(TYPE_TO_STR[sym.orig_type],
|
||||
_name_and_loc(sym),
|
||||
_name_and_loc(low),
|
||||
_name_and_loc(high)))
|
||||
sym.name_and_loc,
|
||||
low.name_and_loc,
|
||||
high.name_and_loc))
|
||||
|
||||
def _check_choice_sanity(self):
|
||||
# Checks various choice properties that are handiest to check after
|
||||
|
@ -3714,43 +3761,43 @@ class Kconfig(object):
|
|||
def warn_select_imply(sym, expr, expr_type):
|
||||
msg = "the choice symbol {} is {} by the following symbols, but " \
|
||||
"select/imply has no effect on choice symbols" \
|
||||
.format(_name_and_loc(sym), expr_type)
|
||||
.format(sym.name_and_loc, expr_type)
|
||||
|
||||
# si = select/imply
|
||||
for si in split_expr(expr, OR):
|
||||
msg += "\n - " + _name_and_loc(split_expr(si, AND)[0])
|
||||
msg += "\n - " + split_expr(si, AND)[0].name_and_loc
|
||||
|
||||
self._warn(msg)
|
||||
|
||||
for choice in self.unique_choices:
|
||||
if choice.orig_type not in _BOOL_TRISTATE:
|
||||
self._warn("{} defined with type {}"
|
||||
.format(_name_and_loc(choice),
|
||||
.format(choice.name_and_loc,
|
||||
TYPE_TO_STR[choice.orig_type]))
|
||||
|
||||
for node in choice.nodes:
|
||||
if node.prompt:
|
||||
break
|
||||
else:
|
||||
self._warn(_name_and_loc(choice) + " defined without a prompt")
|
||||
self._warn(choice.name_and_loc + " defined without a prompt")
|
||||
|
||||
for default, _ in choice.defaults:
|
||||
if default.__class__ is not Symbol:
|
||||
raise KconfigError(
|
||||
"{} has a malformed default {}"
|
||||
.format(_name_and_loc(choice), expr_str(default)))
|
||||
.format(choice.name_and_loc, expr_str(default)))
|
||||
|
||||
if default.choice is not choice:
|
||||
self._warn("the default selection {} of {} is not "
|
||||
"contained in the choice"
|
||||
.format(_name_and_loc(default),
|
||||
_name_and_loc(choice)))
|
||||
.format(default.name_and_loc,
|
||||
choice.name_and_loc))
|
||||
|
||||
for sym in choice.syms:
|
||||
if sym.defaults:
|
||||
self._warn("default on the choice symbol {} will have "
|
||||
"no effect, as defaults do not affect choice "
|
||||
"symbols".format(_name_and_loc(sym)))
|
||||
"symbols".format(sym.name_and_loc))
|
||||
|
||||
if sym.rev_dep is not sym.kconfig.n:
|
||||
warn_select_imply(sym, sym.rev_dep, "selected")
|
||||
|
@ -3762,12 +3809,12 @@ class Kconfig(object):
|
|||
if node.parent.item is choice:
|
||||
if not node.prompt:
|
||||
self._warn("the choice symbol {} has no prompt"
|
||||
.format(_name_and_loc(sym)))
|
||||
.format(sym.name_and_loc))
|
||||
|
||||
elif node.prompt:
|
||||
self._warn("the choice symbol {} is defined with a "
|
||||
"prompt outside the choice"
|
||||
.format(_name_and_loc(sym)))
|
||||
.format(sym.name_and_loc))
|
||||
|
||||
def _parse_error(self, msg):
|
||||
raise KconfigError("{}couldn't parse '{}': {}".format(
|
||||
|
@ -3907,6 +3954,13 @@ class Symbol(object):
|
|||
The type as given in the Kconfig file, without any magic applied. Used
|
||||
when printing the symbol.
|
||||
|
||||
tri_value:
|
||||
The tristate value of the symbol as an integer. One of 0, 1, 2,
|
||||
representing n, m, y. Always 0 (n) for non-bool/tristate symbols.
|
||||
|
||||
This is the symbol value that's used outside of relation expressions
|
||||
(A, !A, A && B, A || B).
|
||||
|
||||
str_value:
|
||||
The value of the symbol as a string. Gives the value for string/int/hex
|
||||
symbols. For bool/tristate symbols, gives "n", "m", or "y".
|
||||
|
@ -3914,17 +3968,20 @@ class Symbol(object):
|
|||
This is the symbol value that's used in relational expressions
|
||||
(A = B, A != B, etc.)
|
||||
|
||||
Gotcha: For int/hex symbols, the exact format of the value must often be
|
||||
preserved (e.g., when writing a .config file), hence why you can't get it
|
||||
Gotcha: For int/hex symbols, the exact format of the value is often
|
||||
preserved (e.g. when writing a .config file), hence why you can't get it
|
||||
directly as an int. Do int(int_sym.str_value) or
|
||||
int(hex_sym.str_value, 16) to get the integer value.
|
||||
|
||||
tri_value:
|
||||
The tristate value of the symbol as an integer. One of 0, 1, 2,
|
||||
representing n, m, y. Always 0 (n) for non-bool/tristate symbols.
|
||||
user_value:
|
||||
The user value of the symbol. None if no user value has been assigned
|
||||
(via Kconfig.load_config() or Symbol.set_value()).
|
||||
|
||||
This is the symbol value that's used outside of relation expressions
|
||||
(A, !A, A && B, A || B).
|
||||
Holds 0, 1, or 2 for bool/tristate symbols, and a string for the other
|
||||
symbol types.
|
||||
|
||||
WARNING: Do not assign directly to this. It will break things. Use
|
||||
Symbol.set_value().
|
||||
|
||||
assignable:
|
||||
A tuple containing the tristate user values that can currently be
|
||||
|
@ -3965,16 +4022,6 @@ class Symbol(object):
|
|||
The visibility of the symbol. One of 0, 1, 2, representing n, m, y. See
|
||||
the module documentation for an overview of symbol values and visibility.
|
||||
|
||||
user_value:
|
||||
The user value of the symbol. None if no user value has been assigned
|
||||
(via Kconfig.load_config() or Symbol.set_value()).
|
||||
|
||||
Holds 0, 1, or 2 for bool/tristate symbols, and a string for the other
|
||||
symbol types.
|
||||
|
||||
WARNING: Do not assign directly to this. It will break things. Use
|
||||
Symbol.set_value().
|
||||
|
||||
config_string:
|
||||
The .config assignment string that would get written out for the symbol
|
||||
by Kconfig.write_config(). Returns the empty string if no .config
|
||||
|
@ -4002,6 +4049,15 @@ class Symbol(object):
|
|||
though you might get some special symbols and possibly some "redundant"
|
||||
n-valued symbol entries in there.
|
||||
|
||||
name_and_loc:
|
||||
Holds a string like
|
||||
|
||||
"MY_SYMBOL (defined at foo/Kconfig:12, bar/Kconfig:14)"
|
||||
|
||||
, giving the name of the symbol and its definition location(s).
|
||||
|
||||
If the symbol is undefined, the location is given as "(undefined)".
|
||||
|
||||
nodes:
|
||||
A list of MenuNodes for this symbol. Will contain a single MenuNode for
|
||||
most symbols. Undefined and constant symbols have an empty nodes list.
|
||||
|
@ -4232,7 +4288,7 @@ class Symbol(object):
|
|||
"being outside the active range ([{}, {}]) -- falling "
|
||||
"back on defaults"
|
||||
.format(num2str(user_val), TYPE_TO_STR[self.orig_type],
|
||||
_name_and_loc(self),
|
||||
self.name_and_loc,
|
||||
num2str(low), num2str(high)))
|
||||
else:
|
||||
# If the user value is well-formed and satisfies range
|
||||
|
@ -4282,7 +4338,7 @@ class Symbol(object):
|
|||
self.kconfig._warn(
|
||||
"default value {} on {} clamped to {} due to "
|
||||
"being outside the active range ([{}, {}])"
|
||||
.format(val_num, _name_and_loc(self),
|
||||
.format(val_num, self.name_and_loc,
|
||||
num2str(clamp), num2str(low),
|
||||
num2str(high)))
|
||||
|
||||
|
@ -4323,7 +4379,7 @@ class Symbol(object):
|
|||
self.kconfig._warn(
|
||||
"The {} symbol {} is being evaluated in a logical context "
|
||||
"somewhere. It will always evaluate to n."
|
||||
.format(TYPE_TO_STR[self.orig_type], _name_and_loc(self)))
|
||||
.format(TYPE_TO_STR[self.orig_type], self.name_and_loc))
|
||||
|
||||
self._cached_tri_val = 0
|
||||
return 0
|
||||
|
@ -4433,6 +4489,13 @@ class Symbol(object):
|
|||
return '{}{}="{}"\n' \
|
||||
.format(self.kconfig.config_prefix, self.name, escape(val))
|
||||
|
||||
@property
|
||||
def name_and_loc(self):
|
||||
"""
|
||||
See the class documentation.
|
||||
"""
|
||||
return self.name + " " + _locs(self)
|
||||
|
||||
def set_value(self, value):
|
||||
"""
|
||||
Sets the user value of the symbol.
|
||||
|
@ -4454,8 +4517,8 @@ class Symbol(object):
|
|||
value:
|
||||
The user value to give to the symbol. For bool and tristate symbols,
|
||||
n/m/y can be specified either as 0/1/2 (the usual format for tristate
|
||||
values in Kconfiglib) or as one of the strings "n"/"m"/"y". For other
|
||||
symbol types, pass a string.
|
||||
values in Kconfiglib) or as one of the strings "n", "m", or "y". For
|
||||
other symbol types, pass a string.
|
||||
|
||||
Note that the value for an int/hex symbol is passed as a string, e.g.
|
||||
"123" or "0x0123". The format of this string is preserved in the
|
||||
|
@ -4502,7 +4565,7 @@ class Symbol(object):
|
|||
"assignment ignored"
|
||||
.format(TRI_TO_STR[value] if value in TRI_TO_STR else
|
||||
"'{}'".format(value),
|
||||
_name_and_loc(self), TYPE_TO_STR[self.orig_type]))
|
||||
self.name_and_loc, TYPE_TO_STR[self.orig_type]))
|
||||
|
||||
return False
|
||||
|
||||
|
@ -4790,7 +4853,7 @@ class Symbol(object):
|
|||
return
|
||||
|
||||
if self.kconfig._warn_assign_no_prompt:
|
||||
self.kconfig._warn(_name_and_loc(self) + " has no prompt, meaning "
|
||||
self.kconfig._warn(self.name_and_loc + " has no prompt, meaning "
|
||||
"user values have no effect on it")
|
||||
|
||||
def _str_default(self):
|
||||
|
@ -4836,7 +4899,7 @@ class Symbol(object):
|
|||
|
||||
msg = "{} has direct dependencies {} with value {}, but is " \
|
||||
"currently being {}-selected by the following symbols:" \
|
||||
.format(_name_and_loc(self), expr_str(self.direct_dep),
|
||||
.format(self.name_and_loc, expr_str(self.direct_dep),
|
||||
TRI_TO_STR[expr_value(self.direct_dep)],
|
||||
TRI_TO_STR[expr_value(self.rev_dep)])
|
||||
|
||||
|
@ -4854,7 +4917,7 @@ class Symbol(object):
|
|||
|
||||
msg += "\n - {}, with value {}, direct dependencies {} " \
|
||||
"(value: {})" \
|
||||
.format(_name_and_loc(selecting_sym),
|
||||
.format(selecting_sym.name_and_loc,
|
||||
selecting_sym.str_value,
|
||||
expr_str(selecting_sym.direct_dep),
|
||||
TRI_TO_STR[expr_value(selecting_sym.direct_dep)])
|
||||
|
@ -4938,19 +5001,9 @@ class Choice(object):
|
|||
Corresponding attributes have the same name in the Symbol and Choice
|
||||
classes, for consistency and compatibility.
|
||||
|
||||
assignable:
|
||||
See the symbol class documentation. Gives the assignable values (modes).
|
||||
|
||||
visibility:
|
||||
See the Symbol class documentation. Acts on the value (mode).
|
||||
|
||||
selection:
|
||||
The Symbol instance of the currently selected symbol. None if the Choice
|
||||
is not in y mode or has no selected symbol (due to unsatisfied
|
||||
dependencies on choice symbols).
|
||||
|
||||
WARNING: Do not assign directly to this. It will break things. Call
|
||||
sym.set_value(2) on the choice symbol you want to select instead.
|
||||
str_value:
|
||||
Like choice.tri_value, but gives the value as one of the strings
|
||||
"n", "m", or "y"
|
||||
|
||||
user_value:
|
||||
The value (mode) selected by the user through Choice.set_value(). Either
|
||||
|
@ -4960,6 +5013,17 @@ class Choice(object):
|
|||
WARNING: Do not assign directly to this. It will break things. Use
|
||||
Choice.set_value() instead.
|
||||
|
||||
assignable:
|
||||
See the symbol class documentation. Gives the assignable values (modes).
|
||||
|
||||
selection:
|
||||
The Symbol instance of the currently selected symbol. None if the Choice
|
||||
is not in y mode or has no selected symbol (due to unsatisfied
|
||||
dependencies on choice symbols).
|
||||
|
||||
WARNING: Do not assign directly to this. It will break things. Call
|
||||
sym.set_value(2) on the choice symbol you want to select instead.
|
||||
|
||||
user_selection:
|
||||
The symbol selected by the user (by setting it to y). Ignored if the
|
||||
choice is not in y mode, but still remembered so that the choice "snaps
|
||||
|
@ -4969,6 +5033,19 @@ class Choice(object):
|
|||
WARNING: Do not assign directly to this. It will break things. Call
|
||||
sym.set_value(2) on the choice symbol to be selected instead.
|
||||
|
||||
visibility:
|
||||
See the Symbol class documentation. Acts on the value (mode).
|
||||
|
||||
name_and_loc:
|
||||
Holds a string like
|
||||
|
||||
"<choice MY_CHOICE> (defined at foo/Kconfig:12)"
|
||||
|
||||
, giving the name of the choice and its definition location(s). If the
|
||||
choice has no name (isn't defined with 'choice MY_CHOICE'), then it will
|
||||
be shown as "<choice>" before the list of locations (always a single one
|
||||
in that case).
|
||||
|
||||
syms:
|
||||
List of symbols contained in the choice.
|
||||
|
||||
|
@ -5088,6 +5165,14 @@ class Choice(object):
|
|||
self._cached_vis = _visibility(self)
|
||||
return self._cached_vis
|
||||
|
||||
@property
|
||||
def name_and_loc(self):
|
||||
"""
|
||||
See the class documentation.
|
||||
"""
|
||||
# Reuse the expression format, which is '<choice (name, if any)>'.
|
||||
return standard_sc_expr_str(self) + " " + _locs(self)
|
||||
|
||||
@property
|
||||
def selection(self):
|
||||
"""
|
||||
|
@ -5128,7 +5213,7 @@ class Choice(object):
|
|||
"assignment ignored"
|
||||
.format(TRI_TO_STR[value] if value in TRI_TO_STR else
|
||||
"'{}'".format(value),
|
||||
_name_and_loc(self), TYPE_TO_STR[self.orig_type]))
|
||||
self.name_and_loc, TYPE_TO_STR[self.orig_type]))
|
||||
|
||||
return False
|
||||
|
||||
|
@ -6050,21 +6135,36 @@ def unescape(s):
|
|||
_unescape_sub = re.compile(r"\\(.)").sub
|
||||
|
||||
|
||||
def standard_kconfig():
|
||||
def standard_kconfig(description=None):
|
||||
"""
|
||||
Helper for tools. Loads the top-level Kconfig specified as the first
|
||||
command-line argument, or "Kconfig" if there are no command-line arguments.
|
||||
Returns the Kconfig instance.
|
||||
Argument parsing helper for tools that take a single optional Kconfig file
|
||||
argument (default: Kconfig). Returns the Kconfig instance for the parsed
|
||||
configuration. Uses argparse internally.
|
||||
|
||||
Exits with sys.exit() (which raises a SystemExit exception) and prints a
|
||||
usage note to stderr if more than one command-line argument is passed.
|
||||
Exits with sys.exit() (which raises SystemExit) on errors.
|
||||
|
||||
description (default: None):
|
||||
The 'description' passed to argparse.ArgumentParser().
|
||||
argparse.RawDescriptionHelpFormatter is used, so formatting is preserved.
|
||||
"""
|
||||
if len(sys.argv) > 2:
|
||||
sys.exit("usage: {} [Kconfig]".format(sys.argv[0]))
|
||||
import argparse
|
||||
|
||||
# Only show backtraces for unexpected exceptions
|
||||
parser = argparse.ArgumentParser(
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
description=description)
|
||||
|
||||
parser.add_argument(
|
||||
"kconfig",
|
||||
metavar="KCONFIG",
|
||||
default="Kconfig",
|
||||
nargs="?",
|
||||
help="Kconfig file (default: Kconfig)")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Suppress backtraces for expected exceptions
|
||||
try:
|
||||
return Kconfig("Kconfig" if len(sys.argv) < 2 else sys.argv[1])
|
||||
return Kconfig(args.kconfig)
|
||||
except (EnvironmentError, KconfigError) as e:
|
||||
# Some long exception messages have extra newlines for better
|
||||
# formatting when reported as an unhandled exception. Strip them here.
|
||||
|
@ -6286,20 +6386,16 @@ def _save_old(path):
|
|||
pass
|
||||
|
||||
|
||||
def _name_and_loc(sc):
|
||||
# Helper for giving the symbol/choice name and location(s) in e.g. warnings
|
||||
def _locs(sc):
|
||||
# Symbol/Choice.name_and_loc helper. Returns the "(defined at ...)" part of
|
||||
# the string. 'sc' is a Symbol or Choice.
|
||||
|
||||
# Reuse the expression format. That way choices show up as
|
||||
# '<choice (name, if any)>'
|
||||
name = standard_sc_expr_str(sc)
|
||||
if sc.nodes:
|
||||
return "(defined at {})".format(
|
||||
", ".join("{0.filename}:{0.linenr}".format(node)
|
||||
for node in sc.nodes))
|
||||
|
||||
if not sc.nodes:
|
||||
return name + " (undefined)"
|
||||
|
||||
return "{} (defined at {})".format(
|
||||
name,
|
||||
", ".join("{}:{}".format(node.filename, node.linenr)
|
||||
for node in sc.nodes))
|
||||
return "(undefined)"
|
||||
|
||||
|
||||
# Menu manipulation
|
||||
|
@ -6554,7 +6650,7 @@ def _found_dep_loop(loop, cur):
|
|||
msg += "the choice symbol "
|
||||
|
||||
msg += "{}, with definition...\n\n{}\n\n" \
|
||||
.format(_name_and_loc(item), item)
|
||||
.format(item.name_and_loc, item)
|
||||
|
||||
# Small wart: Since we reuse the already calculated
|
||||
# Symbol/Choice._dependents sets for recursive dependency detection, we
|
||||
|
@ -6578,7 +6674,7 @@ def _found_dep_loop(loop, cur):
|
|||
msg += "(imply-related dependencies: {})\n\n" \
|
||||
.format(expr_str(item.rev_dep))
|
||||
|
||||
msg += "...depends again on {}".format(_name_and_loc(loop[0]))
|
||||
msg += "...depends again on " + loop[0].name_and_loc
|
||||
|
||||
raise KconfigError(msg)
|
||||
|
||||
|
@ -7015,8 +7111,8 @@ _assignment_lhs_fragment_match = _re_match("[A-Za-z0-9_-]*")
|
|||
# variable assignment
|
||||
_assignment_rhs_match = _re_match(r"\s*(=|:=|\+=)\s*(.*)")
|
||||
|
||||
# Special characters/strings while expanding a macro (')', ',', and '$(')
|
||||
_macro_special_search = _re_search(r"\)|,|\$\(")
|
||||
# Special characters/strings while expanding a macro ('(', ')', ',', and '$(')
|
||||
_macro_special_search = _re_search(r"\(|\)|,|\$\(")
|
||||
|
||||
# Special characters/strings while expanding a string (quotes, '\', and '$(')
|
||||
_string_special_search = _re_search(r'"|\'|\\|\$\(')
|
||||
|
|
|
@ -76,7 +76,7 @@ This is the current list of built-in styles:
|
|||
- default classic Kconfiglib theme with a yellow accent
|
||||
- monochrome colorless theme (uses only bold and standout) attributes,
|
||||
this style is used if the terminal doesn't support colors
|
||||
- aquatic blue tinted style loosely resembling the lxdialog theme
|
||||
- aquatic blue-tinted style loosely resembling the lxdialog theme
|
||||
|
||||
It is possible to customize the current style by changing colors of UI
|
||||
elements on the screen. This is the list of elements that can be stylized:
|
||||
|
@ -140,13 +140,16 @@ If there's an error in the style definition or if a missing style is assigned
|
|||
to, the assignment will be ignored, along with a warning being printed on
|
||||
stderr.
|
||||
|
||||
The 'default' theme is always implicitly parsed first (or the 'monochrome'
|
||||
theme if the terminal lacks colors), so the following two settings have the
|
||||
same effect:
|
||||
The 'default' theme is always implicitly parsed first, so the following two
|
||||
settings have the same effect:
|
||||
|
||||
MENUCONFIG_STYLE="selection=fg:white,bg:red"
|
||||
MENUCONFIG_STYLE="default selection=fg:white,bg:red"
|
||||
|
||||
If the terminal doesn't support colors, the 'monochrome' theme is used, and
|
||||
MENUCONFIG_STYLE is ignored. The assumption is that the environment is broken
|
||||
somehow, and that the important thing is to get something usable.
|
||||
|
||||
|
||||
Other features
|
||||
==============
|
||||
|
@ -177,27 +180,41 @@ Other features
|
|||
Limitations
|
||||
===========
|
||||
|
||||
Doesn't work out of the box on Windows, but can be made to work with 'pip
|
||||
install windows-curses'. See the
|
||||
https://github.com/zephyrproject-rtos/windows-curses repository.
|
||||
Doesn't work out of the box on Windows, but can be made to work with
|
||||
|
||||
'pip install kconfiglib' on Windows automatically installs windows-curses
|
||||
to make the menuconfig usable.
|
||||
pip install windows-curses
|
||||
|
||||
See the https://github.com/zephyrproject-rtos/windows-curses repository.
|
||||
"""
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
_IS_WINDOWS = os.name == "nt" # Are we running on Windows?
|
||||
|
||||
try:
|
||||
import curses
|
||||
except ImportError:
|
||||
print('"windows-curses" package is required in Windows command line. Please install it by running '
|
||||
'"{} -m pip install --user windows-curses" (or without the "--user" option)'
|
||||
''.format(sys.executable))
|
||||
exit(1)
|
||||
except ImportError as e:
|
||||
if not _IS_WINDOWS:
|
||||
raise
|
||||
sys.exit("""\
|
||||
menuconfig failed to import the standard Python 'curses' library. Try
|
||||
installing a package like windows-curses
|
||||
(https://github.com/zephyrproject-rtos/windows-curses) by running this command
|
||||
in cmd.exe:
|
||||
|
||||
pip install windows-curses
|
||||
|
||||
Starting with Kconfiglib 13.0.0, windows-curses is no longer automatically
|
||||
installed when installing Kconfiglib via pip on Windows (because it breaks
|
||||
installation on MSYS2).
|
||||
|
||||
Exception:
|
||||
{}: {}""".format(type(e).__name__, e))
|
||||
|
||||
import errno
|
||||
import locale
|
||||
import os
|
||||
import re
|
||||
import textwrap
|
||||
|
||||
|
@ -309,19 +326,18 @@ _STYLES = {
|
|||
text=
|
||||
""",
|
||||
|
||||
# Blue tinted style loosely resembling lxdialog
|
||||
# Blue-tinted style loosely resembling lxdialog
|
||||
"aquatic": """
|
||||
path=fg:cyan,bg:blue,bold
|
||||
separator=fg:white,bg:cyan,bold
|
||||
help=path
|
||||
frame=fg:white,bg:cyan,bold
|
||||
body=fg:brightwhite,bg:blue
|
||||
body=fg:white,bg:blue
|
||||
edit=fg:black,bg:white
|
||||
"""
|
||||
}
|
||||
|
||||
# Standard colors definition
|
||||
_STYLE_STD_COLORS = {
|
||||
_NAMED_COLORS = {
|
||||
# Basic colors
|
||||
"black": curses.COLOR_BLACK,
|
||||
"red": curses.COLOR_RED,
|
||||
|
@ -547,9 +563,6 @@ def _style_to_curses(style_def):
|
|||
def parse_color(color_def):
|
||||
color_def = color_def.split(":", 1)[1]
|
||||
|
||||
if color_def in _STYLE_STD_COLORS:
|
||||
return _color_from_num(_STYLE_STD_COLORS[color_def])
|
||||
|
||||
# HTML format, #RRGGBB
|
||||
if re.match("#[A-Fa-f0-9]{6}", color_def):
|
||||
return _color_from_rgb((
|
||||
|
@ -557,19 +570,20 @@ def _style_to_curses(style_def):
|
|||
int(color_def[3:5], 16),
|
||||
int(color_def[5:7], 16)))
|
||||
|
||||
try:
|
||||
color_num = _color_from_num(int(color_def, 0))
|
||||
except ValueError:
|
||||
_warn("Ignoring color ", color_def, "that's neither predefined "
|
||||
"nor a number")
|
||||
|
||||
return -1
|
||||
if color_def in _NAMED_COLORS:
|
||||
color_num = _color_from_num(_NAMED_COLORS[color_def])
|
||||
else:
|
||||
try:
|
||||
color_num = _color_from_num(int(color_def, 0))
|
||||
except ValueError:
|
||||
_warn("Ignoring color", color_def, "that's neither "
|
||||
"predefined nor a number")
|
||||
return -1
|
||||
|
||||
if not -1 <= color_num < curses.COLORS:
|
||||
_warn("Ignoring color {}, which is outside the range "
|
||||
"-1..curses.COLORS-1 (-1..{})"
|
||||
.format(color_def, curses.COLORS - 1))
|
||||
|
||||
return -1
|
||||
|
||||
return color_num
|
||||
|
@ -602,15 +616,26 @@ def _style_to_curses(style_def):
|
|||
|
||||
def _init_styles():
|
||||
if curses.has_colors():
|
||||
curses.use_default_colors()
|
||||
try:
|
||||
curses.use_default_colors()
|
||||
except curses.error:
|
||||
# Ignore errors on funky terminals that support colors but not
|
||||
# using default colors. Worst it can do is break transparency and
|
||||
# the like. Ran across this with the MSYS2/winpty setup in
|
||||
# https://github.com/msys2/MINGW-packages/issues/5823, though there
|
||||
# seems to be a lot of general brokenness there.
|
||||
pass
|
||||
|
||||
# Use the 'monochrome' style template as the base on terminals without
|
||||
# color
|
||||
_parse_style("default" if curses.has_colors() else "monochrome", True)
|
||||
|
||||
# Add any user-defined style from the environment
|
||||
if "MENUCONFIG_STYLE" in os.environ:
|
||||
_parse_style(os.environ["MENUCONFIG_STYLE"], False)
|
||||
# Use the 'default' theme as the base, and add any user-defined style
|
||||
# settings from the environment
|
||||
_parse_style("default", True)
|
||||
if "MENUCONFIG_STYLE" in os.environ:
|
||||
_parse_style(os.environ["MENUCONFIG_STYLE"], False)
|
||||
else:
|
||||
# Force the 'monochrome' theme if the terminal doesn't support colors.
|
||||
# MENUCONFIG_STYLE is likely to mess things up here (though any colors
|
||||
# would be ignored), so ignore it.
|
||||
_parse_style("monochrome", True)
|
||||
|
||||
|
||||
# color_attribs holds the color pairs we've already created, indexed by a
|
||||
|
@ -644,7 +669,7 @@ def _style_attr(fg_color, bg_color, attribs, color_attribs={}):
|
|||
|
||||
|
||||
def _main():
|
||||
menuconfig(standard_kconfig())
|
||||
menuconfig(standard_kconfig(__doc__))
|
||||
|
||||
|
||||
def menuconfig(kconf):
|
||||
|
@ -2210,9 +2235,7 @@ def _sorted_sc_nodes(cached_nodes=[]):
|
|||
key=lambda choice: choice.name or "")
|
||||
|
||||
cached_nodes += sorted(
|
||||
[node
|
||||
for choice in choices
|
||||
for node in choice.nodes],
|
||||
[node for choice in choices for node in choice.nodes],
|
||||
key=lambda node: node.prompt[0] if node.prompt else "")
|
||||
|
||||
return cached_nodes
|
||||
|
@ -3273,8 +3296,5 @@ def _change_c_lc_ctype_to_utf8():
|
|||
return
|
||||
|
||||
|
||||
# Are we running on Windows?
|
||||
_IS_WINDOWS = os.name == "nt"
|
||||
|
||||
if __name__ == "__main__":
|
||||
_main()
|
||||
|
|
Loading…
Reference in a new issue