fix: hitting 'b' or 'h' in main menu raises exception
Signed-off-by: Dominik Willner <th33xitus@gmail.com>
This commit is contained in:
@@ -21,8 +21,7 @@ class KlipperNoFirmwareErrorMenu(BaseMenu):
|
|||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
self.flash_options = FlashOptions()
|
self.flash_options = FlashOptions()
|
||||||
self.options = {"": self.go_back}
|
self.default_option = self.go_back
|
||||||
self.default_options = self.go_back
|
|
||||||
self.footer_type = FooterType.BLANK
|
self.footer_type = FooterType.BLANK
|
||||||
self.input_label_txt = "Press ENTER to go back to [Advanced Menu]"
|
self.input_label_txt = "Press ENTER to go back to [Advanced Menu]"
|
||||||
|
|
||||||
@@ -64,8 +63,7 @@ class KlipperNoBoardTypesErrorMenu(BaseMenu):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
self.options = {"": self.go_back}
|
self.default_option = self.go_back
|
||||||
self.default_options = self.go_back
|
|
||||||
self.footer_type = FooterType.BLANK
|
self.footer_type = FooterType.BLANK
|
||||||
self.input_label_txt = "Press ENTER to go back to [Main Menu]"
|
self.input_label_txt = "Press ENTER to go back to [Main Menu]"
|
||||||
|
|
||||||
|
|||||||
@@ -48,10 +48,10 @@ class KlipperFlashMethodMenu(BaseMenu):
|
|||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
self.previous_menu: BaseMenu = previous_menu
|
self.previous_menu: BaseMenu = previous_menu
|
||||||
|
self.help_menu = KlipperFlashMethodHelpMenu
|
||||||
self.options = {
|
self.options = {
|
||||||
"1": self.select_regular,
|
"1": self.select_regular,
|
||||||
"2": self.select_sdcard,
|
"2": self.select_sdcard,
|
||||||
"h": self.help_menu,
|
|
||||||
}
|
}
|
||||||
self.input_label_txt = "Select flash method"
|
self.input_label_txt = "Select flash method"
|
||||||
self.footer_type = FooterType.BACK_HELP
|
self.footer_type = FooterType.BACK_HELP
|
||||||
@@ -99,9 +99,6 @@ class KlipperFlashMethodMenu(BaseMenu):
|
|||||||
else:
|
else:
|
||||||
KlipperNoFirmwareErrorMenu().run()
|
KlipperNoFirmwareErrorMenu().run()
|
||||||
|
|
||||||
def help_menu(self, **kwargs):
|
|
||||||
KlipperFlashMethodHelpMenu(previous_menu=self).run()
|
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal
|
# noinspection PyUnusedLocal
|
||||||
# noinspection PyMethodMayBeStatic
|
# noinspection PyMethodMayBeStatic
|
||||||
@@ -110,10 +107,10 @@ class KlipperFlashCommandMenu(BaseMenu):
|
|||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
self.previous_menu: BaseMenu = previous_menu
|
self.previous_menu: BaseMenu = previous_menu
|
||||||
|
self.help_menu = KlipperFlashCommandHelpMenu
|
||||||
self.options = {
|
self.options = {
|
||||||
"1": self.select_flash,
|
"1": self.select_flash,
|
||||||
"2": self.select_serialflash,
|
"2": self.select_serialflash,
|
||||||
"h": self.help_menu,
|
|
||||||
}
|
}
|
||||||
self.default_option = self.select_flash
|
self.default_option = self.select_flash
|
||||||
self.input_label_txt = "Select flash command"
|
self.input_label_txt = "Select flash command"
|
||||||
@@ -145,9 +142,6 @@ class KlipperFlashCommandMenu(BaseMenu):
|
|||||||
def goto_next_menu(self, **kwargs):
|
def goto_next_menu(self, **kwargs):
|
||||||
KlipperSelectMcuConnectionMenu(previous_menu=self).run()
|
KlipperSelectMcuConnectionMenu(previous_menu=self).run()
|
||||||
|
|
||||||
def help_menu(self, **kwargs):
|
|
||||||
KlipperFlashCommandHelpMenu(previous_menu=self).run()
|
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal
|
# noinspection PyUnusedLocal
|
||||||
# noinspection PyMethodMayBeStatic
|
# noinspection PyMethodMayBeStatic
|
||||||
@@ -157,11 +151,11 @@ class KlipperSelectMcuConnectionMenu(BaseMenu):
|
|||||||
|
|
||||||
self.__standalone = standalone
|
self.__standalone = standalone
|
||||||
self.previous_menu: BaseMenu = previous_menu
|
self.previous_menu: BaseMenu = previous_menu
|
||||||
|
self.help_menu = KlipperMcuConnectionHelpMenu
|
||||||
self.options = {
|
self.options = {
|
||||||
"1": self.select_usb,
|
"1": self.select_usb,
|
||||||
"2": self.select_dfu,
|
"2": self.select_dfu,
|
||||||
"3": self.select_usb_dfu,
|
"3": self.select_usb_dfu,
|
||||||
"h": self.help_menu,
|
|
||||||
}
|
}
|
||||||
self.input_label_txt = "Select connection type"
|
self.input_label_txt = "Select connection type"
|
||||||
self.footer_type = FooterType.BACK_HELP
|
self.footer_type = FooterType.BACK_HELP
|
||||||
@@ -229,9 +223,6 @@ class KlipperSelectMcuConnectionMenu(BaseMenu):
|
|||||||
def goto_next_menu(self, **kwargs):
|
def goto_next_menu(self, **kwargs):
|
||||||
KlipperSelectMcuIdMenu(previous_menu=self).run()
|
KlipperSelectMcuIdMenu(previous_menu=self).run()
|
||||||
|
|
||||||
def help_menu(self, **kwargs):
|
|
||||||
KlipperMcuConnectionHelpMenu(previous_menu=self).run()
|
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal
|
# noinspection PyUnusedLocal
|
||||||
# noinspection PyMethodMayBeStatic
|
# noinspection PyMethodMayBeStatic
|
||||||
|
|||||||
@@ -17,14 +17,6 @@ class FooterType(Enum):
|
|||||||
BLANK = "BLANK"
|
BLANK = "BLANK"
|
||||||
|
|
||||||
|
|
||||||
NAVI_OPTIONS = {
|
|
||||||
FooterType.QUIT: ["q"],
|
|
||||||
FooterType.BACK: ["b"],
|
|
||||||
FooterType.BACK_HELP: ["b", "h"],
|
|
||||||
FooterType.BLANK: [],
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class ExitAppException(Exception):
|
class ExitAppException(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|||||||
@@ -12,10 +12,10 @@ from __future__ import annotations
|
|||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import textwrap
|
import textwrap
|
||||||
from abc import abstractmethod, ABC
|
from abc import abstractmethod
|
||||||
from typing import Dict, Union, Callable, Type, Tuple
|
from typing import Dict, Union, Callable, Type, Tuple
|
||||||
|
|
||||||
from core.menus import FooterType, NAVI_OPTIONS, ExitAppException, GoBackException
|
from core.menus import FooterType, ExitAppException, GoBackException
|
||||||
from utils.constants import (
|
from utils.constants import (
|
||||||
COLOR_GREEN,
|
COLOR_GREEN,
|
||||||
COLOR_YELLOW,
|
COLOR_YELLOW,
|
||||||
@@ -96,22 +96,51 @@ def print_blank_footer():
|
|||||||
print("\=======================================================/")
|
print("\=======================================================/")
|
||||||
|
|
||||||
|
|
||||||
Options = Dict[str, Callable]
|
class PostInitCaller(type):
|
||||||
|
def __call__(cls, *args, **kwargs):
|
||||||
|
obj = type.__call__(cls, *args, **kwargs)
|
||||||
|
obj.__post_init__()
|
||||||
|
return obj
|
||||||
|
|
||||||
|
|
||||||
class BaseMenu(ABC):
|
# noinspection PyUnusedLocal
|
||||||
options: Options = {}
|
# noinspection PyMethodMayBeStatic
|
||||||
|
class BaseMenu(metaclass=PostInitCaller):
|
||||||
|
options: Dict[str, Callable] = {}
|
||||||
options_offset: int = 0
|
options_offset: int = 0
|
||||||
default_option: Union[Callable, None] = None
|
default_option: Union[Callable, None] = None
|
||||||
input_label_txt: str = "Perform action"
|
input_label_txt: str = "Perform action"
|
||||||
header: bool = False
|
header: bool = False
|
||||||
previous_menu: Union[Type[BaseMenu], BaseMenu] = None
|
previous_menu: Union[Type[BaseMenu], BaseMenu] = None
|
||||||
|
help_menu: Type[BaseMenu] = None
|
||||||
footer_type: FooterType = FooterType.BACK
|
footer_type: FooterType = FooterType.BACK
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, **kwargs):
|
||||||
if type(self) is BaseMenu:
|
if type(self) is BaseMenu:
|
||||||
raise NotImplementedError("BaseMenu cannot be instantiated directly.")
|
raise NotImplementedError("BaseMenu cannot be instantiated directly.")
|
||||||
|
|
||||||
|
def __post_init__(self):
|
||||||
|
# conditionally add options based on footer type
|
||||||
|
if self.footer_type is FooterType.QUIT:
|
||||||
|
self.options["q"] = self.__exit
|
||||||
|
if self.footer_type is FooterType.BACK:
|
||||||
|
self.options["b"] = self.__go_back
|
||||||
|
if self.footer_type is FooterType.BACK_HELP:
|
||||||
|
self.options["b"] = self.__go_back
|
||||||
|
self.options["h"] = self.__go_to_help
|
||||||
|
# if defined, add the default option to the options dict
|
||||||
|
if self.default_option is not None:
|
||||||
|
self.options[""] = self.default_option
|
||||||
|
|
||||||
|
def __go_back(self, **kwargs):
|
||||||
|
raise GoBackException()
|
||||||
|
|
||||||
|
def __go_to_help(self, **kwargs):
|
||||||
|
self.help_menu(previous_menu=self).run()
|
||||||
|
|
||||||
|
def __exit(self, **kwargs):
|
||||||
|
raise ExitAppException()
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def print_menu(self) -> None:
|
def print_menu(self) -> None:
|
||||||
raise NotImplementedError("Subclasses must implement the print_menu method")
|
raise NotImplementedError("Subclasses must implement the print_menu method")
|
||||||
@@ -144,20 +173,8 @@ class BaseMenu(ABC):
|
|||||||
usr_input = usr_input.lower()
|
usr_input = usr_input.lower()
|
||||||
option = self.options.get(usr_input, None)
|
option = self.options.get(usr_input, None)
|
||||||
|
|
||||||
# check if usr_input contains a character used for basic navigation, e.g. b, h or q
|
# if option/usr_input is None/empty string, we execute the menus default option if specified
|
||||||
# and if the current menu has the appropriate footer to allow for that action
|
if (option is None or usr_input == "") and self.default_option is not None:
|
||||||
is_valid_navigation = self.footer_type in NAVI_OPTIONS
|
|
||||||
user_navigated = usr_input in NAVI_OPTIONS[self.footer_type]
|
|
||||||
if is_valid_navigation and user_navigated:
|
|
||||||
if usr_input == "q":
|
|
||||||
raise ExitAppException()
|
|
||||||
elif usr_input == "b":
|
|
||||||
raise GoBackException()
|
|
||||||
elif usr_input == "h":
|
|
||||||
return option, usr_input
|
|
||||||
|
|
||||||
# if usr_input is None or an empty string, we execute the menues default option if specified
|
|
||||||
if usr_input == "" and self.default_option is not None:
|
|
||||||
return self.default_option, usr_input
|
return self.default_option, usr_input
|
||||||
|
|
||||||
# user selected a regular option
|
# user selected a regular option
|
||||||
@@ -168,8 +185,10 @@ class BaseMenu(ABC):
|
|||||||
while True:
|
while True:
|
||||||
print(f"{COLOR_CYAN}###### {self.input_label_txt}: {RESET_FORMAT}", end="")
|
print(f"{COLOR_CYAN}###### {self.input_label_txt}: {RESET_FORMAT}", end="")
|
||||||
usr_input = input().lower()
|
usr_input = input().lower()
|
||||||
|
validated_input = self.validate_user_input(usr_input)
|
||||||
|
method_to_call = validated_input[0]
|
||||||
|
|
||||||
if (validated_input := self.validate_user_input(usr_input)) is not None:
|
if method_to_call is not None:
|
||||||
return validated_input
|
return validated_input
|
||||||
else:
|
else:
|
||||||
Logger.print_error("Invalid input!", False)
|
Logger.print_error("Invalid input!", False)
|
||||||
|
|||||||
Reference in New Issue
Block a user