feat(glossy): improve pluralize
This commit is contained in:
2 files changed
+418
-12
No files matched your search
+110
-12
@@ -10,29 +10,127 @@
|
||||
// word: The singular word to pluralize
|
||||
// Returns: The pluralized form of the word, or none if input is none
|
||||
#let __pluralize(word) = {
|
||||
// early exit with invalid input
|
||||
// Early exit for invalid input
|
||||
if word == none {
|
||||
return none
|
||||
}
|
||||
|
||||
// Define helper functions for checking endings
|
||||
// Helper functions for checking endings
|
||||
let ends_with = (suffix) => lower(word).ends-with(suffix)
|
||||
let ends_with_any = (suffixes) => suffixes.any((suffix) => ends_with(suffix))
|
||||
|
||||
// Handle special cases for "es" endings (s, x, z, sh, ch)
|
||||
if ends_with_any(( "s", "x", "z", "sh", "ch" )) {
|
||||
// Map of irregular plurals for common words
|
||||
let irregulars = (
|
||||
"alumna": "alumnae",
|
||||
"alumnus": "alumni",
|
||||
"analysis": "analyses",
|
||||
"appendix": "appendices",
|
||||
"basis": "bases",
|
||||
"cactus": "cacti",
|
||||
"child": "children",
|
||||
"crisis": "crises",
|
||||
"criterion": "criteria",
|
||||
"datum": "data",
|
||||
"foot": "feet",
|
||||
"fungus": "fungi",
|
||||
"goose": "geese",
|
||||
"man": "men",
|
||||
"medium": "media",
|
||||
"mouse": "mice",
|
||||
"nucleus": "nuclei",
|
||||
"oasis": "oases",
|
||||
"person": "people",
|
||||
"phenomenon": "phenomena",
|
||||
"stimulus": "stimuli",
|
||||
"thesis": "theses",
|
||||
"tooth": "teeth",
|
||||
"woman": "women",
|
||||
)
|
||||
|
||||
// Set of plural-only words
|
||||
let plural_only = (
|
||||
"advice",
|
||||
"alumni",
|
||||
"bison",
|
||||
"children",
|
||||
"criteria",
|
||||
"data",
|
||||
"deer",
|
||||
"feet",
|
||||
"fish",
|
||||
"geese",
|
||||
"information",
|
||||
"media",
|
||||
"men",
|
||||
"mice",
|
||||
"money",
|
||||
"moose",
|
||||
"octopi",
|
||||
"octopodes",
|
||||
"people",
|
||||
"scissors",
|
||||
"series",
|
||||
"sheep",
|
||||
"species",
|
||||
"teeth",
|
||||
"trousers",
|
||||
"women",
|
||||
)
|
||||
|
||||
// Irregular suffixes
|
||||
let f_to_ves = ("leaf", "loaf", "calf", "half", "wolf", "thief")
|
||||
let fe_to_ves = ("wife", "knife", "life")
|
||||
let o_to_os = ("photo", "piano", "halo", "radio", "video", "studio", "solo", "taco", "memo", "zero")
|
||||
|
||||
// Convenience
|
||||
let w = lower(word)
|
||||
|
||||
// Check for words already plural
|
||||
if plural_only.contains(w) {
|
||||
return word
|
||||
}
|
||||
|
||||
// Check for irregular singulars
|
||||
if irregulars.keys().contains(w) {
|
||||
return irregulars.at(w)
|
||||
}
|
||||
|
||||
// Standard pluralization rules
|
||||
if ends_with("iz") {
|
||||
word + "zes"
|
||||
} else if ends_with_any(("s", "x", "z", "sh", "ch")) {
|
||||
word + "es"
|
||||
} else if ends_with("y") and not ends_with_any(( "a", "e", "i", "o", "u" )) {
|
||||
// Convert y to ies when y follows a consonant
|
||||
word.slice(0, -1) + "ies"
|
||||
} else if ends_with("y") {
|
||||
if not ends_with_any(("ay", "ey", "iy", "oy", "uy")) {
|
||||
word.slice(0, -1) + "ies"
|
||||
} else {
|
||||
word + "s"
|
||||
}
|
||||
} else if ends_with("f") {
|
||||
// Convert f to ves
|
||||
word.slice(0, -1) + "ves"
|
||||
if f_to_ves.contains(w) {
|
||||
word.slice(0, -1) + "ves"
|
||||
} else {
|
||||
word + "s"
|
||||
}
|
||||
} else if ends_with("fe") {
|
||||
// Convert fe to ves
|
||||
word.slice(0, -2) + "ves"
|
||||
if fe_to_ves.contains(w) {
|
||||
word.slice(0, -2) + "ves"
|
||||
} else {
|
||||
word + "s"
|
||||
}
|
||||
} else if ends_with("us") {
|
||||
word.slice(0, -2) + "i"
|
||||
} else if ends_with("is") {
|
||||
word.slice(0, -2) + "es"
|
||||
} else if ends_with("on") {
|
||||
word + "s"
|
||||
} else if ends_with("o") {
|
||||
if o_to_os.contains(w) {
|
||||
word + "s"
|
||||
} else {
|
||||
word + "es"
|
||||
}
|
||||
} else {
|
||||
// Default case: just add s
|
||||
word + "s"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,308 @@
|
||||
#import "/src/utils.typ": __pluralize
|
||||
|
||||
#let plural_tests = (
|
||||
("BUS", "BUSes"),
|
||||
("Box", "Boxes"),
|
||||
("Buzz", "Buzzes"),
|
||||
("CHURCH", "CHURCHes"),
|
||||
("Lady", "Ladies"),
|
||||
("Leaf", "Leaves"),
|
||||
("Loaf", "Loaves"),
|
||||
("ability", "abilities"),
|
||||
("account", "accounts"),
|
||||
("advice", "advice"),
|
||||
("age", "ages"),
|
||||
("agent", "agents"),
|
||||
("alumna", "alumnae"),
|
||||
("alumni", "alumni"),
|
||||
("alumnus", "alumni"),
|
||||
("answer", "answers"),
|
||||
("appendix", "appendices"),
|
||||
("apple", "apples"),
|
||||
("art", "arts"),
|
||||
("artist", "artists"),
|
||||
("attention", "attentions"),
|
||||
("ax", "axes"),
|
||||
("baby", "babies"),
|
||||
("ball", "balls"),
|
||||
("bank", "banks"),
|
||||
("basis", "bases"),
|
||||
("beauty", "beauties"),
|
||||
("bed", "beds"),
|
||||
("belief", "beliefs"),
|
||||
("berry", "berries"),
|
||||
("bird", "birds"),
|
||||
("book", "books"),
|
||||
("bottle", "bottles"),
|
||||
("box", "boxes"),
|
||||
("boy", "boys"),
|
||||
("branch", "branches"),
|
||||
("brother", "brothers"),
|
||||
("brush", "brushes"),
|
||||
("bus", "buses"),
|
||||
("business", "businesses"),
|
||||
("cactus", "cacti"),
|
||||
("cake", "cakes"),
|
||||
("calf", "calves"),
|
||||
("car", "cars"),
|
||||
("care", "cares"),
|
||||
("carrot", "carrots"),
|
||||
("cart", "carts"),
|
||||
("cat", "cats"),
|
||||
("chair", "chairs"),
|
||||
("chance", "chances"),
|
||||
("change", "changes"),
|
||||
("chef", "chefs"),
|
||||
("chief", "chiefs"),
|
||||
("child", "children"),
|
||||
("church", "churches"),
|
||||
("city", "cities"),
|
||||
("class", "classes"),
|
||||
("cloud", "clouds"),
|
||||
("coach", "coaches"),
|
||||
("comfort", "comforts"),
|
||||
("company", "companies"),
|
||||
("computer", "computers"),
|
||||
("confidence", "confidences"),
|
||||
("cookie", "cookies"),
|
||||
("corpus", "corpuses"),
|
||||
("country", "countries"),
|
||||
("courage", "courages"),
|
||||
("cow", "cows"),
|
||||
("criterion", "criteria"),
|
||||
("culture", "cultures"),
|
||||
("cup", "cups"),
|
||||
("danger", "dangers"),
|
||||
("dart", "darts"),
|
||||
("day", "days"),
|
||||
("deer", "deer"),
|
||||
("desk", "desks"),
|
||||
("development", "developments"),
|
||||
("dish", "dishes"),
|
||||
("dog", "dogs"),
|
||||
("door", "doors"),
|
||||
("dream", "dreams"),
|
||||
("education", "educations"),
|
||||
("egg", "eggs"),
|
||||
("elephant", "elephants"),
|
||||
("employee", "employees"),
|
||||
("energy", "energies"),
|
||||
("entertainment", "entertainments"),
|
||||
("exam", "exams"),
|
||||
("experience", "experiences"),
|
||||
("family", "families"),
|
||||
("farm", "farms"),
|
||||
("father", "fathers"),
|
||||
("fish", "fish"),
|
||||
("floor", "floors"),
|
||||
("flower", "flowers"),
|
||||
("fly", "flies"),
|
||||
("focus", "focuses"),
|
||||
("foot", "feet"),
|
||||
("fork", "forks"),
|
||||
("fox", "foxes"),
|
||||
("freedom", "freedoms"),
|
||||
("friend", "friends"),
|
||||
("future", "futures"),
|
||||
("game", "games"),
|
||||
("garden", "gardens"),
|
||||
("gas", "gases"),
|
||||
("gift", "gifts"),
|
||||
("girl", "girls"),
|
||||
("glass", "glasses"),
|
||||
("goat", "goats"),
|
||||
("goose", "geese"),
|
||||
("grass", "grasses"),
|
||||
("guy", "guys"),
|
||||
("half", "halves"),
|
||||
("hand", "hands"),
|
||||
("hat", "hats"),
|
||||
("head", "heads"),
|
||||
("health", "healths"),
|
||||
("help", "helps"),
|
||||
("hero", "heroes"),
|
||||
("history", "histories"),
|
||||
("holiday", "holidays"),
|
||||
("hope", "hopes"),
|
||||
("horse", "horses"),
|
||||
("house", "houses"),
|
||||
("idea", "ideas"),
|
||||
("image", "images"),
|
||||
("information", "information"),
|
||||
("interest", "interests"),
|
||||
("island", "islands"),
|
||||
("journey", "journeys"),
|
||||
("joy", "joys"),
|
||||
("justice", "justices"),
|
||||
("key", "keys"),
|
||||
("keyboard", "keyboards"),
|
||||
("king", "kings"),
|
||||
("kiss", "kisses"),
|
||||
("kitchen", "kitchens"),
|
||||
("knife", "knives"),
|
||||
("knowledge", "knowledges"),
|
||||
("lady", "ladies"),
|
||||
("lamp", "lamps"),
|
||||
("laptop", "laptops"),
|
||||
("law", "laws"),
|
||||
("leaf", "leaves"),
|
||||
("learning", "learnings"),
|
||||
("leg", "legs"),
|
||||
("letter", "letters"),
|
||||
("life", "lives"),
|
||||
("light", "lights"),
|
||||
("line", "lines"),
|
||||
("lion", "lions"),
|
||||
("loaf", "loaves"),
|
||||
("love", "loves"),
|
||||
("luck", "lucks"),
|
||||
("man", "men"),
|
||||
("map", "maps"),
|
||||
("market", "markets"),
|
||||
("match", "matches"),
|
||||
("memory", "memories"),
|
||||
("milk", "milks"),
|
||||
("money", "money"),
|
||||
("monitor", "monitors"),
|
||||
("month", "months"),
|
||||
("mosquito", "mosquitoes"),
|
||||
("mother", "mothers"),
|
||||
("mountain", "mountains"),
|
||||
("mouse", "mice"),
|
||||
("movie", "movies"),
|
||||
("name", "names"),
|
||||
("nation", "nations"),
|
||||
("neck", "necks"),
|
||||
("night", "nights"),
|
||||
("nucleus", "nuclei"),
|
||||
("ocean", "oceans"),
|
||||
("octopi", "octopi"),
|
||||
("octopodes", "octopodes"),
|
||||
("octopus", "octopuses"),
|
||||
("office", "offices"),
|
||||
("onion", "onions"),
|
||||
("opinion", "opinions"),
|
||||
("orange", "oranges"),
|
||||
("page", "pages"),
|
||||
("park", "parks"),
|
||||
("party", "parties"),
|
||||
("peace", "peaces"),
|
||||
("peach", "peaches"),
|
||||
("pen", "pens"),
|
||||
("person", "people"),
|
||||
("phenomenon", "phenomena"),
|
||||
("phone", "phones"),
|
||||
("photo", "photos"),
|
||||
("piano", "pianos"),
|
||||
("picture", "pictures"),
|
||||
("pig", "pigs"),
|
||||
("place", "places"),
|
||||
("plane", "planes"),
|
||||
("plant", "plants"),
|
||||
("plate", "plates"),
|
||||
("play", "plays"),
|
||||
("player", "players"),
|
||||
("pocket", "pockets"),
|
||||
("potato", "potatoes"),
|
||||
("power", "powers"),
|
||||
("printer", "printers"),
|
||||
("problem", "problems"),
|
||||
("program", "programs"),
|
||||
("proof", "proofs"),
|
||||
("puppy", "puppies"),
|
||||
("queen", "queens"),
|
||||
("quiz", "quizzes"),
|
||||
("radio", "radios"),
|
||||
("rain", "rains"),
|
||||
("respect", "respects"),
|
||||
("responsibility", "responsibilities"),
|
||||
("river", "rivers"),
|
||||
("road", "roads"),
|
||||
("roof", "roofs"),
|
||||
("room", "rooms"),
|
||||
("safe", "safes"),
|
||||
("school", "schools"),
|
||||
("scissors", "scissors"),
|
||||
("sea", "seas"),
|
||||
("series", "series"),
|
||||
("sheep", "sheep"),
|
||||
("ship", "ships"),
|
||||
("shoe", "shoes"),
|
||||
("shop", "shops"),
|
||||
("shore", "shores"),
|
||||
("sister", "sisters"),
|
||||
("sky", "skies"),
|
||||
("snow", "snows"),
|
||||
("solo", "solos"),
|
||||
("son", "sons"),
|
||||
("song", "songs"),
|
||||
("sound", "sounds"),
|
||||
("spoon", "spoons"),
|
||||
("star", "stars"),
|
||||
("station", "stations"),
|
||||
("stone", "stones"),
|
||||
("store", "stores"),
|
||||
("story", "stories"),
|
||||
("street", "streets"),
|
||||
("student", "students"),
|
||||
("studio", "studios"),
|
||||
("success", "successes"),
|
||||
("sun", "suns"),
|
||||
("syllabus", "syllabuses"),
|
||||
("table", "tables"),
|
||||
("taco", "tacos"),
|
||||
("teacher", "teachers"),
|
||||
("team", "teams"),
|
||||
("television", "televisions"),
|
||||
("test", "tests"),
|
||||
("thief", "thieves"),
|
||||
("thing", "things"),
|
||||
("time", "times"),
|
||||
("tomato", "tomatoes"),
|
||||
("tooth", "teeth"),
|
||||
("town", "towns"),
|
||||
("toy", "toys"),
|
||||
("tree", "trees"),
|
||||
("trousers", "trousers"),
|
||||
("truth", "truths"),
|
||||
("umbrella", "umbrellas"),
|
||||
("valley", "valleys"),
|
||||
("victory", "victories"),
|
||||
("video", "videos"),
|
||||
("village", "villages"),
|
||||
("wall", "walls"),
|
||||
("watch", "watches"),
|
||||
("water", "waters"),
|
||||
("wealth", "wealths"),
|
||||
("week", "weeks"),
|
||||
("wife", "wives"),
|
||||
("window", "windows"),
|
||||
("wisdom", "wisdoms"),
|
||||
("wish", "wishes"),
|
||||
("wolf", "wolves"),
|
||||
("woman", "women"),
|
||||
("wood", "woods"),
|
||||
("word", "words"),
|
||||
("work", "works"),
|
||||
("year", "years"),
|
||||
("zero", "zeros"),
|
||||
(none, none),
|
||||
)
|
||||
|
||||
#for (singular, expected) in plural_tests {
|
||||
let result = __pluralize(singular)
|
||||
if result != expected {
|
||||
panic(
|
||||
"Pluralization failed for: "
|
||||
+ (if singular == none { "none" } else { str(singular) })
|
||||
+ ". Expected: "
|
||||
+ (if expected == none { "none" } else { str(expected) })
|
||||
+ ", got: "
|
||||
+ (if result == none { "none" } else { str(result) })
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#set page(height: auto, width: auto, margin: 1em)
|
||||
|
||||
"Success! All pluralizations determined properly!"
|
||||
Reference in new issue
Block a user