Text statistics
Words, sentences, syllables, reading and speaking time, Flesch reading ease and grade level of a text, for editors and writing tools.
Version 1.0.0 · 4 functions · 0 crates
Functions
What use text_stats.qwer gives a program, with the types Quillo sees. To take only some, or under other names: use text_stats, text_word_count from text_stats (Quillo 0.6).
text_stats(text: str) → anyor an errorThe counts of text: { characters, letters, words, sentences, paragraphs, syllables, reading_seconds, speaking_seconds, flesch_ease, grade_level, avg_words_per_sentence }. Reading is at 238 words a minute, speaking at 150. flesch_ease runs from about 0 (hard: law) to 100 (easy: comics), 60 to 70 being plain English; grade_level is the Flesch-Kincaid US school grade. Syllables are counted for English. Up to 5 MB.
text_word_count(text: str) → intHow many words text has, as a word processor counts them.
text_reading_time(text: str) → str"4 min read" for text, at 238 words a minute; at least "1 min read".
text_syllables(word: str) → intThe syllables of one English word, estimated from its vowels: "readability" is 5.
Get it
$ quillo install text_stats # text_stats.qwer into this folder$ quillo install text_stats --example # and its example, text_stats.qweOr with curl:
$ curl -O https://quillolang.org/plugins/files/text_stats.qwer$ curl -O https://quillolang.org/plugins/files/text_stats.qweThen, in your program, all of it or only what you call:
use text_stats.qweruse text_stats, text_word_count from text_stats // Quillo 0.6: only theseIt uses these crates, which cargo fetches the first time the plugin is built:
Example
// An editor's sidebar: a draft's length, reading time and how easy it is to read.//// quillo run text_stats.qwe then open http://localhost:8080/draftuse "text_stats.qwer"let easy = "The cat sat on the mat. It was a sunny day. The cat was happy."let hard = "Notwithstanding the aforementioned considerations, the committee's deliberations necessitated comprehensive reevaluation of institutional responsibilities."route GET /draft = { easy: text_stats(easy)?, hard: text_stats(hard)?, label: text_reading_time(easy) }route POST /stats = text_stats(request.body)?route GET /syllables ? { word: str } = { word, syllables: text_syllables(word) }$ quillo run text_stats.qwe$ curl 'localhost:8080/draft'$ curl 'localhost:8080/syllables?word=readability'Source
//! Counts of a text for writers and editors: words, sentences, syllables, reading time, and how easy it is to read (Flesch reading ease and grade level).//! version: 1.0.0//!//! [dependencies]use serde_json::{json, Value};/// Syllables in an English word, by its vowel groups: close for most words, never 0.fn syllables(word: &str) -> usize { let w: Vec<char> = word.to_lowercase().chars().filter(|c| c.is_alphabetic()).collect(); if w.is_empty() { return 0; } if w.len() <= 3 { return 1; } let vowel = |c: char| "aeiouy".contains(c); let mut n = 0; let mut prev = false; for &c in &w { let v = vowel(c); if v && !prev { n += 1; } prev = v; } let s: String = w.iter().collect(); // A silent e at the end ("make"), but not "-le" after a consonant ("table"). if s.ends_with('e') && !s.ends_with("le") && !s.ends_with("ee") && n > 1 { n -= 1; } if (s.ends_with("ed") && !s.ends_with("ted") && !s.ends_with("ded")) && n > 1 { n -= 1; } n.max(1)}fn words(text: &str) -> Vec<&str> { text.split(|c: char| c.is_whitespace() || "—–/".contains(c)) .map(|w| w.trim_matches(|c: char| !c.is_alphanumeric())) .filter(|w| !w.is_empty()) .collect()}fn sentences(text: &str) -> usize { let mut n = 0; let mut in_sentence = false; for c in text.chars() { if ".!?…".contains(c) || c == '\n' { if in_sentence { n += 1; } in_sentence = false; } else if c.is_alphanumeric() { in_sentence = true; } } n + in_sentence as usize}fn round(x: f64, places: i32) -> f64 { let p = 10f64.powi(places); (x * p).round() / p}/// The counts of `text`: `{ characters, letters, words, sentences, paragraphs, syllables, reading_seconds, speaking_seconds, flesch_ease, grade_level, avg_words_per_sentence }`. Reading is at 238 words a minute, speaking at 150. `flesch_ease` runs from about 0 (hard: law) to 100 (easy: comics), 60 to 70 being plain English; `grade_level` is the Flesch-Kincaid US school grade. Syllables are counted for English. Up to 5 MB.pub fn text_stats(text: &str) -> Result<Value, String> { if text.len() > 5_000_000 { return Err("text up to 5 MB".into()); } let ws = words(text); let w = ws.len(); let s = sentences(text).max(if w > 0 { 1 } else { 0 }); let syl: usize = ws.iter().map(|x| syllables(x)).sum(); let paragraphs = text.split("\n\n").filter(|p| !p.trim().is_empty()).count(); let (ease, grade) = if w == 0 { (0.0, 0.0) } else { let wps = w as f64 / s as f64; let spw = syl as f64 / w as f64; (206.835 - 1.015 * wps - 84.6 * spw, 0.39 * wps + 11.8 * spw - 15.59) }; Ok(json!({ "characters": text.chars().count(), "letters": text.chars().filter(|c| c.is_alphanumeric()).count(), "words": w, "sentences": s, "paragraphs": paragraphs, "syllables": syl, "reading_seconds": ((w as f64) * 60.0 / 238.0).ceil() as i64, "speaking_seconds": ((w as f64) * 60.0 / 150.0).ceil() as i64, "flesch_ease": round(ease, 1), "grade_level": round(grade.max(0.0), 1), "avg_words_per_sentence": if s == 0 { 0.0 } else { round(w as f64 / s as f64, 1) }, }))}/// How many words `text` has, as a word processor counts them.pub fn text_word_count(text: &str) -> i64 { words(text).len() as i64}/// "4 min read" for `text`, at 238 words a minute; at least "1 min read".pub fn text_reading_time(text: &str) -> String { let m = ((words(text).len() as f64) / 238.0).ceil().max(1.0) as i64; format!("{} min read", m)}/// The syllables of one English word, estimated from its vowels: "readability" is 5.pub fn text_syllables(word: &str) -> i64 { syllables(word) as i64}Related
sentences.qwer · 1.0.0Text split into sentences as a reader would: "Dr.", "p.m.", initials, decimals, "e.g." and quoted questions handled, with abbreviations for seven languages; positions for highlighting, and previews of whole sentences that fit a length.7 views · 9 downloadsHyphenation hyphenation.qwer · 1.0.0Words hyphenated by the rules of 80 languages and spellings, patterns built in: a word's syllables, soft hyphens put in text and HTML for narrow columns and e-mails, and text wrapped at a width with words broken where they may be.6 views · 7 downloadsKeywords keywords.qwer · 1.0.0The keywords and key phrases of a text by RAKE, TextRank or TF-IDF, with stop words of 58 languages left out: tags, SEO and related posts.7 views · 6 downloadsSlugs slug.qwer · 1.0.0Slugs for addresses from titles in any script, unique ones for a blog, and text transliterated to ASCII.7 views · 8 downloadsTypography typography.qwer · 1.0.0Typed text set as a typographer would, by language: curly quotes (“ ”, « », „ “) and apostrophes, en and em dashes, ellipses, ×, ©, French spaces before ; : ! ?, and no widows; in plain text or HTML, code left alone.7 views · 10 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 downloadsThread 0 posts
On Text statistics: questions, tips, corrections, and code that uses it.
No posts yet. The first one opens the thread.