2023-11-02 13:06:48 -04:00
|
|
|
/**
|
|
|
|
* 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);
|
|
|
|
}
|
|
|
|
|
2023-11-09 12:05:30 -05:00
|
|
|
/**
|
|
|
|
* 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;
|
|
|
|
}
|
|
|
|
|
2023-11-02 13:06:48 -04:00
|
|
|
/**
|
|
|
|
* 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);
|
2023-11-09 12:05:30 -05:00
|
|
|
if (point === undefined) {
|
2023-11-02 13:06:48 -04:00
|
|
|
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;
|
|
|
|
}
|
2023-11-09 12:05:30 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 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('');
|
|
|
|
}
|