Generate a wcwidth for Go as well

This commit is contained in:
Kovid Goyal 2022-08-24 16:01:54 +05:30
parent 7bb310d3af
commit 05d768d8df
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
5 changed files with 3258 additions and 24 deletions

2
.gitattributes vendored
View File

@ -15,6 +15,8 @@ kittens/diff/options/parse.py linguist-generated=true
glfw/*.c linguist-vendored=true glfw/*.c linguist-vendored=true
glfw/*.h linguist-vendored=true glfw/*.h linguist-vendored=true
kittens/unicode_input/names.h linguist-generated=true kittens/unicode_input/names.h linguist-generated=true
tools/tui/wcwidth-std.go linguist-generated=true
*.py text diff=python *.py text diff=python
*.m text diff=objc *.m text diff=objc
*.go text diff=go

View File

@ -21,6 +21,7 @@ kitty/options/parse.py
kitty/options/to-c-generated.h kitty/options/to-c-generated.h
kittens/diff/options/types.py kittens/diff/options/types.py
kittens/diff/options/parse.py kittens/diff/options/parse.py
tools/tui/wcwidth-std.go
''' '''
ignored = [] ignored = []

View File

@ -3,6 +3,7 @@
import os import os
import re import re
import subprocess
import sys import sys
from collections import defaultdict from collections import defaultdict
from contextlib import contextmanager from contextlib import contextmanager
@ -254,8 +255,12 @@ def get_ranges(items: List[int]) -> Generator[Union[int, Tuple[int, int]], None,
yield a, b yield a, b
def write_case(spec: Union[Tuple[int, ...], int], p: Callable[..., None]) -> None: def write_case(spec: Union[Tuple[int, ...], int], p: Callable[..., None], for_go: bool = False) -> None:
if isinstance(spec, tuple): if isinstance(spec, tuple):
if for_go:
v = ', '.join(f'0x{x:x}' for x in range(spec[0], spec[1] + 1))
p(f'\t\tcase {v}:')
else:
p('\t\tcase 0x{:x} ... 0x{:x}:'.format(*spec)) p('\t\tcase 0x{:x} ... 0x{:x}:'.format(*spec))
else: else:
p(f'\t\tcase 0x{spec:x}:') p(f'\t\tcase 0x{spec:x}:')
@ -524,45 +529,61 @@ def gen_names() -> None:
def gen_wcwidth() -> None: def gen_wcwidth() -> None:
seen: Set[int] = set() seen: Set[int] = set()
non_printing = class_maps['Cc'] | class_maps['Cf'] | class_maps['Cs']
def add(p: Callable[..., None], comment: str, chars_: Union[Set[int], FrozenSet[int]], ret: int) -> None: def add(p: Callable[..., None], comment: str, chars_: Union[Set[int], FrozenSet[int]], ret: int, for_go: bool = False) -> None:
chars = chars_ - seen chars = chars_ - seen
seen.update(chars) seen.update(chars)
p(f'\t\t// {comment} ({len(chars)} codepoints)' + ' {{' '{') p(f'\t\t// {comment} ({len(chars)} codepoints)' + ' {{' '{')
for spec in get_ranges(list(chars)): for spec in get_ranges(list(chars)):
write_case(spec, p) write_case(spec, p, for_go)
p(f'\t\t\treturn {ret};') p(f'\t\t\treturn {ret};')
p('\t\t// }}}\n') p('\t\t// }}}\n')
with create_header('kitty/wcwidth-std.h') as p: def add_all(p: Callable[..., None], for_go: bool = False) -> None:
p('static inline int\nwcwidth_std(int32_t code) {') seen.clear()
p('\tif (LIKELY(0x20 <= code && code <= 0x7e)) return 1;') add(p, 'Flags', flag_codepoints, 2, for_go)
p('\tswitch(code) {') add(p, 'Marks', marks | {0}, 0, for_go)
add(p, 'Non-printing characters', non_printing, -1, for_go)
add(p, 'Private use', class_maps['Co'], -3, for_go)
add(p, 'Text Presentation', narrow_emoji, 1, for_go)
add(p, 'East Asian ambiguous width', ambiguous, -2, for_go)
add(p, 'East Asian double width', doublewidth, 2, for_go)
add(p, 'Emoji Presentation', wide_emoji, 2, for_go)
non_printing = class_maps['Cc'] | class_maps['Cf'] | class_maps['Cs'] add(p, 'Not assigned in the unicode character database', not_assigned, -4, for_go)
add(p, 'Flags', flag_codepoints, 2)
add(p, 'Marks', marks | {0}, 0)
add(p, 'Non-printing characters', non_printing, -1)
add(p, 'Private use', class_maps['Co'], -3)
add(p, 'Text Presentation', narrow_emoji, 1)
add(p, 'East Asian ambiguous width', ambiguous, -2)
add(p, 'East Asian double width', doublewidth, 2)
add(p, 'Emoji Presentation', wide_emoji, 2)
add(p, 'Not assigned in the unicode character database', not_assigned, -4) p('\t\tdefault:\n\t\t\treturn 1;')
p('\t\tdefault: return 1;')
p('\t}') p('\t}')
p('\treturn 1;\n}') p('\treturn 1;\n}')
with create_header('kitty/wcwidth-std.h') as p, open('tools/tui/wcwidth-std.go', 'w') as gof:
gop = partial(print, file=gof)
gop('package tui\n\n')
gop('func Wcwidth(code rune) int {')
p('static inline int\nwcwidth_std(int32_t code) {')
p('\tif (LIKELY(0x20 <= code && code <= 0x7e)) { return 1; }')
p('\tswitch(code) {')
gop('\tswitch(code) {')
add_all(p)
add_all(gop, True)
p('static inline bool\nis_emoji_presentation_base(uint32_t code) {') p('static inline bool\nis_emoji_presentation_base(uint32_t code) {')
gop('func IsEmojiPresentationBase(code rune) bool {')
p('\tswitch(code) {') p('\tswitch(code) {')
gop('\tswitch(code) {')
for spec in get_ranges(list(emoji_presentation_bases)): for spec in get_ranges(list(emoji_presentation_bases)):
write_case(spec, p) write_case(spec, p)
write_case(spec, gop, for_go=True)
p('\t\t\treturn true;') p('\t\t\treturn true;')
gop('\t\t\treturn true;')
p('\t\tdefault: return false;') p('\t\tdefault: return false;')
p('\t}') p('\t}')
p('\treturn 1;\n}') gop('\t\tdefault:\n\t\t\treturn false')
gop('\t}')
p('\treturn true;\n}')
gop('\n}')
subprocess.check_call(['gofmt', '-w', '-s', gof.name])
parse_ucd() parse_ucd()

7
kitty/wcwidth-std.h generated
View File

@ -7,7 +7,7 @@ START_ALLOW_CASE_RANGE
static inline int static inline int
wcwidth_std(int32_t code) { wcwidth_std(int32_t code) {
if (LIKELY(0x20 <= code && code <= 0x7e)) return 1; if (LIKELY(0x20 <= code && code <= 0x7e)) { return 1; }
switch(code) { switch(code) {
// Flags (26 codepoints) {{{ // Flags (26 codepoints) {{{
case 0x1f1e6 ... 0x1f1ff: case 0x1f1e6 ... 0x1f1ff:
@ -2932,7 +2932,8 @@ wcwidth_std(int32_t code) {
return -4; return -4;
// }}} // }}}
default: return 1; default:
return 1;
} }
return 1; return 1;
} }
@ -3247,7 +3248,7 @@ is_emoji_presentation_base(uint32_t code) {
return true; return true;
default: return false; default: return false;
} }
return 1; return true;
} }
END_ALLOW_CASE_RANGE END_ALLOW_CASE_RANGE

3209
tools/tui/wcwidth-std.go generated Normal file

File diff suppressed because one or more lines are too long