diff options
| author | Ulf Magnusson <ulfalizer@gmail.com> | 2019-04-23 21:45:57 +0200 |
|---|---|---|
| committer | Ulf Magnusson <ulfalizer@gmail.com> | 2019-04-26 17:35:34 +0200 |
| commit | 61591f0cb40a2e0c82f055fe0261d3c33be7b25a (patch) | |
| tree | 760b3eaed4f33dcf148485f03613ca19345d54ad | |
| parent | 6fcd01985dbdc29ee231b8bc01488fd286debabc (diff) | |
menuconfig: Improve space/enter behavior slightly
Space toggles value is possible, and enters menus otherwise. Enter works
the other way around.
Make this explicit in the code, which also fixes some corner cases, like
space doing nothing on a y-selected menuconfig symbol.
| -rwxr-xr-x | menuconfig.py | 117 |
1 files changed, 67 insertions, 50 deletions
diff --git a/menuconfig.py b/menuconfig.py index 7b554a7..28cb26c 100755 --- a/menuconfig.py +++ b/menuconfig.py @@ -20,14 +20,14 @@ inspired by Vi: G/End : Jump to end of list g/Home : Jump to beginning of list +[Space] toggles values if possible, and enters menus otherwise. [Enter] works +the other way around. + The mconf feature where pressing a key jumps to a menu entry with that character in it in the current menu isn't supported. A jump-to feature for jumping directly to any symbol (including invisible symbols), choice, menu or comment (as in a Kconfig 'comment "Foo"') is available instead. -Space and Enter are "smart" and try to do what you'd expect for the given menu -entry. - A few different modes are available: F: Toggle show-help mode, which shows the help text of the currently selected @@ -828,26 +828,17 @@ def _menuconfig(stdscr): elif c in (curses.KEY_HOME, "g"): _select_first_menu_entry() - elif c in (curses.KEY_RIGHT, " ", "\n", "l", "L"): - # Do appropriate node action. Only Space is treated specially, - # preferring to toggle nodes rather than enter menus. - + elif c == " ": + # Toggle the node if possible sel_node = _shown[_sel_node_i] - - if sel_node.is_menuconfig and not \ - (c == " " and _prefer_toggle(sel_node.item)): - + if not _change_node(sel_node): _enter_menu(sel_node) - else: + elif c in (curses.KEY_RIGHT, "\n", "l", "L"): + # Enter the node if possible + sel_node = _shown[_sel_node_i] + if not _enter_menu(sel_node): _change_node(sel_node) - if _is_y_mode_choice_sym(sel_node.item) and not sel_node.list: - # Immediately jump to the parent menu after making a choice - # selection, like 'make menuconfig' does, except if the - # menu node has children (which can happen if a symbol - # 'depends on' a choice symbol that immediately precedes - # it). - _leave_menu() elif c in ("n", "N"): _set_sel_node_tri_val(0) @@ -1059,39 +1050,40 @@ def _width(win): return win.getmaxyx()[1] -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 - # when they're defined with 'menuconfig') and choices that can be in more - # than one mode (e.g. optional choices). In other cases, we enter the menu. - - 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. + # Makes 'menu' the currently displayed menu. In addition to actual 'menu's, + # "Menu" here includes choices and symbols defined with the 'menuconfig' + # keyword. + # + # Returns False if 'menu' can't be entered. global _cur_menu global _shown global _sel_node_i global _menu_scroll + if not menu.is_menuconfig: + # Not a menu + return False + shown_sub = _shown_nodes(menu) # Never enter empty menus. We depend on having a current node. - if shown_sub: - # Remember where the current node appears on the screen, so we can try - # to get it to appear in the same place when we leave the menu - _parent_screen_rows.append(_sel_node_i - _menu_scroll) + if not shown_sub: + return False + + # Remember where the current node appears on the screen, so we can try + # to get it to appear in the same place when we leave the menu + _parent_screen_rows.append(_sel_node_i - _menu_scroll) - # Jump into menu - _cur_menu = menu - _shown = shown_sub - _sel_node_i = _menu_scroll = 0 + # Jump into menu + _cur_menu = menu + _shown = shown_sub + _sel_node_i = _menu_scroll = 0 + + if isinstance(menu.item, Choice): + _select_selected_choice_sym() - if isinstance(menu.item, Choice): - _select_selected_choice_sym() + return True def _select_selected_choice_sym(): @@ -1553,15 +1545,11 @@ 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 # dialog. + # + # Returns False if the value of 'node' can't be changed. - if not isinstance(node.item, (Symbol, Choice)): - return - - # This will hit for invisible symbols, which appear in show-all mode and - # when an invisible symbol has visible children (which can happen e.g. for - # symbols with optional prompts) - if not (node.prompt and expr_value(node.prompt[1])): - return + if not _changeable(node): + return False # sc = symbol/choice sc = node.item @@ -1594,13 +1582,42 @@ def _change_node(node): # case: .assignable can be (2,) while .tri_value is 0. _set_val(sc, sc.assignable[0]) - elif sc.assignable: + else: # Set the symbol to the value after the current value in # sc.assignable, with wrapping val_index = sc.assignable.index(sc.tri_value) _set_val(sc, sc.assignable[(val_index + 1) % len(sc.assignable)]) + if _is_y_mode_choice_sym(sc) and not node.list: + # Immediately jump to the parent menu after making a choice selection, + # like 'make menuconfig' does, except if the menu node has children + # (which can happen if a symbol 'depends on' a choice symbol that + # immediately precedes it). + _leave_menu() + + + return True + + +def _changeable(node): + # Returns True if the value if 'node' can be changed + + sc = node.item + + if not isinstance(sc, (Symbol, Choice)): + return False + + # This will hit for invisible symbols, which appear in show-all mode and + # when an invisible symbol has visible children (which can happen e.g. for + # symbols with optional prompts) + if not (node.prompt and expr_value(node.prompt[1])): + return False + + return sc.orig_type in (STRING, INT, HEX) or len(sc.assignable) > 1 \ + or _is_y_mode_choice_sym(sc) + + 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 |
