diff options
| author | Ulf Magnusson <ulfalizer@gmail.com> | 2019-03-14 15:26:24 +0100 |
|---|---|---|
| committer | Ulf Magnusson <ulfalizer@gmail.com> | 2019-03-14 16:43:36 +0100 |
| commit | bf407654df1081e7fbc3f876288cc275092cf549 (patch) | |
| tree | f14e7308605104a0efe386d89251a37ae3fbe7be | |
| parent | d6e6f7aee1fa4d34ffe814ac2c0f7ea4a64de13a (diff) | |
menuconfig: Put two blank lines between top-level functions
Be consistent with the other utilities.
| -rwxr-xr-x | menuconfig.py | 104 |
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") |
