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

View File

@ -5,7 +5,6 @@
import json
import os
import re
import sys
from contextlib import contextmanager, suppress
from functools import partial
from typing import (
@ -21,12 +20,13 @@ from .conf.utils import (
)
from .config_data import all_options
from .constants import cache_dir, defconf, is_macos
from .fonts import FontFeature
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 .typing import TypedDict
from .utils import expandvars, log_error
from .utils import log_error
KeyMap = Dict[SingleKey, '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))
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:
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
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
def handle_font_features(key: str, val: str, ans: Dict[str, Any]) -> None:
if val != 'none':
parts = val.split()
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)
for key, features in font_features(val):
ans['font_features'][key] = features
@special_handler
@ -662,9 +619,8 @@ def handle_deprecated_macos_show_window_title_in_menubar_alias(key: str, val: st
@special_handler
def handle_env(key: str, val: str, ans: Dict[str, Any]) -> None:
key, val = val.partition('=')[::2]
key, val = key.strip(), val.strip()
ans['env'][key] = expandvars(val, ans['env'])
for key, val in env(val, ans['env']):
ans['env'][key] = val
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,
allow_remote_control, box_drawing_scale, clipboard_control,
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,
optional_edge_width, resize_draw_strategy, scrollback_lines,
scrollback_pager_history_size, tab_activity_symbol, tab_bar_edge,
tab_bar_min_tabs, tab_fade, tab_font_style, tab_separator,
scrollback_pager_history_size, symbol_map, tab_activity_symbol,
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,
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
# }}}
# Groups {{{
@ -263,7 +262,7 @@ o('adjust_column_width', 0, option_type=adjust_line_height)
o(
'+symbol_map',
'U+E0A0-U+E0A3,U+E0C0-U+E0C7 PowerlineSymbols',
add_to_default=False,
add_to_default=False, option_type=symbol_map,
long_text=_('''
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
@ -294,7 +293,7 @@ Note that this refers to programming ligatures, typically implemented using the
: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
some fonts might have features worthwhile in a terminal. For example, Fira
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.
'''))
o(
'+env', '',
add_to_default=False,
long_text=_('''
o('+env', '', add_to_default=False, option_type=env, long_text=_('''
Specify environment variables to set in all child processes. Note that
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
text = as_type_stub(
all_options,
special_types={
'symbol_map': 'typing.Dict[typing.Tuple[int, int], str]',
'font_features': 'typing.Dict[str, typing.Tuple[FontFeature, ...]]'
},
preamble_lines=(
'from kitty.types import SingleKey',
'from kitty.config import KeyAction, KeyMap, SequenceMap, MouseMap',

View File

@ -4,6 +4,7 @@
import os
import sys
from typing import (
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
)
from .constants import config_dir
from .fonts import FontFeature
from .key_names import (
character_key_name_aliases, functional_key_name_aliases,
get_key_name_lookup
@ -22,7 +24,7 @@ from .key_names import (
from .layout.interface import all_layouts
from .rgb import Color, color_as_int
from .types import FloatEdges, SingleKey
from .utils import log_error
from .utils import expandvars, log_error
MINIMUM_FONT_SIZE = 4
default_tab_separator = ''
@ -345,3 +347,56 @@ def macos_option_as_alt(x: str) -> int:
if to_bool(x):
return 0b11
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