Source code for ReFreSH.MobileSuit.UI.CommandLineUI

from typing import Callable, Dict, List, Optional, TypeVar, Iterable

from ..IIOHub import IIOHub
from ..OutputType import OutputType

T = TypeVar('T')


[docs] class ConsoleInput: """Useful input components for console UI.""" def __init__(self, io: IIOHub): self.hub = io
[docs] @staticmethod def ToStringOrEmptySerializer(origin: Optional[T]) -> str: """Serialize target with ToString()??"" Args: origin: Origin value Returns: Serialized target used ToString()??"" """ return str(origin) if origin is not None else ""
[docs] def SelectItemFrom(self, prompt: str, selectFrom: List[T], serializer: Optional[Callable[[T], str]] = None, labeler: Optional[Callable[[int, T], str]] = None) -> T: """A CUI that allows the user select ONE objective from Alternative objectives. Args: self prompt: Prompt to guide user selection selectFrom: Alternative objectives serializer: Method of Serializing Object as Text labeler: Label of objectives to guide user selection Returns: Selected item from selectFrom """ serializer = serializer or ConsoleInput.ToStringOrEmptySerializer labeler = labeler or (lambda _i, _: str(_i)) labels = {} while True: self.hub.WriteLine(prompt, OutputType.Title) for i, t in enumerate(selectFrom): label = labeler(i, t) labels[label] = i self.hub.WriteLine([ (f"{label}\t", None, self.hub.ColorSetting.TitleColor), (serializer(t), self.hub.ColorSetting.DefaultColor, None) ]) ans = self.hub.ReadLine("", defaultValue="0") if ans is not None and ans in labels: return selectFrom[labels[ans]]
[docs] class SpaceHyphenParserException(Exception): pass
[docs] @classmethod def SpaceHyphenParser(cls, userInput: Optional[str], labelMapping: Dict[str, int]) -> Optional[List[int]]: """Split user input using space and hyphen. E.g., "1-3 4" will be parsed to {1,2,3,4}. Args: userInput: String from user labelMapping: Dictionary maps label to index. Returns: Parsed indices or None if failed to parse. """ try: return list(ConsoleInput.SpaceHyphenParserInternal(userInput, labelMapping)) except (cls.SpaceHyphenParserException, KeyError): return None
[docs] @classmethod def SpaceHyphenParserInternal(cls, userInput: Optional[str], labelMapping: Dict[str, int]) -> Iterable[int]: if not userInput: return inputGroups = userInput.split(' ') for inputGroup in inputGroups: labels = [labelMapping[l] for l in inputGroup.split("-")] if len(labels) == 1: yield labels[0] elif len(labels) == 2: lt, gt = labels if gt < lt: raise cls.SpaceHyphenParserException() for it in range(lt, gt + 1): yield it else: raise cls.SpaceHyphenParserException()
[docs] @staticmethod def SelectItemsFrom(self, prompt: str, selectFrom: List[T], serializer: Optional[Callable[[T], str]] = None, labeler: Optional[Callable[[int, T], str]] = None, parser: Optional[Callable[[Optional[str], Dict[str, int]], Optional[List[int]]]] = None) -> \ Iterable[T]: """A CUI that allows the user select ONE objective from Alternative objectives. Args: self prompt: Prompt to guide user selection selectFrom: Alternative objectives serializer: Method of Serializing Object as Text labeler: Label of objectives to guide user selection parser: Function to parse user input into several int index Returns: Selected items from selectFrom """ serializer = serializer or ConsoleInput.ToStringOrEmptySerializer parser = parser or ConsoleInput.SpaceHyphenParser labeler = labeler or (lambda _i, _: str(_i)) labels = {} while True: self.hub.WriteLine(prompt, OutputType.Title) for i, t in enumerate(selectFrom): label = labeler(i, t) labels[label] = i self.hub.WriteLine([ (f"{label}\t", None, self.hub.ColorSetting.TitleColor), (serializer(t), self.hub.ColorSetting.DefaultColor, None) ]) ans = parser(self.hub.ReadLine("", defaultValue="0"), labels) if ans is not None: return (selectFrom[i] for i in ans)
[docs] @staticmethod def SelectYesNo(self, prompt: str, default: Optional[bool] = None) -> bool: """A CUI that allows the user answer yes/no by inputting "y" or "n". Args: self prompt: Prompt to guide user input default: NULL if only y/n is allowed; Otherwise, if user input is null or empty, such default value will be returned. Returns: True if user says "yes". """ while True: ans = self.hub.ReadLine(prompt) if ans is not None: ans = ans.lower() if ans == "y": return True elif ans == "n": return False elif not ans and default is not None: return default