summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlf Magnusson <ulfalizer@gmail.com>2019-03-14 15:26:24 +0100
committerUlf Magnusson <ulfalizer@gmail.com>2019-03-14 16:43:36 +0100
commitbf407654df1081e7fbc3f876288cc275092cf549 (patch)
treef14e7308605104a0efe386d89251a37ae3fbe7be
parentd6e6f7aee1fa4d34ffe814ac2c0f7ea4a64de13a (diff)
menuconfig: Put two blank lines between top-level functions
Be consistent with the other utilities.
-rwxr-xr-xmenuconfig.py104
1 files changed, 101 insertions, 3 deletions
diff --git a/menuconfig.py b/menuconfig.py
index d7661b4..b978e08 100755
--- a/menuconfig.py
+++ b/menuconfig.py
@@ -331,6 +331,7 @@ _STYLE_STD_COLORS = {
"brightpurple": curses.COLOR_MAGENTA + 8,
}
+
def _rgb_to_6cube(rgb):
# Converts an 888 RGB color to a 3-tuple (nice in that it's hashable)
# representing the closests xterm 256-color 6x6x6 color cube color.
@@ -346,11 +347,13 @@ def _rgb_to_6cube(rgb):
# 48 is the middle ground between 0 and 95.
return tuple(0 if x < 48 else int(round(max(1, (x - 55)/40))) for x in rgb)
+
def _6cube_to_rgb(r6g6b6):
# Returns the 888 RGB color for a 666 xterm color cube index
return tuple(0 if x == 0 else 40*x + 55 for x in r6g6b6)
+
def _rgb_to_gray(rgb):
# Converts an 888 RGB color to the index of an xterm 256-color grayscale
# color with approx. the same perceived brightness
@@ -368,11 +371,13 @@ def _rgb_to_gray(rgb):
# Clamp the index to 0-23, corresponding to 232-255
return max(0, min(index, 23))
+
def _gray_to_rgb(index):
# Convert a grayscale index to its closet single RGB component
return 3*(10*index + 8,) # Returns a 3-tuple
+
# Obscure Python: We never pass a value for rgb2index, and it keeps pointing to
# the same dict. This avoids a global.
def _alloc_rgb(rgb, rgb2index={}):
@@ -406,6 +411,7 @@ def _alloc_rgb(rgb, rgb2index={}):
return color_index
+
def _color_from_num(num):
# Returns the index of a color that looks like color 'num' in the xterm
# 256-color palette (but that might not be 'num', if we're redefining
@@ -431,6 +437,7 @@ def _color_from_num(num):
return _alloc_rgb(_gray_to_rgb(num - 232))
+
def _color_from_rgb(rgb):
# Returns the index of a color matching the 888 RGB color 'rgb'. The
# returned color might be an ~exact match or an approximation, depending on
@@ -477,9 +484,6 @@ def _color_from_rgb(rgb):
return best
-# Dictionary mapping element types to the curses attributes used to display
-# them
-_style = {}
def _parse_style(style_str, parsing_default):
# Parses a string with '<element>=<style>' assignments. Anything not
@@ -515,6 +519,11 @@ def _parse_style(style_str, parsing_default):
else:
_warn("Ignoring non-existent style template", sline)
+# Dictionary mapping element types to the curses attributes used to display
+# them
+_style = {}
+
+
def _style_to_curses(style_def):
# Parses a style definition string (<element>=<style>), returning
# a (fg_color, bg_color, attributes) tuple.
@@ -574,6 +583,7 @@ def _style_to_curses(style_def):
return _style_attr(fg_color, bg_color, attrs)
+
def _init_styles():
if curses.has_colors():
curses.use_default_colors()
@@ -586,6 +596,7 @@ def _init_styles():
if "MENUCONFIG_STYLE" in os.environ:
_parse_style(os.environ["MENUCONFIG_STYLE"], False)
+
# color_attribs holds the color pairs we've already created, indexed by a
# (<foreground color>, <background color>) tuple.
#
@@ -610,14 +621,17 @@ def _style_attr(fg_color, bg_color, attribs, color_attribs={}):
return color_attribs[(fg_color, bg_color)] | attribs
+
#
# Main application
#
+
# Used as the entry point in setup.py
def _main():
menuconfig(standard_kconfig())
+
def menuconfig(kconf):
"""
Launches the configuration interface, returning after the user exits.
@@ -678,6 +692,7 @@ def menuconfig(kconf):
# curses has been de-initialized.
print(curses.wrapper(_menuconfig))
+
def _load_config():
# Loads any existing .config file. See the Kconfig.load_config() docstring.
#
@@ -705,6 +720,7 @@ def _load_config():
# No need to prompt for save
return False
+
# Global variables used below:
#
# _stdscr:
@@ -740,6 +756,7 @@ def _load_config():
# We reset this to False whenever the configuration is saved explicitly
# from the save dialog.
+
def _menuconfig(stdscr):
# Logic for the main display, with the list of symbols, etc.
@@ -878,6 +895,7 @@ def _menuconfig(stdscr):
if res:
return res
+
def _quit_dialog():
if not _conf_changed:
return "No changes to save"
@@ -903,6 +921,7 @@ def _quit_dialog():
elif c == "n":
return "Configuration was not saved"
+
def _init():
# Initializes the main display with the list of symbols, etc. Also does
# misc. global initialization that needs to happen after initializing
@@ -971,6 +990,7 @@ def _init():
# Give windows their initial size
_resize_main()
+
def _resize_main():
# Resizes the main display, with the list of symbols, etc., to fill the
# terminal
@@ -1012,11 +1032,13 @@ def _resize_main():
if _sel_node_i - _menu_scroll >= menu_win_height:
_menu_scroll = _sel_node_i - menu_win_height + 1
+
def _menu_win_height():
# Returns the height of the menu display
return _menu_win.getmaxyx()[0]
+
def _prefer_toggle(item):
# For nodes with menus, determines whether Space should change the value of
# the node's item or enter its menu. We toggle symbols (which have menus
@@ -1026,6 +1048,7 @@ def _prefer_toggle(item):
return isinstance(item, Symbol) or \
(isinstance(item, Choice) and len(item.assignable) > 1)
+
def _enter_menu(menu):
# Makes 'menu' the currently displayed menu. "Menu" here includes choices
# and symbols defined with the 'menuconfig' keyword.
@@ -1050,6 +1073,7 @@ def _enter_menu(menu):
if isinstance(menu.item, Choice):
_select_selected_choice_sym()
+
def _select_selected_choice_sym():
# Puts the cursor on the currently selected (y-valued) choice symbol, if
# any. Does nothing if if the choice has no selection (is not visible/in y
@@ -1066,6 +1090,7 @@ def _select_selected_choice_sym():
_sel_node_i = _shown.index(node)
_center_vertically()
+
def _jump_to(node):
# Jumps directly to the menu node 'node'
@@ -1114,6 +1139,7 @@ def _jump_to(node):
if jump_into and isinstance(_cur_menu.item, Choice):
_select_selected_choice_sym()
+
def _leave_menu():
# Jumps to the parent menu of the current menu. Does nothing if we're in
# the top menu.
@@ -1144,6 +1170,7 @@ def _leave_menu():
# node earlier
_center_vertically()
+
def _select_next_menu_entry():
# Selects the menu entry after the current one, adjusting the scroll if
# necessary. Does nothing if we're already at the last menu entry.
@@ -1164,6 +1191,7 @@ def _select_next_menu_entry():
_menu_scroll += 1
+
def _select_prev_menu_entry():
# Selects the menu entry before the current one, adjusting the scroll if
# necessary. Does nothing if we're already at the first menu entry.
@@ -1179,6 +1207,7 @@ def _select_prev_menu_entry():
if _sel_node_i <= _menu_scroll + _SCROLL_OFFSET:
_menu_scroll = max(_menu_scroll - 1, 0)
+
def _select_last_menu_entry():
# Selects the last menu entry in the current menu
@@ -1188,6 +1217,7 @@ def _select_last_menu_entry():
_sel_node_i = len(_shown) - 1
_menu_scroll = _max_scroll(_shown, _menu_win)
+
def _select_first_menu_entry():
# Selects the first menu entry in the current menu
@@ -1196,6 +1226,7 @@ def _select_first_menu_entry():
_sel_node_i = _menu_scroll = 0
+
def _toggle_show_all():
# Toggles show-all mode on/off. If turning it off would give no visible
# items in the current menu, it is left on.
@@ -1244,6 +1275,7 @@ def _toggle_show_all():
# might be impossible if too many nodes have disappeared above the node.
_menu_scroll = max(_sel_node_i - old_row, 0)
+
def _center_vertically():
# Centers the selected node vertically, if possible
@@ -1252,6 +1284,7 @@ def _center_vertically():
_menu_scroll = min(max(_sel_node_i - _menu_win_height()//2, 0),
_max_scroll(_shown, _menu_win))
+
def _draw_main():
# Draws the "main" display, with the list of symbols, the header, and the
# footer.
@@ -1400,6 +1433,7 @@ def _draw_main():
_path_win.noutrefresh()
+
def _parent_menu(node):
# Returns the menu node of the menu that contains 'node'. In addition to
# proper 'menu's, this might also be a 'menuconfig' symbol or a 'choice'.
@@ -1410,6 +1444,7 @@ def _parent_menu(node):
menu = menu.parent
return menu
+
def _shown_nodes(menu):
# Returns the list of menu nodes from 'menu' (see _parent_menu()) that
# would be shown when entering it
@@ -1483,6 +1518,7 @@ def _shown_nodes(menu):
return rec(menu.list)
+
def _change_node(node):
# Changes the value of the menu node 'node' if it is a symbol. Bools and
# tristates are toggled, while other symbol types pop up a text entry
@@ -1534,6 +1570,7 @@ def _change_node(node):
val_index = sc.assignable.index(sc.tri_value)
_set_val(sc, sc.assignable[(val_index + 1) % len(sc.assignable)])
+
def _set_sel_node_tri_val(tri_val):
# Sets the value of the currently selected menu entry to 'tri_val', if that
# value can be assigned
@@ -1542,6 +1579,7 @@ def _set_sel_node_tri_val(tri_val):
if isinstance(sc, (Symbol, Choice)) and tri_val in sc.assignable:
_set_val(sc, tri_val)
+
def _set_val(sc, val):
# Wrapper around Symbol/Choice.set_value() for updating the menu state and
# _conf_changed
@@ -1561,6 +1599,7 @@ def _set_val(sc, val):
# current menu are visible. Recalculate the state.
_update_menu()
+
def _update_menu():
# Updates the current menu after the value of a symbol or choice has been
# changed. Changing a value might change which items in the menu are
@@ -1588,6 +1627,7 @@ def _update_menu():
# might be impossible if too many nodes have disappeared above the node.
_menu_scroll = max(_sel_node_i - old_row, 0)
+
def _input_dialog(title, initial_text, info_text=None):
# Pops up a dialog that prompts the user for a string
#
@@ -1650,6 +1690,7 @@ def _input_dialog(title, initial_text, info_text=None):
else:
s, i, hscroll = _edit_text(c, s, i, hscroll, edit_width())
+
def _resize_input_dialog(win, title, info_lines):
# Resizes the input dialog to a size appropriate for the terminal size
@@ -1669,6 +1710,7 @@ def _resize_input_dialog(win, title, info_lines):
win.mvwin((screen_height - win_height)//2,
(screen_width - win_width)//2)
+
def _draw_input_dialog(win, title, info_lines, s, i, hscroll):
edit_width = win.getmaxyx()[1] - 4
@@ -1689,6 +1731,7 @@ def _draw_input_dialog(win, title, info_lines, s, i, hscroll):
win.noutrefresh()
+
def _load_dialog():
# Dialog for loading a new configuration
#
@@ -1721,6 +1764,7 @@ def _load_dialog():
_msg("Success", "Loaded {}".format(filename))
return True
+
def _try_load(filename):
# Tries to load a configuration file. Pops up an error and returns False on
# failure.
@@ -1736,6 +1780,7 @@ def _try_load(filename):
.format(filename, e.strerror, errno.errorcode[e.errno]))
return False
+
def _save_dialog(save_fn, default_filename, description):
# Dialog for saving the current configuration
#
@@ -1766,6 +1811,7 @@ def _save_dialog(save_fn, default_filename, description):
_msg("Success", "{} saved to {}".format(description, filename))
return True
+
def _try_save(save_fn, filename, description):
# Tries to save a configuration file. Pops up an error and returns False on
# failure.
@@ -1785,6 +1831,7 @@ def _try_save(save_fn, filename, description):
errno.errorcode[e.errno]))
return False
+
def _key_dialog(title, text, keys):
# Pops up a dialog that can be closed by pressing a key
#
@@ -1831,6 +1878,7 @@ def _key_dialog(title, text, keys):
if c in keys:
return c
+
def _resize_key_dialog(win, text):
# Resizes the key dialog to a size appropriate for the terminal size
@@ -1845,6 +1893,7 @@ def _resize_key_dialog(win, text):
win.mvwin((screen_height - win_height)//2,
(screen_width - win_width)//2)
+
def _draw_key_dialog(win, title, text):
win.erase()
@@ -1856,6 +1905,7 @@ def _draw_key_dialog(win, title, text):
win.noutrefresh()
+
def _draw_frame(win, title):
# Draw a frame around the inner edges of 'win', with 'title' at the top
@@ -1876,6 +1926,7 @@ def _draw_frame(win, title):
win.attroff(_style["frame"])
+
def _jump_to_dialog():
# Implements the jump-to dialog, where symbols can be looked up via
# incremental search and jumped to.
@@ -2072,6 +2123,7 @@ def _jump_to_dialog():
s, s_i, hscroll = _edit_text(c, s, s_i, hscroll,
edit_box.getmaxyx()[1] - 2)
+
# Obscure Python: We never pass a value for cached_nodes, and it keeps pointing
# to the same list. This avoids a global.
def _sorted_sc_nodes(cached_nodes=[]):
@@ -2099,6 +2151,7 @@ def _sorted_sc_nodes(cached_nodes=[]):
return cached_nodes
+
def _sorted_menu_comment_nodes(cached_nodes=[]):
# Returns a list of menu and comment nodes to search, sorted by prompt,
# with the menus first
@@ -2112,6 +2165,7 @@ def _sorted_menu_comment_nodes(cached_nodes=[]):
return cached_nodes
+
def _resize_jump_to_dialog(edit_box, matches_win, bot_sep_win, help_win,
sel_node_i, scroll):
# Resizes the jump-to dialog to fill the terminal.
@@ -2152,6 +2206,7 @@ def _resize_jump_to_dialog(edit_box, matches_win, bot_sep_win, help_win,
return sel_node_i - matches_win_height + 1
return scroll
+
def _draw_jump_to_dialog(edit_box, matches_win, bot_sep_win, help_win,
s, s_i, hscroll,
bad_re, matches, sel_node_i, scroll):
@@ -2237,6 +2292,7 @@ def _draw_jump_to_dialog(edit_box, matches_win, bot_sep_win, help_win,
edit_box.noutrefresh()
+
def _info_dialog(node, from_jump_to_dialog):
# Shows a fullscreen window with information about 'node'.
#
@@ -2321,6 +2377,7 @@ def _info_dialog(node, from_jump_to_dialog):
return
+
def _resize_info_dialog(top_line_win, text_win, bot_sep_win, help_win):
# Resizes the info dialog to fill the terminal
@@ -2348,6 +2405,7 @@ def _resize_info_dialog(top_line_win, text_win, bot_sep_win, help_win):
for win in text_win, bot_sep_win, help_win:
win.mvwin(0, 0)
+
def _draw_info_dialog(node, lines, scroll, top_line_win, text_win,
bot_sep_win, help_win):
@@ -2414,6 +2472,7 @@ def _draw_info_dialog(node, lines, scroll, top_line_win, text_win,
top_line_win.noutrefresh()
+
def _info_str(node):
# Returns information about the menu node 'node' as a string.
#
@@ -2453,12 +2512,14 @@ def _info_str(node):
# node.item in (MENU, COMMENT)
return _kconfig_def_info(node)
+
def _name_info(sc):
# Returns a string with the name of the symbol/choice. Names are optional
# for choices.
return "Name: {}\n".format(sc.name) if sc.name else ""
+
def _prompt_info(sc):
# Returns a string listing the prompts of 'sc' (Symbol or Choice)
@@ -2470,6 +2531,7 @@ def _prompt_info(sc):
return s
+
def _value_info(sym):
# Returns a string showing 'sym's value
@@ -2479,6 +2541,7 @@ def _value_info(sym):
if sym.orig_type == STRING
else sym.str_value)
+
def _choice_syms_info(choice):
# Returns a string listing the choice symbols in 'choice'. Adds
# "(selected)" next to the selected one.
@@ -2493,6 +2556,7 @@ def _choice_syms_info(choice):
return s + "\n"
+
def _help_info(sc):
# Returns a string with the help text(s) of 'sc' (Symbol or Choice).
# Symbols and choices defined in multiple locations can have multiple help
@@ -2507,6 +2571,7 @@ def _help_info(sc):
return s
+
def _direct_dep_info(sc):
# Returns a string describing the direct dependencies of 'sc' (Symbol or
# Choice). The direct dependencies are the OR of the dependencies from each
@@ -2520,6 +2585,7 @@ def _direct_dep_info(sc):
.format(TRI_TO_STR[expr_value(sc.direct_dep)],
_split_expr_info(sc.direct_dep, 2))
+
def _defaults_info(sc):
# Returns a string describing the defaults of 'sc' (Symbol or Choice)
@@ -2553,6 +2619,7 @@ def _defaults_info(sc):
return s + "\n"
+
def _split_expr_info(expr, indent):
# Returns a string with 'expr' split into its top-level && or || operands,
# with one operand per line, together with the operand's value. This is
@@ -2584,6 +2651,7 @@ def _split_expr_info(expr, indent):
return s
+
def _select_imply_info(sym):
# Returns a string with information about which symbols 'select' or 'imply'
# 'sym'. The selecting/implying symbols are grouped according to which
@@ -2621,6 +2689,7 @@ def _select_imply_info(sym):
return s
+
def _kconfig_def_info(item):
# Returns a string with the definition of 'item' in Kconfig syntax,
# together with the definition location(s) and their include and menu paths
@@ -2644,6 +2713,7 @@ def _kconfig_def_info(item):
return s
+
def _include_path_info(node):
if not node.include_path:
# In the top-level Kconfig file
@@ -2653,6 +2723,7 @@ def _include_path_info(node):
" -> ".join("{}:{}".format(filename, linenr)
for filename, linenr in node.include_path))
+
def _menu_path_info(node):
# Returns a string describing the menu path leading up to 'node'
@@ -2669,6 +2740,7 @@ def _menu_path_info(node):
return "(top menu)" + path
+
def _name_and_val_str(sc):
# Custom symbol/choice printer that shows symbol values after symbols
@@ -2686,10 +2758,12 @@ def _name_and_val_str(sc):
# For other items, use the standard format
return standard_sc_expr_str(sc)
+
def _expr_str(expr):
# Custom expression printer that shows symbol values
return expr_str(expr, _name_and_val_str)
+
def _styled_win(style):
# Returns a new curses window with style 'style' and space as the fill
# character. The initial dimensions are (1, 1), so the window needs to be
@@ -2699,11 +2773,13 @@ def _styled_win(style):
_set_style(win, style)
return win
+
def _set_style(win, style):
# Changes the style of an existing window
win.bkgdset(" ", _style[style])
+
def _max_scroll(lst, win):
# Assuming 'lst' is a list of items to be displayed in 'win',
# returns the maximum number of steps 'win' can be scrolled down.
@@ -2711,6 +2787,7 @@ def _max_scroll(lst, win):
return max(0, len(lst) - win.getmaxyx()[0])
+
def _edit_text(c, s, i, hscroll, width):
# Implements text editing commands for edit boxes. Takes a character (which
# could also be e.g. curses.KEY_LEFT) and the edit box state, and returns
@@ -2788,22 +2865,26 @@ def _edit_text(c, s, i, hscroll, width):
return s, i, hscroll
+
def _load_save_info():
# Returns an information string for load/save dialog boxes
return "(Relative to {})\n\nRefer to your home directory with ~" \
.format(os.path.join(os.getcwd(), ""))
+
def _msg(title, text):
# Pops up a message dialog that can be dismissed with Space/Enter/ESC
_key_dialog(title, text, " \n")
+
def _error(text):
# Pops up an error dialog that can be dismissed with Space/Enter/ESC
_msg("Error", text)
+
def _node_str(node):
# Returns the complete menu entry text for a menu node.
#
@@ -2874,6 +2955,7 @@ def _node_str(node):
return s
+
def _should_show_name(node):
# Returns True if 'node' is a symbol or choice whose name should shown (if
# any, as names are optional for choices)
@@ -2883,6 +2965,7 @@ def _should_show_name(node):
return not node.prompt or \
(_show_name and isinstance(node.item, (Symbol, Choice)))
+
def _value_str(node):
# Returns the value part ("[*]", "<M>", "(foo)" etc.) of a menu node
@@ -2917,12 +3000,14 @@ def _value_str(node):
return "{{{}}}".format(tri_val_str) # {M}/{*}
return "<{}>".format(tri_val_str)
+
def _is_y_mode_choice_sym(item):
# 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
return isinstance(item, Symbol) and item.choice and item.visibility == 2
+
def _check_validity(sym, s):
# Returns True if the string 's' is a well-formed value for 'sym'.
# Otherwise, displays an error and returns False.
@@ -2956,6 +3041,7 @@ def _check_validity(sym, s):
return True
+
def _range_info(sym):
# Returns a string with information about the valid range for the symbol
# 'sym', or None if 'sym' doesn't have a range
@@ -2967,6 +3053,7 @@ def _range_info(sym):
return None
+
def _is_num(name):
# Heuristic to see if a symbol name looks like a number, for nicer output
# when printing expressions. Things like 16 are actually symbol names, only
@@ -2985,6 +3072,7 @@ def _is_num(name):
return True
+
def _get_wch_compat(win):
# Decent resizing behavior on PDCurses requires calling resize_term(0, 0)
# after receiving KEY_RESIZE, while NCURSES (usually) handles terminal
@@ -3004,6 +3092,7 @@ def _get_wch_compat(win):
return c
+
def _warn(*args):
# Temporarily returns from curses to shell mode and prints a warning to
# stderr. The warning would get lost in curses mode.
@@ -3012,15 +3101,18 @@ def _warn(*args):
print(*args, file=sys.stderr)
curses.doupdate()
+
# Ignore exceptions from some functions that might fail, e.g. for small
# windows. They usually do reasonable things anyway.
+
def _safe_curs_set(visibility):
try:
curses.curs_set(visibility)
except curses.error:
pass
+
def _safe_addstr(win, *args):
# Clip the line to avoid wrapping to the next line, which looks glitchy.
# addchstr() would do it for us, but it's not available in the 'curses'
@@ -3051,30 +3143,35 @@ def _safe_addstr(win, *args):
except curses.error:
pass
+
def _safe_addch(win, *args):
try:
win.addch(*args)
except curses.error:
pass
+
def _safe_hline(win, *args):
try:
win.hline(*args)
except curses.error:
pass
+
def _safe_vline(win, *args):
try:
win.vline(*args)
except curses.error:
pass
+
def _safe_move(win, *args):
try:
win.move(*args)
except curses.error:
pass
+
def _convert_c_lc_ctype_to_utf8():
# See _CONVERT_C_LC_CTYPE_TO_UTF8
@@ -3102,6 +3199,7 @@ def _convert_c_lc_ctype_to_utf8():
"C locale to the {} locale.".format(loc))
break
+
# Are we running on Windows?
_IS_WINDOWS = (platform.system() == "Windows")