Add Indic Conjunct Break data

This commit is contained in:
Kovid Goyal
2025-03-13 09:18:42 +05:30
parent f7521120e6
commit 039af78785
3 changed files with 3127 additions and 1441 deletions

View File

@@ -72,6 +72,7 @@ marks = set(emoji_skin_tone_modifiers) | flag_codepoints
not_assigned = set(range(0, sys.maxunicode))
property_maps: dict[str, set[int]] = defaultdict(set)
grapheme_segmentation_maps: dict[str, set[int]] = defaultdict(set)
incb_map: dict[str, set[int]] = defaultdict(set)
def parse_prop_list() -> None:
@@ -264,6 +265,15 @@ def parse_grapheme_segmentation() -> None:
for line in get_data('ucd/auxiliary/GraphemeBreakProperty.txt'):
chars, category = split_two(line)
grapheme_segmentation_maps[category] |= chars
for line in get_data('ucd/DerivedCoreProperties.txt'):
spec, rest = line.split(';', 1)
category = rest.strip().split(' ', 1)[0].strip().rstrip(';')
chars = parse_range_spec(spec.strip())
if category == 'InCB':
# Most InCB chars also have a GBP categorization, but not all,
# there exist some InCB chars that do not have a GBP category
subcat = rest.strip().split(';')[1].strip().split()[0].strip()
incb_map[subcat] |= chars
def get_ranges(items: list[int]) -> Generator[Union[int, tuple[int, int]], None, None]:
@@ -443,46 +453,63 @@ def gen_names() -> None:
print(cp, *words, end=end, file=f)
def gofmt(*files: str) -> None:
subprocess.check_call(['gofmt', '-w', '-s'] + list(files))
def gen_grapheme_segmentation() -> None:
with create_header('kitty/grapheme-segmentation-data.h') as p, open('tools/wcswidth/grapheme-segmentation-data.go', 'w') as gof:
gp = partial(print, file=gof)
p('typedef enum GraphemeBreakProperty {') # }
p(' GBP_None,')
gp('package wcswidth\n\n')
gp('type GraphemeBreakProperty uint8\n')
gp('const (') # )
gp('None = iota') # )
for category in grapheme_segmentation_maps:
p(f' GBP_{category},')
gp(f' {category}')
p('} GraphemeBreakProperty;')
p('')
gp(')')
gp('')
p('static inline GraphemeBreakProperty')
p('grapheme_break_property(const char_type c) {') # }
p('\tswitch(c) {') # }
gp('func GraphemeBreakPropertyFor(code rune) GraphemeBreakProperty {') # }
gp('\tswitch code {') # }
for category, codepoints in grapheme_segmentation_maps.items():
p(f'\t\t // {category} ({len(codepoints)} codepoints ''{{''{')
gp(f'\t\t // {category} ({len(codepoints)} codepoints ''{{''{')
for spec in get_ranges(list(codepoints)):
write_case(spec, p)
p(f'\t\t\treturn GBP_{category};')
write_case(spec, gp, for_go=True)
gp(f'\t\t\treturn {category}')
p('\t\t // }}''}')
def enum(name: str, *items: str, prefix: str = '') -> None:
p(f'typedef enum {name} {{') # }}
gp(f'type {name} uint8\n')
gp('const (') # )
for i, x in enumerate(items):
x = prefix + x
p(f'\t{x},')
if i == 0:
gp(f'{x} {name} = iota')
else:
gp(x)
p(f'}} {name};')
gp(')')
p('')
gp('\t\t // }}''}')
gp('')
p('\t}') # }
gp('\t}') # }
p('\treturn GBP_None;') # }
gp('\treturn None') # }
p('}')
gp('}')
subprocess.check_call(['gofmt', '-w', '-s', gof.name])
enum('GraphemeBreakProperty', 'None', *grapheme_segmentation_maps, prefix='GBP_')
enum('IndicConjunctBreak', 'None', *incb_map, prefix='ICB_')
def get_cat(name: str, c_func_name: str, go_func_name: str, prefix: str, m: dict[str, set[int]]) -> None:
p(f'static inline {name}')
p(f'{c_func_name}(const char_type c) {{') # }}
p('\tswitch(c) {') # }
gp(f'func {go_func_name}(code rune) {name} {{') # }}
gp('\tswitch code {') # }
for category, codepoints in m.items():
p(f'\t\t // {category} ({len(codepoints)} codepoints ''{{''{')
gp(f'\t\t // {category} ({len(codepoints)} codepoints ''{{''{')
category = prefix + category
for spec in get_ranges(list(codepoints)):
write_case(spec, p)
p(f'\t\t\treturn {category};')
write_case(spec, gp, for_go=True)
gp(f'\t\t\treturn {category}')
p('\t\t // }}''}')
p('')
gp('\t\t // }}''}')
gp('')
p('\t}') # }
gp('\t}') # }
p(f'\treturn {prefix + "None"};') # }
gp(f'\treturn {prefix + "None"}') # }
p('}')
gp('}')
get_cat('GraphemeBreakProperty', 'grapheme_break_property', 'GraphemeBreakPropertyFor', 'GBP_', grapheme_segmentation_maps)
p('')
gp('')
get_cat('IndicConjunctBreak', 'indic_conjunct_break', 'IndicConjunctBreakFor', 'ICB_', incb_map)
gofmt(gof.name)
def gen_wcwidth() -> None:
@@ -549,7 +576,7 @@ def gen_wcwidth() -> None:
p(f'#define UNICODE_MINOR_VERSION {uv[1]}')
p(f'#define UNICODE_PATCH_VERSION {uv[2]}')
gop('var UnicodeDatabaseVersion [3]int = [3]int{' f'{uv[0]}, {uv[1]}, {uv[2]}' + '}')
subprocess.check_call(['gofmt', '-w', '-s', gof.name])
gofmt(gof.name)
def gen_rowcolumn_diacritics() -> None:
@@ -595,7 +622,7 @@ def gen_rowcolumn_diacritics() -> None:
p('\t}')
p('\treturn 0;')
p('}')
subprocess.check_call(['gofmt', '-w', '-s', go_file])
gofmt(go_file)
def main(args: list[str]=sys.argv) -> None: