Remove the special_types kludge for is_multiple options

This commit is contained in:
Kovid Goyal 2021-05-25 11:25:39 +05:30
parent ba821cb02f
commit f178dff4e0
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
5 changed files with 77 additions and 75 deletions

View File

@ -40,8 +40,6 @@ class Option:
ans = x.__name__ ans = x.__name__
if x.__module__ and x.__module__ != 'builtins': if x.__module__ and x.__module__ != 'builtins':
imports.add((x.__module__, x.__name__)) imports.add((x.__module__, x.__name__))
if self.is_multiple:
ans = 'typing.Dict[str, str]'
return ans return ans
def option_type_as_str(x: Any) -> str: def option_type_as_str(x: Any) -> str:
@ -49,6 +47,9 @@ class Option:
return type_name(x) return type_name(x)
ans = repr(x) ans = repr(x)
ans = ans.replace('NoneType', 'None') ans = ans.replace('NoneType', 'None')
if self.is_multiple:
ans = ans[ans.index('[') + 1:-1]
ans = ans.replace('Tuple', 'Dict', 1)
return ans return ans
if type(self.option_type) is type: if type(self.option_type) is type:
@ -354,18 +355,16 @@ def config_lines(
def as_type_stub( def as_type_stub(
all_options: Dict[str, OptionOrAction], all_options: Dict[str, OptionOrAction],
special_types: Optional[Dict[str, str]] = None,
preamble_lines: Union[Tuple[str, ...], List[str], Iterable[str]] = (), preamble_lines: Union[Tuple[str, ...], List[str], Iterable[str]] = (),
extra_fields: Union[Tuple[Tuple[str, str], ...], List[Tuple[str, str]], Iterable[Tuple[str, str]]] = (), extra_fields: Union[Tuple[Tuple[str, str], ...], List[Tuple[str, str]], Iterable[Tuple[str, str]]] = (),
class_name: str = 'Options' class_name: str = 'Options'
) -> str: ) -> str:
ans = ['import typing\n'] + list(preamble_lines) + ['', 'class {}:'.format(class_name)] ans = ['import typing\n'] + list(preamble_lines) + ['', 'class {}:'.format(class_name)]
imports: Set[Tuple[str, str]] = set() imports: Set[Tuple[str, str]] = set()
overrides = special_types or {}
for name, val in all_options.items(): for name, val in all_options.items():
if isinstance(val, Option): if isinstance(val, Option):
field_name = name.partition(' ')[0] field_name = name.partition(' ')[0]
ans.append(' {}: {}'.format(field_name, overrides.get(field_name, val.type_definition(imports)))) ans.append(' {}: {}'.format(field_name, val.type_definition(imports)))
for mod, name in imports: for mod, name in imports:
ans.insert(0, 'from {} import {}'.format(mod, name)) ans.insert(0, 'from {} import {}'.format(mod, name))
ans.insert(0, 'import {}'.format(mod)) ans.insert(0, 'import {}'.format(mod))

View File

@ -5,7 +5,6 @@
import json import json
import os import os
import re import re
import sys
from contextlib import contextmanager, suppress from contextlib import contextmanager, suppress
from functools import partial from functools import partial
from typing import ( from typing import (
@ -21,12 +20,13 @@ from .conf.utils import (
) )
from .config_data import all_options from .config_data import all_options
from .constants import cache_dir, defconf, is_macos from .constants import cache_dir, defconf, is_macos
from .fonts import FontFeature
from .options_stub import Options as OptionsStub from .options_stub import Options as OptionsStub
from .options_types import InvalidMods, parse_mods, parse_shortcut from .options_types import (
InvalidMods, env, font_features, parse_mods, parse_shortcut, symbol_map
)
from .types import MouseEvent, SingleKey from .types import MouseEvent, SingleKey
from .typing import TypedDict from .typing import TypedDict
from .utils import expandvars, log_error from .utils import log_error
KeyMap = Dict[SingleKey, 'KeyAction'] KeyMap = Dict[SingleKey, 'KeyAction']
MouseMap = Dict[MouseEvent, 'KeyAction'] MouseMap = Dict[MouseEvent, 'KeyAction']
@ -511,37 +511,6 @@ def parse_mouse_action(val: str, mouse_mappings: List[MouseMapping]) -> None:
mouse_mappings.append(MouseMapping(button, mods, count, mode == 'grabbed', paction)) mouse_mappings.append(MouseMapping(button, mods, count, mode == 'grabbed', paction))
def parse_symbol_map(val: str) -> Dict[Tuple[int, int], str]:
parts = val.split()
symbol_map: Dict[Tuple[int, int], str] = {}
def abort() -> Dict[Tuple[int, int], str]:
log_error('Symbol map: {} is invalid, ignoring'.format(
val))
return {}
if len(parts) < 2:
return abort()
family = ' '.join(parts[1:])
def to_chr(x: str) -> int:
if not x.startswith('U+'):
raise ValueError()
return int(x[2:], 16)
for x in parts[0].split(','):
a_, b_ = x.partition('-')[::2]
b_ = b_ or a_
try:
a, b = map(to_chr, (a_, b_))
except Exception:
return abort()
if b < a or max(a, b) > sys.maxunicode or min(a, b) < 1:
return abort()
symbol_map[(a, b)] = family
return symbol_map
def parse_send_text_bytes(text: str) -> bytes: def parse_send_text_bytes(text: str) -> bytes:
return python_string(text).encode('utf-8') return python_string(text).encode('utf-8')
@ -590,26 +559,14 @@ def handle_mouse_map(key: str, val: str, ans: Dict[str, Any]) -> None:
@special_handler @special_handler
def handle_symbol_map(key: str, val: str, ans: Dict[str, Any]) -> None: def handle_symbol_map(key: str, val: str, ans: Dict[str, Any]) -> None:
ans['symbol_map'].update(parse_symbol_map(val)) for k, v in symbol_map(val):
ans['symbol_map'][k] = v
@special_handler @special_handler
def handle_font_features(key: str, val: str, ans: Dict[str, Any]) -> None: def handle_font_features(key: str, val: str, ans: Dict[str, Any]) -> None:
if val != 'none': for key, features in font_features(val):
parts = val.split() ans['font_features'][key] = features
if len(parts) < 2:
log_error("Ignoring invalid font_features {}".format(val))
else:
features = []
for feat in parts[1:]:
try:
parsed = defines.parse_font_feature(feat)
except ValueError:
log_error('Ignoring invalid font feature: {}'.format(feat))
else:
features.append(FontFeature(feat, parsed))
if features:
ans['font_features'][parts[0]] = tuple(features)
@special_handler @special_handler
@ -662,9 +619,8 @@ def handle_deprecated_macos_show_window_title_in_menubar_alias(key: str, val: st
@special_handler @special_handler
def handle_env(key: str, val: str, ans: Dict[str, Any]) -> None: def handle_env(key: str, val: str, ans: Dict[str, Any]) -> None:
key, val = val.partition('=')[::2] for key, val in env(val, ans['env']):
key, val = key.strip(), val.strip() ans['env'][key] = val
ans['env'][key] = expandvars(val, ans['env'])
def special_handling(key: str, val: str, ans: Dict[str, Any]) -> bool: def special_handling(key: str, val: str, ans: Dict[str, Any]) -> bool:

View File

@ -17,17 +17,16 @@ from .options_types import (
active_tab_title_template, adjust_line_height, allow_hyperlinks, active_tab_title_template, adjust_line_height, allow_hyperlinks,
allow_remote_control, box_drawing_scale, clipboard_control, allow_remote_control, box_drawing_scale, clipboard_control,
config_or_absolute_path, copy_on_select, cursor_text_color, config_or_absolute_path, copy_on_select, cursor_text_color,
default_tab_separator, disable_ligatures, edge_width, default_tab_separator, disable_ligatures, edge_width, env, font_features,
hide_window_decorations, macos_option_as_alt, macos_titlebar_color, hide_window_decorations, macos_option_as_alt, macos_titlebar_color,
optional_edge_width, resize_draw_strategy, scrollback_lines, optional_edge_width, resize_draw_strategy, scrollback_lines,
scrollback_pager_history_size, tab_activity_symbol, tab_bar_edge, scrollback_pager_history_size, symbol_map, tab_activity_symbol,
tab_bar_min_tabs, tab_fade, tab_font_style, tab_separator, tab_bar_edge, tab_bar_min_tabs, tab_fade, tab_font_style, tab_separator,
tab_title_template, to_cursor_shape, to_font_size, to_layout_names, tab_title_template, to_cursor_shape, to_font_size, to_layout_names,
url_prefixes, url_style, window_border_width, window_size, to_modifiers to_modifiers, url_prefixes, url_style, window_border_width, window_size
) )
from .rgb import color_as_sharp, color_from_int from .rgb import color_as_sharp, color_from_int
# }}} # }}}
# Groups {{{ # Groups {{{
@ -263,7 +262,7 @@ o('adjust_column_width', 0, option_type=adjust_line_height)
o( o(
'+symbol_map', '+symbol_map',
'U+E0A0-U+E0A3,U+E0C0-U+E0C7 PowerlineSymbols', 'U+E0A0-U+E0A3,U+E0C0-U+E0C7 PowerlineSymbols',
add_to_default=False, add_to_default=False, option_type=symbol_map,
long_text=_(''' long_text=_('''
Map the specified unicode codepoints to a particular font. Useful if you need Map the specified unicode codepoints to a particular font. Useful if you need
special rendering for some symbols, such as for Powerline. Avoids the need for special rendering for some symbols, such as for Powerline. Avoids the need for
@ -294,7 +293,7 @@ Note that this refers to programming ligatures, typically implemented using the
:opt:`font_features` setting. :opt:`font_features` setting.
''')) '''))
o('+font_features', 'none', add_to_default=False, long_text=_(''' o('+font_features', 'none', add_to_default=False, option_type=font_features, long_text=_('''
Choose exactly which OpenType features to enable or disable. This is useful as Choose exactly which OpenType features to enable or disable. This is useful as
some fonts might have features worthwhile in a terminal. For example, Fira some fonts might have features worthwhile in a terminal. For example, Fira
Code Retina includes a discretionary feature, :code:`zero`, which in that font Code Retina includes a discretionary feature, :code:`zero`, which in that font
@ -920,10 +919,7 @@ you also set :opt:`allow_remote_control` to enable remote control. See the
help for :option:`kitty --listen-on` for more details. help for :option:`kitty --listen-on` for more details.
''')) '''))
o( o('+env', '', add_to_default=False, option_type=env, long_text=_('''
'+env', '',
add_to_default=False,
long_text=_('''
Specify environment variables to set in all child processes. Note that Specify environment variables to set in all child processes. Note that
environment variables are expanded recursively, so if you use:: environment variables are expanded recursively, so if you use::

View File

@ -15,10 +15,6 @@ def generate_stub():
from .conf.definition import as_type_stub, save_type_stub from .conf.definition import as_type_stub, save_type_stub
text = as_type_stub( text = as_type_stub(
all_options, all_options,
special_types={
'symbol_map': 'typing.Dict[typing.Tuple[int, int], str]',
'font_features': 'typing.Dict[str, typing.Tuple[FontFeature, ...]]'
},
preamble_lines=( preamble_lines=(
'from kitty.types import SingleKey', 'from kitty.types import SingleKey',
'from kitty.config import KeyAction, KeyMap, SequenceMap, MouseMap', 'from kitty.config import KeyAction, KeyMap, SequenceMap, MouseMap',

View File

@ -4,6 +4,7 @@
import os import os
import sys
from typing import ( from typing import (
Callable, Dict, FrozenSet, Iterable, List, Optional, Tuple, Union Callable, Dict, FrozenSet, Iterable, List, Optional, Tuple, Union
) )
@ -15,6 +16,7 @@ from .conf.utils import (
positive_float, positive_int, to_bool, to_color, uniq, unit_float positive_float, positive_int, to_bool, to_color, uniq, unit_float
) )
from .constants import config_dir from .constants import config_dir
from .fonts import FontFeature
from .key_names import ( from .key_names import (
character_key_name_aliases, functional_key_name_aliases, character_key_name_aliases, functional_key_name_aliases,
get_key_name_lookup get_key_name_lookup
@ -22,7 +24,7 @@ from .key_names import (
from .layout.interface import all_layouts from .layout.interface import all_layouts
from .rgb import Color, color_as_int from .rgb import Color, color_as_int
from .types import FloatEdges, SingleKey from .types import FloatEdges, SingleKey
from .utils import log_error from .utils import expandvars, log_error
MINIMUM_FONT_SIZE = 4 MINIMUM_FONT_SIZE = 4
default_tab_separator = '' default_tab_separator = ''
@ -345,3 +347,56 @@ def macos_option_as_alt(x: str) -> int:
if to_bool(x): if to_bool(x):
return 0b11 return 0b11
return 0 return 0
def font_features(val: str) -> Iterable[Tuple[str, Tuple[FontFeature, ...]]]:
if val == 'none':
return
parts = val.split()
if len(parts) < 2:
log_error("Ignoring invalid font_features {}".format(val))
return
if parts[0]:
features = []
for feat in parts[1:]:
try:
parsed = defines.parse_font_feature(feat)
except ValueError:
log_error('Ignoring invalid font feature: {}'.format(feat))
else:
features.append(FontFeature(feat, parsed))
yield parts[0], tuple(features)
def env(val: str, current_val: Dict[str, str]) -> Iterable[Tuple[str, str]]:
key, val = val.partition('=')[::2]
key, val = key.strip(), val.strip()
if key:
yield key, expandvars(val, current_val)
def symbol_map(val: str) -> Iterable[Tuple[Tuple[int, int], str]]:
parts = val.split()
def abort() -> Dict[Tuple[int, int], str]:
log_error(f'Symbol map: {val} is invalid, ignoring')
if len(parts) < 2:
return abort()
family = ' '.join(parts[1:])
def to_chr(x: str) -> int:
if not x.startswith('U+'):
raise ValueError()
return int(x[2:], 16)
for x in parts[0].split(','):
a_, b_ = x.partition('-')[::2]
b_ = b_ or a_
try:
a, b = map(to_chr, (a_, b_))
except Exception:
return abort()
if b < a or max(a, b) > sys.maxunicode or min(a, b) < 1:
return abort()
yield (a, b), family