From c92aca5d1901d176ea88c3c9e0c16f94f27a7f6e Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 24 Apr 2020 19:45:51 +0530 Subject: [PATCH] Use a Literal as the type for choice based options --- kitty/conf/definition.py | 4 +++- kitty/conf/utils.py | 18 +++++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/kitty/conf/definition.py b/kitty/conf/definition.py index 3c1e77757..a858e34ff 100644 --- a/kitty/conf/definition.py +++ b/kitty/conf/definition.py @@ -9,7 +9,7 @@ from typing import ( Set, Tuple, Union, get_type_hints ) -from .utils import to_bool +from .utils import Choice, to_bool def to_string(x: str) -> str: @@ -56,6 +56,8 @@ class Option: if type(self.option_type) is type: return type_name(self.option_type) + if isinstance(self.option_type, Choice): + return 'typing.Literal[{}]'.format(','.join(f'{x!r}' for x in self.option_type.all_choices)) th = get_type_hints(self.option_type) try: rettype = th['return'] diff --git a/kitty/conf/utils.py b/kitty/conf/utils.py index e007c175d..9bc0134e5 100644 --- a/kitty/conf/utils.py +++ b/kitty/conf/utils.py @@ -68,17 +68,21 @@ def python_string(text: str) -> str: return ans -def choices(*choices: str) -> Callable[[str], str]: - defval = choices[0] - uc = frozenset(choices) +class Choice: - def choice(x: str) -> str: + def __init__(self, choices: Sequence[str]): + self.defval = choices[0] + self.all_choices = frozenset(choices) + + def __call__(self, x: str) -> str: x = x.lower() - if x not in uc: - x = defval + if x not in self.all_choices: + x = self.defval return x - return choice + +def choices(*choices: str) -> Choice: + return Choice(choices) def parse_line(