diff --git a/ATTRIBUTION.md b/ATTRIBUTION.md index 6297e0ff..30386eac 100644 --- a/ATTRIBUTION.md +++ b/ATTRIBUTION.md @@ -14,7 +14,8 @@ author, source and license. Library code and original assets are under the repos | `crates/cms/tests/data/FOGRA39.txt` (unmodified) | Fogra | [Fogra characterisation data](https://fogra.org/en/downloads/work-tools/characterisation-data), `FOGRA39_to_FOGRA60_v2.zip` | Fogra terms: free use and redistribution, unmodified, with Fogra identified as the source; "FOGRA39" identifies the reference data only and implies no certification, approval or endorsement by Fogra (full text in [NOTICE](NOTICE)) | | `crates/i18n/data/collation.postcard` | Unicode, Inc. (ICU 78.1 collation data, CLDR 48.2.1); generated by `crates/i18n/data/generate-collation.sh` | [ICU](https://github.com/unicode-org/icu/releases/tag/release-78.1rc) | Unicode-3.0 | | `crates/text/assets/hyphen/en-us.dic` | Grady Ward (Moby Hyphenator II), converted by DesignCraft | [Project Gutenberg eBook #3204](https://www.gutenberg.org/ebooks/3204) | Public domain | -| `crates/proof/data/en-core.txt` | Grady Ward (Moby Hyphenator II word list); selected by craft-proof contributors with `crates/proof/examples/en_core.rs`, ranked by word frequency in 50 public-domain Project Gutenberg books | [Project Gutenberg eBook #3204](https://www.gutenberg.org/ebooks/3204), via craft-i18n `language-data/en-us/en-us.dic` | Public domain | +| `crates/proof/data/en-words.dic` | Grady Ward (Moby Hyphenator II word list); break points dropped by craft-proof contributors with `crates/proof/examples/en_words.rs` | [Project Gutenberg eBook #3204](https://www.gutenberg.org/ebooks/3204), via craft-i18n `language-data/en-us/en-us.dic` | Public domain | +| `crates/proof/data/en-extra.txt` | WordCraft contributors (original list, no other dictionary copied) | craft-i18n `language-data/en-us/en-extra.txt` | MIT OR Apache-2.0 | | `crates/text/assets/hyphen/en-us.pat` | DesignCraft contributors, trained from the Moby Hyphenator II list | `crates/text/examples/hyphgen.rs` | CC0-1.0 | | Patterns embedded through `hypher` (optional `craft-text` language features) | hyph-utf8 authors, per language | [tex-hyphen](https://github.com/hyphenation/tex-hyphen), as packaged in [hypher](https://github.com/typst/hypher/tree/main/patterns) | Per file header: LPPL, MIT, BSD-3-Clause, Unlicense or a permit-any-use notice (or a choice including one); Slovak (`hyph-sk.tex`, embedded whenever `hypher/slovak` is on: feature `slovak-gpl`, or another dependency through feature unification) is GPL-2.0-or-later; Spanish (`hyph-es.tex` 5.0, Javier Bezos, CervanTeX) is MIT | | Word-break dictionaries and LSTM models embedded through `icu_segmenter_data` (optional `craft-text` features `thai`, `lao`, `khmer`, `burmese`) | Unicode, Inc. and ICU4X contributors | [ICU4X](https://github.com/unicode-org/icu4x) | Unicode-3.0 | diff --git a/NOTICE b/NOTICE index c2de6bed..1c7ac9c9 100644 --- a/NOTICE +++ b/NOTICE @@ -21,9 +21,10 @@ crates/cms/tests/data/FOGRA39.txt: FOGRA39 characterisation data, distributed un imply certification, approval or endorsement by Fogra." crates/text/assets/hyphen/en-us.dic: public domain, derived from the Moby Hyphenator II list by Grady Ward (Project Gutenberg eBook #3204). -crates/proof/data/en-core.txt: public domain, about 11,000 words of the Moby Hyphenator II list by - Grady Ward (Project Gutenberg eBook #3204), ranked by frequency in public-domain Project - Gutenberg books. +crates/proof/data/en-words.dic: public domain, the words of the Moby Hyphenator II list by Grady + Ward (Project Gutenberg eBook #3204), without its break points. +crates/proof/data/en-extra.txt: MIT OR Apache-2.0, WordCraft contributors' own list of modern + English words (a copy of craft-i18n's language-data/en-us/en-extra.txt). crates/text/assets/hyphen/en-us.pat: CC0-1.0, trained from en-us.dic by DesignCraft's trainer. Hyphenation patterns for other languages, embedded through the hypher crate only when the matching craft-text feature is enabled (none are by default). They come from hyph-utf8, diff --git a/crates/proof/README.md b/crates/proof/README.md index b909bfb3..57d80673 100644 --- a/crates/proof/README.md +++ b/crates/proof/README.md @@ -13,7 +13,7 @@ craft-proof = { git = "https://github.com/storytold/craft-libs", rev = " | Language | Spelling | Grammar | Hyphenation | |---|---|---|---| -| English (en-US, en-GB and the British-spelling Englishes, en-CA) | Moby word list + `en-extra.txt`, dialect variants (`en-variants.txt`); without them the installed Hunspell English, else the built-in core list ([below](#english-is-always-checked)) | yes | Moby list, our patterns, heuristic | +| English (en-US, en-GB and the British-spelling Englishes, en-CA) | Moby word list + `en-extra.txt`, dialect variants (`en-variants.txt`); without them the installed Hunspell English, else the built-in Moby list ([below](#english-is-always-checked)) | yes | Moby list, our patterns, heuristic | | Polish, Portuguese, Italian | the installed Hunspell dictionary | yes | TeX patterns | | Croatian, Turkish, Russian, Czech, Indonesian, Spanish (es, es-MX, es-419, es-UY) | the installed Hunspell dictionary (Russian also `ru-extra.txt`) | yes | Turkish and Russian rules; English fallback otherwise | | German | — | — | TeX patterns | @@ -55,8 +55,9 @@ The word lists and patterns live in [craft-i18n](https://github.com/storytold/cr grammar and the Hunspell languages work as before. - `CRAFT_I18N_REQUIRED=1` (releases) makes a missing directory or file an error. -Tests that pin results of the data are ignored without it; `src/no_data.rs` runs every public -entry point with no data embedded. +Tests that pin results of the data run only when every file is embedded (`craft_proof_data`); +`src/no_data.rs` runs every public entry point when none is (`craft_proof_no_data`). A partial +data folder runs neither set. ### English is always checked @@ -64,23 +65,27 @@ English spelling uses the first of these that is there; `english_source(lang)` s 1. **Embedded:** the Moby word list from `CRAFT_I18N_DIR` (above). Nothing below is used then. 2. **System Hunspell:** an English `.aff`/`.dic` pair in the dictionaries folder or the system - locations, the run's English first (`en_US`, `en_GB`, `en_CA`…), then another English. None on - the web. -3. **Core list:** `data/en-core.txt`, about 11,000 common words built into the crate (inflections - come from the same rules as the Moby list's). It marks only near misses of common words: two - letters swapped (`teh`, `recieved`), or one letter added, missing or changed in a lower-case - word of four letters or more (`definately`). Other words it doesn't know (rare words, names, - terms) are taken as right. + locations, the run's English first (`en_US`, `en_GB`, `en_CA`…), then another English: en-GB + and en-CA use an `en_US` dictionary when no regional one is installed. A file that can't be + read is skipped for the next name or folder; one file is read once for every English that uses + it. Compounding (`COMPOUNDMIN`, `COMPOUNDRULE`…, used by English dictionaries only for + ordinals) and `OCONV` are ignored for English rather than refused. None on the web. +3. **Built-in list:** `data/en-words.dic`, the whole Moby word list (about 165,000 words, 344 KB + compressed, words only) built into the crate, with `data/en-extra.txt` (WordCraft's supplement + of modern words, a copy of craft-i18n's) and the same inflection rules as the embedded list. A + word it doesn't know is misspelled. Suggestions are the words one edit away (swap, missing, + added or changed letter), looked up in the list, for words of up to 32 letters. A dictionary that is there but can't be read (encoding, size, parse error, no words) is skipped, and `dictionary_load_error(lang)` gives the reason; it never panics. Text in other languages is never checked against English: a language without its dictionary has no spelling marks. -The core list is public domain. Every word is from the Moby Hyphenator II list by Grady Ward -(Project Gutenberg eBook #3204, as in craft-i18n's `language-data/en-us/en-us.dic`); 50 -public-domain Project Gutenberg books only rank them by how often they are written in lower case. -No other word list or dictionary was used. Regenerate with -`cargo run -p craft-proof --example en_core -- 12000 crates/proof/data/en-core.txt `. +`data/en-words.dic` is public domain: the Moby Hyphenator II list by Grady Ward (Project Gutenberg +eBook #3204), from craft-i18n's `language-data/en-us/en-us.dic` with its break points dropped. +Regenerate with +`cargo run -p craft-proof --example en_words -- /language-data/en-us/en-us.dic crates/proof/data/en-words.dic`. +`data/en-extra.txt` is WordCraft contributors' own list (MIT OR Apache-2.0); keep it in step with +craft-i18n's copy. ## Check diff --git a/crates/proof/data/en-core.txt b/crates/proof/data/en-core.txt deleted file mode 100644 index ff4bbbb5..00000000 --- a/crates/proof/data/en-core.txt +++ /dev/null @@ -1,11372 +0,0 @@ -# English core word list: the built-in fallback when neither the embedded Language data nor a -# system Hunspell English dictionary is available (see crates/proof/README.md). -# Public domain: every word is from the Moby Hyphenator II list by Grady Ward (Project -# Gutenberg eBook #3204), ranked by frequency in public-domain Project Gutenberg books. -# Generated by `cargo run -p craft-proof --example en_core`. Do not edit by hand. -aback -abandon -abandoned -abandonment -abasement -abate -abated -abatement -abhor -abhorred -abhorrence -abide -abiding -ability -abject -ablaze -able -abnormal -aboard -abode -abolition -abominable -abominably -abominate -abomination -abound -abounding -about -above -abreast -abroad -abrupt -abruptly -abruptness -absence -absent -absolute -absolutely -absolved -absorb -absorbed -absorbing -absorption -abstain -abstinence -abstract -abstracted -abstraction -absurd -absurdity -absurdly -abundance -abundant -abundantly -abuse -abused -abusing -abyss -academic -acceded -accent -accept -acceptable -acceptance -accepted -access -accessible -accession -accessory -accident -accidental -accidentally -accommodate -accommodated -accommodation -accompanied -accompaniment -accompany -accompanying -accomplice -accomplish -accomplished -accomplishment -accord -accordance -accorded -according -accordingly -accosted -account -accountable -accounting -accumulate -accumulated -accumulating -accumulation -accuracy -accurate -accurately -accursed -accusation -accuse -accused -accusing -accustom -accustomed -ache -achieve -achieved -achievement -aching -acid -acknowledge -acknowledged -acknowledging -acknowledgment -acquaintance -acquainted -acquiescence -acquire -acquired -acquiring -acquisition -acquit -acquitted -acre -acres -acrid -across -act -acted -acting -action -active -actively -activity -actor -actress -acts -actual -actually -actuated -acute -acutely -acuteness -ad -adapt -adapted -add -added -addicted -adding -addition -additional -address -addressed -addressing -adequate -adequately -adhere -adhered -adhering -adieu -adieus -adjacent -adjective -adjoining -adjust -adjusted -adjusting -administer -administered -administering -administration -admirable -admirably -admiral -admiration -admire -admired -admirer -admiring -admiringly -admission -admit -admittance -admitted -admitting -admonition -ado -adopt -adopted -adoption -adoration -adore -adored -adorn -adorned -adrift -adult -advance -advanced -advancement -advances -advancing -advantage -advantageous -advent -adventure -adventurous -adversary -adversity -advertise -advertised -advertisement -advertising -advice -advisable -advise -advised -adviser -advocate -afar -affability -affable -affair -affairs -affect -affectation -affected -affecting -affection -affectionate -affectionately -affinity -affirm -affirmative -affliction -afford -affright -affront -afire -afloat -afoot -afore -aforesaid -afraid -afresh -after -afternoon -afternoons -afterward -afterwards -again -against -age -aged -agency -agent -ages -aggravated -aggravating -aggravation -aggrieved -aghast -agile -agility -agitated -agitation -ago -agonised -agonizing -agony -agree -agreeable -agreeably -agreed -agreeing -agreement -agricultural -agriculture -ague -ahead -aid -aids -ailing -aim -aimlessly -ain -air -airily -airing -airs -airy -aisle -ajar -akin -alacrity -alarm -alas -albeit -ale -alert -alertness -alien -alienated -alight -alighted -alighting -alike -alive -all -allay -allayed -alleged -alley -alliance -allied -allies -allotted -allow -allowable -allowance -allowed -alloy -allude -alluded -alluding -alluring -allusion -ally -almost -alms -aloft -alone -along -alongside -aloof -aloud -alphabet -already -also -altar -alter -alteration -altercation -altered -alternate -alternately -alternating -alternative -although -altogether -always -am -amateur -amaze -amazed -amazement -amazing -amazingly -amber -ambition -ambitious -ambush -amenable -amend -amendment -amends -amiability -amiable -amiably -amid -amidst -amiss -ammunition -among -amongst -amorous -amount -ample -amply -amuse -amused -amusement -amusing -an -analogous -analogy -analysis -anatomy -ancestor -ancestral -anchor -ancient -and -anecdote -anew -angel -angelic -angels -anger -angle -angles -angrily -angry -anguish -animal -animate -animated -animating -animation -animosity -ankle -annihilate -annihilated -annihilation -anniversary -announce -announced -announcement -announcing -annoy -annoyance -annoyed -annoying -annual -annum -anointed -anon -anonymous -another -answer -answered -ant -antagonist -antagonistic -anticipate -anticipated -anticipating -anticipation -antidote -antipathy -antique -antiquity -anxiety -anxious -anxiously -any -anybody -anyhow -anyone -anything -anyway -anywhere -apart -apartment -apathy -ape -aperture -apex -apiece -apologetic -apologetically -apologise -apologize -apology -apoplectic -apoplexy -apothecary -appalled -appalling -apparatus -apparel -apparent -apparently -apparition -appeal -appealing -appear -appearance -appearing -appease -appeased -appellation -appetite -applauded -applause -apple -apples -applicable -application -applied -apply -applying -appoint -appointed -appointment -appreciate -appreciated -appreciation -appreciative -apprehend -apprehension -apprehensive -apprenticeship -approach -approached -approbation -appropriate -appropriated -approval -approve -approved -approving -approvingly -apron -apropos -apt -aptitude -arbitrary -arch -arched -arches -architect -architecture -archly -archway -ardent -ardently -ardour -arduous -are -area -argue -argued -arguing -argument -argumentative -arid -aright -arise -arisen -aristocracy -aristocratic -arithmetic -ark -arm -armchair -armed -armor -armour -arms -army -aromatic -arose -around -arouse -aroused -arrange -arranged -arrangement -arranging -array -arrayed -arrears -arrest -arresting -arrival -arrive -arrived -arriving -arrogance -arrogant -arrow -arrows -art -arteries -artful -article -articles -articulate -articulated -artifice -artificial -artificially -artillery -artist -artistic -artless -arts -as -ascend -ascending -ascent -ascertain -ascertained -ascribed -ash -ashamed -ashes -ashore -ashy -aside -ask -askance -askew -asking -aslant -asleep -asparagus -aspect -asperity -aspiration -aspire -aspired -aspiring -ass -assail -assailant -assassin -assault -assemblage -assemble -assembled -assembly -assent -assert -asserted -assertion -asses -assiduity -assiduous -assiduously -assign -assigned -assist -assistance -assistant -assisted -associate -associated -association -assorted -assuage -assume -assumed -assuming -assumption -assurance -assure -assured -assuredly -assuring -astir -astonish -astonishing -astonishment -astounding -astray -astride -asunder -asylum -at -ate -athletic -athwart -atmosphere -atom -atone -atonement -atrocious -attach -attached -attachment -attack -attain -attained -attempt -attempted -attend -attendance -attendant -attended -attending -attention -attentive -attentively -attested -attic -attire -attired -attitude -attorney -attract -attraction -attractive -attribute -attributed -attributing -auction -audacious -audacity -audible -audibly -audience -auditor -aught -augment -augmented -augur -august -aunt -auspices -auspicious -austere -austerity -authentic -author -authoritative -authority -authorized -authors -autumn -autumnal -auxiliary -avail -available -avarice -avaricious -avenge -avenged -avenger -avenging -avenue -average -averse -aversion -avert -avoid -avoidance -avow -avowal -avowed -await -awake -awaken -awakened -awakening -awaking -awarded -aware -away -awe -awed -awful -awfully -awhile -awkward -awkwardly -awkwardness -awoke -awry -axe -axes -aye -babbling -babe -babies -baby -bachelor -bachelors -back -backbone -backed -background -backing -backs -backward -backwards -bacon -bad -bade -badge -badly -badness -bag -baggage -bags -bailiff -bait -bake -baked -baker -baking -balance -balanced -balancing -balcony -bald -ball -ballad -balloon -ballroom -balls -balm -balmy -balustrade -bamboo -band -bandage -bandaged -bands -bane -bang -banish -banished -banishment -banisters -bank -banker -banking -bankrupt -banks -banner -banquet -baptism -baptized -bar -barbarian -barbarism -barbarous -barber -bare -barefoot -bareheaded -barely -bargain -bargaining -barge -bark -barking -barley -barn -baron -barracks -barred -barrel -barren -barricade -barrier -barring -barrow -bars -base -basely -basement -baseness -bashful -bashfully -bashfulness -basin -basis -bask -basket -bass -bastard -bat -batch -bath -bathe -bathing -bats -battalion -battered -battery -battle -bay -be -beach -beacon -beaded -beadle -beads -beak -beam -beaming -bean -bear -beard -bearded -bearer -bearers -bearing -bearings -beast -beastly -beat -beaten -beating -beau -beautiful -beautifully -beauty -beaver -became -because -become -becoming -bed -bedchamber -bedclothes -bedding -bedroom -beds -bedside -bedstead -bedtime -bee -beech -beef -been -beer -beetle -befall -befallen -befell -befitting -before -beforehand -befriend -beg -began -beggar -beggarly -begging -begin -beginning -begone -begotten -beguile -beguiled -begun -behalf -behave -behaved -behavior -behaviour -beheld -behind -behold -beholding -being -belated -belfry -belied -belief -believe -believed -believer -believing -bell -belle -bellows -bells -belly -belong -belonging -belongings -beloved -below -belt -bench -bend -bending -bends -beneath -benediction -benefactor -beneficent -beneficial -benefit -benefited -benevolence -benevolent -bent -bequeath -bequest -berries -berth -beseech -beseeching -beset -besetting -beside -besides -besought -bespeak -bespoke -best -bestow -bestowed -bet -bethought -betimes -betook -betray -betraying -betrothed -better -between -betwixt -beware -bewilderment -beyond -bias -bid -bidden -bidding -bide -bier -big -bigger -biggest -bile -bilious -bill -billiard -billows -bind -binding -biography -birch -bird -birds -birth -birthday -biscuit -bishop -bit -bite -biting -bitten -bitter -bitterly -bitterness -black -blackguard -blackness -blacksmith -blade -blame -blamed -blameless -blaming -bland -blandly -blank -blanket -blankly -blasphemous -blasphemy -blast -blasted -blaze -blazing -bleak -bleed -bleeding -blemish -blend -blended -blending -bless -blessed -blessing -blest -blew -blight -blind -blinded -blindfold -blinding -blindly -blindness -blinds -blinking -bliss -blissful -bloated -block -blocked -blockhead -blond -blood -blooded -bloodhound -bloodless -bloodshot -bloody -bloom -bloomed -blooming -blossom -blot -blotted -blotting -blow -blowing -blown -blue -bluff -bluish -blunder -blunt -bluntly -blush -board -boarder -boarding -boast -boastful -boat -bob -bobbing -bodice -bodies -bodily -body -bog -boil -boiled -boiler -boiling -boisterous -bold -boldly -boldness -bolt -bond -bondage -bonds -bone -bones -bonnet -bony -book -bookcase -books -boom -boon -boot -booted -boots -booty -border -bordered -borders -bore -born -borne -borrow -borrowing -bosom -both -bother -bottle -bottom -bottoms -boudoir -bough -bought -bounce -bouncing -bound -boundary -bounded -boundless -bounds -bounty -bouquet -bout -bow -bower -bowing -bowl -bowling -bowls -box -boxing -boy -boyhood -boyish -boys -brace -bracelet -bracelets -braces -bracing -braided -brain -branch -brand -branded -brandy -brass -brat -bravado -brave -bravely -braver -bravery -bravest -brazen -breach -bread -breadth -break -breakfast -breaking -breast -breasted -breath -breathe -breathing -breathless -breathlessly -bred -breeches -breed -breeding -breeze -brethren -brevity -brewing -bribe -brick -bridal -bride -bridegroom -bridge -bridges -bridle -brief -briefly -bright -brightly -brightness -brilliancy -brilliant -brilliantly -brim -bring -bringing -brink -brisk -briskly -brittle -broad -broadly -brocade -broke -broken -bronze -brooch -brood -brook -broom -broth -brother -brotherhood -brotherly -brothers -brought -brow -brown -bruise -brush -brushed -brusquely -brutal -brutality -brutally -brute -bubble -bucket -buckle -bud -budge -buff -bug -build -builder -building -built -bulk -bulky -bull -bullet -bully -bulwark -bump -bunch -bunches -bundle -burden -burdened -bureau -burglar -burial -buried -burly -burn -burned -burning -burns -burnt -burst -bursting -bury -burying -bush -bushel -bushy -busied -busily -business -bust -bustle -bustled -busy -but -butcher -butler -butt -butter -butterflies -butterfly -button -buttoned -buttons -buy -buying -buys -buzz -by -bye -bygone -cab -cabbage -cabin -cabinet -cabman -cadence -cage -cake -calamity -calculate -calculated -calculating -calculation -calendar -calf -calico -call -calling -callous -calm -calmly -calmness -calves -cambric -came -camel -camp -campaign -can -canal -canary -candid -candidate -candidly -candle -candlelight -candlestick -candour -cane -cannibal -cannon -cannot -canopy -cant -canter -canvas -cap -capable -capacious -capacity -cape -caper -capers -capital -caprice -capricious -caps -captain -captivated -captivating -captive -captivity -capture -captured -capturing -car -caravan -carcass -card -cardboard -cardinal -cards -care -career -careful -carefully -careless -carelessly -carelessness -caress -careworn -cargo -caricature -caring -carpenter -carpet -carpeted -carriage -carried -carrier -carrion -carry -carrying -cart -carve -carving -case -casement -cash -cashier -cask -casket -cast -caste -casting -castle -casual -casually -cat -catalogue -catastrophe -catch -catching -catechism -category -cathedral -cattle -caught -cause -causing -caution -cautioned -cautious -cautiously -cavalier -cavalry -cave -cavern -cease -ceaseless -ceasing -ceiling -celebrate -celebrated -celebration -celebrity -celestial -cell -cellar -cemetery -censure -cent -central -centre -centred -century -ceremonies -ceremonious -ceremony -certain -certainly -certainty -certificate -cessation -chafing -chagrin -chain -chair -chairs -chaise -chalk -challenge -challenged -chamber -chambers -chamois -champagne -champion -chance -chandelier -change -changeable -changes -changing -channel -chaos -chaotic -chap -chapel -chaplain -chaps -chapter -character -characteristic -characterized -charge -charged -charging -chariot -charitable -charity -charm -charming -charmingly -chart -chase -chasing -chasm -chaste -chat -chatted -chatter -chatting -cheap -cheaply -cheat -check -checked -checking -checks -cheek -cheer -cheerful -cheerfully -cheerfulness -cheerily -cheerless -cheers -cheery -cheese -chemical -chemist -chemistry -cheque -cherish -cherished -cherry -chess -chest -chestnut -chew -chewing -chicken -chickens -chief -chiefly -child -childhood -childish -childless -childlike -children -chill -chilly -chimney -chin -china -chink -chintz -chip -chisel -chiselled -chivalrous -chivalry -chocolate -choice -choir -choke -choking -choose -chop -chopping -chops -chord -chorus -chose -chosen -chronic -chubby -chuckle -chuckled -chuckling -church -churchyard -cigar -cigarette -cipher -circle -circuit -circular -circulated -circulating -circulation -circumference -circumspect -circumspection -circumstance -circumstanced -circumstances -circumstantial -circus -citadel -cited -cities -citizen -citizens -city -civil -civilian -civilisation -civilised -civility -civilization -civilized -civilly -clad -claim -claiming -clammy -clamorous -clang -clap -clapping -claret -clash -clasp -clasping -class -classes -classic -classical -clatter -clause -claw -clay -clean -cleaner -cleaning -cleanliness -cleanly -cleanse -clear -clearer -clearing -clearly -clearness -cleft -clemency -clergy -clergyman -clerical -clerk -clever -cleverly -cleverness -click -client -cliff -climate -climax -climb -climbing -cling -clinging -clink -clipped -cloak -clock -close -closed -closely -closeness -closer -closest -closet -closing -cloth -clothe -clothes -clothing -clotted -cloud -clouded -cloudless -clouds -cloudy -clover -clown -club -clue -clump -clumsily -clumsy -clung -cluster -clustered -clutch -co -coach -coachman -coal -coarse -coarsely -coarseness -coarser -coarsest -coast -coat -coated -coax -coaxing -cobbler -cobwebs -cock -cocking -code -coffee -coffin -cogitation -coherent -coil -coin -coincidence -cold -coldly -coldness -collapse -collapsed -collar -collared -colleague -collect -collected -collection -college -collision -colonel -colony -color -colored -colors -colossal -colour -column -comb -combat -combination -combinations -combine -combined -come -comedy -comely -comer -comes -comfort -comfortable -comfortably -comforter -comfortless -comforts -comic -comical -coming -command -commanded -commander -commanding -commence -commenced -commencement -commencing -commend -commendation -commended -comment -commerce -commercial -commiseration -commission -commissioned -commissioner -commit -committed -committee -committing -commodious -common -commoner -commonly -commonplace -commotion -commune -communicate -communicated -communicating -communication -communications -communicative -communing -communion -community -compact -companion -companionship -company -comparable -comparative -comparatively -compare -compared -comparing -comparison -compass -compassion -compassionate -compassionately -compatible -compel -compelled -compelling -compensate -compensated -compensation -competent -competition -complacency -complacent -complacently -complain -complaint -complete -completed -completely -completeness -completing -completion -complex -complexion -complexioned -compliance -complicated -complied -compliment -complimentary -comply -compose -composed -composedly -composing -composition -composure -compound -comprehend -comprehended -comprehending -comprehension -comprehensive -compressed -comprised -compromise -compromised -compromising -compulsion -compulsory -compunction -computation -comrade -conceal -concealed -concealing -concealment -conceded -conceit -conceited -conceivable -conceive -conceived -conceiving -concentrate -concentrated -concentrating -concentration -conception -concern -concerned -concerning -concert -concession -conciliate -conciliating -concise -conclude -concluded -concluding -conclusion -conclusive -conclusively -concourse -concrete -concurrence -concussion -condemn -condemnation -condemned -condemning -condensed -condescend -condescending -condescension -condition -conditioned -condolence -conduce -conducive -conduct -conductor -confer -conference -conferences -conferred -conferring -confess -confessed -confession -confessor -confidant -confide -confided -confidence -confident -confidential -confidentially -confidently -confiding -confine -confined -confinement -confirm -confirmation -confirmed -conflagration -conflict -conform -confound -confounded -confront -confuse -confused -confusedly -confusing -confusion -congenial -congratulate -congratulated -congratulating -congratulation -congratulations -congregation -conjecture -conjectured -conjugal -conjunction -conjure -conjured -connect -connected -connecting -connection -connexion -connoisseur -conquer -conquered -conqueror -conquest -conscience -conscientious -conscientiously -conscious -consciously -consciousness -consecrated -consecutive -consent -consenting -consequence -consequences -consequent -consequently -conservative -conservatory -consider -considerable -considerably -considerate -considerately -consideration -considered -considering -consist -consistency -consistent -consolation -consolatory -console -consoled -consoling -consort -conspicuous -conspiracy -conspired -constable -constancy -constant -constantly -consternation -constitute -constituted -constitution -constitutional -constrained -constraint -construct -constructed -construction -consult -consultation -consulting -consume -consumed -consuming -consummate -consummation -consumption -contact -contagion -contagious -contain -contained -contemplate -contemplated -contemplating -contemplation -contemporaries -contemporary -contempt -contemptible -contemptuous -contemptuously -contend -content -contented -contentedly -contention -contentment -contest -contiguous -continent -contingency -contingent -continual -continually -continuance -continuation -continue -continued -continuing -continuous -continuously -contorted -contract -contracted -contraction -contradict -contradiction -contradictory -contrary -contrast -contrasted -contribute -contributed -contributing -contribution -contrition -contrivance -contrive -contrived -contriving -control -controlled -controlling -convalescence -convalescent -convenience -convenient -conveniently -convent -conventional -conversant -conversation -conversational -converse -conversed -conversing -conversion -convert -converted -convex -convey -conveyance -conveyed -convict -convicted -conviction -convince -convinced -convincing -convivial -convulsed -convulsion -convulsive -convulsively -cook -cookery -cooking -cooks -cool -cooled -cooler -cooling -coolly -coolness -cope -copied -copies -copious -copper -copy -copying -coquetry -coquettish -coral -cord -cordial -cordiality -cordially -cords -core -cork -corkscrew -corn -corner -cornered -coronation -coroner -corporal -corps -corpse -corpulent -correct -corrected -correcting -correction -correctly -correctness -correspond -correspondence -correspondent -corridor -corroborated -corrupt -corruption -cost -costly -costume -cot -cottage -cotton -couch -cough -could -council -counsel -counsellor -count -counted -countenance -counter -counteract -counterfeit -counterpane -counterpart -counting -countless -countries -country -countryman -countryside -county -couple -coupled -courage -courageous -course -courses -court -courted -courteous -courteously -courtesy -courtier -courtly -courts -courtship -courtyard -cousin -cousins -cove -cover -covered -covering -coverlet -covers -covert -covet -cow -coward -cowardice -cowardly -coxcomb -crab -crack -cracked -cracking -crackling -cradle -craft -crafty -craggy -cramp -cramped -crape -crash -crashing -cravat -craving -crawl -crawling -crazed -crazy -creak -cream -create -created -creating -creation -creative -creature -credible -credit -creditable -creditor -creed -creek -creep -creeping -creeps -crept -crest -crestfallen -crevice -crew -crib -cricket -cried -crime -criminal -crimson -cringing -cripple -crisis -crisp -critical -critically -criticise -criticism -crockery -crocodile -crooked -crop -cross -crossed -crosses -crossing -crow -crowd -crowded -crowing -crown -crowned -crowning -crucified -crude -cruel -cruelly -cruelty -crumb -crumble -crumbled -crumbling -crumbs -crumpled -crush -crushing -crust -cry -crying -crystal -cub -cuff -cuffs -culinary -culprit -cultivate -cultivated -cultivation -culture -cumbrous -cunning -cunningly -cup -cupboard -cur -curate -curb -cure -curiosity -curious -curiously -curl -curling -curly -currant -current -curse -cursed -curses -cursing -curtain -curtains -curtly -curtsey -curve -curving -cushion -cushioned -custody -custom -customary -customer -customs -cut -cuts -cutting -cylinder -cynical -dab -dad -dagger -daily -daintily -dainty -dairy -dale -dam -damage -damaged -damask -dame -damn -damned -damp -damsel -dance -dancers -dancing -dandy -danger -dangerous -dangerously -dangling -dank -dare -dares -daresay -daring -dark -darken -darkened -darkly -darkness -darling -darned -dart -darts -dash -dashed -dashing -data -date -dated -dates -daughter -daughters -dawn -day -daybreak -daylight -days -daytime -de -dead -deaden -deadly -deaf -deafened -deafening -deal -dealer -dealing -dealings -dealt -dear -dearly -death -deathbed -deathlike -deathly -debased -debate -debated -debauchery -debt -decanter -decay -decease -deceased -deceit -deceitful -deceive -deceived -deceiving -decency -decent -decently -deception -decide -decided -decidedly -deciding -decipher -decision -decisive -decisively -deck -decked -decks -declaration -declare -declared -declaring -decline -declined -declining -decorated -decoration -decorous -decorum -decree -decreed -decrepit -dedicated -deduce -deduced -deduction -deed -deem -deep -deeply -deer -defaced -default -defeat -defeated -defect -defective -defence -defenceless -defend -defended -defensive -defer -deference -deferential -deferred -defiance -defiant -defiantly -deficiency -deficient -defiled -define -defined -definite -definitely -definition -deformed -deformity -deftly -defy -degenerate -degenerated -degradation -degrade -degraded -degrading -degree -deity -dejected -dejection -delay -delayed -deliberate -deliberated -deliberately -deliberating -deliberation -delicacy -delicate -delicately -delicious -deliciously -delight -delighted -delightful -delightfully -delirious -delirium -deliver -deliverance -delivered -delivery -delude -deluded -deluge -delusion -demand -demanding -demolished -demon -demonstrated -demonstration -demonstrative -demure -den -denial -denied -denominated -denote -denoted -denounce -denounced -denouncing -dens -dense -density -dentist -deny -denying -depart -departed -department -departure -depend -dependence -dependent -depending -depict -depicted -deplorable -deplore -deplored -deportment -depose -deposed -deposit -depraved -depravity -depressed -depression -deprive -deprived -depriving -depth -deputy -deranged -derision -derive -derived -des -descend -descendant -descent -describe -described -describing -descried -description -descriptive -desert -deserted -desertion -deserve -deserved -deservedly -deserving -design -designated -designation -designed -designing -desirable -desire -desired -desiring -desirous -desist -desk -desolate -desolation -despair -despairing -despairingly -despatch -desperate -desperately -desperation -despicable -despise -despised -despising -despite -despondency -despondent -despot -despotic -dessert -destination -destined -destiny -destitute -destitution -destroy -destroyed -destroyer -destroying -destruction -destructive -detach -detached -detachment -detail -detailed -detain -detect -detection -detective -determination -determine -determined -determining -deterred -detest -detestable -detestation -detriment -deuce -devastation -develop -developed -developing -development -deviation -device -devil -devilish -devils -devise -devised -devising -devoid -devote -devoted -devotedly -devoting -devotion -devour -devouring -devoutly -dew -dewy -dexterity -dexterously -diabolical -dial -dialect -dialogue -diameter -diametrically -diamond -diary -dice -dictate -dictation -dictionary -did -didst -die -dies -diet -differ -difference -different -differently -difficult -difficulties -difficulty -diffidence -diffident -diffuse -diffused -dig -digest -digestion -digger -digging -dignified -dignity -dilapidated -dilated -dilating -dilemma -diligence -diligent -diligently -dim -diminish -diminished -diminution -diminutive -dimly -din -dine -dingy -dining -dinner -dint -dip -dipping -dire -direct -directed -directing -direction -directions -directly -directness -director -dirt -dirty -disabled -disadvantage -disagree -disagreeable -disagreeably -disagreement -disappear -disappearance -disappoint -disappointed -disappointment -disapprobation -disapproval -disapprove -disapproved -disarm -disaster -disastrous -disbelieve -discern -discernible -discerning -discernment -discharge -disciple -disciples -discipline -disciplined -disclose -disclosed -disclosing -disclosure -discomfiture -discomfort -discomposed -discomposure -disconcerted -disconsolate -disconsolately -discontent -discontented -discord -discourage -discouraged -discouragement -discouraging -discourse -discoursed -discoursing -discover -discoveries -discovery -discredit -discreet -discreetly -discretion -discrimination -discuss -discussed -discussion -disdain -disdainful -disdainfully -disease -diseased -disengaged -disengaging -disfigured -disgrace -disgraced -disgraceful -disguise -disguised -disgust -disgusted -disgusting -dish -dishevelled -dishonest -disinclination -disinclined -disinterested -disinterestedness -disjointed -disk -dislike -disliked -dislocated -dismal -dismally -dismay -dismiss -dismissal -dismount -disobedience -disobey -disorder -disordered -disorderly -disparagement -disparity -dispatch -dispel -dispelled -dispense -dispensed -dispensing -disperse -dispersed -dispirited -displaced -display -displayed -displease -displeased -displeasure -disposal -dispose -disposed -disposing -disposition -dispute -disputed -disputing -disquiet -disquietude -disregard -disreputable -disrespect -disrespectful -dissatisfaction -dissatisfied -dissecting -dissent -dissimilar -dissipated -dissipation -dissolute -dissolution -dissolve -dissolved -dissolving -dissuade -distance -distant -distantly -distasteful -distinct -distinction -distinctive -distinctly -distinctness -distinguish -distinguishable -distinguished -distinguishing -distorted -distract -distracted -distractedly -distraction -distress -distressed -distribute -distributed -distributing -distribution -district -distrust -distrustful -disturb -disturbance -disturbed -disturbing -disuse -disused -ditch -divan -dive -diver -diverged -divers -diversified -diversion -diversity -divert -diverting -divide -divided -dividing -divine -divined -divinely -diving -divinity -division -divorce -dizzy -do -docile -dock -doctor -doctrine -document -dodge -does -dog -dogged -doggedly -dogs -doing -doings -doleful -dolefully -doll -domain -dome -domestic -domesticated -dominant -dominion -dominions -don -done -donkey -doom -door -doorstep -doorway -dormant -dose -dost -dot -doth -dotted -double -doubles -doubling -doubly -doubt -doubtful -doubtfully -doubting -doubtless -dove -down -downcast -downfall -downhill -downright -downs -downstairs -downward -downwards -downy -doze -dozen -dozens -dozing -drab -draft -drag -dragging -dragon -drain -drama -dramatic -drank -drapery -draught -draw -drawback -drawer -drawing -drawings -drawn -dread -dreadful -dreadfully -dream -dreamer -dreamily -dreaming -dreams -dreamt -dreamy -dreary -dregs -dress -dresser -dressing -dressmaker -drew -dried -drift -drill -drily -drink -drinking -drip -dripping -drive -driven -driver -driving -droll -drone -droning -droop -drop -dropping -drops -drove -drown -drowning -drowsily -drowsiness -drowsy -drudge -drug -drum -drunk -drunkard -drunken -drunkenness -dry -drying -dryly -du -dubious -dubiously -duck -ducks -due -duel -duet -dug -duke -dull -dulness -duly -dumb -dummy -dun -dungeon -dupe -duplicate -durable -duration -during -durst -dusk -dusky -dust -dusted -dusting -dusty -dutiful -dutifully -duty -dwarf -dwell -dwelling -dwelt -dye -dying -dynasty -each -eager -eagerly -eagerness -eagle -ear -earlier -earliest -early -earn -earned -earnest -earnestly -earnestness -earning -earth -earthly -earthquake -earthy -ease -easier -easiest -easily -east -easterly -eastern -eastward -easy -eat -eatable -eaten -eating -eats -eaves -ebb -ebony -ebullition -eccentric -eccentricity -ecclesiastical -echo -echoed -echoes -echoing -eclipsed -economic -economical -economy -ecstasy -ecstatic -ecstatically -ed -eddy -eddying -edge -edged -edging -edifice -edifying -edition -editor -educate -educated -educating -education -educational -eel -efface -effaced -effect -effected -effective -effects -effectual -effectually -efficacy -efficiency -efficient -effigy -effort -effusion -egg -eggs -egotism -egotistical -eight -eighteen -eighteenth -eighth -eighty -either -ejaculated -ejaculation -elaborate -elaborately -elapsed -elastic -elasticity -elated -elbow -elder -elderly -eldest -elect -elected -election -electric -electricity -electrified -elegance -elegant -elegantly -element -elemental -elementary -elephant -elevate -elevated -elevating -elevation -eleven -eleventh -eligible -elm -elongated -eloquence -eloquent -eloquently -else -elsewhere -elude -eluded -elusive -emaciated -embankment -embarrassment -emblem -embodied -embrace -embraced -embracing -embroidery -embryo -emerald -emerge -emerged -emergency -emerging -emigrant -eminence -eminent -eminently -emotion -emotional -emperor -emphasis -emphatic -empire -employ -employed -employer -employment -emptied -emptiness -empty -emptying -emulation -en -enable -enabling -enacted -enchanter -enchanting -enchantment -enclosed -enclosing -enclosure -encounter -encourage -encouraged -encouragement -encouraging -encouragingly -encumbrance -end -endanger -ended -ending -endless -endowed -endurance -endure -endured -enduring -enemy -energetic -energetically -energy -enforce -enforced -engage -engaged -engagement -engaging -engine -engraved -engrossed -engrossing -enhance -enhanced -enigma -enigmatical -enjoy -enjoyment -enlarge -enlarged -enlargement -enlarging -enlighten -enlightened -enlightenment -enlist -enmity -ennui -enormous -enormously -enough -enraged -enraptured -enrolled -enslaved -ensue -ensued -ensuing -ensure -entangled -enter -entered -entering -enterprise -entertain -entertained -entertainer -entertaining -entertainment -enthusiasm -enthusiast -enthusiastic -enthusiastically -enticed -entire -entirely -entitle -entitled -entrails -entrance -entreat -entreaties -entreaty -entry -enumerated -envelope -enveloped -enviable -envied -envious -environment -environs -envy -envying -episode -epistle -epithet -epoch -equal -equality -equalled -equally -equals -equanimity -equestrian -equilibrium -equipage -equipped -equitable -equity -equivalent -era -erase -ere -erect -erected -err -errand -erring -erroneous -error -eruption -es -escape -escaped -escaping -escort -escorted -especial -especially -essay -essayed -essence -essential -essentially -est -establish -established -establishment -estate -estates -esteem -esteemed -estimable -estimate -estimated -estimation -estranged -et -etc -eternal -eternally -eternity -ether -ethereal -etiquette -evade -evaded -eve -even -evening -evenings -evenly -event -eventful -eventually -ever -evergreen -everlasting -evermore -every -everybody -everyday -everyone -everything -everywhere -evidence -evident -evidently -evil -evince -evinced -evincing -evoke -evoked -evolution -ex -exact -exacting -exactly -exactness -exaggerate -exaggerated -exaggeration -exalt -exaltation -exalted -examination -examine -examined -examining -example -exasperated -exasperating -exasperation -excavation -exceed -exceeding -exceedingly -excellence -excellent -excellently -except -excepting -exception -exceptional -excess -excessive -excessively -exchange -exchanged -exchanging -excitable -excite -excited -excitedly -excitement -exciting -exclaim -exclamation -exclude -excluded -exclusion -exclusive -exclusively -excursion -excusable -excuse -excused -excusing -execute -executed -executing -execution -executioner -exemplary -exempt -exercise -exercised -exercising -exert -exerted -exertion -exhaust -exhaustion -exhibit -exhibited -exhibition -exhilarating -exile -exiled -exist -existence -exit -exordium -exotic -expand -expanded -expanding -expanse -expansion -expect -expectant -expectantly -expectation -expected -expecting -expediency -expedient -expedition -expeditiously -expelled -expended -expenditure -expense -expenses -expensive -experience -experienced -experiencing -experiment -experimental -expert -expiation -expiration -expire -expired -expiring -explain -explained -explaining -explanation -explanatory -explicit -explode -exploded -exploit -explore -explored -exploring -explosion -expose -exposed -exposing -exposition -exposure -expound -express -expressed -expression -expressive -expressively -expressly -exquisite -exquisitely -extant -extend -extended -extension -extensive -extent -exterior -exterminated -extermination -external -externally -extinct -extinction -extinguish -extort -extra -extract -extraneous -extraordinarily -extraordinary -extravagance -extravagant -extreme -extremely -extremest -extremity -extricate -extricated -exultation -exulting -exultingly -eye -eyebrow -eyed -eyeing -eyes -eyesight -fa -fable -fabric -fabulous -face -faced -facetious -facilitate -facility -facing -fact -factory -facts -faculty -fade -faded -fading -fail -failing -failure -fain -faint -fainter -faintly -faintness -fair -fairies -fairly -fairy -faith -faithful -faithfully -fall -fallen -falling -falls -false -falsehood -falsely -falter -fame -famed -familiar -familiarity -familiarly -family -famine -famished -famous -fan -fancied -fanciful -fancy -fancying -fanning -fantastic -far -farce -fare -farewell -farm -farmer -farmers -farmhouse -farming -farther -farthest -farthing -fascinated -fascinating -fascination -fashion -fashionable -fashioned -fast -fasten -fastened -fastening -fastidious -fat -fatal -fatality -fatally -fate -fated -fateful -father -fatherless -fatherly -fathers -fathom -fatigue -fatigued -fatiguing -fatten -fault -faultless -faulty -favor -favorite -favour -favourable -favourably -favoured -favourite -favours -fear -fearful -fearfully -fearing -fearless -feasible -feast -feat -feather -feathered -feathers -feathery -feature -featured -fed -fee -feeble -feebleness -feebly -feed -feeding -feel -feeling -feelingly -feet -feigned -feint -felicity -fell -fellow -fellowship -felony -felt -female -feminine -fence -fencing -fender -ferocious -ferociously -ferocity -ferret -ferry -fertile -fertility -fervent -fervently -fervour -festival -festive -festivity -fetch -fetching -fever -feverish -feverishly -few -fewer -fibre -fickle -fiction -fictitious -fiddle -fidelity -fidget -field -fields -fiend -fiendish -fierce -fiercely -fierceness -fiercer -fiery -fifteen -fifteenth -fifth -fiftieth -fifty -fight -fighting -figuratively -figure -figured -figures -file -filial -filing -fill -filling -film -filth -filthy -final -finally -find -finding -fine -finely -finer -finery -finest -finger -fingering -fingers -finish -finished -finishing -fir -fire -fired -firelight -fireplace -fireside -firewood -firing -firm -firmament -firmer -firmly -firmness -first -firstly -fish -fisherman -fishes -fishing -fist -fit -fitful -fitfully -fitness -fitted -fitting -five -fix -fixed -fixedly -fixing -flabby -flag -flagrant -flags -flame -flaming -flank -flannel -flap -flapping -flare -flaring -flash -flashing -flask -flat -flatly -flats -flatter -flattered -flattering -flattery -flavor -flavour -flaw -flaxen -fled -flee -fleeing -fleet -fleeting -flesh -fleshy -flew -flexibility -flexible -flicker -flight -flighty -flinch -fling -flinging -flint -flirt -flirtation -flit -flitted -flitting -float -floated -floating -flock -flogging -flood -flooded -floor -flooring -florid -flour -flourish -flourishing -flow -flower -flowered -flowering -flowers -flowery -flowing -flown -fluctuating -fluently -fluid -flung -flurried -flurry -flush -flushing -flute -flutter -fly -flying -foam -focus -foe -fog -foggy -foil -fold -folded -folding -folds -foliage -folk -follow -followed -following -folly -fond -fondly -fondness -food -fool -foolish -foolishly -foolishness -foot -footed -footing -footman -footpath -footsore -footstep -footstool -for -forbade -forbear -forbearance -forbearing -forbid -forbidden -forbidding -forbore -force -forced -forces -forcible -forcibly -forcing -fore -foreboding -forefinger -forego -foregoing -foreground -forehead -foreign -foreigner -foreman -foremost -forenoon -forerunner -foresaw -foresee -foreseeing -foreseen -foresight -forest -forestall -foretaste -foretold -forever -forfeit -forgave -forge -forgery -forget -forgetful -forgetfulness -forgetting -forgive -forgiven -forgiveness -forgiving -forgot -forgotten -fork -forked -forks -forlorn -form -formal -formality -formally -formation -former -formerly -formidable -forming -formless -forsake -forsaken -forsook -forth -forthwith -fortified -fortify -fortitude -fortnight -fortress -fortunate -fortunately -fortune -forty -forward -forwards -foster -fought -foul -found -foundation -founded -founder -fountain -four -fourteen -fourth -fowl -fox -foxes -fraction -fractured -fragile -fragment -fragmentary -fragrance -fragrant -frail -frame -framework -frank -frankly -frankness -frantic -frantically -fraternal -fraternity -fraud -fraught -freak -freckled -free -freedom -freely -freezing -freight -frenzied -frenzy -frequency -frequent -frequented -frequently -fresh -fresher -freshly -freshness -fret -fretful -fretted -fretting -friction -fried -friend -friendless -friendliness -friendly -friends -friendship -fright -frighten -frightened -frightful -frightfully -frigid -frill -fringe -fringed -frivolous -fro -frock -frog -frolic -frolicsome -from -front -frontier -frost -frosty -frown -frowning -froze -frozen -frugal -fruit -fruitful -fruition -fruitless -fry -frying -fuel -fugitive -fulfil -fulfilled -fulfilling -fulfilment -full -fuller -fullness -fully -fulness -fun -function -functionary -fund -fundamental -funds -funeral -funereal -funnel -funny -fur -furious -furiously -furnace -furnish -furnished -furnishing -furniture -furrow -furry -further -furthest -furtive -furtively -fury -fuss -futile -future -gable -gaiety -gaily -gain -gains -gait -gale -gall -gallant -gallantly -gallantry -galleries -gallery -galley -galling -gallop -galloping -gallows -gambler -game -games -gaming -gang -gap -gape -gaping -garb -garden -gardener -gardening -garment -garments -garnished -garret -garrison -gas -gash -gasp -gate -gates -gateway -gather -gathered -gathering -gaudy -gauge -gaunt -gauze -gave -gay -gaze -gazing -gear -geese -gem -gems -gen -general -generality -generally -generated -generation -generations -generosity -generous -generously -genial -genially -genius -genteel -gentility -gentle -gentleman -gentlemanly -gentlemen -gentleness -gentlewoman -gently -gentry -genuine -geographical -geography -geometrical -geometry -germ -gesticulating -gesture -get -getting -ghastly -ghost -ghostly -giant -giddiness -giddy -gift -gifted -gig -gigantic -giggle -gilded -gilt -gin -ginger -gingerbread -gingerly -gipsy -girdle -girl -girlhood -girlish -girt -give -given -giver -giving -glad -glade -gladly -gladness -glance -glancing -glare -glaring -glass -glasses -glassy -glazed -gleam -glee -gleefully -glide -glided -gliding -glimmer -glimmering -glimpse -glitter -globe -gloom -gloomily -gloomy -glorified -glorious -gloriously -glory -gloss -glossy -glove -glow -glowing -gnarled -gnaw -gnawing -go -goal -goat -goblin -god -goddess -gods -goes -going -goings -gold -golden -gone -good -goodly -goodness -goods -goodwill -goose -gooseberry -gorge -gorgeous -gospel -gossip -gossiping -got -gout -gouty -govern -governed -governess -governing -government -governor -gown -grab -grace -graceful -gracefully -graces -gracious -graciously -grade -gradual -gradually -graduated -grain -grains -grammar -grand -grandchildren -grandeur -grandfather -grandly -grandmother -grandson -granite -grant -grape -grapes -grapple -grasp -grasping -grass -grassy -grate -grated -grateful -gratefully -gratification -gratified -gratify -gratifying -grating -gratitude -gratuitous -grave -gravel -gravely -graven -graver -graves -gravest -gravity -gray -grease -greasy -great -greater -greatest -greatly -greatness -greed -greedily -greedy -green -greenhouse -greenish -greet -greeted -greeting -grew -grey -greyish -grief -grievance -grieve -grieving -grievous -grievously -grim -grimace -grimly -grimy -grin -grind -grinding -grinning -grip -gripping -grizzled -groan -grocer -grog -groom -groove -grope -groping -gross -grossly -grotesque -ground -grounded -group -grove -grovelling -groves -grow -growing -growl -grown -growth -grub -grudge -grudging -gruff -gruffly -grumble -grunt -guarantee -guard -guarded -guardian -guardianship -guards -guess -guest -guidance -guide -guided -guiding -guilt -guilty -guinea -guineas -guise -guitar -gulf -gull -gulp -gum -gun -gunpowder -guns -gush -gust -gutter -ha -habit -habitation -habitual -habitually -habituated -hack -hackney -had -hag -haggard -hail -hair -hairy -hale -half -halfpenny -halfway -hall -halo -halt -halter -halting -halves -ham -hamlet -hammer -hammered -hammering -hand -handcuffs -handed -handful -handiwork -handkerchief -handle -handled -handling -hands -handsome -handsomely -handsomer -handsomest -handwriting -handy -hang -hanging -hangman -hansom -hap -haphazard -hapless -happen -happening -happier -happiest -happily -happiness -happy -harassed -harbour -hard -harden -hardened -hardihood -hardly -hardness -hardship -hardy -hare -hark -harm -harming -harmless -harmonious -harmony -harness -harnessed -harp -harping -harsh -harshly -harshness -harvest -has -hast -haste -hasten -hastily -hasty -hat -hatchet -hate -hated -hateful -hath -hating -hatred -haughtily -haughty -haul -haunt -haunted -haunting -have -haven -having -havoc -hawk -hay -hazard -hazarded -haze -hazel -hazy -he -head -headache -headed -heading -headless -headlong -headquarters -heads -headstrong -heal -healing -health -healthy -heap -heaping -hear -hearer -hearing -hearken -hearse -heart -hearted -heartfelt -hearth -heartily -heartless -hearts -hearty -heat -heated -heath -heathen -heather -heave -heaven -heavenly -heavier -heaviest -heavily -heaviness -heaving -heavy -hedge -heed -heedless -heel -height -heighten -heir -heiress -held -hell -hellish -helm -helmet -help -helper -helpful -helping -helpless -helplessly -helplessness -hem -hen -hence -henceforth -henceforward -her -herald -herb -herd -here -hereabouts -hereafter -hereditary -heretofore -hermit -hero -heroic -heroine -heroism -hers -herself -hesitate -hesitated -hesitating -hesitatingly -hesitation -hewn -hey -hid -hidden -hide -hideous -hideously -hiding -hieroglyphics -high -higher -highest -highly -highway -hilarious -hilarity -hill -hillock -hills -hillside -hilly -hilt -him -himself -hind -hinder -hindrance -hint -hip -hire -his -hiss -hissing -historian -historical -history -hit -hitch -hither -hitherto -hitting -hive -ho -hoard -hoarse -hoarsely -hoary -hob -hobby -hoist -hold -holder -holding -hole -holiday -holiness -hollow -holly -holy -homage -home -homeless -homely -homeward -honest -honestly -honesty -honey -honeymoon -honor -honorable -honored -honors -hood -hoof -hook -hooked -hop -hope -hopeful -hopefully -hopeless -hopelessly -hopelessness -hoping -hopping -horizon -horizontal -horizontally -horn -horrible -horribly -horrid -horrified -horror -horrors -horse -horseback -horseman -horses -hospitable -hospital -hospitality -host -hostess -hostile -hostility -hot -hotel -hotly -hotter -hottest -hound -hour -hourly -hours -house -household -housekeeper -housekeeping -housemaid -houses -housewife -hovel -hover -how -however -howl -howling -hubbub -hue -hug -huge -hugging -hull -hum -human -humane -humanity -humble -humbly -humbug -humiliated -humiliating -humiliation -humility -humming -humor -humorous -humour -humoured -humouredly -hump -hundred -hundreds -hundredth -hung -hunger -hungry -hunt -hunted -hunter -hunting -hunts -hurl -hurling -hurricane -hurried -hurriedly -hurry -hurrying -hurt -hurting -husband -hush -huskily -husky -hussy -hut -hymn -hypocrisy -hypocrite -hypothesis -hysterical -hysterics -ice -icy -idea -ideal -identical -identified -identify -identity -idiot -idiotic -idle -idleness -idly -idol -ignoble -ignominious -ignominy -ignorance -ignorant -ill -illegal -illiterate -illness -illuminated -illumination -illumined -illusion -illustrate -illustrated -illustration -illustrious -image -imaginable -imaginary -imagination -imaginative -imagine -imagined -imagines -imagining -imbecile -imbecility -imbibed -imbued -imitate -imitated -imitating -imitation -immaculate -immaterial -immeasurable -immeasurably -immediate -immediately -immemorial -immense -immensely -immensity -imminent -immoderately -immoral -immortal -immortality -immovable -immutable -imp -impalpable -impart -impartial -impartiality -impartially -imparting -impassable -impassioned -impassive -impatience -impatient -impatiently -impeded -impediment -impelled -impending -impenetrable -imperative -imperceptible -imperceptibly -imperfect -imperfection -imperfectly -imperial -imperious -imperiously -impersonal -impertinence -impertinent -imperturbable -impetuosity -impetuous -impetuously -impetus -impious -implacable -implicated -implicit -implicitly -implied -implore -implored -imploring -imploringly -imply -implying -import -importance -important -importunate -importunity -impose -imposed -imposing -impossibility -impossible -impostor -impotence -impotent -impracticable -impregnable -impress -impressed -impressing -impression -impressive -impressively -imprisonment -improbable -impromptu -improper -improperly -impropriety -improve -improved -improvement -improving -imprudence -imprudent -impudence -impudent -impulse -impulsive -impulsively -impunity -impure -impute -imputed -in -inability -inaccessible -inaction -inactive -inadequate -inadvertently -inanimate -inarticulate -inasmuch -inattention -inattentive -inaudible -incalculable -incapable -incapacity -incarnate -incense -incensed -incessant -incessantly -inch -incident -incidental -incidentally -incipient -incited -inclement -inclination -incline -inclined -inclining -include -included -including -incoherent -incoherently -income -incommoded -incompatible -incomplete -incomprehensible -inconceivable -incongruity -incongruous -inconsiderable -inconsiderate -inconsistency -inconsistent -inconsolable -inconstant -inconvenience -inconvenient -incorporated -incorrigible -incorruptible -increase -increased -increasing -incredible -incredibly -incredulity -incredulous -incredulously -incumbent -incur -incurable -incurred -incurring -indebted -indecision -indecorous -indeed -indefatigable -indefinable -indefinite -indefinitely -indelible -independence -independent -independently -indescribable -indescribably -indestructible -index -indicate -indicated -indicating -indication -indicative -indifference -indifferent -indifferently -indignant -indignantly -indignation -indignity -indirect -indirectly -indiscreet -indiscretion -indiscriminately -indispensable -indisposed -indisposition -indisputable -indistinct -indistinctly -individual -individuality -individually -indolence -indolent -indomitable -indoors -induce -induced -inducement -indulge -indulged -indulgence -indulgent -indulging -industrious -industry -ineffable -ineffectual -inequality -inert -inestimable -inevitable -inevitably -inexcusable -inexhaustible -inexorable -inexperience -inexperienced -inexplicable -inexpressible -inexpressibly -inextricable -infallible -infallibly -infamous -infamy -infancy -infant -infantry -infatuated -infatuation -infection -infectious -infer -inference -inferior -inferiority -infernal -inferred -infinite -infinitely -infinity -infirm -infirmity -inflamed -inflammation -inflated -inflexible -inflict -inflicted -infliction -influence -influenced -influential -inform -informant -information -informed -informer -informing -infuriated -infused -ingenious -ingenuity -ingratitude -inhabit -inhabitant -inhabited -inhaling -inherent -inherit -inheritance -inherited -inhuman -inimitable -initial -initiated -initiation -injunction -injure -injured -injuries -injuring -injurious -injury -injustice -ink -inkling -inkstand -inky -inlaid -inland -inmate -inmost -inn -innate -inner -innermost -innocence -innocent -innocently -innumerable -inoffensive -inordinate -inquest -inquire -inquired -inquiries -inquiring -inquiringly -inquiry -inquisitive -inquisitively -insane -insanity -insatiable -inscribed -inscription -inscrutable -insect -insensibility -insensible -insensibly -inseparable -insert -inserted -inside -insidious -insight -insignificance -insignificant -insinuating -insipid -insist -insolence -insolent -insolently -insomuch -inspect -inspected -inspection -inspector -inspiration -inspire -inspired -inspiring -installed -instance -instant -instantaneous -instantaneously -instantly -instead -instigation -instinct -instinctive -instinctively -instituted -institution -instruct -instructed -instructing -instruction -instructions -instructive -instructor -instrument -insufferable -insufficient -insult -insulted -insulting -insupportable -insurance -insured -insurmountable -insurrection -intact -integrity -intellect -intellectual -intelligence -intelligent -intelligible -intend -intended -intense -intensely -intensified -intensity -intent -intention -intentionally -intently -inter -intercept -interchange -interchanged -intercourse -interest -interested -interesting -interfere -interfered -interference -interfering -interim -interior -intermediate -interment -interminable -intermission -intermittent -internal -internally -interpose -interposed -interpret -interpretation -interpreted -interpreter -interpreting -interrupt -interrupted -interrupting -interruption -interspersed -interval -intervened -intervening -intervention -interview -intimacy -intimate -intimated -intimately -intimating -intimation -intimidated -into -intolerable -intonation -intoxicated -intoxication -intricate -intrigue -introduce -introduced -introducing -introduction -intrude -intruder -intruding -intrusion -intuition -inured -invade -invaded -invading -invalid -invaluable -invariable -invariably -invasion -invent -invented -invention -inventor -invest -invested -investigate -investigated -investigating -investigation -investment -inveterate -invincible -invisible -invitation -invite -invited -inviting -invoked -involuntarily -involuntary -involve -involved -involving -inward -inwardly -inwards -irksome -iron -ironed -ironical -ironically -irons -irony -irrational -irregular -irregularity -irregularly -irrelevant -irremediable -irreparable -irrepressible -irreproachable -irresistible -irresistibly -irresolute -irresolutely -irresponsible -irrevocable -irrevocably -irritability -irritable -irritate -irritated -irritating -irritation -is -island -islands -isolated -isolation -issue -issued -issuing -it -item -its -itself -ivory -ivy -jack -jacket -jaded -jagged -jail -jam -jar -jargon -jaunty -jaw -jaws -jealous -jealously -jealousy -jelly -jerk -jerks -jest -jesting -jet -jewel -jeweller -jewellery -jewels -jingle -job -join -joint -joke -joking -jolly -jolt -jot -journal -journey -jovial -joy -joyful -joyfully -joyous -joyously -judge -judges -judging -judgment -judicial -judicious -judiciously -jug -juice -jumbled -jump -jumping -junction -juncture -junior -jury -just -justice -justifiable -justification -justified -justify -justifying -justly -jutting -juvenile -keel -keen -keener -keenly -keenness -keep -keeper -keeping -ken -kennel -kep -kept -kerchief -kettle -key -keyhole -kick -kid -kill -killing -kin -kind -kindle -kindled -kindliness -kindling -kindly -kindness -kindred -king -kingdom -kings -kinsman -kiss -kissing -kitchen -kite -kitten -knack -knave -knee -kneel -kneeling -knell -knelt -knew -knife -knight -knights -knit -knitted -knitting -knives -knob -knock -knocker -knocking -knoll -knot -knotted -knotty -know -knowing -knowledge -known -la -label -labelled -labor -laboratory -laborious -laboriously -labour -laboured -labourer -labyrinth -lace -lack -lacking -laconic -lad -ladder -ladders -laden -ladies -lady -ladyship -lagging -laid -lain -lair -lake -lakes -lamb -lame -lament -lamentable -lamentation -lamentations -lamented -lamp -lamplight -lance -land -landed -landing -landlady -landlord -lands -landscape -lane -language -languid -languidly -languishing -languor -lank -lantern -lanterns -lap -lapping -lapse -larboard -larder -large -largely -larger -largest -lark -lash -lashed -lashing -lass -lassitude -last -lasting -lastly -latch -late -lately -latent -later -latest -lath -latitude -latter -latterly -lattice -latticed -laudable -laudanum -laugh -laughable -laughing -laughingly -laughter -launch -laurel -lavender -lavish -law -lawful -lawless -lawn -laws -lawyer -lay -layer -layers -laying -lazily -lazy -le -lead -leaden -leader -leading -leaf -leafless -leafy -league -leak -leaky -lean -leaning -leant -leap -leaping -leapt -learn -learned -learning -learnt -lease -least -leastways -leather -leathern -leave -leaves -leaving -lecture -led -ledge -lee -leech -leer -left -leg -legacy -legal -legally -legend -legged -legible -legion -legitimate -leisure -leisurely -lemon -lemonade -lend -lending -length -lengthen -lent -less -lessen -lesser -lesson -lest -let -lethargy -letter -letters -letting -level -levelled -lever -levity -liable -liar -liberal -liberality -liberally -liberated -liberty -library -licence -license -licensed -lick -licking -lid -lie -lied -lies -lieu -lieutenant -life -lifeless -lifetime -lift -lifting -light -lighted -lighten -lighter -lighthouse -lighting -lightly -lightness -lightning -lights -like -likelihood -likely -likeness -likewise -liking -lilac -lilies -lily -limb -lime -limit -limitation -limitations -limited -limits -limp -line -lined -linen -lines -linger -lining -link -linked -links -lion -lions -lip -lipped -liquid -liquor -lisp -list -listen -listener -listening -listless -listlessly -listlessness -lists -lit -literal -literally -literary -literature -lithe -litter -little -live -lived -livelier -liveliest -livelihood -liveliness -lively -liver -livery -lives -livid -living -load -loaded -loading -loads -loaf -loan -loath -loathing -loathsome -loaves -lobby -lobster -local -locality -lock -locking -lodge -lodged -lodger -lodging -lodgings -loft -loftier -loftiest -lofty -log -logic -logical -loins -loiter -lone -loneliness -lonely -lonesome -long -longer -longing -look -looking -lookout -looming -loop -loophole -loose -loosely -loosen -lord -lordly -lords -lose -loser -losing -loss -lost -lot -loth -lots -loud -loudly -lounge -lounging -lovable -love -loveliest -loveliness -lovely -lover -lovers -loving -lovingly -low -lower -lowering -lowest -lowly -loyal -loyalty -lucid -luck -luckily -lucky -lucrative -ludicrous -luggage -lugubrious -lull -lumber -luminous -lump -lunatic -lunch -luncheon -lure -lurid -luring -lurk -lust -lustily -lustre -lustrous -lusty -luxuriant -luxurious -luxuriously -luxury -lying -machine -machinery -mad -madam -maddening -made -madly -madman -madness -magazine -magic -magical -magician -magistrate -magistrates -magnanimity -magnanimous -magnificence -magnificent -magnificently -magnified -magnify -magnifying -magnitude -mahogany -maid -maiden -maids -mail -main -mainly -maintain -maintained -maintaining -maintenance -majestic -majestically -majesty -major -majority -make -maker -making -malady -male -malevolent -malice -malicious -malignant -malignity -mamma -man -manage -managed -management -manager -managing -mane -manfully -manger -manhood -mania -manifest -manifestation -manifold -mankind -manly -manned -manner -mannered -manners -manor -mansion -mantel -mantelpiece -mantle -manual -manufacture -manufactured -manufacturing -manuscript -many -map -mar -marble -marbles -march -marches -marching -mare -margin -marine -mariner -mark -marked -market -marking -marriage -married -marrow -marry -marrying -marsh -marshal -marshes -marshy -martial -martyr -martyrdom -martyrs -marvel -marvelled -marvelling -marvellous -marvellously -masculine -mask -masked -masonry -mass -massacre -masses -massive -mast -master -mastered -mastering -masterly -masterpiece -masters -mastery -mat -match -matched -mate -material -materially -materials -maternal -mathematical -mathematics -matrimonial -matrimony -matron -matronly -matted -matter -matting -mattress -mature -matured -maturity -maxim -may -maybe -mayor -maze -me -meadow -meagre -meal -mean -meaning -meanly -means -meant -meantime -meanwhile -measles -measure -measured -measurement -measures -measuring -meat -mechanical -mechanically -mechanics -mechanism -medal -meddle -mediation -medical -medicine -meditate -meditated -meditating -meditation -meditatively -medium -medley -meek -meekly -meekness -meet -meeting -melancholy -mell -mellow -melodious -melody -melt -melting -member -memoirs -memorable -memorandum -memorial -memory -men -menace -menaced -menacing -mend -mended -mending -mental -mentally -mention -mercenary -merchandise -merchant -merciful -mercifully -merciless -mercilessly -mercy -mere -merely -merest -merit -merited -meritorious -merits -merrily -merriment -merry -mess -message -messenger -met -metal -metallic -metals -metaphor -metaphorically -metaphysical -metaphysics -method -methodical -methodically -metropolis -mice -microscope -microscopic -mid -midday -middle -midnight -midst -midsummer -midway -mien -might -mightier -mightily -mighty -mild -mildly -mildness -mile -miles -military -militia -milk -mill -miller -million -millionaire -mills -mimic -mince -mind -minded -mindful -mine -mineral -mines -mingle -mingled -miniature -minister -minor -mint -minute -minutely -minuteness -minutes -minutest -miracle -miraculous -mire -mirror -mirth -miscellaneous -mischance -mischief -mischievous -misconduct -miser -miserable -miserably -miseries -misery -misfortune -misgiving -mishap -mislead -misled -misplaced -miss -misses -missile -missing -mission -missionary -missis -mist -mistake -mistaken -mistaking -mistook -mistress -mistrust -misty -misunderstand -misunderstanding -misunderstood -mite -mix -mixed -mixing -mixture -mo -moan -mob -mock -mockery -mode -model -modelled -moderate -moderately -moderation -modern -modest -modestly -modesty -modified -moist -moisture -mole -moment -momentarily -momentary -momentous -mon -monarch -money -mongrel -monkey -monomania -monosyllable -monotonous -monotony -monsieur -monster -monstrous -month -monthly -monument -mood -moodily -moody -moon -moonlight -moonlit -moonshine -moor -moral -morality -morbid -more -moreover -morn -morning -mornings -morose -morrow -morsel -mortal -mortality -mortally -mortar -mortification -mortified -mortify -mortifying -moss -mossy -most -mostly -moth -mother -motherly -mothers -motion -motionless -motive -motley -motor -mottled -motto -mould -moulding -mouldy -mound -mounds -mount -mountain -mountains -mounted -mounting -mourn -mourner -mournful -mourning -mouse -moustache -mouth -mouthed -mouthful -move -movement -moving -much -mud -muddle -muddy -muffin -mug -mule -multiplication -multiplied -multiply -multiplying -multitude -multitudinous -mumbled -murder -murdered -murderer -murderous -murky -murmur -muscle -muscular -museum -mushroom -music -musical -musician -musing -musk -musket -muslin -must -mustard -muster -musty -mute -mutilated -mutinous -mutiny -mutter -mutton -mutual -mutually -muzzle -my -myself -mysteries -mysterious -mysteriously -mystery -mystic -na -nail -naked -name -named -nameless -namely -naming -nap -nape -napkin -narcotic -narrate -narrated -narration -narrative -narrator -narrow -narrowly -nasty -nation -national -nations -native -natural -naturally -nature -natured -naturedly -naught -naughty -nautical -naval -navigation -navy -nay -ne -near -nearly -neat -neatly -neatness -necessaries -necessarily -necessary -necessity -neck -neckcloth -necked -necklace -need -needed -needful -needle -needles -needless -needlework -needs -negative -neglect -neglected -neglecting -negligence -negligent -negligently -negotiation -negro -neighbor -neighborhood -neighbour -neighbourhood -neighbouring -neither -nephew -nerve -nerved -nerves -nervous -nervously -nervousness -nest -nestling -net -nether -network -neutral -never -nevertheless -new -newcomer -newly -news -newspaper -next -nice -nicely -nicer -nicest -nicety -nick -nickname -niece -nigh -night -nightcap -nightfall -nightingale -nightly -nightmare -nights -nimble -nimbly -nine -nineteen -nineteenth -ninety -ninth -nip -no -nobility -noble -nobleman -nobody -nocturnal -nod -nodded -nodding -noise -noiseless -noiselessly -noisily -noisy -nominal -non -none -nonsense -nonsensical -nook -noon -noonday -nor -normal -north -northern -northward -nose -nosed -nosegay -nostril -not -notable -notably -note -notebook -noted -notes -nothing -nothingness -notice -noticeable -noticed -noticing -noting -notion -notions -notorious -notwithstanding -nought -nourish -nourished -nourishing -nourishment -novel -novels -novelty -novice -now -nowadays -nowhere -nuisance -number -numbers -numerous -nun -nuptial -nurse -nursery -nursing -nurture -nurtured -nut -nutmeg -nuts -oak -oaken -oaks -oar -oars -oasis -oath -oaths -obdurate -obedience -obedient -obediently -obeisance -obey -obeyed -object -objection -objectionable -obligation -oblige -obliged -obliging -obligingly -oblique -obliquely -obliterated -oblivion -oblivious -oblong -obnoxious -obscene -obscure -obscurity -obsequious -observable -observance -observant -observation -observe -observed -observer -observing -obstacle -obstinacy -obstinate -obstinately -obstruction -obtain -obtaining -obtruded -obtrusive -obvious -obviously -occasion -occasional -occasionally -occasions -occupant -occupation -occupied -occupy -occur -occurred -occurrence -occurring -ocean -odd -oddly -odds -odious -odor -odour -of -off -offence -offend -offended -offender -offensive -offer -offered -offering -office -officer -official -officially -officiating -officious -offspring -oft -often -oh -oil -oily -old -olden -older -oldest -olive -omen -ominous -omission -omit -omitted -omitting -omnipotent -on -once -one -oneself -onion -onions -only -onset -onslaught -onto -onward -onwards -ooze -opaque -open -opened -opening -opera -operate -operated -operating -operation -operations -opinion -opium -opponent -opportune -opportunity -oppose -opposed -opposite -opposition -oppress -oppression -oppressive -opulence -or -oracle -orange -oration -orator -oratory -orb -orchard -orchestra -ordained -ordeal -order -ordered -orderly -orders -ordinarily -ordinary -organ -organisation -organism -organization -organized -origin -original -originality -originally -originate -originated -ornament -ornamental -ornamented -orphan -orthodox -ostentation -ostentatiously -ostrich -other -otherwise -ought -ounce -our -ours -ourselves -out -outbreak -outburst -outcast -outcry -outdone -outdoor -outer -outfit -outhouse -outlandish -outlet -outline -outlined -outlived -outrage -outraged -outrageous -outright -outset -outside -outsider -outskirts -outspread -outstrip -outward -outwardly -outwards -outweigh -oval -oven -over -overbearing -overboard -overcame -overcast -overcoat -overcome -overcoming -overdo -overflow -overgrown -overhanging -overhead -overhear -overheard -overhearing -overhung -overlook -overmuch -overnight -overpowering -overspread -overtake -overthrow -overtook -overwhelm -overwhelming -owe -owing -owl -own -owner -ox -oxen -oyster -pace -paced -pacify -pacing -pack -package -packed -packet -packing -padded -pagan -page -pages -paid -pail -pain -pained -painful -painfully -pains -paint -painted -painter -painting -pair -pairs -palace -palate -pale -paler -pall -pallid -pallor -palm -palpable -palpitating -paltry -pampered -pan -pane -panel -panelled -pang -panic -pant -pantomime -pantry -papa -paper -papers -par -parade -paradise -paradox -paragraph -parallel -paralysed -paralysis -paramount -parapet -parasol -parcel -parchment -pardon -pardonable -parent -parentage -parental -parish -park -parley -parliamentary -parlor -parlour -paroxysm -parrot -parsley -parson -parsonage -part -partake -parted -partial -partiality -participate -participation -particle -particular -particularly -particulars -parting -partition -partly -partner -partners -partnership -partook -partridges -parts -party -pass -passable -passage -passed -passenger -passer -passers -passing -passion -passionate -passionately -passive -passport -past -paste -pasteboard -pasted -pastor -pastry -pasture -pat -patch -patchwork -patent -paternal -paternity -path -pathetic -pathetically -pathos -pathway -patience -patient -patiently -patriarch -patriarchal -patrician -patriot -patriotic -patriotism -patron -patronage -patroness -patted -patter -pattern -patting -pauper -pause -pausing -pavement -paving -paw -pawnbroker -pay -paying -payment -pea -peace -peaceful -peacefully -peach -peacock -peak -peaked -peal -pear -pearl -peasant -pebble -peck -pecking -peculiar -peculiarity -peculiarly -pecuniary -pedestal -pedestrian -peel -peeling -peep -peeping -peer -peevish -peg -pen -penalty -penance -pence -pencil -pendent -pendulum -penetrate -penetrating -penetration -penitence -penitent -penknife -penniless -penny -pension -pensive -pent -people -peopled -pepper -per -perceive -perceived -perceiving -perceptible -perceptibly -perception -perch -perchance -perdition -peremptory -perennial -perfect -perfecting -perfection -perfectly -perforce -perform -performance -performed -performer -performing -perfume -perhaps -peril -perilous -period -periodical -periodically -perish -perished -perishing -permanent -permanently -permission -permit -perpendicular -perpetrated -perpetual -perpetually -perplex -perplexed -perplexity -persecuted -persecuting -persecution -perseverance -persevere -persevering -persist -persistence -persistent -persistently -person -personage -personal -personality -personally -personification -personified -perspective -perspiration -persuade -persuaded -persuasion -persuasive -pert -perturbation -perusal -perused -pervaded -pervading -perverse -perversity -pestilence -pet -petition -petrified -petted -petticoat -petting -pettishly -petty -petulance -pew -pewter -phantom -phase -phenomena -phenomenon -philanthropy -philosopher -philosophic -philosophical -philosophically -philosophy -phlegm -photograph -phrase -phraseology -physic -physical -physically -physician -physiognomy -physiology -piano -pianoforte -pick -picked -picking -pickle -pickled -picnic -picture -pictured -picturesque -picturing -pie -piece -pier -pierce -pierced -piercing -piety -pig -pigeon -pigs -pike -pile -piled -piles -pilgrim -pilgrimage -pilgrims -piling -pill -pillar -pillars -pillow -pills -pilot -pin -pinch -pinching -pine -pines -pink -pinnacle -pins -pint -pious -piously -pipe -piping -pique -pirate -pistol -pit -pitch -pitched -pitcher -pitching -piteous -pitiable -pitied -pitiful -pitiless -pitilessly -pittance -pity -pitying -pivot -place -places -placid -placidity -placidly -placing -plague -plaid -plain -plainly -plainness -plains -plaintive -plaintively -plan -plane -planet -planets -plank -planning -plant -plantation -planted -plaster -plastered -plate -platform -plausible -play -player -playfellow -playful -playfully -playfulness -playing -playmate -plaything -plea -plead -pleaded -pleading -pleasant -pleasantry -please -pleasing -pleasurable -pleasure -plebeian -pledge -plentiful -plentifully -plenty -plight -plodding -plot -plotted -plough -pluck -plum -plumage -plume -plump -plunder -plunge -plunging -plying -pocket -pocketbook -pocketing -poem -poet -poetic -poetical -poetry -poets -poignant -point -pointed -pointedly -pointing -points -poise -poised -poison -poisoning -poisonous -poke -poker -poking -pole -poles -police -policeman -policy -polish -polished -polite -politely -politeness -politic -political -politician -politics -polluted -pomp -pompous -pond -ponder -pondered -ponderous -pony -pooh -pool -pools -poor -poorly -pop -popular -popularity -population -populous -porcelain -porch -pore -poring -pork -porridge -port -portal -portentous -porter -portfolio -portico -portion -portly -portmanteau -portrait -pose -position -positive -positively -possess -possessed -possession -possessor -possibility -possible -possibly -post -posted -posterity -posting -postman -postpone -postponed -postscript -posture -pot -potato -potatoes -potent -poultry -pounce -pound -pour -poverty -powder -power -powerful -powerfully -powerless -powers -pr -practicable -practical -practically -practice -practise -practised -practitioner -praise -praiseworthy -praising -pray -prayer -praying -pre -preach -preacher -precarious -precaution -precede -preceded -precedence -preceding -precept -precincts -precious -precipice -precipitate -precipitately -precipitation -precise -precisely -precision -precocious -predecessor -predestined -predicament -predict -prediction -predominant -predominated -preface -prefer -preferable -preference -preferred -preferring -pregnant -prejudice -prejudiced -preliminaries -preliminary -prelude -premature -prematurely -premeditated -premises -premium -preoccupation -preoccupied -preparation -preparatory -prepare -prepared -preparing -prepossessing -preposterous -prescribed -prescription -presence -present -presentable -presentation -presented -presentiment -presently -presents -preservation -preserve -preserved -preserver -preserving -preside -president -press -pressing -pressure -presumably -presume -presumed -presuming -presumption -presumptuous -pretence -pretend -pretended -pretension -pretext -prettier -prettiest -prettily -pretty -prevail -prevailing -prevalent -prevent -prevented -previous -prey -price -priceless -prick -pride -priest -prig -prim -primary -prime -primitive -prince -princely -princess -principal -principally -principle -print -printed -printer -printing -prior -prison -prisoner -privacy -private -privately -privation -privilege -privileged -privy -prize -pro -probability -probable -probably -probing -problem -procedure -proceed -proceeding -proceedings -proceeds -process -processes -procession -proclaim -proclaimed -proclaiming -proclamation -procure -procured -procuring -prodigal -prodigious -prodigiously -prodigy -produce -produced -producing -product -production -productive -profane -profess -professed -profession -professional -professionally -professor -profile -profit -profitable -profound -profoundly -profundity -profusion -progeny -programme -progress -prohibition -project -projection -prolong -prolonged -prominent -promise -promised -promising -promote -promoted -promoting -promotion -prompt -promptitude -promptly -prone -pronounce -pronounced -pronouncing -pronunciation -proof -prop -propensity -proper -properly -property -prophecy -prophet -prophetic -propitiate -propitious -proportion -proportionate -proportioned -proposal -propose -proposed -proposing -proposition -proprietor -propriety -prosaic -prose -prosecute -prosecuted -prosecution -prospect -prospective -prosper -prosperity -prosperous -prostrate -prostration -prot -protect -protected -protecting -protection -protector -protest -protestation -protested -protesting -protruded -protruding -proud -proudly -prove -proverb -provide -provided -providence -providential -providing -province -provinces -provincial -proving -provision -provisions -provocation -provoke -provoked -provoking -prow -prowess -prowl -proximity -prudence -prudent -prudently -pry -prying -psychological -public -publication -publicity -publicly -publish -published -publishing -pudding -puddle -puff -pull -pulpit -pulse -pump -pumping -punch -punctual -punctuality -punctually -pungent -punish -punished -punishing -punishment -puny -pupil -puppy -purchase -purchased -purchaser -pure -purely -purer -purest -purge -purified -purify -purity -purple -purport -purpose -purposed -purposeless -purposely -purse -pursuance -pursue -pursued -pursuing -pursuit -push -pushed -pushing -put -putting -puzzle -pyramid -quaint -quaking -qualified -quality -quantity -quarrel -quarrelled -quarrelling -quarrelsome -quarry -quart -quarter -quartered -quarterly -quarters -quay -queen -queens -queer -quench -querulous -query -quest -question -questionable -questioner -questioning -quick -quicken -quicker -quickly -quickness -quid -quiet -quieter -quietly -quietness -quill -quilt -quit -quite -quiver -quotation -quote -quoted -quoting -rabbit -rabble -race -races -racing -rack -racket -racking -radiance -radiant -raft -rag -rage -ragged -raging -rags -rail -railing -raillery -railway -raiment -rain -rainbow -rains -rainy -raise -raised -raising -rake -raked -rakish -rallied -rally -rallying -ram -ramble -rambling -ran -random -rang -range -ranged -ranges -ranging -rank -rap -rapid -rapidity -rapidly -rapt -rapture -rapturous -rapturously -rare -rarely -rarity -rascal -rascally -rash -rashly -rat -rate -rated -rates -rather -rational -rationally -rats -rattle -rattling -raven -ravenous -raving -raw -ray -rays -razor -re -reach -reaching -reaction -read -reader -readily -readiness -reading -ready -real -realisation -realise -realised -reality -realization -realize -realized -really -realm -reap -reappear -reappearance -rear -reason -reasonable -reasonableness -reasonably -reasoned -reasoning -reassurance -reassure -rebel -rebellion -rebellious -rebuke -recall -recede -receding -receipt -receive -received -receiver -receiving -recent -recently -receptacle -reception -recess -recipe -reciprocal -reciprocated -recital -recite -recited -reciting -reckless -reckon -reckoning -reclaim -reclaimed -reclined -reclining -recognise -recognised -recognising -recognition -recognize -recognized -recognizing -recoil -recollect -recollected -recollection -recommenced -recommend -recommendation -recommended -recompense -reconcile -reconciled -reconciling -record -recorded -recourse -recover -recovered -recovery -recreation -recruit -recur -recurrence -recurring -red -redder -reddish -redeem -redeeming -redness -redress -reduce -reduced -reducing -reduction -reed -reef -reel -refer -reference -referred -referring -refined -refinement -reflect -reflected -reflecting -reflection -reflectively -reform -reformation -refractory -refrain -refresh -refreshed -refreshing -refreshment -refuge -refusal -refuse -refused -refusing -refute -regain -regained -regard -regarded -regarding -regardless -regiment -region -regions -register -registered -regret -regretfully -regular -regularity -regularly -regulate -regulated -regulating -regulation -regulations -rehearsal -reign -rein -reinforced -reins -reject -rejected -rejection -rejoice -rejoiced -rejoicing -rejoin -rejoinder -relapse -relapsing -relate -related -relating -relation -relations -relationship -relative -relax -relaxation -release -released -releasing -relent -relentless -reliable -reliance -relic -relied -relief -relieve -relieved -relieving -religion -religious -relinquish -relish -reluctance -reluctant -reluctantly -rely -relying -remain -remainder -remains -remark -remarkable -remarked -remedy -remember -remembered -remembrance -remind -reminiscence -remiss -remnant -remonstrance -remonstrate -remorse -remorselessly -remote -remotely -remoter -remotest -removal -remove -removed -removing -rend -render -rendered -rendering -rending -renew -renewal -renewed -renounce -renounced -renouncing -renown -renowned -rent -repaid -repair -repaired -reparation -repast -repay -repeat -repeated -repeatedly -repeating -repel -repelled -repent -repentance -repentant -repetition -repine -replace -replaced -replacing -replenished -replete -reply -report -reported -repose -reposed -reposing -reprehensible -represent -representation -representative -representatives -represented -repress -repressed -repressing -reprimand -reproach -reproachful -reproachfully -reproaching -reproof -reproved -reproving -republic -republican -repudiated -repugnance -repugnant -repulse -repulsed -repulsion -repulsive -reputation -repute -reputed -request -require -required -requiring -requisite -requisition -requited -res -rescue -rescued -rescuing -research -resemblance -resemble -resent -resentful -resentment -reservation -reserve -reserved -reserving -reside -resided -residence -resident -residing -resign -resignation -resigned -resist -resistance -resisted -resolute -resolutely -resolution -resolve -resolved -resolving -resort -resource -resources -respect -respectability -respectable -respected -respectful -respectfully -respecting -respective -respiration -respite -resplendent -respond -response -responsibility -responsible -responsive -rest -restaurant -rested -resting -restless -restlessly -restlessness -restoration -restorative -restore -restored -restoring -restrain -restraining -restraint -restricted -result -resume -resumed -resuming -resurrection -retail -retain -retained -retaining -retaliation -retarded -reticule -retire -retired -retirement -retiring -retort -retrace -retraced -retract -retreat -retribution -return -returning -reveal -revealed -revealing -revelation -revenge -revengeful -revenue -reverence -reverend -reverent -reverential -reverie -reverse -reversed -reversion -revert -review -reviewed -revival -revive -revived -reviving -revolt -revolting -revolution -revolved -revolver -revolving -reward -rewarded -rheumatic -rhyme -rhythm -rib -ribbon -rice -rich -riches -richly -richness -rickety -rid -ridden -riddle -ride -rider -ridge -ridicule -ridiculous -riding -rifle -rift -rigging -right -righteous -righteousness -rightful -rightly -rights -rigid -rigidity -rigorous -rim -ring -ringing -riot -riotous -rip -ripe -ripened -ripple -rise -risen -rising -risk -rite -rival -river -rivers -riveted -road -roadway -roam -roar -roaring -roast -roasted -roasting -rob -robber -robbery -robbing -robe -robes -robin -robust -rock -rocket -rocking -rocks -rocky -rod -rode -rogue -rogues -roll -rolling -rolls -romance -romantic -roof -roofed -room -roomy -root -rooted -rope -rose -rosy -rot -rotted -rotten -rotting -rouge -rough -roughly -roughness -round -roundabout -rounded -roundly -rouse -rousing -rout -route -routed -routine -roving -row -rowing -royal -rub -rubber -rubbing -rubbish -ruby -ruddy -rude -rudely -rudeness -ruffian -ruffle -ruffled -rug -rugged -ruin -ruined -ruinous -rule -ruler -rules -ruling -rum -rumble -rummage -rummaged -rumour -run -rung -runners -running -rural -ruse -rush -rushing -rust -rustic -rustle -rusty -ruthless -ruthlessly -sable -sack -sacred -sacrifice -sacrificed -sacrificing -sad -saddle -saddles -sadly -sadness -safe -safeguard -safely -safety -sagacious -sagacity -sage -said -sail -sailing -sailor -saint -saintly -saints -saith -sake -salad -salary -sale -sallied -sallow -sally -salmon -saloon -salt -salts -salutary -salutation -salute -saluted -saluting -salvation -same -sample -sanction -sanctity -sanctuary -sand -sands -sandwich -sandy -sane -sang -sanguinary -sanguine -sanity -sank -sap -sar -sarcasm -sarcastic -sash -sat -satin -satire -satirical -satisfaction -satisfactorily -satisfactory -satisfied -satisfy -satisfying -saturated -sauce -saucepan -saucer -saucy -sausage -savage -savagely -save -saving -savings -savoury -saw -sawdust -say -saying -scaffold -scaffolding -scale -scaled -scales -scandal -scant -scantily -scanty -scar -scarce -scarcely -scarcity -scare -scarf -scarlet -scarred -scatter -scattered -scattering -scene -scenery -scent -scented -sceptical -scepticism -scheme -scheming -scholar -school -schoolboy -schooling -schoolmaster -schoolroom -schools -schooner -science -scientific -scissors -scold -scope -scorched -score -scorn -scornful -scornfully -scoundrel -scourge -scowl -scramble -scrambled -scrap -scrape -scraping -scratch -scratches -scrawl -scream -screaming -screen -screw -screwed -scrub -scrubbed -scrubbing -scruple -scrupulous -scrupulously -scrutinized -scrutinizing -scrutiny -scuffle -scullery -sculptor -scum -scuttle -se -sea -seal -sealed -sealing -seaman -search -searching -searchingly -seas -season -seasoned -seat -seated -seating -seaward -seaweed -secluded -seclusion -second -secondary -secondly -secrecy -secret -secretary -secretly -sect -section -secure -secured -securely -security -sedentary -seduced -seductive -sedulously -see -seed -seeing -seek -seeker -seeking -seem -seeming -seen -seize -seizing -seizure -seldom -select -selected -selection -self -selfish -selfishness -sell -selling -selves -semblance -semi -semicircle -send -sending -senior -sensation -sense -senseless -sensibility -sensible -sensibly -sensitive -sensual -sent -sentence -sentenced -sentiment -sentimental -sentinel -sentry -separate -separated -separately -separates -separating -separation -sepulchral -sepulchre -sequel -sequence -serene -serenely -serenity -sergeant -series -serious -seriously -seriousness -sermon -serpent -servant -serve -service -serviceable -services -servile -servility -serving -servitude -set -settee -setting -settle -settled -settlement -settling -seven -seventeen -seventeenth -seventh -seventy -sever -several -severe -severed -severely -severest -severity -sew -sewing -sewn -sex -sexton -shabby -shade -shaded -shades -shading -shadow -shadowed -shadowy -shady -shaft -shaggy -shake -shaken -shaking -shall -shallow -shalt -sham -shame -shameful -shameless -shan -shape -shaped -shapeless -shaping -share -shares -sharing -sharp -sharpened -sharper -sharply -sharpness -shave -shaven -shaving -shawl -she -sheaf -sheath -shed -shedding -sheep -sheepishly -sheer -sheet -shelf -shell -shelter -sheltered -shelves -shepherd -sheriff -sherry -shield -shift -shifting -shilling -shine -shines -shining -shiny -ship -shipping -shipwreck -shirt -shiver -shoal -shock -shocking -shod -shoe -shoes -shone -shook -shoot -shooting -shop -shore -shorn -short -shorten -shorter -shortly -shortness -shot -should -shoulder -shouldered -shout -shouted -shove -shovel -shoving -show -shower -showered -showers -showing -shown -showy -shrank -shrewd -shrewdly -shrewdness -shriek -shrill -shrine -shrink -shrinking -shroud -shrubbery -shrug -shrugging -shrunk -shudder -shuddering -shun -shut -shutter -shy -shyly -shyness -si -sick -sickening -sickly -sickness -side -sideboard -sided -sidelong -sideways -siege -sigh -sight -sighted -sign -signal -signature -significance -significant -signified -signify -silence -silenced -silent -silently -silhouette -silk -silken -silky -sill -silly -silver -silvery -similar -similarity -similarly -simile -simple -simpleton -simplicity -simply -simultaneous -simultaneously -sin -since -sincere -sincerely -sincerity -sinewy -sinful -sing -singer -singing -single -singly -singular -singularity -singularly -sinister -sink -sinking -sinner -sins -sip -sipping -sir -sire -sister -sisterly -sisters -sit -site -sitting -situated -situation -six -sixpence -sixteen -sixteenth -sixth -sixty -size -sized -skeleton -sketch -skiff -skilful -skilfully -skill -skilled -skimming -skin -skinned -skinny -skip -skipper -skipping -skirt -skirting -skull -sky -skylight -slab -slack -slain -slam -slamming -slander -slang -slap -slapping -slate -slatternly -slaughter -slave -slavery -slay -sledge -sleek -sleep -sleeper -sleepers -sleeping -sleepless -sleeplessness -sleeps -sleepy -sleet -sleeve -slender -slept -slice -slide -sliding -slight -slighter -slighting -slightingly -slightly -slim -slime -slimy -sling -slinking -slip -slipper -slippers -slippery -slit -slope -slopes -sloping -sloth -slouch -slough -slovenly -slow -slowly -slowness -sluggish -slumber -slung -slunk -sly -slyly -smack -small -smart -smartly -smash -smashed -smashing -smear -smell -smelling -smelt -smile -smiling -smitten -smoke -smoked -smoking -smoky -smooth -smoothing -smoothly -smoothness -smote -smother -smothered -snail -snake -snakes -snap -snapping -snare -snarl -snatch -sneak -sneaking -sneer -sneeze -sneezing -sniff -snore -snoring -snort -snow -snowy -snub -snuff -snug -snugly -so -soap -soar -soaring -sob -sobbing -sober -soberly -sobriety -sociable -social -society -socks -soda -sodden -sofa -soft -soften -softly -softness -soil -sojourn -solace -solar -sold -soldier -sole -solely -solemn -solemnity -solemnly -solicit -solicitor -solicitous -solicitude -solid -soliloquy -solitary -solitude -solution -solve -sombre -some -somebody -somehow -someone -something -sometime -sometimes -somewhat -somewhere -son -song -sonorous -sons -soon -sooner -soot -soothe -soothing -soothingly -sooty -sordid -sore -sorely -sorrow -sorrowfully -sorry -sort -sought -soul -sound -sounding -soundly -soup -sour -source -south -southern -southward -sovereign -sow -sowing -sown -space -spacious -spade -span -spare -sparing -spark -sparkle -sparkling -sparks -sparrow -spasm -spasmodic -spat -speak -speaker -speaking -spear -special -specialist -specially -species -specific -specimen -speck -speckled -spectacle -spectacles -spectator -spectral -spectre -speculate -speculating -speculation -sped -speech -speechless -speed -speedily -speedy -spell -spelling -spelt -spend -spending -spends -spent -sphere -spice -spider -spike -spilling -spilt -spin -spine -spinning -spire -spires -spirit -spirited -spirits -spiritual -spit -spite -spiteful -spitting -splash -spleen -splendid -splendidly -splendor -splendour -splinter -split -splitting -spoil -spoiling -spoils -spoilt -spoke -spoken -sponge -spontaneous -spontaneously -spoon -spoonful -sport -sporting -sports -spot -spotless -spotted -spout -sprang -spray -spread -spreading -spree -sprightly -spring -springing -springs -sprinkling -spruce -sprung -spun -spur -spurred -spy -spying -squalid -square -squarely -squat -squatted -squeeze -squeezing -squint -squire -squirrel -st -stab -stability -stable -stables -stack -staff -stage -stagger -stagnant -staid -stain -stair -staircase -stairs -stake -stakes -stale -stalk -stalked -stalking -stall -stalls -stalwart -stammer -stamp -stamping -stand -standard -standing -standstill -staple -star -starboard -stare -staring -stark -starlight -starred -starry -stars -start -starting -startle -starvation -starve -starving -state -stated -stateliness -stately -statement -states -statesman -stating -station -stationary -stations -statue -stature -status -staunch -stay -staying -stays -stead -steadfast -steadfastly -steadier -steadily -steadiness -steady -steak -steal -stealing -stealth -stealthily -stealthy -steam -steamer -steel -steep -steeple -steer -steering -stem -step -stepmother -stepping -sterling -stern -steward -stick -sticking -stiff -stiffly -stiffness -stifle -stifling -stile -still -stimulate -stimulated -stimulating -stimulus -sting -stinging -stingy -stipulate -stipulated -stir -stirring -stitch -stock -stocking -stocks -stole -stolen -stolid -stomach -stone -stones -stony -stood -stool -stoop -stop -stopped -stopping -stops -store -stores -storm -storms -stormy -story -stout -stoutly -stove -straight -straightened -straightforward -straightway -strain -straining -strait -strand -strange -strangely -strangeness -stranger -strangest -strangle -strap -stratagem -straw -stray -streak -stream -streaming -street -strength -strengthen -strenuous -strenuously -stress -stretch -strewn -stricken -strict -strictly -stride -strife -strike -striking -string -strings -strip -striped -strive -striven -strode -stroke -stroking -stroll -strong -strove -struck -structure -struggle -strung -stubble -stubborn -stuck -studded -student -studied -studies -studious -study -studying -stuff -stuffed -stuffing -stumble -stumbling -stump -stung -stunning -stupefied -stupendous -stupid -stupidity -stupidly -stupor -sturdy -style -sub -subdue -subdued -subduing -subject -subjection -sublime -sublimity -submerged -submission -submissive -submit -submitted -submitting -subordinate -subsequent -subsequently -subside -subsist -subsistence -substance -substantial -substitute -substituted -substituting -subterranean -subtle -subtlety -subtly -succeed -success -successful -successfully -succession -successive -successively -successor -such -suck -sucking -sudden -suddenly -suddenness -suffer -sufferer -suffering -suffice -sufficed -sufficiency -sufficient -sufficiently -suffocated -suffocating -suffused -sugar -suggest -suggestion -suggestive -suicide -suit -suitable -suitably -suite -suited -suitor -sulky -sullen -sullenly -sullenness -sulphur -sultry -sum -summary -summer -summit -summon -summons -sumptuous -sun -sunbeam -sunburnt -sundry -sung -sunk -sunken -sunlight -sunlit -sunny -sunrise -sunset -sunshine -sup -super -superannuated -superb -supercilious -superficial -superfluous -superhuman -superintend -superintendence -superintendent -superior -superiority -supernatural -superseded -superstition -superstitious -supper -supple -supplication -supplied -supply -supplying -support -supported -supporting -suppose -supposed -supposing -supposition -suppress -suppressed -suppressing -suppression -supremacy -supreme -supremely -sure -surely -surer -surest -surf -surface -surge -surgeon -surging -surly -surmise -surname -surpass -surpassing -surplus -surprise -surprised -surprising -surprisingly -surrender -surround -surrounding -surroundings -survey -surveyed -surveying -survival -survive -survived -surviving -susceptibility -susceptible -suspect -suspend -suspended -suspense -suspicion -suspicious -suspiciously -sustain -sustained -sustaining -sustenance -swagger -swallow -swam -swamp -swan -swarm -swarthy -sway -swear -swearing -sweat -sweated -sweating -sweep -sweeping -sweeps -sweet -sweetheart -sweetly -sweetness -swell -swelled -swelling -swept -swift -swifter -swiftly -swiftness -swim -swimming -swine -swing -swinging -switch -swollen -swoon -sword -swore -sworn -swung -syllable -symbol -symmetrically -symmetry -sympathetic -sympathetically -sympathise -sympathising -sympathize -sympathy -symptom -system -systematic -systems -table -tablecloth -tables -tablet -tacit -tacitly -taciturn -tack -tackle -tact -tail -tailed -tails -taint -take -taken -taking -tale -talent -tales -talisman -talk -talkative -talker -talking -tall -tallow -tame -tan -tangible -tangle -tangled -tantalizing -tap -tape -taper -tapestry -tapping -taps -tar -target -tart -task -taste -tasted -tasting -tat -tattered -tattoo -tattooed -taught -tavern -tawny -tax -taxes -te -tea -teach -teacher -teaching -team -teapot -tear -tearful -tearing -tears -tease -teasing -technical -tedious -teeth -telegram -telegraph -telescope -tell -teller -telling -temper -temperament -temperate -temperature -tempered -tempest -tempestuous -temple -temporarily -temporary -tempt -temptation -tempted -tempting -ten -tenacious -tenant -tend -tended -tendency -tender -tenderly -tenderness -tenement -tenfold -tenor -tense -tension -tent -tenth -term -terminate -terminated -terminating -termination -terms -terrace -terrestrial -terrible -terribly -terrier -terrific -terrified -terrify -terrifying -territory -terror -test -testament -tested -testified -testify -testimony -text -texture -th -than -thank -thankful -thankfully -thankfulness -thankless -thanks -that -the -theatre -theatrical -thee -theft -their -theirs -them -theme -themselves -then -thence -thenceforth -theological -theology -theoretical -theory -there -thereabouts -thereafter -thereby -therefore -therein -thereof -thereon -thereupon -these -they -thick -thicket -thickly -thickness -thief -thigh -thimble -thin -thine -thing -think -thinking -thinner -thinness -third -thirdly -thirst -thirsty -thirteen -thirteenth -thirty -this -thither -thorn -thorny -thorough -thoroughfare -thoroughly -those -thou -though -thought -thoughtful -thoughtless -thoughtlessness -thousand -thousands -thousandth -thrashing -thread -threadbare -threading -threat -threaten -threateningly -three -threshold -threw -thrice -thrift -thrill -thrilling -thrive -throat -throb -throbbing -throne -throng -through -throughout -throw -throwing -thrown -thrust -thrusting -thud -thumb -thump -thumping -thunder -thunderbolt -thundering -thunderstorm -thunderstruck -thus -thy -thyself -tick -ticket -ticking -tickle -ticklish -tidal -tide -tidied -tidings -tie -tied -tiger -tight -tightening -tightly -tigress -tiled -till -tilt -timber -time -timely -timid -timidity -timidly -timorous -tin -tinge -tingle -tinker -tinkling -tint -tinted -tiny -tip -tipped -tipsy -tiptoe -tiptoed -tire -tired -tiresome -tiring -tissue -title -to -toad -toast -tobacco -today -toe -together -toil -toilet -toilette -token -told -tolerable -tolerably -tolerant -tolerate -toleration -toll -tomb -tomorrow -ton -tone -tongs -tongue -tongues -tonight -too -took -tool -tooth -toothache -toothless -top -topic -topmost -tops -topsy -torch -tore -torment -tormented -tormenting -torn -torpid -torpor -torrent -tortoise -torture -tortured -torturing -toss -tossed -total -totally -tottering -touch -touched -touching -tough -tour -tout -tow -toward -towards -towel -tower -towered -towering -town -toy -trace -tracing -track -tracks -tract -tractable -trade -trader -trades -tradesman -trading -tradition -traditional -traffic -tragedy -tragic -trail -trailing -train -training -trait -traitor -tramp -trample -trance -tranquil -tranquillity -tranquilly -transact -transaction -transfer -transferred -transferring -transform -transformation -transformed -transient -transit -transition -transitory -translate -translated -translation -transmit -transmitted -transparency -transparent -transpired -transport -transportation -transported -trap -trappings -traps -trash -travel -travelled -traveller -travelling -traverse -traversed -traversing -tray -treacherous -treachery -tread -treading -treason -treasure -treasured -treat -treated -treatment -treaty -treble -tree -tremble -trembles -trembling -tremendous -tremendously -tremor -tremulous -tremulously -trepidation -trespass -tresses -trial -triangle -triangular -tribe -tribunal -tribute -trick -trickle -tricks -tried -trifle -trifling -trigger -trim -trimming -trio -trip -tripping -triumph -triumphant -triumphantly -trivial -trod -trodden -troop -troops -trophy -tropical -trot -trotted -trotting -trouble -troubled -troubles -troublesome -troubling -trough -trouser -trousers -truce -truck -true -truer -truest -truly -trumpet -trunk -trunks -trust -trusted -trustful -trusting -trustworthy -trusty -truth -truthful -try -trying -tub -tube -tubes -tuck -tuft -tug -tugging -tuition -tumble -tumbler -tumbling -tumult -tumultuous -tumultuously -tune -tunic -tunnel -turban -turbulent -turf -turkey -turmoil -turn -turned -turning -turvy -tut -tutor -twain -twelfth -twelve -twelvemonth -twentieth -twenty -twice -twig -twilight -twin -twine -twinkle -twinkling -twins -twist -twisted -twitch -two -twopence -tying -type -typical -tyrannical -tyranny -tyrant -ud -ugliness -ugly -ultimate -ultimately -umbrella -un -unable -unaccountable -unaccountably -unaccustomed -unacquainted -unaffected -unalterable -unamiable -unanimous -unanimously -unanswerable -unapproachable -unassuming -unattainable -unattended -unavailing -unavoidable -unaware -unawares -unbearable -unbecoming -unbending -unborn -unbounded -unbroken -uncanny -unceasing -unceremoniously -uncertain -uncertainty -unchangeable -unchanged -unchanging -uncivil -uncle -unclean -uncomfortable -uncomfortably -uncommon -uncommonly -unconcern -unconcerned -uncongenial -unconnected -unconquerable -unconscious -unconsciously -unconsciousness -uncontrollable -uncouth -uncovered -undaunted -undeceive -undecided -undefined -undeniable -under -underfoot -undergo -undergoing -undergone -underground -undergrowth -underneath -understand -understanding -understood -undertake -undertaker -undertaking -undertone -undertook -underwent -undesirable -undid -undiscovered -undisguised -undisturbed -undivided -undo -undoing -undone -undoubted -undoubtedly -undress -undressed -undue -unearthly -uneasily -uneasiness -uneasy -uneducated -unemployed -unendurable -unequal -unerring -uneven -unexpected -unexpectedly -unexplained -unexplored -unfailing -unfair -unfaithful -unfamiliar -unfathomable -unfavourable -unfeeling -unfinished -unfit -unfitted -unfold -unforeseen -unfortunate -unfortunately -unfriendly -unfurnished -ungainly -ungenerous -ungovernable -ungrateful -unguarded -unhappiness -unhappy -unhealthy -unheard -unheeded -unhesitatingly -unholy -uniform -uniformity -uniformly -unimpaired -unimportant -uninhabited -uninteresting -uninterrupted -uninvited -union -unique -unison -unite -united -uniting -unity -universal -universally -universe -university -unjust -unjustly -unkempt -unkind -unknown -unlawful -unless -unlike -unlikely -unlimited -unlooked -unluckily -unlucky -unmarried -unmercifully -unmistakable -unmistakably -unmixed -unmoved -unnatural -unnaturally -unnecessarily -unnecessary -unnoticed -unobserved -unobtrusive -unoccupied -unparalleled -unpardonable -unperceived -unpleasant -unpleasantness -unpolished -unprecedented -unprepared -unprofitable -unprotected -unqualified -unquestionable -unquestionably -unquiet -unreal -unreasonable -unreasonably -unreasoning -unrelenting -unreserved -unreservedly -unrestrained -unruly -unsafe -unsaid -unsatisfactory -unscrupulous -unseasonable -unseemly -unseen -unselfish -unsettled -unshaken -unsolved -unspeakable -unspeakably -unspoken -unsteady -unsubstantial -unsuccessful -unsuccessfully -unsuitable -unsuspected -unsuspicious -untasted -untaught -untenanted -unthought -untidy -untied -until -untimely -untiring -unto -untold -untouched -untoward -untrue -untying -unused -unusual -unusually -unutterable -unvarying -unwelcome -unwell -unwholesome -unwilling -unwillingly -unwillingness -unwise -unwittingly -unwonted -unworthiness -unworthy -unyielding -up -upheld -uphill -uphold -upon -upper -uppermost -upraised -upright -uproar -upset -upsetting -upside -upstairs -upward -upwards -urchin -urge -urgency -urgent -urging -urn -usage -use -used -useful -usefulness -useless -uselessness -usher -using -usual -usually -utility -utmost -utter -utterance -vacancy -vacant -vacantly -vacation -vagabond -vagaries -vagrant -vague -vaguely -vain -vainly -vale -valet -valiantly -valid -valley -valour -valuable -value -valued -valueless -values -vampire -van -vanish -vanishing -vanity -vapour -variable -variance -variation -variations -varied -variety -various -varnished -vary -varying -vase -vast -vastly -vastness -vault -veal -vegetable -vegetation -vehemence -vehement -vehemently -vehicle -veil -veiled -vein -veins -velvet -venerable -veneration -vengeance -venom -vent -venture -ventured -venturing -veranda -verb -verbal -verdant -verdict -verdure -verge -verified -verily -veritable -vermin -verse -version -very -vessel -vest -vestibule -vestige -vestry -veteran -vex -vexation -vexatious -vexed -vibrate -vibrated -vibrating -vibration -vice -vicinity -vicious -victim -victor -victorious -victory -victuals -view -viewing -vigil -vigilance -vigilant -vigor -vigorous -vigorously -vigour -vile -villa -village -villain -villainous -villainy -vindictive -vindictiveness -vine -vinegar -violate -violence -violent -violet -violin -virgin -virtue -virtues -virtuous -visage -visible -vision -visionary -visit -visitation -visiting -visitor -vista -vital -vitality -vitals -vivacious -vivacity -vivid -vividly -vocabulary -vocal -vocation -vogue -voice -voiced -void -volatile -volcanic -volcano -volition -volley -volume -voluntarily -voluntary -volunteer -voluptuous -vote -voted -vouchsafe -vouchsafed -vow -voyage -vulgar -vulgarity -vulnerable -vulture -wade -waded -wading -wag -wager -wages -wagging -waggon -wagon -wail -wailing -waist -waistcoat -wait -waiter -waiting -wake -wakeful -waken -waking -walk -walking -wall -walled -walnut -waltz -wan -wand -wander -wanderer -wandering -wane -waning -want -wanting -wanton -war -ward -wardrobe -ware -warehouse -warehouses -warfare -warily -warlike -warm -warmer -warming -warmly -warmth -warn -warning -warrant -warrior -wars -wary -was -wash -washing -waste -wasted -wasteful -wasting -watch -watcher -watchful -watchfulness -watchman -water -watered -watering -waterproof -waters -watery -wave -waved -waves -waving -wax -waxen -way -ways -wayside -wayward -weak -weaken -weaker -weakly -weakness -weal -wealth -wealthy -weapon -wear -wearer -wearied -wearily -weariness -wearing -wearisome -weary -wearying -weather -weave -web -wed -wedded -wedding -wedge -wedged -wee -weed -weeds -week -weekly -weep -weeping -weigh -weight -weighty -weird -welcome -welfare -well -wells -wench -went -wept -were -west -western -westward -wet -wetted -wetting -whale -wharf -what -whatever -whatsoever -wheat -wheel -wheeled -wheeling -wheels -when -whence -whenever -where -whereabouts -whereas -whereat -whereby -wherefore -wherein -whereof -whereupon -wherever -wherewith -whether -which -whichever -whiff -while -whiles -whilst -whim -whimsical -whine -whining -whip -whipping -whips -whirl -whirlpool -whirlwind -whiskers -whisper -whispered -whispering -whist -whistle -whistling -whit -white -whiteness -whites -whither -who -whoever -whole -wholesale -wholesome -wholly -whom -whomsoever -whoop -whose -whosoever -why -wick -wicked -wickedness -wicker -wicket -wide -widely -wider -widespread -widow -widower -width -wife -wig -wild -wilder -wilderness -wildly -wildness -wilful -wilfully -will -willed -willing -willingly -willingness -willow -wills -wilt -wily -win -wind -winded -winding -window -windows -windy -wine -wing -winged -wings -wink -winks -winner -winning -winter -wintry -wipe -wire -wiry -wisdom -wise -wiser -wisest -wish -wishing -wisp -wistful -wistfully -wit -witch -witches -with -withal -withdraw -withdrawal -withdrawing -withdrawn -withdrew -wither -withheld -withhold -within -without -withstand -withstood -witness -witnessed -wits -witted -witty -wives -woe -woeful -woke -wolf -wolves -woman -womanhood -womanly -womb -women -won -wonder -wonderful -wonderfully -wondering -wonderingly -wont -wonted -wood -wooded -wooden -woods -woody -wool -woollen -word -worded -words -wore -work -worked -worker -working -workman -workmanship -works -workshop -world -worldly -worm -worms -worn -worried -worry -worse -worship -worshipped -worst -worsted -worth -worthless -worthy -wot -would -wound -wounded -wounding -woven -wrap -wrapped -wrapper -wrapping -wrath -wreath -wreck -wrench -wrestling -wretch -wretched -wretchedly -wretchedness -wring -wringing -wrinkle -wrist -writ -write -writer -writhe -writhing -writing -writings -written -wrong -wrongly -wrote -wrought -wrung -yard -yarn -yawn -yawning -year -yearly -yearning -years -yell -yellow -yellowish -yes -yesterday -yet -yew -yield -yielding -yoke -yonder -yore -you -young -younger -youngster -your -yours -yourself -youth -youthful -zeal -zealous -zenith -zest -zigzag diff --git a/crates/proof/data/en-extra.txt b/crates/proof/data/en-extra.txt new file mode 100644 index 00000000..7d04908e --- /dev/null +++ b/crates/proof/data/en-extra.txt @@ -0,0 +1,241 @@ +# English spelling supplement: common words the public-domain Moby list (1990s) lacks. +# Written by WordCraft contributors (MIT OR Apache-2.0); see ATTRIBUTION.md. +# One lowercase base form per line, sorted. Plurals, -ed, -ing, -er, -ly… come from the +# inflection rules in crates/proof/src/lib.rs, so list "desktop", not "desktops". +airbag +airfare +artcraft +autocomplete +autocorrect +autofill +autoformat +autosave +backend +bitcoin +bitmap +blockchain +blog +blogger +bluetooth +captcha +caregiver +carpool +cellphone +chatbot +chatroom +checkbox +checklist +childcare +clamour +clickable +colourful +colourisation +colourise +colourless +configurable +copyedit +coronavirus +covid +crowdfunding +crowdsource +crypto +cryptocurrency +customizable +customization +cyber +cybersecurity +cyberspace +database +dataset +daycare +desktop +download +downloadable +downsize +dropdown +earbud +ebook +ecommerce +email +emoji +emoticon +endeavour +esports +facebook +favicon +fintech +firewall +flowchart +foodie +freeware +frontend +fundraiser +gameplay +gamification +geeky +geolocation +gigabit +gigabyte +github +glamour +globalization +google +groupthink +hackathon +hardcode +hashtag +healthcare +homepage +homeschool +honour +honourable +honourably +hotspot +hyperlink +hypertext +inbox +incentivize +infographic +instagram +internet +interoperability +intranet +ipad +iphone +javascript +kickstart +kilobyte +laptop +lifestyle +linkedin +linux +livestream +lockdown +login +logout +lowercase +makeover +malware +manoeuvrable +megabyte +megapixel +meme +metadata +microchip +microsoft +middleware +mindset +multicultural +multiplayer +multitask +nerdy +netbook +netflix +newsfeed +offboard +offline +onboard +online +onscreen +outsource +paediatric +paralegal +passcode +petabyte +phishing +photobomb +playdate +playlist +plugin +podcast +popup +prequel +printout +prioritise +prioritization +prioritize +privatise +ransomware +recyclable +rigour +ringtone +roadmap +rollout +runtime +scalability +screencast +screensaver +screenshot +scrollbar +selfie +signup +sitemap +skillset +smartphone +smartwatch +smiley +snowboard +spellcheck +spellchecker +spreadsheet +spyware +stakeholder +standup +startup +subfolder +sunscreen +superfood +superuser +synthesise +tagline +takeout +techie +telecommute +teleconference +telehealth +telemedicine +terabyte +textbox +timeline +timestamp +toolbar +toolkit +touchpad +touchscreen +trackball +trackpad +travelogue +upcycle +upload +uppercase +upsell +upskill +usability +username +videoconference +videogame +vlog +vlogger +voicemail +walkthrough +webcam +webcast +webinar +weblog +webmaster +webpage +website +whatsapp +whiteboard +wifi +wiki +wikipedia +wireframe +wordcraft +workaround +workflow +workforce +workplace +workspace +workstation +youtube diff --git a/crates/proof/data/en-words.dic b/crates/proof/data/en-words.dic new file mode 100644 index 00000000..8fc609eb Binary files /dev/null and b/crates/proof/data/en-words.dic differ diff --git a/crates/proof/examples/en_core.rs b/crates/proof/examples/en_core.rs deleted file mode 100644 index 2c1e7a3d..00000000 --- a/crates/proof/examples/en_core.rs +++ /dev/null @@ -1,70 +0,0 @@ -//! Regenerate `data/en-core.txt`, the English core word list (see the crate README). -//! -//! ```sh -//! cargo run -p craft-proof --example en_core -- /language-data/en-us/en-us.dic ... -//! ``` -//! -//! Every word in the list comes from the public-domain Moby Hyphenator II list (`en-us.dic`). -//! The books (public-domain Project Gutenberg plain-text files) only rank those words: a word is -//! counted where it is written in lower case (so names, which are capitalized, rank low), must -//! appear in at least [`MIN_BOOKS`] of the books, and the `` most frequent are written, -//! sorted. No other word list or dictionary is read. -//! -//! `data/en-core.txt` was made with `` 12000 (11,367 words pass [`MIN_BOOKS`]) from these -//! Project Gutenberg eBooks (`https://www.gutenberg.org/cache/epub//pg.txt`, fetched -//! 2026-11-01): 11 16 35 36 43 45 55 74 76 84 98 105 113 120 135 141 158 161 174 215 219 244 345 -//! 408 514 730 766 768 1023 1080 1184 1228 1260 1342 1400 1497 1661 1952 2542 2554 2600 2701 2814 -//! 2852 3600 3825 4300 5230 25344 64317. - -use std::collections::{HashMap, HashSet}; - -/// A word must occur, in lower case, in at least this many books. -const MIN_BOOKS: usize = 8; - -fn main() -> Result<(), String> { - let args: Vec = std::env::args().skip(1).collect(); - let [dic, count, out, books @ ..] = args.as_slice() else { - return Err("usage: en_core ...".into()); - }; - let count: usize = count.parse().map_err(|e| format!("count: {e}"))?; - let bytes = std::fs::read(dic).map_err(|e| format!("{dic}: {e}"))?; - let moby = craft_proof::dict::Dictionary::from_bytes(&bytes)?; - let moby: HashSet<&str> = moby.iter().map(|(w, _)| w).collect(); - let mut freq: HashMap = HashMap::new(); - for book in books { - let text = std::fs::read_to_string(book).map_err(|e| format!("{book}: {e}"))?; - // The Project Gutenberg header and licence are not the book. - let body = text.split_once("*** START OF").map_or(text.as_str(), |(_, b)| b); - let body = body.split_once("*** END OF").map_or(body, |(b, _)| b); - let mut seen: HashSet<&str> = HashSet::new(); - for w in body.split(|c: char| !(c.is_ascii_alphabetic() || c == '\'')).map(|w| w.trim_matches('\'')) { - if w.len() < 2 || !w.bytes().all(|b| b.is_ascii_lowercase() || b == b'\'') || !moby.contains(w) { - continue; - } - let e = freq.entry(w.to_string()).or_default(); - e.0 += 1; - if seen.insert(w) { - e.1 += 1; - } - } - } - let mut ranked: Vec<(String, u64)> = freq.into_iter().filter(|(_, (_, b))| *b >= MIN_BOOKS).map(|(w, (n, _))| (w, n)).collect(); - ranked.sort_by(|a, b| b.1.cmp(&a.1).then_with(|| a.0.cmp(&b.0))); - ranked.truncate(count); - let mut words: Vec = ranked.into_iter().map(|(w, _)| w).collect(); - words.sort(); - let mut o = String::from( - "# English core word list: the built-in fallback when neither the embedded Language data nor a\n\ - # system Hunspell English dictionary is available (see crates/proof/README.md).\n\ - # Public domain: every word is from the Moby Hyphenator II list by Grady Ward (Project\n\ - # Gutenberg eBook #3204), ranked by frequency in public-domain Project Gutenberg books.\n\ - # Generated by `cargo run -p craft-proof --example en_core`. Do not edit by hand.\n", - ); - for w in &words { - o.push_str(w); - o.push('\n'); - } - std::fs::write(out, o).map_err(|e| format!("{out}: {e}"))?; - eprintln!("{} words", words.len()); - Ok(()) -} diff --git a/crates/proof/examples/en_words.rs b/crates/proof/examples/en_words.rs new file mode 100644 index 00000000..f6933cb0 --- /dev/null +++ b/crates/proof/examples/en_words.rs @@ -0,0 +1,28 @@ +//! Regenerate `data/en-words.dic`, the English word list built into the crate (see the crate +//! README): every word of the public-domain Moby Hyphenator II list, without its break points. +//! +//! ```sh +//! cargo run -p craft-proof --example en_words -- /language-data/en-us/en-us.dic data/en-words.dic +//! ``` +//! +//! The input is craft-i18n's `en-us.dic`: the Moby Hyphenator II list by Grady Ward (Project +//! Gutenberg eBook #3204, `mhyph.txt`), already stripped of the Project Gutenberg header and +//! licence, with its break points. The output keeps the words only (in [`Dictionary`]'s format, +//! every break mask zero), so it is smaller and carries no hyphenation. No other word list or +//! dictionary is read. + +use craft_proof::dict::Dictionary; + +fn main() -> Result<(), String> { + let args: Vec = std::env::args().skip(1).collect(); + let [dic, out] = args.as_slice() else { + return Err("usage: en_words ".into()); + }; + let bytes = std::fs::read(dic).map_err(|e| format!("{dic}: {e}"))?; + let moby = Dictionary::from_bytes(&bytes)?; + let words = Dictionary::from_entries(moby.iter().map(|(w, _)| (w.to_string(), 0)).collect()); + let data = words.to_bytes(); + std::fs::write(out, &data).map_err(|e| format!("{out}: {e}"))?; + eprintln!("{} words, {} bytes", words.len(), data.len()); + Ok(()) +} diff --git a/crates/proof/src/affix.rs b/crates/proof/src/affix.rs index cb462121..701e168c 100644 --- a/crates/proof/src/affix.rs +++ b/crates/proof/src/affix.rs @@ -19,7 +19,9 @@ //! read as `fi`) and ignored characters (`IGNORE`), and the suggestion tables `TRY`, `KEY`, `MAP` //! and `REP`. //! Morphological data (`AM` aliases, the fields after a stem) is skipped. Rejected: compounding, -//! long or numeric flags, `NEEDAFFIX` and the other directives that change which words are correct. +//! long or numeric flags, `NEEDAFFIX` and the other directives that change which words are correct +//! (an English dictionary's compounding and `OCONV` are ignored instead: +//! [`AffixDict::from_hunspell_english`]). //! //! Lookups never panic: stems sit in one string, found through an open-addressing hash table, and //! a probe allocates only small scratch strings for the candidate roots it tries. @@ -339,6 +341,8 @@ struct Rules { substandard: Option, /// The `KEEPCASE` flag. keepcase: Option, + /// The `ONLYINCOMPOUND` flag, read for English only ([`AffixDict::from_hunspell_english`]). + only_in_compound: Option, iconv: Vec<(String, String)>, ignore: Vec, /// `AF` flag aliases: alias `n` (1-based) stands for `aliases[n - 1]`. @@ -422,8 +426,27 @@ fn zero_empty(s: &str) -> String { /// but it is not a flag of its own: it is dropped wherever flags are read. const EMOJI_SELECTOR: char = '\u{fe0f}'; -/// Read Hunspell `.aff` text (already decoded to UTF-8). -fn parse_aff(aff: &str) -> Result { +/// Directives an English dictionary may carry that don't change which English words are correct +/// here, ignored by [`AffixDict::from_hunspell_english`]: compounding (English dictionaries use +/// it only for ordinals such as `1st`, which have digits and are skipped by the spelling check) +/// and output conversion (`OCONV`: how suggestions are written, such as `'` as `’`). +const IGNORED_IN_ENGLISH: &[&str] = &[ + "COMPOUNDBEGIN", + "COMPOUNDEND", + "COMPOUNDFIRST", + "COMPOUNDFLAG", + "COMPOUNDLAST", + "COMPOUNDMIDDLE", + "COMPOUNDMIN", + "COMPOUNDPERMITFLAG", + "COMPOUNDRULE", + "OCONV", +]; + +/// Read Hunspell `.aff` text (already decoded to UTF-8). `english`: ignore the directives in +/// [`IGNORED_IN_ENGLISH`], and keep the `ONLYINCOMPOUND` flag so the stems that are only parts of +/// compounds can be left out. +fn parse_aff(aff: &str, english: bool) -> Result { let mut r = Rules::default(); let mut cross: HashMap<(bool, char), bool> = HashMap::new(); let mut map_header = false; @@ -518,6 +541,8 @@ fn parse_aff(aff: &str) -> Result { r.prefixes.push(rule); } } + "ONLYINCOMPOUND" if english => r.only_in_compound = Some(one_flag(at(1), dir, n)?), + d if english && IGNORED_IN_ENGLISH.contains(&d) => {} d if UNSUPPORTED.contains(&d) => return Err(format!("line {}: {d} is not supported", n + 1)), _ => {} } @@ -542,11 +567,23 @@ impl AffixDict { /// Build from Hunspell `.aff` and `.dic` text (decoded to UTF-8; the `.dic` count line and /// morphological fields are ignored). `comments` (provenance, licence) are kept with the data. pub fn from_hunspell(aff: &str, dic: &str, comments: &[&str]) -> Result { + AffixDict::from_hunspell_in(aff, dic, comments, false) + } + + /// [`AffixDict::from_hunspell`] for an English dictionary: compounding and output conversion + /// (`COMPOUNDMIN`, `COMPOUNDRULE`, `OCONV`…), which other languages need but English spelling + /// doesn't, are ignored rather than refused, and the stems marked `ONLYINCOMPOUND` (parts of + /// compounds only) are left out. + pub fn from_hunspell_english(aff: &str, dic: &str, comments: &[&str]) -> Result { + AffixDict::from_hunspell_in(aff, dic, comments, true) + } + + fn from_hunspell_in(aff: &str, dic: &str, comments: &[&str], english: bool) -> Result { // Some dictionaries open with a UTF-8 BOM; it must not glue itself to the first // directive or turn the `.dic` count line into a stem. let aff = aff.strip_prefix('\u{feff}').unwrap_or(aff); let dic = dic.strip_prefix('\u{feff}').unwrap_or(dic); - let rules = parse_aff(aff)?; + let rules = parse_aff(aff, english)?; let mut stems: Vec<(String, String)> = Vec::new(); for (n, line) in dic.lines().enumerate() { // The entry may hold spaces (`ad hoc/B\tpo:adv`); it ends where Hunspell ends it. @@ -582,6 +619,9 @@ impl AffixDict { continue; } let flags = rules.flags(&flags).to_string(); + if rules.only_in_compound.is_some_and(|f| flags.contains(f)) { + continue; + } stems.push((word, flags)); } AffixDict::build(rules, stems, comments.iter().map(ToString::to_string).collect()) @@ -1756,6 +1796,29 @@ pub(crate) mod tests { } } + /// craft-libs#482 review: an English dictionary with compounding (for ordinals) and output + /// conversion, as the usual en_US and en_GB ones have, loads for English; its `ONLYINCOMPOUND` + /// stems are left out. Other languages still refuse those directives. (A synthetic `.aff` + /// written for this test.) + #[test] + fn english_dictionaries_ignore_compounding_and_output_conversion() { + let aff = "SET UTF-8\nTRY esianrtolcdugmphbyfvkwz'\nICONV 1\nICONV ’ '\nOCONV 1\nOCONV ' ’\nNOSUGGEST !\n\ + COMPOUNDMIN 1\nONLYINCOMPOUND c\nCOMPOUNDRULE 2\nCOMPOUNDRULE n*1t\nCOMPOUNDRULE n*mp\nCOMPOUNDFLAG Z\n\ + WORDCHARS 0123456789\nSFX S Y 1\nSFX S 0 s [^sxzhy]\nSFX D Y 1\nSFX D 0 ed [^ey]\n"; + let dic = "5\nhouse/S\nwalk/SD\n0th/pc\n1st/c\nthe\n"; + assert!(AffixDict::from_hunspell(aff, dic, &[]).is_err(), "refused for other languages"); + let d = AffixDict::from_hunspell_english(aff, dic, &[]).unwrap(); + for w in ["house", "houses", "walked", "walks", "the"] { + assert!(d.check(w), "{w}"); + } + assert!(!d.check("0th") && !d.check("1st"), "parts of compounds only"); + assert!(!d.check("housed") && !d.check("hous")); + // The directives that change which words are right are still refused. + for dir in ["NEEDAFFIX", "CIRCUMFIX", "PSEUDOROOT", "FULLSTRIP"] { + assert!(AffixDict::from_hunspell_english(&format!("{dir} X\n"), dic, &[]).is_err(), "{dir}"); + } + } + #[test] fn unsupported_and_broken_input_is_an_error() { assert!(AffixDict::from_hunspell("FLAG long\n", DIC, &[]).is_err()); diff --git a/crates/proof/src/english.rs b/crates/proof/src/english.rs index 698f85c3..c2c4b0eb 100644 --- a/crates/proof/src/english.rs +++ b/crates/proof/src/english.rs @@ -5,27 +5,43 @@ //! 2. **System Hunspell**: an English Hunspell `.aff`/`.dic` pair found by [`crate::hunspell`] //! (the dictionaries folder first, then the system locations; none on the web). The run's //! English is tried first (`en_US`, `en_GB`, `en_CA`…), then the other Englishes: a full -//! dictionary in the other spelling marks fewer right words than the core list. -//! 3. **Core list**: [`CORE_LIST`], about 11,000 common words compiled into the crate (with the -//! usual inflections). A word it doesn't know is marked only when it is a near miss of a -//! common word (`teh`, `recieve`, `definately`); any other word it doesn't know (a rare word, a -//! name, a term) is taken as correct, as it may well be right. +//! dictionary in the other spelling marks fewer right words than none. So British and Canadian +//! English use an `en_US` dictionary when no regional one is installed (and American English +//! an `en_GB` one). A file that can't be read is skipped for the next name or folder, and one +//! file is read once for every English that uses it. Directives that only matter for other +//! languages (compounding, output conversion) are ignored ([`crate::hunspell::load_english`]). +//! 3. **Built-in word list**: [`WORDS`], the whole public-domain Moby word list compiled into +//! the crate (without its break points), with WordCraft's own supplement of modern words +//! ([`EXTRA`]) and the usual inflections. A word it doesn't know is misspelled, as with the +//! embedded list. //! //! A Hunspell dictionary that is there but can't be read (unsupported encoding, too large, a -//! parse error, no words) is skipped for the core list, and its reason is reported by +//! parse error, no words) is skipped, and its reason is reported by //! [`crate::dictionary_load_error`]. Non-English text is never checked against any of these. -use std::path::PathBuf; -use std::sync::{Arc, OnceLock, RwLock}; +use std::path::{Path, PathBuf}; +use std::sync::{Arc, OnceLock, PoisonError, RwLock}; use crate::affix::AffixDict; +use crate::dict::Dictionary; use crate::{Options, ProofLang}; -/// The English core word list (`data/en-core.txt`): the most common words of the public-domain -/// Moby Hyphenator II list by Grady Ward, ranked by their frequency in public-domain Project -/// Gutenberg books (generated by `examples/en_core.rs`). One lowercase word per line, `#` -/// comments. -const CORE_LIST: &str = include_str!("../data/en-core.txt"); +/// The English word list built into the crate (`data/en-words.dic`, [`Dictionary`]'s format with +/// no break points): every word of the public-domain Moby Hyphenator II list by Grady Ward +/// (generated by `examples/en_words.rs` from craft-i18n's `en-us.dic`). +const WORDS: &[u8] = include_bytes!("../data/en-words.dic"); + +/// WordCraft's supplement of common modern words the Moby list lacks (`data/en-extra.txt`, a copy +/// of craft-i18n's `language-data/en-us/en-extra.txt`, MIT OR Apache-2.0): one lowercase base +/// form per line, `#` comments. Used when the Language data doesn't embed its own copy. +pub(crate) const EXTRA: &str = include_str!("../data/en-extra.txt"); + +/// Longest word (in characters) suggestions are looked for: longer ones get none, which keeps +/// the edits tried per word bounded. +const MAX_SUGGEST_CHARS: usize = 32; + +/// Most Hunspell `.aff`/`.dic` pairs tried for one English before giving up on Hunspell. +const MAX_CANDIDATES: usize = 8; /// Where English spelling comes from now ([`crate::english_source`]). #[derive(Clone, Debug, PartialEq, Eq)] @@ -34,19 +50,25 @@ pub enum EnglishSource { Embedded, /// An English Hunspell dictionary from the dictionaries folder or the system: its `.dic` file. Hunspell(PathBuf), - /// The core word list built into the crate: only near misses of common words are marked. + /// The Moby word list built into the crate: a word it doesn't know is misspelled. CoreList, } -/// The words of [`CORE_LIST`]. -fn core() -> &'static std::collections::HashSet<&'static str> { - static C: OnceLock> = OnceLock::new(); - C.get_or_init(|| CORE_LIST.lines().map(str::trim).filter(|l| !l.is_empty() && !l.starts_with('#')).collect()) +/// The words of [`WORDS`] (decoded on first use; empty if they fail to decode, which a test rules +/// out). +fn words() -> &'static Dictionary { + static W: OnceLock = OnceLock::new(); + W.get_or_init(|| { + Dictionary::from_bytes(WORDS).unwrap_or_else(|e| { + log::error!("built-in English word list: {e}"); + Dictionary::default() + }) + }) } -/// Is `w` (lower case) a word of the core list? -pub(crate) fn core_contains(w: &str) -> bool { - core().contains(w) +/// Is `w` (lower case) a word of the built-in list? +pub(crate) fn word_list_contains(w: &str) -> bool { + words().get(w).is_some() } /// Hunspell file names to look for, the run's English first. @@ -58,7 +80,7 @@ fn names(lang: ProofLang) -> &'static [&'static str] { } } -/// The slot of each English in [`HUNSPELL`]. +/// The slot of each English in [`State::slots`]. fn slot(lang: ProofLang) -> usize { match lang { ProofLang::EnGb => 1, @@ -70,8 +92,23 @@ fn slot(lang: ProofLang) -> usize { /// A loaded Hunspell dictionary and its `.dic` file; `None` when none could be loaded. type Loaded = Option<(Arc, PathBuf)>; -/// Per English (see [`slot`]): `None` until first use, then what was found. -static HUNSPELL: RwLock<[Option; 3]> = RwLock::new([None, None, None]); +/// The English Hunspell dictionaries, under one lock. +struct State { + /// Per English (see [`slot`]): `None` until first use, then what was found. + slots: [Option; 3], + /// Every `.dic` file read, so Englishes that use the same file share one copy. + files: Vec<(PathBuf, Arc)>, + /// Counts reloads, so a load that started before one is not kept. + reloads: u64, +} + +impl State { + const fn new() -> Self { + State { slots: [None, None, None], files: Vec::new(), reloads: 0 } + } +} + +static HUNSPELL: RwLock = RwLock::new(State::new()); /// Why the embedded word list failed to decode, if it did. static EMBEDDED_ERROR: OnceLock = OnceLock::new(); @@ -79,51 +116,117 @@ static EMBEDDED_ERROR: OnceLock = OnceLock::new(); /// Remember that the embedded word list is there but failed to decode (English then uses the /// next source). pub(crate) fn note_embedded_error(e: String) { - log::error!("embedded English word list: {e}; English spelling falls back to Hunspell or the core word list"); + log::error!("embedded English word list: {e}; English spelling falls back to Hunspell or the built-in word list"); let _ = EMBEDDED_ERROR.set(e); } /// The English Hunspell dictionary for `lang` (read on first use). fn hunspell(lang: ProofLang) -> Loaded { let i = slot(lang); - if let Some(Some(found)) = HUNSPELL.read().unwrap_or_else(std::sync::PoisonError::into_inner).get(i) { - return found.clone(); + let reloads = { + let s = HUNSPELL.read().unwrap_or_else(PoisonError::into_inner); + if let Some(Some(found)) = s.slots.get(i) { + return found.clone(); + } + s.reloads + }; + keep(&HUNSPELL, i, reloads, load(lang)) +} + +/// Keep in `state` what the load of slot `i`, started after `reloads` reloads, found. If the +/// folder was reloaded since, the load may have read the old folder: it serves this one check and +/// the next one loads again. +fn keep(state: &RwLock, i: usize, reloads: u64, loaded: Loaded) -> Loaded { + let mut s = state.write().unwrap_or_else(PoisonError::into_inner); + if s.reloads != reloads { + return match s.slots.get(i) { + Some(Some(found)) => found.clone(), + _ => loaded, + }; } - let loaded = load(lang); - let mut slots = HUNSPELL.write().unwrap_or_else(std::sync::PoisonError::into_inner); + let loaded = loaded.map(|(d, dic)| { + // Another English may have read the same file meanwhile: share its copy. + let d = match s.files.iter().find(|(p, _)| *p == dic) { + Some((_, shared)) => shared.clone(), + None => { + s.files.push((dic.clone(), d.clone())); + d + } + }; + (d, dic) + }); // Another thread may have filled it meanwhile: that one wins. - match slots.get_mut(i) { - Some(s) => s.get_or_insert(loaded).clone(), + match s.slots.get_mut(i) { + Some(slot) => slot.get_or_insert(loaded).clone(), None => loaded, } } +/// The dictionary of the `.dic` file `dic` in `state`, if an English already read it. +fn already_read(state: &RwLock, dic: &Path) -> Option> { + state.read().unwrap_or_else(PoisonError::into_inner).files.iter().find(|(p, _)| p == dic).map(|(_, d)| d.clone()) +} + +/// Forget what `state` holds, so the next check looks again. +fn forget(state: &RwLock) { + let mut s = state.write().unwrap_or_else(PoisonError::into_inner); + s.slots = [None, None, None]; + s.files.clear(); + s.reloads = s.reloads.wrapping_add(1); +} + /// The key load errors of `lang` are kept under ([`crate::hunspell::load_error`]). fn key(lang: ProofLang) -> &'static str { names(lang).first().copied().unwrap_or("en_US") } +/// Read the first English Hunspell pair for `lang` that loads, trying each name in each folder +/// ([`crate::hunspell::candidates`]). The first failure before it (the file `lang` would rather +/// use) is reported for `lang`. fn load(lang: ProofLang) -> Loaded { let key = key(lang); - let Some((aff, dic)) = crate::hunspell::find(names(lang)) else { + let candidates = crate::hunspell::candidates(names(lang)); + if candidates.is_empty() { crate::hunspell::clear_load_error(key); - log::info!("English spelling: no Hunspell English dictionary installed; using the core word list"); + log::info!("English spelling: no Hunspell English dictionary installed; using the built-in word list"); return None; - }; - let loaded = crate::hunspell::load(&aff, &dic).and_then(|d| if d.is_empty() { Err(format!("{}: no words", dic.display())) } else { Ok(d) }); - match crate::hunspell::note_load(key, &dic, loaded) { - Ok(d) => Some((Arc::new(d), dic)), - Err(e) => { - log::warn!("English spelling: {e}; using the core word list"); - None + } + let mut first_error: Option<(PathBuf, String)> = None; + let mut found = None; + for (aff, dic) in candidates.into_iter().take(MAX_CANDIDATES) { + let loaded = match already_read(&HUNSPELL, &dic) { + Some(d) => Ok(d), + None => crate::hunspell::load_english(&aff, &dic) + .and_then(|d| if d.is_empty() { Err(format!("{}: no words", dic.display())) } else { Ok(d) }) + .map(Arc::new), + }; + match loaded { + Ok(d) => { + found = Some((d, dic)); + break; + } + Err(e) => { + log::warn!("English spelling: {e}; trying the next dictionary"); + first_error.get_or_insert((dic, e)); + } } } + match first_error { + Some((dic, e)) => { + let _ = crate::hunspell::note_load::<()>(key, &dic, Err(e)); + } + None => crate::hunspell::clear_load_error(key), + } + if found.is_none() { + log::warn!("English spelling: no English Hunspell dictionary could be read; using the built-in word list"); + } + found } /// Forget the loaded dictionaries, so the next check looks for them again (the dictionaries /// folder changed). pub(crate) fn reload() { - *HUNSPELL.write().unwrap_or_else(std::sync::PoisonError::into_inner) = [None, None, None]; + forget(&HUNSPELL); } /// Where the spelling of `lang` (an English) comes from now. Reads the Hunspell dictionary once @@ -149,7 +252,7 @@ pub(crate) fn load_error(lang: ProofLang) -> Option { } /// Is `word` spelled right in `lang` (an English) when no word list is embedded: against the -/// Hunspell dictionary, or else the core list. +/// Hunspell dictionary, or else the built-in word list. pub(crate) fn is_correct(word: &str, lang: ProofLang, opts: &Options) -> bool { let w = word.trim_matches(|c: char| !c.is_alphanumeric() && c != '\'' && c != '’').trim_matches(['\'', '’']); if crate::accepted_by_options(w, opts) || !w.chars().any(|c| c.is_ascii_alphabetic()) { @@ -158,7 +261,7 @@ pub(crate) fn is_correct(word: &str, lang: ProofLang, opts: &Options) -> bool { let w = w.replace('’', "'"); match hunspell(lang) { Some((d, _)) => hunspell_correct(&d, &w), - None => core_correct(&w), + None => list_correct(&w), } } @@ -168,67 +271,75 @@ fn hunspell_correct(d: &AffixDict, w: &str) -> bool { known(w) || (w.contains('-') && w.split('-').filter(|p| !p.is_empty()).all(known)) } -/// Against the core list: known words and their inflections are right, and so is any other word -/// that isn't a near miss of a common one ([`near_miss`]). -fn core_correct(w: &str) -> bool { - let capitalized = w.chars().next().is_some_and(char::is_uppercase); - let lower = w.to_lowercase(); - let ok = |p: &str| crate::known_in_core_list(p) || !near_miss(p, capitalized); - if lower.contains('-') { crate::known_in_core_list(&lower) || lower.split('-').filter(|p| !p.is_empty()).all(ok) } else { ok(&lower) } -} - -/// Is `lower` (a word the core list doesn't know) an obvious misspelling of a common word? Two -/// neighbouring letters swapped (`teh`, `Hte`, `recieved`) always is. Otherwise, for lower-case -/// words of four letters or more, one letter added, missing or changed (`definately`, -/// `ocurred`). Shorter words and capitalized ones (names) are left alone: too many right ones are -/// one letter from a common word. -fn near_miss(lower: &str, capitalized: bool) -> bool { - let target: Vec = lower.chars().collect(); - let n = target.len(); - if !(3..=40).contains(&n) { - return false; - } - if core().iter().any(|c| is_swap(&target, c)) { +/// Against the built-in word list: its words and their inflections, or each part of a +/// hyphenated word. Anything else is misspelled. (Should the list fail to decode, nothing is +/// marked rather than everything.) +fn list_correct(w: &str) -> bool { + if words().is_empty() { return true; } - if capitalized || n < 4 { - return false; - } - core().iter().any(|c| { - let m = c.chars().count(); - m + 1 >= n && m <= n + 1 && crate::damerau(&target, c) <= 1 - }) -} - -/// Is `b` `a` with two neighbouring letters swapped? -fn is_swap(a: &[char], b: &str) -> bool { - if b.len() < a.len() || b.chars().count() != a.len() { - return false; - } - let diff: Vec<(usize, char)> = b.chars().enumerate().filter(|&(i, c)| a.get(i) != Some(&c)).collect(); - match diff.as_slice() { - [(i, x), (j, y)] => *j == i + 1 && a.get(*i) == Some(y) && a.get(*j) == Some(x), - _ => false, - } + let lower = w.to_lowercase(); + crate::known_in_word_list(&lower) || (lower.contains('-') && lower.split('-').filter(|p| !p.is_empty()).all(crate::known_in_word_list)) } /// Spelling suggestions in `lang` (an English) when no word list is embedded: from the Hunspell -/// dictionary, or else the core list. +/// dictionary, or else the built-in word list. pub(crate) fn suggest(word: &str, max: usize, lang: ProofLang) -> Vec { match hunspell(lang) { Some((d, _)) => crate::cs::suggest::suggest_in(&d, word, max), - None => core_suggest(word, max), + None => list_suggest(word, max), } } -/// Suggestions from the core list: by edit distance ([`crate::suggest_from`]), two swapped -/// letters first (`teh` → `the` before `tea`). -fn core_suggest(word: &str, max: usize) -> Vec { - let target: Vec = word.to_lowercase().chars().collect(); - let mut out = crate::suggest_from(word, max.saturating_add(4), core().iter().copied()); - out.sort_by_key(|s| !is_swap(&target, &s.to_lowercase())); - out.truncate(max); - out +/// Letters an edit may add or put in a word's place. +const ALPHABET: &str = "abcdefghijklmnopqrstuvwxyz'"; + +/// Suggestions from the built-in word list: the words one edit away (two neighbouring letters +/// swapped, one letter missing, added or changed), looked up in the list rather than compared +/// with every word, so the cost is bounded by the word's length (at most +/// [`MAX_SUGGEST_CHARS`]). Swaps first (`hte` → `the` and `het` before `hate`), then words with the same +/// first letter, then the nearest in length. +fn list_suggest(word: &str, max: usize) -> Vec { + let lower = word.to_lowercase().replace('’', "'"); + let target: Vec = lower.chars().collect(); + let n = target.len(); + if max == 0 || n == 0 || n > MAX_SUGGEST_CHARS { + return Vec::new(); + } + let mut found: Vec<(bool, bool, usize, String)> = Vec::new(); + let mut tried = std::collections::HashSet::new(); + let mut consider = |c: Vec, swap: bool| { + let s: String = c.iter().collect(); + if s != lower && tried.insert(s.clone()) && crate::known_in_word_list(&s) { + found.push((!swap, c.first() != target.first(), c.len().abs_diff(n), s)); + } + }; + for i in 1..n { + let mut c = target.clone(); + c.swap(i - 1, i); + consider(c, true); + } + for i in 0..n { + let mut c = target.clone(); + c.remove(i); + consider(c, false); + } + for i in 0..=n { + for a in ALPHABET.chars() { + if i < n { + let mut c = target.clone(); + if let Some(l) = c.get_mut(i) { + *l = a; + } + consider(c, false); + } + let mut c = target.clone(); + c.insert(i, a); + consider(c, false); + } + } + found.sort(); + found.into_iter().take(max).map(|(_, _, _, w)| crate::match_case(word, w)).collect() } #[cfg(test)] @@ -236,24 +347,20 @@ mod tests { use super::*; #[test] - fn core_list_is_small_sorted_lowercase_and_has_the_common_words() { - assert!(CORE_LIST.len() < 100 * 1024, "{} bytes", CORE_LIST.len()); - let words: Vec<&str> = CORE_LIST.lines().filter(|l| !l.starts_with('#')).collect(); - assert!(words.len() > 5_000, "{}", words.len()); - assert!(words.windows(2).all(|w| w[0] < w[1]), "sorted, no repeats"); - assert!(words.iter().all(|w| !w.is_empty() && w.chars().all(|c| c.is_ascii_lowercase() || c == '\''))); - for w in ["the", "house", "because", "received", "definitely", "separate", "occurred", "beautiful", "people", "water"] { - assert!(core_contains(w), "{w}"); - } + fn built_in_list_is_the_whole_moby_list() { + let d = words(); + assert!(d.len() > 150_000, "{}", d.len()); + assert!(d.iter().all(|(w, m)| m == 0 && !w.is_empty() && w.chars().all(|c| !c.is_uppercase()))); + assert!(WORDS.len() < 400 * 1024, "{} bytes", WORDS.len()); + let extra: Vec<&str> = EXTRA.lines().filter(|l| !l.is_empty() && !l.starts_with('#')).collect(); + assert!(extra.len() > 100 && extra.windows(2).all(|p| p[0] < p[1]), "the supplement is sorted"); } - /// The core list marks obvious misspellings and leaves right words alone, inflected ones and - /// words it doesn't know included. + /// The built-in list knows right words, the rare and the modern ones included, and marks + /// every word it doesn't know (craft-libs#482 review: the old core list let any unknown word + /// through unless it was a near miss of a common one, and marked right words that were). #[test] - fn core_list_flags_near_misses_only() { - for w in ["teh", "Teh", "hte", "recieved", "definately", "seperate", "ocurred", "becuase", "peopel", "beautifull", "watre"] { - assert!(!core_correct(w), "{w} is marked"); - } + fn built_in_list_marks_unknown_words_only() { for w in [ "the", "The", @@ -264,31 +371,70 @@ mod tests { "kindness", "Received", "well-known", - // Not in the list, but not a near miss of a common word either: left alone. "photosynthesis", - "zxqv", - "Nguyen", - "Jarndyce", - "cat", + "fiber", + "theater", + "organize", + "budget", + "phone", + "people's", + // WordCraft's supplement. + "login", + "blog", + "email", + "emails", ] { - assert!(core_correct(w), "{w} is not marked"); + assert!(list_correct(w), "{w} is not marked"); } - assert!(!core_correct("well-knwon"), "each part of a compound is checked"); + for w in ["recieved", "definately", "seperate", "ocurred", "becuase", "peopel", "beautifull", "zxqv", "Jarndycey"] { + assert!(!list_correct(w), "{w} is marked"); + } + assert!(!list_correct("well-knwon"), "each part of a compound is checked"); } #[test] - fn swaps_are_two_neighbouring_letters() { - let a: Vec = "teh".chars().collect(); - assert!(is_swap(&a, "the")); - assert!(!is_swap(&a, "teh") && !is_swap(&a, "ten") && !is_swap(&a, "thee") && !is_swap(&a, "het")); - assert!(!is_swap(&"é".chars().collect::>(), "ab")); + fn built_in_list_suggests_one_edit_away() { + assert_eq!(list_suggest("becuase", 3).first().map(String::as_str), Some("because")); + assert_eq!(list_suggest("Becuase", 3).first().map(String::as_str), Some("Because")); + assert!(list_suggest("hte", 3).contains(&"the".to_string()), "{:?}", list_suggest("hte", 3)); + assert!(list_suggest("definately", 5).contains(&"definitely".to_string())); + assert!(list_suggest("recieve", 5).contains(&"receive".to_string())); + assert!(list_suggest("", 5).is_empty() && list_suggest("becuase", 0).is_empty()); + assert!(list_suggest(&"a".repeat(MAX_SUGGEST_CHARS + 1), 5).is_empty()); } + /// Suggestions look words up rather than scanning the list: the longest word is still quick. #[test] - fn core_list_suggests_the_common_word() { - assert_eq!(core_suggest("teh", 3).first().map(String::as_str), Some("the")); - assert_eq!(core_suggest("Teh", 3).first().map(String::as_str), Some("The")); - assert!(core_suggest("definately", 5).contains(&"definitely".to_string())); - assert!(core_suggest("", 5).is_empty() && core_suggest("teh", 0).is_empty()); + fn built_in_list_suggestions_are_bounded() { + let _ = words(); + let word: String = "qwertyuiopasdfghjklzxcvbnm".chars().cycle().take(MAX_SUGGEST_CHARS).collect(); + let start = std::time::Instant::now(); + for _ in 0..10 { + let _ = list_suggest(&word, 5); + } + assert!(start.elapsed() < std::time::Duration::from_secs(5), "{:?}", start.elapsed()); + } + + /// craft-libs#482 review: a load that started before a reload (the dictionaries folder + /// changed) serves its own check but isn't kept, so the next check reads the new folder; a + /// load after it is kept, and shared with the Englishes that read the same file. + #[test] + fn a_load_from_before_a_reload_is_not_kept() { + let state = RwLock::new(State::new()); + let dict = || Arc::new(AffixDict::from_hunspell("", "1\nzzyzx\n", &[]).unwrap()); + let file = PathBuf::from("/old/folder/en_US.dic"); + let before = state.read().unwrap().reloads; + forget(&state); // The folder changes while the load runs. + let got = keep(&state, slot(ProofLang::En), before, Some((dict(), file.clone()))); + assert_eq!(got.map(|(_, p)| p), Some(file.clone()), "the stale load still answers its own check"); + assert!(state.read().unwrap().slots.iter().all(Option::is_none), "but it isn't kept"); + assert!(already_read(&state, &file).is_none()); + let now = state.read().unwrap().reloads; + let a = keep(&state, slot(ProofLang::En), now, Some((dict(), file.clone()))).unwrap(); + let b = keep(&state, slot(ProofLang::EnGb), now, Some((dict(), file.clone()))).unwrap(); + assert!(Arc::ptr_eq(&a.0, &b.0), "one copy of a file for every English that reads it"); + assert!(already_read(&state, &file).is_some()); + forget(&state); + assert!(already_read(&state, &file).is_none() && state.read().unwrap().slots.iter().all(Option::is_none)); } } diff --git a/crates/proof/src/hunspell.rs b/crates/proof/src/hunspell.rs index b19bdbd8..da2acb3e 100644 --- a/crates/proof/src/hunspell.rs +++ b/crates/proof/src/hunspell.rs @@ -145,6 +145,24 @@ pub fn find(names: &[&str]) -> Option<(PathBuf, PathBuf)> { search_dirs(lo.as_deref()).into_iter().find_map(|dir| find_in(&dir, names)) } +/// Every `.aff`/`.dic` pair for `names`, in the order [`find`] prefers them: folder +/// by folder ([`search_dirs`]), each folder's in the order of `names`. A caller that can't read +/// one tries the next. +pub fn candidates(names: &[&str]) -> Vec<(PathBuf, PathBuf)> { + let lo = names.first().copied().map(lo_ext_dirs); + let mut out: Vec<(PathBuf, PathBuf)> = Vec::new(); + for dir in search_dirs(lo.as_deref()) { + for n in names { + let aff = dir.join(format!("{n}.aff")); + let dic = dir.join(format!("{n}.dic")); + if aff.is_file() && dic.is_file() && !out.iter().any(|(_, d)| *d == dic) { + out.push((aff, dic)); + } + } + } + out +} + /// The first `.aff`/`.dic` pair for any of `names` in `dir`. pub fn find_in(dir: &Path, names: &[&str]) -> Option<(PathBuf, PathBuf)> { names.iter().find_map(|n| { @@ -183,6 +201,15 @@ pub fn load(aff: &Path, dic: &Path) -> Result { AffixDict::from_hunspell(&aff_text, &dic_text, &[source.as_str()]) } +/// [`load`] for an English dictionary: directives that only matter for other languages +/// (compounding, output conversion) are ignored rather than refused +/// ([`AffixDict::from_hunspell_english`]). +pub fn load_english(aff: &Path, dic: &Path) -> Result { + let (aff_text, dic_text) = decode(&read_capped(aff)?, &read_capped(dic)?)?; + let source = format!("Hunspell dictionary {}", dic.display()); + AffixDict::from_hunspell_english(&aff_text, &dic_text, &[source.as_str()]) +} + /// ISO 8859-1: every byte is the code point of the same value (the original VERO pt_BR uses it). fn decode_latin1(bytes: &[u8]) -> String { bytes.iter().map(|&b| char::from(b)).collect() diff --git a/crates/proof/src/lib.rs b/crates/proof/src/lib.rs index bb9866d6..85835797 100644 --- a/crates/proof/src/lib.rs +++ b/crates/proof/src/lib.rs @@ -51,8 +51,8 @@ //! **Language data** (the Moby word list, the pattern files, our word supplements) is embedded at //! build time from craft-i18n's `language-data/` (`CRAFT_I18N_DIR`, see `build.rs`). English //! spelling never goes unchecked: without the embedded word list it uses an English Hunspell -//! dictionary installed on the system, and without one the core word list built into the crate -//! (see [`english_source`]). Hyphenation that needs the data is off without it; grammar and the +//! dictionary installed on the system, and without one the whole Moby word list built into the +//! crate (see [`english_source`]). Hyphenation that needs the data is off without it; grammar and the //! rule-based hyphenation (Bulgarian, Turkish, Russian) are code and still work. #![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)] @@ -326,8 +326,9 @@ pub fn dictionary_load_error(lang: ProofLang) -> Option { /// Where the spelling of an English `lang` comes from now (`None` for other languages): the word /// list embedded at build time, else an English Hunspell dictionary from the dictionaries folder -/// or the system (the run's English first), else the core word list built into the crate, which -/// marks only near misses of common words. Reads the Hunspell dictionary once when there is no +/// or the system (the run's English first), else the Moby word list built into the crate. +/// British and Canadian English use an `en_US` Hunspell dictionary when no regional one is +/// installed. Reads the Hunspell dictionary once when there is no /// embedded word list (it is cached afterwards). pub fn english_source(lang: ProofLang) -> Option { lang.is_english().then(|| english::source(lang)) @@ -464,9 +465,11 @@ const COMMON: &str = "a an the and or but if of to in on at by for with from as /// lowercase base form per line, `#` comments. Inflections come from [`known_core`]. use data::EXTRA_EN; +/// The supplement's words: the Language data's copy, else the crate's own ([`english::EXTRA`]). fn extra_words() -> &'static HashSet<&'static str> { static E: OnceLock> = OnceLock::new(); - E.get_or_init(|| EXTRA_EN.lines().map(str::trim).filter(|l| !l.is_empty() && !l.starts_with('#')).collect()) + let extra = if EXTRA_EN.is_empty() { english::EXTRA } else { EXTRA_EN }; + E.get_or_init(|| extra.lines().map(str::trim).filter(|l| !l.is_empty() && !l.starts_with('#')).collect()) } /// A base form in the dictionary or the supplement. @@ -479,9 +482,9 @@ fn known_core(w: &str) -> bool { known_with(w, &|s| base_known(d, s)) } -/// [`known_core`] against the core word list built into the crate (no embedded word list). -pub(crate) fn known_in_core_list(w: &str) -> bool { - known_with(w, &|s| english::core_contains(s) || extra_words().contains(s)) +/// [`known_core`] against the word list built into the crate (no embedded word list). +pub(crate) fn known_in_word_list(w: &str) -> bool { + known_with(w, &|s| english::word_list_contains(s) || extra_words().contains(s)) } /// Is `w` (lower case) a word, by `base_known` (a base form in the word list), the common words, @@ -608,7 +611,7 @@ pub(crate) fn accepted_by_options(word: &str, opts: &Options) -> bool { } /// Is the English word list embedded? Without it English is checked against an installed -/// Hunspell dictionary or the core word list ([`english`]). +/// Hunspell dictionary or the word list built into the crate ([`english`]). pub(crate) fn english_data() -> bool { !dict::Dictionary::en_us().is_empty() } @@ -1196,7 +1199,7 @@ mod tests { } /// Remove the English files of `dir` and set it again: English goes back to what it was - /// (the core list, or a dictionary installed on the system), for the tests that follow. + /// (the built-in list, or a dictionary installed on the system), for the tests that follow. fn drop_english_files(dir: &std::path::Path, english: &[(&str, &[u8], &[u8])]) { for (name, _, _) in english { let _ = std::fs::remove_file(dir.join(format!("{name}.aff"))); @@ -1206,18 +1209,18 @@ mod tests { } /// R6.4, English never goes unchecked: with no embedded word list, an English Hunspell - /// dictionary (here in the dictionaries folder) is used before the core word list built into - /// the crate; with one, the embedded list stays in use whatever is installed. + /// dictionary (here in the dictionaries folder) is used before the word list built into the + /// crate; with one, the embedded list stays in use whatever is installed. #[test] - fn english_hunspell_dictionary_is_used_before_the_core_list() { + fn english_hunspell_dictionary_is_used_before_the_built_in_list() { let _guard = DICTIONARY_TESTS.lock().unwrap_or_else(std::sync::PoisonError::into_inner); let dir = std::env::temp_dir().join(format!("wc-proof-en-hunspell-{}", std::process::id())); - // A tiny en_US. `teh` is a word in it, so a right `teh` is this dictionary answering (the - // core list marks it); `hous` and `because` aren't. + // A tiny en_US. `hous` and `because` aren't words in it, so a marked `because` is this + // dictionary answering (the built-in list knows it). let english: &[(&str, &[u8], &[u8])] = &[("en_US", b"SET UTF-8\nTRY esiarntolcdugmphbyfvkwz\nSFX S Y 1\nSFX S 0 s .\n", b"3\nteh\nthe\nhouse/S\n")]; folder_with_english(&dir, english); - if cfg!(craft_proof_data) { + if english_data() { assert_eq!(english_source(ProofLang::En), Some(EnglishSource::Embedded)); // (The Moby list has `teh`.) assert!(!is_correct_in("becuase", ProofLang::En) && is_correct_in("because", ProofLang::En)); @@ -1229,12 +1232,12 @@ mod tests { assert!(is_correct_in(w, ProofLang::En), "{w}"); } for w in ["hous", "because", "housez"] { - assert!(!is_correct_in(w, ProofLang::En), "{w}: the dictionary's words, not the core list's"); + assert!(!is_correct_in(w, ProofLang::En), "{w}: the dictionary's words, not the built-in list's"); } assert!(!is_correct("hous") && is_correct("teh"), "the older English-only functions too"); assert_eq!(check_spelling_in("teh hous", ProofLang::En).len(), 1); assert!(suggest_in("hous", 3, ProofLang::En).contains(&"house".to_string()), "{:?}", suggest_in("hous", 3, ProofLang::En)); - // No en_GB or en_CA file: the en_US one beats the core list. + // No en_GB or en_CA file: they use the en_US one (one copy, shared). assert_eq!(english_source(ProofLang::EnGb), Some(EnglishSource::Hunspell(dic.clone()))); assert_eq!(english_source(ProofLang::EnCa), Some(EnglishSource::Hunspell(dic))); } @@ -1243,14 +1246,15 @@ mod tests { assert!(check_text("hous teh", &[(0..8, ProofLang::De)]).is_empty()); assert_eq!(english_source(ProofLang::Pl), None); drop_english_files(&dir, english); - if !cfg!(craft_proof_data) { + if !english_data() { assert_ne!(english_source(ProofLang::En), Some(EnglishSource::Hunspell(dir.join("en_US.dic")))); } } /// R6.4: an English Hunspell dictionary that is there but can't be read (an encoding we don't /// read, bytes that aren't UTF-8, no words) is an error reported for its English, never a - /// panic, and that English falls back to the core list, which still marks `becuase`. + /// panic, and that English falls back to the next dictionary or the built-in word list, which + /// still marks `becuase`. #[test] fn unreadable_english_dictionary_is_reported_and_skipped() { let _guard = DICTIONARY_TESTS.lock().unwrap_or_else(std::sync::PoisonError::into_inner); @@ -1259,11 +1263,13 @@ mod tests { &[("en_US", b"SET UTF-8\n", b"0\n"), ("en_GB", b"SET SHIFT_JIS\n", b"1\ncolour\n"), ("en_CA", b"SET UTF-8\n", b"1\n\xff\xfe\n")]; folder_with_english(&dir, english); for (lang, reason) in [(ProofLang::En, "no words"), (ProofLang::EnGb, "unsupported encoding"), (ProofLang::EnCa, "not UTF-8")] { - if cfg!(craft_proof_data) { + if english_data() { assert_eq!(english_source(lang), Some(EnglishSource::Embedded)); assert_eq!(dictionary_load_error(lang), None, "{lang:?}: never read"); } else { - assert_eq!(english_source(lang), Some(EnglishSource::CoreList), "{lang:?}"); + // The built-in list, or a dictionary installed on the system (tried next). + let source = english_source(lang); + assert!(!matches!(&source, Some(EnglishSource::Hunspell(p)) if p.starts_with(&dir)), "{lang:?}: {source:?}"); let error = dictionary_load_error(lang).unwrap_or_default(); assert!(error.contains(reason), "{lang:?}: {error}"); } @@ -1274,6 +1280,36 @@ mod tests { assert_eq!(dictionary_load_error(ProofLang::EnGb), None, "a new folder forgets the old errors"); } + /// craft-libs#482 review: an English dictionary that can't be read is skipped for the next + /// name or folder, not for the built-in list; and a dictionary with compounding and output + /// conversion (as the usual en_US and en_GB ones have) is read, not refused. + #[test] + fn english_tries_the_next_dictionary_and_reads_real_world_directives() { + let _guard = DICTIONARY_TESTS.lock().unwrap_or_else(std::sync::PoisonError::into_inner); + let dir = std::env::temp_dir().join(format!("wc-proof-en-next-{}", std::process::id())); + let english: &[(&str, &[u8], &[u8])] = &[ + ("en_GB", b"SET SHIFT_JIS\n", b"1\ncolour\n"), + ( + "en_US", + b"SET UTF-8\nICONV 1\nICONV \xe2\x80\x99 '\nOCONV 1\nOCONV ' \xe2\x80\x99\nCOMPOUNDMIN 1\nONLYINCOMPOUND c\n\ + COMPOUNDRULE 1\nCOMPOUNDRULE n*1t\nSFX S Y 1\nSFX S 0 s .\n", + b"4\nhouse/S\nthe\nqwzzy\n1st/c\n", + ), + ]; + folder_with_english(&dir, english); + if !english_data() { + let us = dir.join("en_US.dic"); + for lang in [ProofLang::En, ProofLang::EnGb, ProofLang::EnCa] { + assert_eq!(english_source(lang), Some(EnglishSource::Hunspell(us.clone())), "{lang:?}"); + assert!(is_correct_in("qwzzy", lang) && is_correct_in("houses", lang) && !is_correct_in("because", lang), "{lang:?}"); + } + let error = dictionary_load_error(ProofLang::EnGb).unwrap_or_default(); + assert!(error.contains("unsupported encoding"), "the en_GB file it would rather use is reported: {error}"); + assert_eq!(dictionary_load_error(ProofLang::En), None); + } + drop_english_files(&dir, english); + } + /// #1063: the dictionaries folder is searched before the system locations; the dictionaries /// in it are reported and used, and cached checks are dropped. The folder holds the same test /// dictionaries the other tests install, so tests running meanwhile see the same words; it @@ -1718,8 +1754,8 @@ mod tests { assert!(words.iter().all(|w| w.chars().all(|c| c.is_lowercase() || c == '\'' || c == '-')), "not lowercase"); } - /// Without the Language data too: the installed English dictionary or the core list marks - /// both near misses (R6.4). + /// Without the Language data too: the installed English dictionary or the built-in word list + /// marks both misspellings (R6.4). #[test] fn spelling_issues_in_text() { let _guard = DICTIONARY_TESTS.lock().unwrap_or_else(std::sync::PoisonError::into_inner); @@ -1758,12 +1794,13 @@ mod tests { assert!(["xyzq", "blorp", "qwirpy", "zxq", "frobq", "zibb", "snorf", "wugwug"].iter().all(|w| bad.contains(w)), "{bad:?}"); } - #[cfg_attr(not(craft_proof_data), ignore = "needs the Language data (CRAFT_I18N_DIR)")] #[test] fn spelling_scales_over_one_long_token() { // #1335: thousands of punctuation-separated words inside a single // whitespace-free token: one classification for the token, one issue per - // misspelled word, through every public spelling entry point. + // misspelled word, through every public spelling entry point. Without the Language data + // too (craft-libs#482 review: the old core list took 14 s here). + let started = std::time::Instant::now(); let word = |i: usize| { let mut w = String::from("zxq"); let mut n = i; @@ -1782,6 +1819,8 @@ mod tests { let opts = Options { ignore_internet: false, ..Options::default() }; assert_eq!(check_spelling_with(&t, &opts).len(), 2000); assert_eq!(check_text(&t, &[]).into_iter().filter(|i| i.kind == IssueKind::Spelling).count(), 2000); + // Debug builds on a loaded CI machine: a bound against blowups, not a benchmark. + assert!(started.elapsed() < std::time::Duration::from_secs(10), "{:?}", started.elapsed()); } #[test] diff --git a/crates/proof/src/no_data.rs b/crates/proof/src/no_data.rs index 017e0ba0..218f5d2c 100644 --- a/crates/proof/src/no_data.rs +++ b/crates/proof/src/no_data.rs @@ -1,6 +1,6 @@ //! A build with no Language data embedded (no `CRAFT_I18N_DIR`): every public entry point still -//! works and never panics. English spelling still marks obvious misspellings, against an English -//! Hunspell dictionary installed on the system or else the core word list built into the crate; +//! works and never panics. English spelling still marks misspellings, against an English +//! Hunspell dictionary installed on the system or else the Moby word list built into the crate; //! the dialect variants and hyphenation that need the data are off, and grammar (code, not data) //! still works. @@ -53,23 +53,25 @@ fn nothing_is_embedded() { } /// R6.4, English never goes unchecked: without the embedded word list, English is checked against -/// an installed English Hunspell dictionary or, without one, the core word list. Either way an -/// obvious misspelling is marked and common words are right. (Before, everything was right.) +/// an installed English Hunspell dictionary or, without one, the Moby word list built into the +/// crate. Either way a misspelling is marked and common words are right. (Before, everything was right.) #[test] fn english_spelling_still_marks_misspellings() { let _guard = crate::DICTIONARY_TESTS.lock().unwrap_or_else(std::sync::PoisonError::into_inner); for l in [ProofLang::En, ProofLang::EnGb, ProofLang::EnCa] { assert!(matches!(crate::english_source(l), Some(EnglishSource::Hunspell(_) | EnglishSource::CoreList)), "{l:?}"); - assert!(!crate::is_correct_in("teh", l), "{l:?}"); - assert!(crate::suggest_in("teh", 5, l).contains(&"the".to_string()), "{l:?}"); + assert!(!crate::is_correct_in("becuase", l), "{l:?}"); + assert!(crate::suggest_in("becuase", 5, l).contains(&"because".to_string()), "{l:?}"); for w in ["the", "The", "house", "houses", "because", "running", "people", "beautiful", "don't"] { assert!(crate::is_correct_in(w, l), "{w} {l:?}"); } - assert_eq!(crate::check_spelling_in("Teh house of the people", l).len(), 1, "{l:?}"); + assert_eq!(crate::check_spelling_in("Becuase the house of the people", l).len(), 1, "{l:?}"); } - assert!(!crate::is_correct("teh") && !crate::is_correct_with("teh", &Options::default()) && !crate::is_correct_for("teh", Some("en-GB"))); - assert!(crate::suggest("teh", 5).contains(&"the".to_string())); - assert_eq!(crate::check_spelling("Teh house").len(), 1); + assert!( + !crate::is_correct("becuase") && !crate::is_correct_with("becuase", &Options::default()) && !crate::is_correct_for("becuase", Some("en-GB")) + ); + assert!(crate::suggest("becuase", 5).contains(&"because".to_string())); + assert_eq!(crate::check_spelling("Becuase house").len(), 1); // The dialect variants are Language data: none without it. for w in ["colour", "color"] { assert_eq!(en_variants::preferred(w, ProofLang::En), None); diff --git a/crates/proof/src/vi.rs b/crates/proof/src/vi.rs index 66a4af76..cef4deb3 100644 --- a/crates/proof/src/vi.rs +++ b/crates/proof/src/vi.rs @@ -83,7 +83,7 @@ mod checker_tests { assert!(check_text_with(text, &[], &Options::default(), true, false).is_empty()); } - /// Without the Language data too: the installed English dictionary or the core list marks + /// Without the Language data too: the installed English dictionary or the built-in word list marks /// `yesterdy` (R6.4). #[test] fn english_keeps_its_marks_and_skips_vietnamese_names() {