mirror of
https://github.com/kovidgoyal/kitty
synced 2026-06-08 22:28:24 +02:00
Code to get specs from options
This commit is contained in:
@@ -5,12 +5,13 @@ import json
|
|||||||
import string
|
import string
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
from typing import Any, Dict, Tuple, TypedDict
|
from typing import Any, Dict, Literal, Tuple, TypedDict
|
||||||
|
|
||||||
|
from kitty.cli import create_default_opts
|
||||||
from kitty.conf.utils import to_color
|
from kitty.conf.utils import to_color
|
||||||
from kitty.constants import kitten_exe
|
from kitty.constants import kitten_exe
|
||||||
from kitty.fonts import Descriptor
|
from kitty.fonts import Descriptor
|
||||||
from kitty.fonts.common import face_from_descriptor, get_font_files, get_variable_data_for_descriptor
|
from kitty.fonts.common import face_from_descriptor, get_font_files, get_variable_data_for_descriptor, spec_for_descriptor
|
||||||
from kitty.fonts.list import create_family_groups
|
from kitty.fonts.list import create_family_groups
|
||||||
from kitty.fonts.render import display_bitmap
|
from kitty.fonts.render import display_bitmap
|
||||||
from kitty.options.types import Options
|
from kitty.options.types import Options
|
||||||
@@ -95,13 +96,31 @@ def render_family_sample(
|
|||||||
return ans
|
return ans
|
||||||
|
|
||||||
|
|
||||||
|
OptNames = Literal['font_family', 'bold_font', 'italic_font', 'bold_italic_font']
|
||||||
|
ResolvedFace = Dict[Literal['family', 'spec'], str]
|
||||||
|
|
||||||
|
|
||||||
|
def resolved_faces(opts: Options) -> Dict[OptNames, ResolvedFace]:
|
||||||
|
font_files = get_font_files(opts)
|
||||||
|
ans: Dict[OptNames, ResolvedFace] = {}
|
||||||
|
def d(key: Literal['medium', 'bold', 'italic', 'bi'], opt_name: OptNames) -> None:
|
||||||
|
descriptor = font_files[key]
|
||||||
|
ans[opt_name] = {'family': descriptor['family'], 'spec': spec_for_descriptor(descriptor)}
|
||||||
|
d('medium', 'font_family')
|
||||||
|
d('bold', 'bold_font')
|
||||||
|
d('italic', 'italic_font')
|
||||||
|
d('bi', 'bold_italic_font')
|
||||||
|
return ans
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
cache: Dict[FaceKey, str] = {}
|
cache: Dict[FaceKey, str] = {}
|
||||||
for line in sys.stdin.buffer:
|
for line in sys.stdin.buffer:
|
||||||
cmd = json.loads(line)
|
cmd = json.loads(line)
|
||||||
action = cmd.get('action', '')
|
action = cmd.get('action', '')
|
||||||
if action == 'list_monospaced_fonts':
|
if action == 'list_monospaced_fonts':
|
||||||
send_to_kitten(create_family_groups())
|
opts = create_default_opts()
|
||||||
|
send_to_kitten({'fonts': create_family_groups(), 'resolved_faces': resolved_faces(opts)})
|
||||||
elif action == 'read_variable_data':
|
elif action == 'read_variable_data':
|
||||||
ans = []
|
ans = []
|
||||||
for descriptor in cmd['descriptors']:
|
for descriptor in cmd['descriptors']:
|
||||||
|
|||||||
@@ -142,6 +142,16 @@ func (self *FamilyList) Lines(num_rows int) []Line {
|
|||||||
return ans
|
return ans
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *FamilyList) SelectFamily(family string) bool {
|
||||||
|
for i, f := range self.families {
|
||||||
|
if f == family {
|
||||||
|
self.current_idx = i
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func (self *FamilyList) CurrentFamily() string {
|
func (self *FamilyList) CurrentFamily() string {
|
||||||
if self.current_idx >= 0 && self.current_idx < len(self.families) {
|
if self.current_idx >= 0 && self.current_idx < len(self.families) {
|
||||||
return self.families[self.current_idx]
|
return self.families[self.current_idx]
|
||||||
|
|||||||
@@ -69,6 +69,23 @@ type VariableData struct {
|
|||||||
Multi_axis_styles []MultiAxisStyle `json:"multi_axis_styles"`
|
Multi_axis_styles []MultiAxisStyle `json:"multi_axis_styles"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ResolvedFace struct {
|
||||||
|
Family string `json:"family"`
|
||||||
|
Spec string `json:"spec"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ResolvedFaces struct {
|
||||||
|
Font_family ResolvedFace `json:"font_family"`
|
||||||
|
Bold_font ResolvedFace `json:"bold_font"`
|
||||||
|
Italic_font ResolvedFace `json:"italic_font"`
|
||||||
|
Bold_italic_font ResolvedFace `json:"bold_italic_font"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListResult struct {
|
||||||
|
Fonts map[string][]ListedFont `json:"fonts"`
|
||||||
|
Resolved_faces ResolvedFaces `json:"resolved_faces"`
|
||||||
|
}
|
||||||
|
|
||||||
var variable_data_cache map[string]VariableData
|
var variable_data_cache map[string]VariableData
|
||||||
var variable_data_cache_mutex sync.Mutex
|
var variable_data_cache_mutex sync.Mutex
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ type TextStyle struct {
|
|||||||
|
|
||||||
type handler struct {
|
type handler struct {
|
||||||
lp *loop.Loop
|
lp *loop.Loop
|
||||||
fonts map[string][]ListedFont
|
|
||||||
state State
|
state State
|
||||||
err_mutex sync.Mutex
|
err_mutex sync.Mutex
|
||||||
err_in_worker_thread error
|
err_in_worker_thread error
|
||||||
@@ -49,6 +48,8 @@ type handler struct {
|
|||||||
rl *readline.Readline
|
rl *readline.Readline
|
||||||
family_list FamilyList
|
family_list FamilyList
|
||||||
variable_data_requested_for *utils.Set[string]
|
variable_data_requested_for *utils.Set[string]
|
||||||
|
fonts map[string][]ListedFont
|
||||||
|
resolved_faces_from_kitty_conf ResolvedFaces
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) set_worker_error(err error) {
|
func (h *handler) set_worker_error(err error) {
|
||||||
@@ -279,7 +280,10 @@ func (h *handler) initialize() {
|
|||||||
initialize_variable_data_cache()
|
initialize_variable_data_cache()
|
||||||
h.graphics_manager.initialize(h.lp)
|
h.graphics_manager.initialize(h.lp)
|
||||||
go func() {
|
go func() {
|
||||||
h.set_worker_error(kitty_font_backend.query("list_monospaced_fonts", nil, &h.fonts))
|
var r ListResult
|
||||||
|
h.set_worker_error(kitty_font_backend.query("list_monospaced_fonts", nil, &r))
|
||||||
|
h.fonts = r.Fonts
|
||||||
|
h.resolved_faces_from_kitty_conf = r.Resolved_faces
|
||||||
h.lp.WakeupMainThread()
|
h.lp.WakeupMainThread()
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
@@ -351,7 +355,7 @@ func (h *handler) on_wakeup() (err error) {
|
|||||||
case SCANNING_FAMILIES:
|
case SCANNING_FAMILIES:
|
||||||
h.state = LISTING_FAMILIES
|
h.state = LISTING_FAMILIES
|
||||||
h.family_list.UpdateFamilies(utils.StableSortWithKey(utils.Keys(h.fonts), strings.ToLower))
|
h.family_list.UpdateFamilies(utils.StableSortWithKey(utils.Keys(h.fonts), strings.ToLower))
|
||||||
case LISTING_FAMILIES:
|
h.family_list.SelectFamily(h.resolved_faces_from_kitty_conf.Font_family.Family)
|
||||||
}
|
}
|
||||||
return h.draw_screen()
|
return h.draw_screen()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -306,11 +306,7 @@ def axis_values_are_equal(defaults: Dict[str, float], a: Dict[str, float], b: Di
|
|||||||
return ad == bd
|
return ad == bd
|
||||||
|
|
||||||
|
|
||||||
def get_named_style(face: Face) -> Optional[NamedStyle]:
|
def _get_named_style(axis_map: Dict[str, float], vd: VariableData) -> Optional[NamedStyle]:
|
||||||
axis_map = face.get_variation()
|
|
||||||
if axis_map is None:
|
|
||||||
return None
|
|
||||||
vd = get_variable_data_for_face(face)
|
|
||||||
defaults = {ax['tag']: ax['default'] for ax in vd['axes']}
|
defaults = {ax['tag']: ax['default'] for ax in vd['axes']}
|
||||||
for ns in vd['named_styles']:
|
for ns in vd['named_styles']:
|
||||||
if axis_values_are_equal(defaults, ns['axis_values'], axis_map):
|
if axis_values_are_equal(defaults, ns['axis_values'], axis_map):
|
||||||
@@ -318,5 +314,73 @@ def get_named_style(face: Face) -> Optional[NamedStyle]:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def get_named_style(face_or_descriptor: Union[Face, Descriptor]) -> Optional[NamedStyle]:
|
||||||
|
if isinstance(face_or_descriptor, dict):
|
||||||
|
d: Descriptor = face_or_descriptor
|
||||||
|
vd = get_variable_data_for_descriptor(d)
|
||||||
|
if d['descriptor_type'] == 'fontconfig':
|
||||||
|
ns = d.get('named_instance', -1)
|
||||||
|
if ns > -1 and ns < len(vd['named_styles']):
|
||||||
|
return vd['named_styles'][ns]
|
||||||
|
axis_map = {}
|
||||||
|
axes = vd['axes']
|
||||||
|
for i, val in enumerate(d.get('axes', ())):
|
||||||
|
if i < len(axes):
|
||||||
|
axis_map[axes[i]['tag']] = val
|
||||||
|
else:
|
||||||
|
axis_map = d.get('axis_map', {}).copy()
|
||||||
|
else:
|
||||||
|
face: Face = face_or_descriptor
|
||||||
|
q = face.get_variation()
|
||||||
|
if q is None:
|
||||||
|
return None
|
||||||
|
axis_map = q
|
||||||
|
return _get_named_style(axis_map, vd)
|
||||||
|
|
||||||
|
|
||||||
|
def get_axis_map(face_or_descriptor: Union[Face, Descriptor]) -> Dict[str, float]:
|
||||||
|
base_axis_map = {}
|
||||||
|
axis_map: Dict[str, float] = {}
|
||||||
|
if isinstance(face_or_descriptor, dict):
|
||||||
|
d: Descriptor = face_or_descriptor
|
||||||
|
vd = get_variable_data_for_descriptor(d)
|
||||||
|
if d['descriptor_type'] == 'fontconfig':
|
||||||
|
ns = d.get('named_instance', -1)
|
||||||
|
if ns > -1 and ns < len(vd['named_styles']):
|
||||||
|
base_axis_map = vd['named_styles'][ns]['axis_values'].copy()
|
||||||
|
axis_map = {}
|
||||||
|
axes = vd['axes']
|
||||||
|
for i, val in enumerate(d.get('axes', ())):
|
||||||
|
if i < len(axes):
|
||||||
|
axis_map[axes[i]['tag']] = val
|
||||||
|
|
||||||
|
else:
|
||||||
|
axis_map = d.get('axis_map', {}).copy()
|
||||||
|
else:
|
||||||
|
face: Face = face_or_descriptor
|
||||||
|
q = face.get_variation()
|
||||||
|
if q is not None:
|
||||||
|
axis_map = q
|
||||||
|
base_axis_map.update(axis_map)
|
||||||
|
return base_axis_map
|
||||||
|
|
||||||
|
|
||||||
|
def spec_for_descriptor(descriptor: Descriptor) -> str:
|
||||||
|
from shlex import quote as q
|
||||||
|
if is_variable(descriptor):
|
||||||
|
vd = get_variable_data_for_descriptor(descriptor)
|
||||||
|
spec = f'family={q(descriptor["family"])}'
|
||||||
|
if vd['variations_postscript_name_prefix']:
|
||||||
|
spec += f' variable_name={q(vd["variations_postscript_name_prefix"])}'
|
||||||
|
ns = get_named_style(descriptor)
|
||||||
|
if ns is None:
|
||||||
|
for key, val in get_axis_map(descriptor).items():
|
||||||
|
spec += f' {key}={val:g}'
|
||||||
|
else:
|
||||||
|
spec = f'{spec} style={q(ns["psname"])}'
|
||||||
|
return spec
|
||||||
|
return descriptor['postscript_name']
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
develop()
|
develop()
|
||||||
|
|||||||
Reference in New Issue
Block a user