More typing work
This commit is contained in:
parent
5bdb405635
commit
92827ae647
@ -6,11 +6,13 @@ import os
|
|||||||
import shlex
|
import shlex
|
||||||
import sys
|
import sys
|
||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
from typing import Callable, Dict, Tuple
|
from typing import Callable, Dict, Iterable, Optional, Tuple
|
||||||
|
|
||||||
from kittens.runner import all_kitten_names, get_kitten_cli_docs
|
from kittens.runner import all_kitten_names, get_kitten_cli_docs
|
||||||
|
|
||||||
from .cli import options_for_completion, parse_option_spec
|
from .cli import (
|
||||||
|
OptionDict, OptionSpecSeq, options_for_completion, parse_option_spec
|
||||||
|
)
|
||||||
from .rc.base import all_command_names, command_for_name
|
from .rc.base import all_command_names, command_for_name
|
||||||
from .shell import options_for_cmd
|
from .shell import options_for_cmd
|
||||||
|
|
||||||
@ -228,7 +230,7 @@ def complete_kitty_cli_arg(ans, opt, prefix):
|
|||||||
|
|
||||||
def complete_alias_map(ans, words, new_word, option_map, complete_args=None):
|
def complete_alias_map(ans, words, new_word, option_map, complete_args=None):
|
||||||
expecting_arg = False
|
expecting_arg = False
|
||||||
opt = None
|
opt: Optional[OptionDict] = None
|
||||||
last_word = words[-1] if words else ''
|
last_word = words[-1] if words else ''
|
||||||
for w in words:
|
for w in words:
|
||||||
if expecting_arg:
|
if expecting_arg:
|
||||||
@ -261,7 +263,7 @@ def complete_alias_map(ans, words, new_word, option_map, complete_args=None):
|
|||||||
ans.match_groups['Options'] = {k: opt['help'] for k, opt in option_map.items() if k.startswith(prefix)}
|
ans.match_groups['Options'] = {k: opt['help'] for k, opt in option_map.items() if k.startswith(prefix)}
|
||||||
|
|
||||||
|
|
||||||
def complete_cli(ans, words, new_word, seq, complete_args=lambda *a: None):
|
def complete_cli(ans, words, new_word, seq: OptionSpecSeq, complete_args=lambda *a: None):
|
||||||
option_map = {}
|
option_map = {}
|
||||||
for opt in seq:
|
for opt in seq:
|
||||||
if not isinstance(opt, str):
|
if not isinstance(opt, str):
|
||||||
@ -292,7 +294,7 @@ def path_completion(prefix=''):
|
|||||||
src = os.path.expandvars(os.path.expanduser(base))
|
src = os.path.expandvars(os.path.expanduser(base))
|
||||||
src_prefix = os.path.abspath(os.path.expandvars(os.path.expanduser(prefix))) if prefix else ''
|
src_prefix = os.path.abspath(os.path.expandvars(os.path.expanduser(prefix))) if prefix else ''
|
||||||
try:
|
try:
|
||||||
items = os.scandir(src)
|
items: Iterable[os.DirEntry] = os.scandir(src)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
items = ()
|
items = ()
|
||||||
for x in items:
|
for x in items:
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
from typing import (
|
from typing import (
|
||||||
Any, AnyStr, Callable, Dict, List, NewType, Optional, Tuple, Union
|
Any, AnyStr, Callable, Dict, List, NewType, Optional, Tuple, TypedDict,
|
||||||
|
Union
|
||||||
)
|
)
|
||||||
|
|
||||||
from kitty.boss import Boss
|
from kitty.boss import Boss
|
||||||
@ -390,7 +391,14 @@ def default_color_table() -> Tuple[int, ...]:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
FontConfigPattern = Dict[str, Union[str, int, bool, float]]
|
class FontConfigPattern(TypedDict):
|
||||||
|
family: str
|
||||||
|
full_name: str
|
||||||
|
postscript_name: str
|
||||||
|
style: str
|
||||||
|
spacing: str
|
||||||
|
weight: int
|
||||||
|
slant: int
|
||||||
|
|
||||||
|
|
||||||
def fc_list(
|
def fc_list(
|
||||||
|
|||||||
@ -4,23 +4,32 @@
|
|||||||
|
|
||||||
import re
|
import re
|
||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
from typing import Generator
|
from typing import TYPE_CHECKING, Dict, Generator, List, Optional, Tuple, cast
|
||||||
|
|
||||||
from kitty.fast_data_types import (
|
from kitty.fast_data_types import (
|
||||||
FC_DUAL, FC_MONO, FC_SLANT_ITALIC, FC_SLANT_ROMAN, FC_WEIGHT_BOLD,
|
FC_DUAL, FC_MONO, FC_SLANT_ITALIC, FC_SLANT_ROMAN, FC_WEIGHT_BOLD,
|
||||||
FC_WEIGHT_REGULAR, fc_list, fc_match as fc_match_impl
|
FC_WEIGHT_REGULAR, fc_list, fc_match as fc_match_impl
|
||||||
)
|
)
|
||||||
|
from kitty.options_stub import Options
|
||||||
|
|
||||||
from . import ListedFont
|
from . import ListedFont
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from kitty.fast_data_types import FontConfigPattern
|
||||||
|
FontConfigPattern
|
||||||
|
|
||||||
|
|
||||||
attr_map = {(False, False): 'font_family',
|
attr_map = {(False, False): 'font_family',
|
||||||
(True, False): 'bold_font',
|
(True, False): 'bold_font',
|
||||||
(False, True): 'italic_font',
|
(False, True): 'italic_font',
|
||||||
(True, True): 'bold_italic_font'}
|
(True, True): 'bold_italic_font'}
|
||||||
|
|
||||||
|
|
||||||
def create_font_map(all_fonts):
|
FontMap = Dict[str, Dict[str, List['FontConfigPattern']]]
|
||||||
ans = {'family_map': {}, 'ps_map': {}, 'full_map': {}}
|
|
||||||
|
|
||||||
|
def create_font_map(all_fonts: Tuple['FontConfigPattern', ...]) -> FontMap:
|
||||||
|
ans: FontMap = {'family_map': {}, 'ps_map': {}, 'full_map': {}}
|
||||||
for x in all_fonts:
|
for x in all_fonts:
|
||||||
if 'path' not in x:
|
if 'path' not in x:
|
||||||
continue
|
continue
|
||||||
@ -34,7 +43,7 @@ def create_font_map(all_fonts):
|
|||||||
|
|
||||||
|
|
||||||
@lru_cache()
|
@lru_cache()
|
||||||
def all_fonts_map(monospaced=True):
|
def all_fonts_map(monospaced=True) -> FontMap:
|
||||||
if monospaced:
|
if monospaced:
|
||||||
ans = fc_list(FC_DUAL) + fc_list(FC_MONO)
|
ans = fc_list(FC_DUAL) + fc_list(FC_MONO)
|
||||||
else:
|
else:
|
||||||
@ -55,16 +64,16 @@ def list_fonts() -> Generator[ListedFont, None, None]:
|
|||||||
yield {'family': f, 'full_name': fn, 'postscript_name': str(fd.get('postscript_name', '')), 'is_monospace': is_mono}
|
yield {'family': f, 'full_name': fn, 'postscript_name': str(fd.get('postscript_name', '')), 'is_monospace': is_mono}
|
||||||
|
|
||||||
|
|
||||||
def family_name_to_key(family):
|
def family_name_to_key(family: str) -> str:
|
||||||
return re.sub(r'\s+', ' ', family.lower())
|
return re.sub(r'\s+', ' ', family.lower())
|
||||||
|
|
||||||
|
|
||||||
@lru_cache()
|
@lru_cache()
|
||||||
def fc_match(family, bold, italic, spacing=FC_MONO):
|
def fc_match(family, bold, italic, spacing=FC_MONO) -> 'FontConfigPattern':
|
||||||
return fc_match_impl(family, bold, italic, spacing)
|
return fc_match_impl(family, bold, italic, spacing)
|
||||||
|
|
||||||
|
|
||||||
def find_best_match(family, bold=False, italic=False, monospaced=True):
|
def find_best_match(family: str, bold=False, italic=False, monospaced=True) -> 'FontConfigPattern':
|
||||||
q = family_name_to_key(family)
|
q = family_name_to_key(family)
|
||||||
font_map = all_fonts_map(monospaced)
|
font_map = all_fonts_map(monospaced)
|
||||||
|
|
||||||
@ -85,7 +94,7 @@ def find_best_match(family, bold=False, italic=False, monospaced=True):
|
|||||||
for spacing in (FC_MONO, FC_DUAL):
|
for spacing in (FC_MONO, FC_DUAL):
|
||||||
possibility = fc_match(family, False, False, spacing)
|
possibility = fc_match(family, False, False, spacing)
|
||||||
for key, map_key in (('postscript_name', 'ps_map'), ('full_name', 'full_map'), ('family', 'family_map')):
|
for key, map_key in (('postscript_name', 'ps_map'), ('full_name', 'full_map'), ('family', 'family_map')):
|
||||||
val = possibility.get(key)
|
val: Optional[str] = cast(Optional[str], possibility.get(key))
|
||||||
if val:
|
if val:
|
||||||
candidates = font_map[map_key].get(family_name_to_key(val))
|
candidates = font_map[map_key].get(family_name_to_key(val))
|
||||||
if candidates:
|
if candidates:
|
||||||
@ -103,14 +112,14 @@ def find_best_match(family, bold=False, italic=False, monospaced=True):
|
|||||||
return fc_match(family, bold, italic)
|
return fc_match(family, bold, italic)
|
||||||
|
|
||||||
|
|
||||||
def resolve_family(f, main_family, bold, italic):
|
def resolve_family(f: str, main_family: str, bold: bool, italic: bool) -> str:
|
||||||
if (bold or italic) and f == 'auto':
|
if (bold or italic) and f == 'auto':
|
||||||
f = main_family
|
f = main_family
|
||||||
return f
|
return f
|
||||||
|
|
||||||
|
|
||||||
def get_font_files(opts):
|
def get_font_files(opts: Options) -> Dict[str, 'FontConfigPattern']:
|
||||||
ans = {}
|
ans: Dict[str, 'FontConfigPattern'] = {}
|
||||||
for (bold, italic), attr in attr_map.items():
|
for (bold, italic), attr in attr_map.items():
|
||||||
rf = resolve_family(getattr(opts, attr), opts.font_family, bold, italic)
|
rf = resolve_family(getattr(opts, attr), opts.font_family, bold, italic)
|
||||||
font = find_best_match(rf, bold, italic)
|
font = find_best_match(rf, bold, italic)
|
||||||
@ -122,6 +131,6 @@ def get_font_files(opts):
|
|||||||
return ans
|
return ans
|
||||||
|
|
||||||
|
|
||||||
def font_for_family(family):
|
def font_for_family(family) -> Tuple['FontConfigPattern', bool, bool]:
|
||||||
ans = find_best_match(family, monospaced=False)
|
ans = find_best_match(family, monospaced=False)
|
||||||
return ans, ans.get('weight', 0) >= FC_WEIGHT_BOLD, ans.get('slant', FC_SLANT_ROMAN) != FC_SLANT_ROMAN
|
return ans, ans.get('weight', 0) >= FC_WEIGHT_BOLD, ans.get('slant', FC_SLANT_ROMAN) != FC_SLANT_ROMAN
|
||||||
|
|||||||
@ -3,8 +3,11 @@
|
|||||||
# License: GPL v3 Copyright: 2017, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPL v3 Copyright: 2017, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
from typing import Dict, List, Sequence
|
||||||
|
|
||||||
from kitty.constants import is_macos
|
from kitty.constants import is_macos
|
||||||
from typing import Sequence
|
|
||||||
|
from . import ListedFont
|
||||||
|
|
||||||
if is_macos:
|
if is_macos:
|
||||||
from .core_text import list_fonts
|
from .core_text import list_fonts
|
||||||
@ -12,8 +15,8 @@ else:
|
|||||||
from .fontconfig import list_fonts
|
from .fontconfig import list_fonts
|
||||||
|
|
||||||
|
|
||||||
def create_family_groups(monospaced=True):
|
def create_family_groups(monospaced: bool = True) -> Dict[str, List[ListedFont]]:
|
||||||
g = {}
|
g: Dict[str, List[ListedFont]] = {}
|
||||||
for f in list_fonts():
|
for f in list_fonts():
|
||||||
if not monospaced or f['is_monospace']:
|
if not monospaced or f['is_monospace']:
|
||||||
g.setdefault(f['family'], []).append(f)
|
g.setdefault(f['family'], []).append(f)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user