Add a test for PUA recog

This commit is contained in:
Kovid Goyal 2025-03-25 16:52:01 +05:30
parent fd2bbf57e3
commit 3e50588525
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
4 changed files with 26 additions and 3 deletions

View file

@ -717,7 +717,7 @@ def aw(s: Iterable[int], width: int) -> None:
raw = f.read()
nraw = re.sub(r'\d+/\*=width_shift\*/', f'{width_shift}/*=width_shift*/', raw)
nraw = re.sub(r'// CharPropsDeclaration.+?// EndCharPropsDeclaration', CharProps.c_declaration(), nraw, flags=re.DOTALL)
nraw = re.sub(r'// UCBDeclaration.+?// EndUCBDeclaration', buf.getvalue(), nraw, flags=re.DOTALL)
nraw = re.sub(r'// UCBDeclaration.+?// EndUCBDeclaration', buf.getvalue().rstrip(), nraw, flags=re.DOTALL)
if nraw != raw:
f.seek(0)
f.truncate()

View file

@ -46,8 +46,6 @@ typedef enum UnicodeCategory {
// EndUCBDeclaration
// CharPropsDeclaration
// Uses 23 bits
typedef union CharProps {
@ -101,3 +99,12 @@ void grapheme_segmentation_reset(GraphemeSegmentationState *s);
bool grapheme_segmentation_step(GraphemeSegmentationState *s, CharProps ch);
static inline int wcwidth_std(CharProps ch) { return (int)ch.shifted_width - 4/*=width_shift*/; }
static inline bool is_private_use(CharProps ch) { return ch.category == UC_Co; }
static inline const char* char_category(CharProps cp) {
#define a(x) case UC_##x: return #x
switch((UnicodeCategory)cp.category) {
a(Cn); a(Cc); a(Zs); a(Po); a(Sc); a(Ps); a(Pe); a(Sm); a(Pd); a(Nd); a(Lu); a(Sk); a(Pc); a(Ll); a(So); a(Lo); a(Pi); a(Cf);
a(No); a(Pf); a(Lt); a(Lm); a(Mn); a(Me); a(Mc); a(Nl); a(Zl); a(Zp); a(Cs); a(Co);
}
return "Cn";
#undef a
}

View file

@ -632,6 +632,19 @@ py_run_atexit_cleanup_functions(PyObject *self UNUSED, PyObject *args UNUSED) {
Py_RETURN_NONE;
}
static PyObject*
py_char_props_for(PyObject *self UNUSED, PyObject *ch) {
if (!PyUnicode_Check(ch) || PyUnicode_GET_LENGTH(ch) != 1) { PyErr_SetString(PyExc_TypeError, "must suply a single character"); return NULL; }
char_type c = PyUnicode_READ_CHAR(ch, 0);
CharProps cp = char_props_for(c);
#define B(x) #x, cp.x ? Py_True : Py_False
return Py_BuildValue("{ si sO sB sB ss }",
"width", wcwidth_std(cp), B(is_extended_pictographic), "grapheme_break", cp.grapheme_break,
"indic_conjunct_break", cp.indic_conjunct_break, "category", char_category(cp)
);
#undef B
}
static PyMethodDef module_methods[] = {
METHODB(replace_c0_codes_except_nl_space_tab, METH_O),
{"wcwidth", (PyCFunction)wcwidth_wrap, METH_O, ""},
@ -647,6 +660,7 @@ static PyMethodDef module_methods[] = {
{"base64_encode_into", (PyCFunction)base64_encode_into, METH_VARARGS, ""},
{"base64_decode", (PyCFunction)(void (*) (void))(pybase64_decode), METH_O, ""},
{"base64_decode_into", (PyCFunction)base64_decode_into, METH_VARARGS, ""},
{"char_props_for", py_char_props_for, METH_O, ""},
{"split_into_graphemes", (PyCFunction)split_into_graphemes, METH_O, ""},
{"thread_write", (PyCFunction)cm_thread_write, METH_VARARGS, ""},
{"redirect_std_streams", (PyCFunction)redirect_std_streams, METH_VARARGS, ""},

View file

@ -11,6 +11,7 @@
Color,
HistoryBuf,
LineBuf,
char_props_for,
expand_ansi_c_escapes,
parse_input_from_terminal,
replace_c0_codes_except_nl_space_tab,
@ -640,3 +641,4 @@ def test_split_into_graphemes(self):
expected = test['data']
actual = split_into_graphemes(''.join(expected))
self.ae(expected, actual, f'Test #{i} failed: {test["comment"]}')
self.assertEqual(char_props_for('\ue000')['category'], 'Co')