Unicode
Unicode text made comparable and measured: NFC and NFKC forms, accents removed, characters counted as people see them, safe truncation and terminal width.
Version 1.0.0 · 6 functions · 3 crates
Functions
What use unicode.qwer gives a program, with the types Quillo sees. To take only some, or under other names: use unicode_normalize, unicode_strip_accents from unicode (Quillo 0.6).
unicode_normalize(text: str, form: str) → stror an errortext in a normal form: "nfc" (composed: what to store and compare; "é" as one character), "nfd" (decomposed: "e" and an accent), "nfkc" or "nfkd" (also folding look-alikes: "fi" is "fi", "①" is "1", full-width "A" is "A", for usernames and search).
unicode_strip_accents(text: str) → stror an errortext without accents and other marks: "Crème Brûlée" is "Creme Brulee", "Ångström" is "Angstrom". Letters that are not a base letter with marks ("ø", "ß", "æ") stay as they are.
unicode_length(text: str) → intor an errorHow many characters text has as a person counts them (grapheme clusters): "👍🏽" and "🇫🇷" are 1, "é" is 1 however it is stored. Quillo's len counts code points, which differ for these.
unicode_truncate(text: str, n: int) → stror an errorThe first n characters of text as a person counts them, never cutting an emoji or an accent in two: for previews and limits like "30 characters".
unicode_width(text: str) → intor an errorHow many columns text takes in a terminal or a monospace font: Chinese, Japanese and most emoji take 2, accents 0. For tables in plain-text emails and CLIs.
unicode_same(a: str, b: str) → boolor an errorWhether two texts are the same once both are in NFKC form and lower case: "Café" and "café" are.
Get it
$ quillo install unicode # unicode.qwer into this folder$ quillo install unicode --example # and its example, unicode.qweOr with curl:
$ curl -O https://quillolang.org/plugins/files/unicode.qwer$ curl -O https://quillolang.org/plugins/files/unicode.qweThen, in your program, all of it or only what you call:
use unicode.qweruse unicode_normalize, unicode_strip_accents from unicode // Quillo 0.6: only theseIt uses these crates, which cargo fetches the first time the plugin is built:
unicode-normalization = "0.1"unicode-segmentation = "1.12"unicode-width = "0.2"Example
// Usernames compared as people read them, and a 10-character preview that never breaks an emoji.//// quillo run unicode.qwe then open http://localhost:8080/textuse "unicode.qwer"let thumbs = "Great job 👍🏽🇫🇷!"let decomposed = "Cafe\u{301}"route GET /text = { code_points: len(thumbs), seen: unicode_length(thumbs)?, preview: unicode_truncate(thumbs, 11)?, plain: unicode_strip_accents("Crème Brûlée, Ångström, São Paulo")?, same_user: unicode_same("Café", "café")?, stored: len(unicode_normalize(decomposed, "nfc")?), width: unicode_width("日本語 ok")?, folded: unicode_normalize("file ①", "nfkc")?,}$ quillo run unicode.qwe$ curl 'localhost:8080/text'Source
//! Unicode text made comparable and measured: NFC/NFD/NFKC/NFKD forms, accents removed, characters counted as people see them (👍🏽 is one), and width in a terminal.//! version: 1.0.0//!//! [dependencies]//! unicode-normalization = "0.1"//! unicode-segmentation = "1.12"//! unicode-width = "0.2"use unicode_normalization::char::is_combining_mark;use unicode_normalization::UnicodeNormalization;use unicode_segmentation::UnicodeSegmentation;use unicode_width::UnicodeWidthStr;const MAX: usize = 10_000_000;fn check(text: &str) -> Result<(), String> { if text.len() > MAX { Err("text up to 10 MB".into()) } else { Ok(()) }}/// `text` in a normal form: "nfc" (composed: what to store and compare; "é" as one character), "nfd" (decomposed: "e" and an accent), "nfkc" or "nfkd" (also folding look-alikes: "fi" is "fi", "①" is "1", full-width "A" is "A", for usernames and search).pub fn unicode_normalize(text: &str, form: &str) -> Result<String, String> { check(text)?; Ok(match form.to_lowercase().as_str() { "nfc" | "" => text.nfc().collect(), "nfd" => text.nfd().collect(), "nfkc" => text.nfkc().collect(), "nfkd" => text.nfkd().collect(), o => return Err(format!("form is \"nfc\", \"nfd\", \"nfkc\" or \"nfkd\", not {:?}", o)), })}/// `text` without accents and other marks: "Crème Brûlée" is "Creme Brulee", "Ångström" is "Angstrom". Letters that are not a base letter with marks ("ø", "ß", "æ") stay as they are.pub fn unicode_strip_accents(text: &str) -> Result<String, String> { check(text)?; Ok(text.nfd().filter(|c| !is_combining_mark(*c)).nfc().collect())}/// How many characters `text` has as a person counts them (grapheme clusters): "👍🏽" and "🇫🇷" are 1, "é" is 1 however it is stored. Quillo's `len` counts code points, which differ for these.pub fn unicode_length(text: &str) -> Result<i64, String> { check(text)?; Ok(text.graphemes(true).count() as i64)}/// The first `n` characters of `text` as a person counts them, never cutting an emoji or an accent in two: for previews and limits like "30 characters".pub fn unicode_truncate(text: &str, n: i64) -> Result<String, String> { check(text)?; Ok(text.graphemes(true).take(n.max(0) as usize).collect())}/// How many columns `text` takes in a terminal or a monospace font: Chinese, Japanese and most emoji take 2, accents 0. For tables in plain-text emails and CLIs.pub fn unicode_width(text: &str) -> Result<i64, String> { check(text)?; Ok(UnicodeWidthStr::width(text) as i64)}/// Whether two texts are the same once both are in NFKC form and lower case: "Café" and "café" are.pub fn unicode_same(a: &str, b: &str) -> Result<bool, String> { check(a)?; check(b)?; Ok(a.nfkc().collect::<String>().to_lowercase() == b.nfkc().collect::<String>().to_lowercase())}Related
kana.qwer · 1.0.0Japanese kana: romaji typed as hiragana or katakana, kana written in Hepburn romaji, hiragana and katakana each to the other, half-width katakana from bank and till systems made full-width, and which scripts a text uses.6 views · 10 downloadsSpellcheck spellcheck.qwer · 1.0.0Spelling checked against a word list you load, in any language: unknown words found with their places, suggestions ranked by closeness and frequency (SymSpell's method), text corrected for "did you mean", and your own words added.7 views · 8 downloadsCase case.qwer · 1.0.0Text in snake_case, camelCase, PascalCase, kebab-case, CONSTANT_CASE, Title Case and Sentence case: column names as API keys and labels.7 views · 8 downloadsChinese words chinese_segment.qwer · 1.0.0Chinese text split into words for search indexes and counts, with parts of speech, and written in pinyin with tones, tone numbers or initials for sorting and finding names.7 views · 7 downloadsEmoji emoji.qwer · 1.0.0Emoji for chat and comments: :shortcodes: turned into emoji and back, emoji found with their names, stripped from subjects, and searched by name for a picker.7 views · 8 downloadsFuzzy search fuzzy.qwer · 1.0.0Rank names against what someone typed, typos and all, edit distances, and did-you-mean.7 views · 8 downloadsThread 0 posts
On Unicode: questions, tips, corrections, and code that uses it.
No posts yet. The first one opens the thread.