// ---------------------------------------------------------------------------- // Strings // ---------------------------------------------------------------------------- /** * Split a string by graphemes, not just bytes * @param s - the string to split into 'characters' */ export function chars(s: string): string[] { return s.split(/(?:)/u); } /** * Get the 'character length' of a string, not its UTF16 byte count * @param s - the string to check */ export function strlen(s: string): number { return chars(s).length; } /** * Is the character part of ascii? * * @param char - a one character string to check */ export function is_ascii(char: string): boolean { return chars(char).every((char) => { const point = char.codePointAt(0); if (point === undefined) { return false; } return point < 0x80; }); } /** * Is the one char in the string an ascii control character? * * @param char - a one character string to check */ export function is_control(char: string): boolean { const code = char.codePointAt(0); if (code === undefined) { return false; } return is_ascii(char) && (code === 0x7f || code < 0x20); } /** * Get the key code for a ctrl chord * @param char - a one character string */ export function ctrl_key(char: string): string { // This is the normal use case, of course if (is_ascii(char)) { const point = char.codePointAt(0); if (point === undefined) { return char; } return String.fromCodePoint(point & 0x1f); } // If it's not ascii, just return the input key code return char; } /** * Trim a string to a max number of characters * @param s * @param maxLen */ export function truncate(s: string, maxLen: number): string { const chin = chars(s); if (maxLen >= chin.length) { return s; } return chin.slice(0, maxLen).join(''); }