From 485da4224c6cad6b37d4caf17fe6160ccf978d70 Mon Sep 17 00:00:00 2001 From: MehdiK Date: Mon, 20 Jan 2014 22:04:51 +0330 Subject: [PATCH 1/4] Added ToPast & ToPastParticiple - #58 --- readme.md | 29 ++ src/Humanizer.Tests/EnglishTenseTests.cs | 357 +++++++++++++++++++++ src/Humanizer.Tests/Humanizer.Tests.csproj | 1 + src/Humanizer/EnglishTenseExtensions.cs | 224 +++++++++++++ src/Humanizer/Humanizer.csproj | 1 + 5 files changed, 612 insertions(+) create mode 100644 src/Humanizer.Tests/EnglishTenseTests.cs create mode 100644 src/Humanizer/EnglishTenseExtensions.cs diff --git a/readme.md b/readme.md index 2c0396a18..33d18235f 100644 --- a/readme.md +++ b/readme.md @@ -313,6 +313,35 @@ This is kind of mixing `ToWords` with `Ordinalize`. You can call `ToOrdinalWords 121.ToOrdinalWords() => "hundred and twenty first" ``` +###English Tense +There are a few methods that help manipulate English verbs. + +####ToPast +`ToPast` converts a simple present verb into simple past taking irregular verbs into consideration: + +```C# +"Test".ToPast() => "Tested" +"Cry".ToPast() => "Cried" +"Love".ToPast() => "Loved" + +"Fly".ToPast() => "Flew" +"Freeze".ToPast() => "Froze" +"Grind".ToPast() => "Ground" +``` + +####ToPastParticiple +`ToPastParticiple` converts simple past to past participle taking irregular verbs into consideration: + +```C# +"Test".ToPastParticiple() => "Tested" +"Cry".ToPastParticiple() => "Cried" +"Love".ToPastParticiple() => "Loved" + +"Fly".ToPastParticiple() => "Flown" +"Freeze".ToPastParticiple() => "Frozen" +"Grind".ToPastParticiple() => "Ground" +``` + ###Mix this into your framework to simplify your life This is just a baseline and you can use this to simplify your day to day job. For example, in Asp.Net MVC we keep chucking `Display` attribute on ViewModel properties so `HtmlHelper` can generate correct labels for us; but, just like enums, in vast majority of cases we just need a space between the words in property name - so why not use `"string".Humanize` for that?! diff --git a/src/Humanizer.Tests/EnglishTenseTests.cs b/src/Humanizer.Tests/EnglishTenseTests.cs new file mode 100644 index 000000000..6a42d68c6 --- /dev/null +++ b/src/Humanizer.Tests/EnglishTenseTests.cs @@ -0,0 +1,357 @@ +using Xunit; +using Xunit.Extensions; + +namespace Humanizer.Tests +{ + public class EnglishTenseTests + { + [Theory] + // Irregular verbs + [InlineData("Arise","Arose")] + [InlineData("Awake","Awoke")] + [InlineData("Be","Was")] + [InlineData("am","Was")] + [InlineData("are","Were")] + [InlineData("is","Was")] + [InlineData("Bear","Bore")] + [InlineData("Beat","Beat")] + [InlineData("Become","Became")] + [InlineData("Begin","Began")] + [InlineData("Bend","Bent")] + [InlineData("Bet","Bet")] + [InlineData("Bind","Bound")] + [InlineData("Bid","Bid")] + [InlineData("Bite","Bit")] + [InlineData("Bleed","Bled")] + [InlineData("Blow","Blew")] + [InlineData("Break","Broke")] + [InlineData("Breed","Bred")] + [InlineData("Bring","Brought")] + [InlineData("Broadcast","Broadcast")] + [InlineData("Build","Built")] + [InlineData("Burn","Burnt")] + [InlineData("Burst","Burst")] + [InlineData("Buy","Bought")] + [InlineData("Cast","Cast")] + [InlineData("Catch","Caught")] + [InlineData("Come","Came")] + [InlineData("Cost","Cost")] + [InlineData("Cut","Cut")] + [InlineData("Choose","Chose")] + [InlineData("Cling","Clung")] + [InlineData("Creep","Crept")] + [InlineData("Deal","Dealt")] + [InlineData("Dig","Dug")] + [InlineData("Do","Did")] + [InlineData("Does","Did")] + [InlineData("Draw","Drew")] + [InlineData("Dream","Dreamt")] + [InlineData("Drink","Drank")] + [InlineData("Drive","Drove")] + [InlineData("Eat","Ate")] + [InlineData("Fall","Fell")] + [InlineData("Feed","Fed")] + [InlineData("Feel","Felt")] + [InlineData("Fight","Fought")] + [InlineData("Find","Found")] + [InlineData("Flee","Fled")] + [InlineData("Fly","Flew")] + [InlineData("Forbid","Forbade")] + [InlineData("Forget","Forgot")] + [InlineData("Forgive","Forgave")] + [InlineData("Freeze","Froze")] + [InlineData("Get","Got")] + [InlineData("Give","Gave")] + [InlineData("Go","Went")] + [InlineData("Goes","Went")] + [InlineData("Grow","Grew")] + [InlineData("Grind","Ground")] + [InlineData("Hang","Hung")] + [InlineData("Have","Had")] + [InlineData("Hear","Heard")] + [InlineData("Hide","Hid")] + [InlineData("Hit","Hit")] + [InlineData("Hold","Held")] + [InlineData("Hurt","Hurt")] + [InlineData("Keep","Kept")] + [InlineData("Know","Knew")] + [InlineData("Kneel","Knelt")] + [InlineData("Knit","Knit")] + [InlineData("Lay","Laid")] + [InlineData("Lead","Led")] + [InlineData("Lean","Leant")] + [InlineData("Leap","Leapt")] + [InlineData("Learn","Learnt")] + [InlineData("Leave","Left")] + [InlineData("Lend","Lent")] + [InlineData("Let","Let")] + [InlineData("Lie","Lay")] + [InlineData("Light","Lit")] + [InlineData("Lose","Lost")] + [InlineData("Make","Made")] + [InlineData("Mean","Meant")] + [InlineData("Meet","Met")] + [InlineData("Mistake","Mistook")] + [InlineData("Overcome","Overcame")] + [InlineData("Pay","Paid")] + [InlineData("Put","Put")] + [InlineData("Read","Read")] + [InlineData("Ride","Rode")] + [InlineData("Ring","Rang")] + [InlineData("Rise","Rose")] + [InlineData("Run","Ran")] + [InlineData("Say","Said")] + [InlineData("See","Saw")] + [InlineData("Seek","Sought")] + [InlineData("Sell","Sold")] + [InlineData("Send","Sent")] + [InlineData("Set","Set")] + [InlineData("Sew","Sewed")] + [InlineData("Shake","Shook")] + [InlineData("Shear","Shore")] + [InlineData("Shine","Shone")] + [InlineData("Shoot","Shot")] + [InlineData("Show","Showed")] + [InlineData("Shrink","Shrank")] + [InlineData("Shut","Shut")] + [InlineData("Sing","Sang")] + [InlineData("Sink","Sank")] + [InlineData("Sit","Sat")] + [InlineData("Sleep","Slept")] + [InlineData("Slide","Slid")] + [InlineData("Smell","Smelt")] + [InlineData("Sow","Sowed")] + [InlineData("Speak","Spoke")] + [InlineData("Speed","Sped")] + [InlineData("Spell","Spelt")] + [InlineData("Spend","Spent")] + [InlineData("Spill","Spilt")] + [InlineData("Spin","Spun")] + [InlineData("Spit","Spat")] + [InlineData("Split","Split")] + [InlineData("Spoil","Spoilt")] + [InlineData("Spread","Spread")] + [InlineData("Spring","Sprang")] + [InlineData("Stand","Stood")] + [InlineData("Steal","Stole")] + [InlineData("Stick","Stuck")] + [InlineData("Sting","Stung")] + [InlineData("Stink","Stank")] + [InlineData("Stride","Strode")] + [InlineData("Strike","Struck")] + [InlineData("Swear","Swore")] + [InlineData("Sweat","Sweat")] + [InlineData("Sweep","Swept")] + [InlineData("Swell","Swelled")] + [InlineData("Swim","Swam")] + [InlineData("Swing","Swung")] + [InlineData("Take","Took")] + [InlineData("Teach","Taught")] + [InlineData("Tear","Tore")] + [InlineData("Tell","Told")] + [InlineData("Think","Thought")] + [InlineData("Throw","Threw")] + [InlineData("Thrust","Thrust")] + [InlineData("Tread","Trod")] + [InlineData("Understand","Understood")] + [InlineData("Undergo","Underwent")] + [InlineData("Undertake","Undertook")] + [InlineData("Wake","Woke")] + [InlineData("Wear","Wore")] + [InlineData("Weave","Wove")] + [InlineData("Weep","Wept")] + [InlineData("Wet","Wet")] + [InlineData("Win","Won")] + [InlineData("Wind","Wound")] + [InlineData("Withdraw","Withdrew")] + [InlineData("Wring","Wrung")] + [InlineData("Write","Wrote")] + // normal verbs + [InlineData("Decide","Decided")] + [InlineData("Perform","Performed")] + [InlineData("Cry","Cried")] + [InlineData("Test","Tested")] + [InlineData("Love","Loved")] + [InlineData("Walk","Walked")] + [InlineData("BDDfy","BDDfied")] + public void ToPast(string present, string past) + { + Assert.Equal(past, present.ToPast()); + } + + [Theory] + // Irregular verbs + [InlineData("Arise","Arisen")] + [InlineData("Awake","Awoken")] + [InlineData("Be","Been")] + [InlineData("am","Been")] + [InlineData("are","Been")] + [InlineData("is","Been")] + [InlineData("Bear","Born")] + [InlineData("Beat","Beaten")] + [InlineData("Become","Become")] + [InlineData("Begin","Begun")] + [InlineData("Bend","Bent")] + [InlineData("Bet","Bet")] + [InlineData("Bind","Bound")] + [InlineData("Bid","Bid")] + [InlineData("Bite","Bitten")] + [InlineData("Bleed","Bled")] + [InlineData("Blow","Blown")] + [InlineData("Break","Broken")] + [InlineData("Breed","Bred")] + [InlineData("Bring","Brought")] + [InlineData("Broadcast","Broadcast")] + [InlineData("Build","Built")] + [InlineData("Burn","Burnt")] + [InlineData("Burst","Burst")] + [InlineData("Buy","Bought")] + [InlineData("Cast","Cast")] + [InlineData("Can","Could")] + [InlineData("Catch","Caught")] + [InlineData("Come","Come")] + [InlineData("Cost","Cost")] + [InlineData("Cut","Cut")] + [InlineData("Choose","Chosen")] + [InlineData("Cling","Clung")] + [InlineData("Creep","Crept")] + [InlineData("Deal","Dealt")] + [InlineData("Dig","Dug")] + [InlineData("Do","Done")] + [InlineData("Does","Done")] + [InlineData("Draw","Drawn")] + [InlineData("Dream","Dreamt")] + [InlineData("Drink","Drunk")] + [InlineData("Drive","Driven")] + [InlineData("Eat","Eaten")] + [InlineData("Fall","Fallen")] + [InlineData("Feed","Fed")] + [InlineData("Feel","Felt")] + [InlineData("Fight","Fought")] + [InlineData("Find","Found")] + [InlineData("Flee","Fled")] + [InlineData("Fly","Flown")] + [InlineData("Forbid","Forbidden")] + [InlineData("Forget","Forgotten")] + [InlineData("Forgive","Forgiven")] + [InlineData("Freeze","Frozen")] + [InlineData("Get","Gotten")] + [InlineData("Give","Given")] + [InlineData("Go","Gone")] + [InlineData("Goes","Gone")] + [InlineData("Grow","Grown")] + [InlineData("Grind","Ground")] + [InlineData("Hang","Hung")] + [InlineData("Have","Had")] + [InlineData("Hear","Heard")] + [InlineData("Hide","Hidden")] + [InlineData("Hit","Hit")] + [InlineData("Hold","Held")] + [InlineData("Hurt","Hurt")] + [InlineData("Keep","Kept")] + [InlineData("Know","Known")] + [InlineData("Kneel","Knelt")] + [InlineData("Knit","Knit")] + [InlineData("Lay","Laid")] + [InlineData("Lead","Led")] + [InlineData("Lean","Leant")] + [InlineData("Leap","Leapt")] + [InlineData("Learn","Learnt")] + [InlineData("Leave","Left")] + [InlineData("Lend","Lent")] + [InlineData("Let","Let")] + [InlineData("Lie","Lain")] + [InlineData("Light","Lit")] + [InlineData("Lose","Lost")] + [InlineData("Make","Made")] + [InlineData("Mean","Meant")] + [InlineData("Meet","Met")] + [InlineData("Mistake","Mistaken")] + [InlineData("Overcome","Overcome")] + [InlineData("Pay","Paid")] + [InlineData("Put","Put")] + [InlineData("Read","Read")] + [InlineData("Ride","Ridden")] + [InlineData("Ring","Rung")] + [InlineData("Rise","Risen")] + [InlineData("Run","Run")] + [InlineData("Say","Said")] + [InlineData("See","Seen")] + [InlineData("Seek","Sought")] + [InlineData("Sell","Sold")] + [InlineData("Send","Sent")] + [InlineData("Set","Set")] + [InlineData("Sew","Sewed")] + [InlineData("Shake","Shaken")] + [InlineData("Shear","Shorn")] + [InlineData("Shine","Shone")] + [InlineData("Shoot","Shot")] + [InlineData("Show","Shown")] + [InlineData("Shrink","Shrunk")] + [InlineData("Shut","Shut")] + [InlineData("Sing","Sung")] + [InlineData("Sink","Sunk")] + [InlineData("Sit","Sat")] + [InlineData("Sleep","Slept")] + [InlineData("Slide","Slid")] + [InlineData("Smell","Smelt")] + [InlineData("Sow","Sowed")] + [InlineData("Speak","Spoken")] + [InlineData("Speed","Sped")] + [InlineData("Spell","Spelt")] + [InlineData("Spend","Spent")] + [InlineData("Spill","Spilt")] + [InlineData("Spin","Spun")] + [InlineData("Spit","Spat")] + [InlineData("Split","Split")] + [InlineData("Spoil","Spoilt")] + [InlineData("Spread","Spread")] + [InlineData("Spring","Sprung")] + [InlineData("Stand","Stood")] + [InlineData("Steal","Stolen")] + [InlineData("Stick","Stuck")] + [InlineData("Sting","Stung")] + [InlineData("Stink","Stunk")] + [InlineData("Stride","Stridden")] + [InlineData("Strike","Struck")] + [InlineData("Swear","Sworn")] + [InlineData("Sweat","Sweat")] + [InlineData("Sweep","Swept")] + [InlineData("Swell","Swollen")] + [InlineData("Swim","Swum")] + [InlineData("Swing","Swung")] + [InlineData("Take","Taken")] + [InlineData("Teach","Taught")] + [InlineData("Tear","Torn")] + [InlineData("Tell","Told")] + [InlineData("Think","Thought")] + [InlineData("Throw","Thrown")] + [InlineData("Thrust","Thrust")] + [InlineData("Tread","Trodden")] + [InlineData("Understand","Understood")] + [InlineData("Undergo","Undergone")] + [InlineData("Undertake","Undertaken")] + [InlineData("Wake","Woken")] + [InlineData("Wear","Worn")] + [InlineData("Weave","Woven")] + [InlineData("Weep","Wept")] + [InlineData("Wet","Wet")] + [InlineData("Win","Won")] + [InlineData("Wind","Wound")] + [InlineData("Withdraw","Withdrawn")] + [InlineData("Wring","Wrung")] + [InlineData("Write","Written")] + // normal verbs + [InlineData("Decide", "Decided")] + [InlineData("Perform", "Performed")] + [InlineData("Cry", "Cried")] + [InlineData("Test", "Tested")] + [InlineData("Love", "Loved")] + [InlineData("Walk", "Walked")] + [InlineData("BDDfy", "BDDfied")] + public void ToPastParticiple(string present, string pastParticiple) + { + Assert.Equal(pastParticiple, present.ToPastParticiple()); + } + } +} diff --git a/src/Humanizer.Tests/Humanizer.Tests.csproj b/src/Humanizer.Tests/Humanizer.Tests.csproj index ae9db0420..77d31b90d 100644 --- a/src/Humanizer.Tests/Humanizer.Tests.csproj +++ b/src/Humanizer.Tests/Humanizer.Tests.csproj @@ -71,6 +71,7 @@ + diff --git a/src/Humanizer/EnglishTenseExtensions.cs b/src/Humanizer/EnglishTenseExtensions.cs new file mode 100644 index 000000000..ceb5a3b0e --- /dev/null +++ b/src/Humanizer/EnglishTenseExtensions.cs @@ -0,0 +1,224 @@ +using System.Collections.Generic; + +namespace Humanizer +{ + public static class EnglishTenseExtensions + { + static EnglishTenseExtensions() + { + SetupDictionaries("Arise","Arose","Arisen"); + SetupDictionaries("Awake","Awoke","Awoken"); + SetupDictionaries("Be","Was","Been"); + SetupDictionaries("am","Was","Been"); + SetupDictionaries("are","Were","Been"); + SetupDictionaries("is","Was","Been"); + SetupDictionaries("Bear","Bore","Born" /* ToDo Borne */); + SetupDictionaries("Beat","Beat","Beaten"); + SetupDictionaries("Become","Became","Become"); + SetupDictionaries("Begin","Began","Begun"); + SetupDictionaries("Bend","Bent","Bent"); + SetupDictionaries("Bet","Bet","Bet"); + SetupDictionaries("Bind","Bound","Bound"); + SetupDictionaries("Bid","Bid","Bid"); + SetupDictionaries("Bite","Bit","Bitten"); + SetupDictionaries("Bleed","Bled","Bled"); + SetupDictionaries("Blow","Blew","Blown"); + SetupDictionaries("Break","Broke","Broken"); + SetupDictionaries("Breed","Bred","Bred"); + SetupDictionaries("Bring","Brought","Brought"); + SetupDictionaries("Broadcast","Broadcast","Broadcast"); + SetupDictionaries("Build","Built","Built"); + //SetupDictionaries("Burn","Burnt /Burned","Burnt / Burned"); + SetupDictionaries("Burn","Burnt","Burnt"); + SetupDictionaries("Burst","Burst","Burst"); + SetupDictionaries("Buy","Bought","Bought"); + SetupDictionaries("Cast","Cast","Cast"); + SetupDictionaries("Can","Could","Could"); + SetupDictionaries("Catch","Caught","Caught"); + SetupDictionaries("Come","Came","Come"); + SetupDictionaries("Cost","Cost","Cost"); + SetupDictionaries("Cut","Cut","Cut"); + SetupDictionaries("Choose","Chose","Chosen"); + SetupDictionaries("Cling","Clung","Clung"); + SetupDictionaries("Creep","Crept","Crept"); + SetupDictionaries("Deal","Dealt","Dealt"); + SetupDictionaries("Dig","Dug","Dug"); + SetupDictionaries("Do","Did","Done"); + SetupDictionaries("Does","Did","Done"); + SetupDictionaries("Draw","Drew","Drawn"); + SetupDictionaries("Dream","Dreamt","Dreamt"); + //SetupDictionaries("Dream","Dreamt / Dreamed","Dreamt / Dreamed"); + SetupDictionaries("Drink","Drank","Drunk"); + SetupDictionaries("Drive","Drove","Driven"); + SetupDictionaries("Eat","Ate","Eaten"); + SetupDictionaries("Fall","Fell","Fallen"); + SetupDictionaries("Feed","Fed","Fed"); + SetupDictionaries("Feel","Felt","Felt"); + SetupDictionaries("Fight","Fought","Fought"); + SetupDictionaries("Find","Found","Found"); + SetupDictionaries("Flee","Fled","Fled"); + SetupDictionaries("Fly","Flew","Flown"); + SetupDictionaries("Forbid","Forbade","Forbidden"); + SetupDictionaries("Forget","Forgot","Forgotten"); + SetupDictionaries("Forgive","Forgave","Forgiven"); + SetupDictionaries("Freeze","Froze","Frozen"); + SetupDictionaries("Get","Got","Gotten"); + //SetupDictionaries("Get","Got","Got / Gotten"); + SetupDictionaries("Give","Gave","Given"); + SetupDictionaries("Go","Went","Gone"); + SetupDictionaries("Goes","Went","Gone"); + SetupDictionaries("Grow","Grew","Grown"); + SetupDictionaries("Grind","Ground","Ground"); + SetupDictionaries("Hang","Hung","Hung"); + SetupDictionaries("Have","Had","Had"); + SetupDictionaries("Hear","Heard","Heard"); + SetupDictionaries("Hide","Hid","Hidden"); + SetupDictionaries("Hit","Hit","Hit"); + SetupDictionaries("Hold","Held","Held"); + SetupDictionaries("Hurt","Hurt","Hurt"); + SetupDictionaries("Keep","Kept","Kept"); + SetupDictionaries("Know","Knew","Known"); + SetupDictionaries("Kneel","Knelt","Knelt"); + SetupDictionaries("Knit","Knit","Knit"); + SetupDictionaries("Lay","Laid","Laid"); + SetupDictionaries("Lead","Led","Led"); + SetupDictionaries("Lean","Leant","Leant"); + SetupDictionaries("Leap","Leapt","Leapt"); + SetupDictionaries("Learn","Learnt","Learnt"); + //SetupDictionaries("Learn","Learnt / Learned","Learnt / Learned"); + SetupDictionaries("Leave","Left","Left"); + SetupDictionaries("Lend","Lent","Lent"); + SetupDictionaries("Let","Let","Let"); + SetupDictionaries("Lie","Lay","Lain"); + SetupDictionaries("Light","Lit","Lit"); + SetupDictionaries("Lose","Lost","Lost"); + SetupDictionaries("Make","Made","Made"); + SetupDictionaries("Mean","Meant","Meant"); + SetupDictionaries("Meet","Met","Met"); + SetupDictionaries("Mistake","Mistook","Mistaken"); + SetupDictionaries("Overcome","Overcame","Overcome"); + SetupDictionaries("Pay","Paid","Paid"); + SetupDictionaries("Put","Put","Put"); + SetupDictionaries("Read","Read","Read"); + SetupDictionaries("Ride","Rode","Ridden"); + SetupDictionaries("Ring","Rang","Rung"); + SetupDictionaries("Rise","Rose","Risen"); + SetupDictionaries("Run","Ran","Run"); + SetupDictionaries("Say","Said","Said"); + SetupDictionaries("See","Saw","Seen"); + SetupDictionaries("Seek","Sought","Sought"); + SetupDictionaries("Sell","Sold","Sold"); + SetupDictionaries("Send","Sent","Sent"); + SetupDictionaries("Set","Set","Set"); + SetupDictionaries("Sew","Sewed","Sewed"); + //SetupDictionaries("Sew","Sewed","Sewed / Sewn"); + SetupDictionaries("Shake","Shook","Shaken"); + SetupDictionaries("Shear","Shore","Shorn"); + SetupDictionaries("Shine","Shone","Shone"); + SetupDictionaries("Shoot","Shot","Shot"); + SetupDictionaries("Show","Showed","Shown"); + SetupDictionaries("Shrink","Shrank","Shrunk"); + SetupDictionaries("Shut","Shut","Shut"); + SetupDictionaries("Sing","Sang","Sung"); + SetupDictionaries("Sink","Sank","Sunk"); + SetupDictionaries("Sit","Sat","Sat"); + SetupDictionaries("Sleep","Slept","Slept"); + SetupDictionaries("Slide","Slid","Slid"); + SetupDictionaries("Smell","Smelt","Smelt"); + SetupDictionaries("Sow","Sowed","Sowed"); + //SetupDictionaries("Sow","Sowed","Sowed / Sown"); + SetupDictionaries("Speak","Spoke","Spoken"); + SetupDictionaries("Speed","Sped","Sped"); + SetupDictionaries("Spell","Spelt","Spelt"); + SetupDictionaries("Spend","Spent","Spent"); + SetupDictionaries("Spill","Spilt","Spilt"); + //SetupDictionaries("Spill","Spilt / Spilled","Spilt / Spilled"); + SetupDictionaries("Spin","Spun","Spun"); + SetupDictionaries("Spit","Spat","Spat"); + SetupDictionaries("Split","Split","Split"); + SetupDictionaries("Spoil","Spoilt","Spoilt"); + //SetupDictionaries("Spoil","Spoilt / Spoiled","Spoilt / Spoiled"); + SetupDictionaries("Spread","Spread","Spread"); + SetupDictionaries("Spring","Sprang","Sprung"); + SetupDictionaries("Stand","Stood","Stood"); + SetupDictionaries("Steal","Stole","Stolen"); + SetupDictionaries("Stick","Stuck","Stuck"); + SetupDictionaries("Sting","Stung","Stung"); + SetupDictionaries("Stink","Stank","Stunk"); + SetupDictionaries("Stride","Strode","Stridden"); + SetupDictionaries("Strike","Struck","Struck"); + SetupDictionaries("Swear","Swore","Sworn"); + SetupDictionaries("Sweat","Sweat","Sweat"); + SetupDictionaries("Sweep","Swept","Swept"); + SetupDictionaries("Swell","Swelled","Swollen"); + SetupDictionaries("Swim","Swam","Swum"); + SetupDictionaries("Swing","Swung","Swung"); + SetupDictionaries("Take","Took","Taken"); + SetupDictionaries("Teach","Taught","Taught"); + SetupDictionaries("Tear","Tore","Torn"); + SetupDictionaries("Tell","Told","Told"); + SetupDictionaries("Think","Thought","Thought"); + SetupDictionaries("Throw","Threw","Thrown"); + SetupDictionaries("Thrust","Thrust","Thrust"); + SetupDictionaries("Tread","Trod","Trodden"); + SetupDictionaries("Understand","Understood","Understood"); + SetupDictionaries("Undergo","Underwent","Undergone"); + SetupDictionaries("Undertake","Undertook","Undertaken"); + SetupDictionaries("Wake","Woke","Woken"); + SetupDictionaries("Wear","Wore","Worn"); + SetupDictionaries("Weave","Wove","Woven"); + SetupDictionaries("Weep","Wept","Wept"); + SetupDictionaries("Wet","Wet","Wet"); + SetupDictionaries("Win","Won","Won"); + SetupDictionaries("Wind","Wound","Wound"); + SetupDictionaries("Withdraw","Withdrew","Withdrawn"); + SetupDictionaries("Wring","Wrung","Wrung"); + SetupDictionaries("Write","Wrote","Written"); + } + + static readonly Dictionary PresentToSimplePast = new Dictionary(); + static readonly Dictionary PresentToPastParticple = new Dictionary(); + private static void SetupDictionaries(string present, string simplePast, string pastParticiple) + { + PresentToSimplePast.Add(present, simplePast); + PresentToPastParticple.Add(present, pastParticiple); + } + + /// + /// Converts a present verb to simple past tense + /// + /// + /// + public static string ToPast(this string present) + { + if (PresentToSimplePast.ContainsKey(present)) + return PresentToSimplePast[present]; + + return AppendEd(present); + } + + private static string AppendEd(string present) + { + if (present.EndsWith("e")) + return present + "d"; + + if (present.EndsWith("y")) + return present.TrimEnd('y') + "ied"; + + return present + "ed"; + } + + /// + /// Converts a present verb to past participle tense + /// + /// + /// + public static string ToPastParticiple(this string present) + { + if (PresentToPastParticple.ContainsKey(present)) + return PresentToPastParticple[present]; + + return AppendEd(present); + } + } +} diff --git a/src/Humanizer/Humanizer.csproj b/src/Humanizer/Humanizer.csproj index 934f38d18..82bae64d2 100644 --- a/src/Humanizer/Humanizer.csproj +++ b/src/Humanizer/Humanizer.csproj @@ -72,6 +72,7 @@ + True True From fab9770a8cbb354e55f76576bd8ead4aaf86aae2 Mon Sep 17 00:00:00 2001 From: MehdiK Date: Tue, 21 Jan 2014 00:54:15 +0330 Subject: [PATCH 2/4] added a few missing rules for changing to past tense --- src/Humanizer.Tests/EnglishTenseTests.cs | 94 ++++++++++++++++++++---- src/Humanizer/EnglishTenseExtensions.cs | 24 ++++++ 2 files changed, 105 insertions(+), 13 deletions(-) diff --git a/src/Humanizer.Tests/EnglishTenseTests.cs b/src/Humanizer.Tests/EnglishTenseTests.cs index 6a42d68c6..8ff647fd2 100644 --- a/src/Humanizer.Tests/EnglishTenseTests.cs +++ b/src/Humanizer.Tests/EnglishTenseTests.cs @@ -165,15 +165,49 @@ public class EnglishTenseTests [InlineData("Wind","Wound")] [InlineData("Withdraw","Withdrew")] [InlineData("Wring","Wrung")] - [InlineData("Write","Wrote")] - // normal verbs - [InlineData("Decide","Decided")] - [InlineData("Perform","Performed")] - [InlineData("Cry","Cried")] - [InlineData("Test","Tested")] - [InlineData("Love","Loved")] - [InlineData("Walk","Walked")] - [InlineData("BDDfy","BDDfied")] + [InlineData("Write","Wrote")] + + // vowel + consonant + [InlineData("Drop", "Dropped")] + [InlineData("Beg", "Begged")] + [InlineData("Stop", "Stopped")] + [InlineData("Rob", "Robbed")] + [InlineData("Admit", "Admitted")] + [InlineData("Occur", "Occurred")] + [InlineData("Permit", "Permitted")] + + // vowel + x/w + [InlineData("Sew", "Sewed")] + [InlineData("Mix", "Mixed")] + + // ending with e + [InlineData("Decide", "Decided")] + [InlineData("Love", "Loved")] + [InlineData("Live", "Lived")] + [InlineData("Care", "Cared")] + [InlineData("Die", "Died")] + + // vowel + y + [InlineData("Play", "Played")] + [InlineData("Pray", "Prayed")] + [InlineData("Stay", "Stayed")] + [InlineData("Destroy", "Destroyed")] + + // ending with y + [InlineData("Dry", "Dried")] + [InlineData("BDDfy", "BDDfied")] + [InlineData("Carry", "Carried")] + [InlineData("Marry", "Married")] + [InlineData("Spy", "Spied")] + [InlineData("Cry", "Cried")] + + // catch all: adding ed to the end + [InlineData("Start", "Started")] + [InlineData("Finish", "Finished")] + [InlineData("Wash", "Washed")] + [InlineData("Perform", "Performed")] + [InlineData("Test", "Tested")] + [InlineData("Walk", "Walked")] public void ToPast(string present, string past) { Assert.Equal(past, present.ToPast()); @@ -341,14 +375,48 @@ public void ToPast(string present, string past) [InlineData("Withdraw","Withdrawn")] [InlineData("Wring","Wrung")] [InlineData("Write","Written")] - // normal verbs + + // vowel + consonant + [InlineData("Drop", "Dropped")] + [InlineData("Beg", "Begged")] + [InlineData("Stop", "Stopped")] + [InlineData("Rob", "Robbed")] + [InlineData("Admit", "Admitted")] + [InlineData("Occur", "Occurred")] + [InlineData("Permit", "Permitted")] + + // vowel + x/w + [InlineData("Sew", "Sewed")] + [InlineData("Mix", "Mixed")] + + // ending with e [InlineData("Decide", "Decided")] - [InlineData("Perform", "Performed")] + [InlineData("Love", "Loved")] + [InlineData("Live", "Lived")] + [InlineData("Care", "Cared")] + [InlineData("Die", "Died")] + + // vowel + y + [InlineData("Play", "Played")] + [InlineData("Pray", "Prayed")] + [InlineData("Stay", "Stayed")] + [InlineData("Destroy", "Destroyed")] + + // ending with y + [InlineData("Dry", "Dried")] + [InlineData("BDDfy", "BDDfied")] + [InlineData("Carry", "Carried")] + [InlineData("Marry", "Married")] + [InlineData("Spy", "Spied")] [InlineData("Cry", "Cried")] + + // catch all: adding ed to the end + [InlineData("Start", "Started")] + [InlineData("Finish", "Finished")] + [InlineData("Wash", "Washed")] + [InlineData("Perform", "Performed")] [InlineData("Test", "Tested")] - [InlineData("Love", "Loved")] [InlineData("Walk", "Walked")] - [InlineData("BDDfy", "BDDfied")] public void ToPastParticiple(string present, string pastParticiple) { Assert.Equal(pastParticiple, present.ToPastParticiple()); diff --git a/src/Humanizer/EnglishTenseExtensions.cs b/src/Humanizer/EnglishTenseExtensions.cs index ceb5a3b0e..427d52610 100644 --- a/src/Humanizer/EnglishTenseExtensions.cs +++ b/src/Humanizer/EnglishTenseExtensions.cs @@ -197,17 +197,41 @@ public static string ToPast(this string present) return AppendEd(present); } + private static readonly List Vowels = new List {'a', 'e', 'i', 'o', 'u'}; + private static string AppendEd(string present) { + var lastChar = present[present.Length - 1]; + var secondLastChar = present[present.Length - 2]; + + // Rule 1: verb ends with vowel + y => + ed; e.g. played + if (Vowels.Contains(secondLastChar) && lastChar == 'y') + return present + "ed"; + + if (Vowels.Contains(secondLastChar) && !Vowels.Contains(lastChar)) + { + // Rule 2: verb ends with vowel + non-vowel => double the last char + ed; e.g. begged + if (lastChar != 'x' && lastChar != 'w') + return present + lastChar + "ed"; + + // Rule 3: don't double the last x & w; e.g. mixed + return present + "ed"; + } + + // Rule 4: verb ends with e => + d; e.g. created if (present.EndsWith("e")) return present + "d"; + // Rule 5: verb ends with y => -y + ied; e.g. cried if (present.EndsWith("y")) return present.TrimEnd('y') + "ied"; + // Catch all: + ed return present + "ed"; } + + /// /// Converts a present verb to past participle tense /// From fa037b4019ee1198aafda31201c74bd06c6b735d Mon Sep 17 00:00:00 2001 From: MehdiK Date: Tue, 21 Jan 2014 01:15:15 +0330 Subject: [PATCH 3/4] refactored the change tense class --- src/Humanizer/ChangeTense/ChangeTenseBase.cs | 21 +++++++ .../EnglishTenseExtensions.cs | 56 +++++++------------ src/Humanizer/ChangeTense/IChangeTense.cs | 8 +++ src/Humanizer/ChangeTense/VerbEndsWithE.cs | 20 +++++++ .../VerbEndsWithVowelAndConsonant.cs | 23 ++++++++ .../ChangeTense/VerbEndsWithVowelAndY.cs | 20 +++++++ src/Humanizer/ChangeTense/VerbEndsWithY.cs | 20 +++++++ src/Humanizer/Humanizer.csproj | 8 ++- src/Humanizer/Humanizer.csproj.DotSettings | 1 + 9 files changed, 141 insertions(+), 36 deletions(-) create mode 100644 src/Humanizer/ChangeTense/ChangeTenseBase.cs rename src/Humanizer/{ => ChangeTense}/EnglishTenseExtensions.cs (91%) create mode 100644 src/Humanizer/ChangeTense/IChangeTense.cs create mode 100644 src/Humanizer/ChangeTense/VerbEndsWithE.cs create mode 100644 src/Humanizer/ChangeTense/VerbEndsWithVowelAndConsonant.cs create mode 100644 src/Humanizer/ChangeTense/VerbEndsWithVowelAndY.cs create mode 100644 src/Humanizer/ChangeTense/VerbEndsWithY.cs diff --git a/src/Humanizer/ChangeTense/ChangeTenseBase.cs b/src/Humanizer/ChangeTense/ChangeTenseBase.cs new file mode 100644 index 000000000..77cf42ddf --- /dev/null +++ b/src/Humanizer/ChangeTense/ChangeTenseBase.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; + +namespace Humanizer +{ + abstract class ChangeTenseBase : IChangeTense + { + protected string Verb { get; private set; } + protected static readonly List Vowels = new List { 'a', 'e', 'i', 'o', 'u' }; + + protected ChangeTenseBase(string verb) + { + Verb = verb; + } + + protected char LastChar { get { return Verb[Verb.Length - 1]; } } + protected char SecondLastChar { get { return Verb[Verb.Length - 2]; } } + + public abstract bool Applies(); + public abstract string Apply(); + } +} \ No newline at end of file diff --git a/src/Humanizer/EnglishTenseExtensions.cs b/src/Humanizer/ChangeTense/EnglishTenseExtensions.cs similarity index 91% rename from src/Humanizer/EnglishTenseExtensions.cs rename to src/Humanizer/ChangeTense/EnglishTenseExtensions.cs index 427d52610..0af545fcd 100644 --- a/src/Humanizer/EnglishTenseExtensions.cs +++ b/src/Humanizer/ChangeTense/EnglishTenseExtensions.cs @@ -184,6 +184,27 @@ private static void SetupDictionaries(string present, string simplePast, string PresentToPastParticple.Add(present, pastParticiple); } + //http://www.scribd.com/doc/5810860/Spelling-Rules-for-Regular-Past-Tense-Verbs + private static string AppendEd(string present) + { + var rules = new List + { + new VerbEndsWithVowelAndY(present), + new VerbEndsWithVowelAndConsonant(present), + new VerbEndsWithE(present), + new VerbEndsWithY(present) + }; + + foreach (var rule in rules) + { + if (rule.Applies()) + return rule.Apply(); + } + + // Catch all: + ed + return present + "ed"; + } + /// /// Converts a present verb to simple past tense /// @@ -197,41 +218,6 @@ public static string ToPast(this string present) return AppendEd(present); } - private static readonly List Vowels = new List {'a', 'e', 'i', 'o', 'u'}; - - private static string AppendEd(string present) - { - var lastChar = present[present.Length - 1]; - var secondLastChar = present[present.Length - 2]; - - // Rule 1: verb ends with vowel + y => + ed; e.g. played - if (Vowels.Contains(secondLastChar) && lastChar == 'y') - return present + "ed"; - - if (Vowels.Contains(secondLastChar) && !Vowels.Contains(lastChar)) - { - // Rule 2: verb ends with vowel + non-vowel => double the last char + ed; e.g. begged - if (lastChar != 'x' && lastChar != 'w') - return present + lastChar + "ed"; - - // Rule 3: don't double the last x & w; e.g. mixed - return present + "ed"; - } - - // Rule 4: verb ends with e => + d; e.g. created - if (present.EndsWith("e")) - return present + "d"; - - // Rule 5: verb ends with y => -y + ied; e.g. cried - if (present.EndsWith("y")) - return present.TrimEnd('y') + "ied"; - - // Catch all: + ed - return present + "ed"; - } - - - /// /// Converts a present verb to past participle tense /// diff --git a/src/Humanizer/ChangeTense/IChangeTense.cs b/src/Humanizer/ChangeTense/IChangeTense.cs new file mode 100644 index 000000000..c638a252f --- /dev/null +++ b/src/Humanizer/ChangeTense/IChangeTense.cs @@ -0,0 +1,8 @@ +namespace Humanizer +{ + interface IChangeTense + { + bool Applies(); + string Apply(); + } +} \ No newline at end of file diff --git a/src/Humanizer/ChangeTense/VerbEndsWithE.cs b/src/Humanizer/ChangeTense/VerbEndsWithE.cs new file mode 100644 index 000000000..dd56bb308 --- /dev/null +++ b/src/Humanizer/ChangeTense/VerbEndsWithE.cs @@ -0,0 +1,20 @@ +namespace Humanizer +{ + class VerbEndsWithE : ChangeTenseBase + { + public VerbEndsWithE(string verb) + : base(verb) + { + } + + public override bool Applies() + { + return LastChar == 'e'; + } + + public override string Apply() + { + return Verb + 'd'; + } + } +} \ No newline at end of file diff --git a/src/Humanizer/ChangeTense/VerbEndsWithVowelAndConsonant.cs b/src/Humanizer/ChangeTense/VerbEndsWithVowelAndConsonant.cs new file mode 100644 index 000000000..05ad75e54 --- /dev/null +++ b/src/Humanizer/ChangeTense/VerbEndsWithVowelAndConsonant.cs @@ -0,0 +1,23 @@ +namespace Humanizer +{ + class VerbEndsWithVowelAndConsonant : ChangeTenseBase + { + public VerbEndsWithVowelAndConsonant(string verb) + : base(verb) + { + } + + public override bool Applies() + { + return Vowels.Contains(SecondLastChar) && !Vowels.Contains(LastChar); + } + + public override string Apply() + { + if (LastChar != 'x' && LastChar != 'w') + return Verb + LastChar + "ed"; + + return Verb + "ed"; + } + } +} \ No newline at end of file diff --git a/src/Humanizer/ChangeTense/VerbEndsWithVowelAndY.cs b/src/Humanizer/ChangeTense/VerbEndsWithVowelAndY.cs new file mode 100644 index 000000000..64d03082b --- /dev/null +++ b/src/Humanizer/ChangeTense/VerbEndsWithVowelAndY.cs @@ -0,0 +1,20 @@ +namespace Humanizer +{ + class VerbEndsWithVowelAndY : ChangeTenseBase + { + public VerbEndsWithVowelAndY(string verb) + : base(verb) + { + } + + public override bool Applies() + { + return Vowels.Contains(SecondLastChar) && LastChar == 'y'; + } + + public override string Apply() + { + return Verb + "ed"; + } + } +} \ No newline at end of file diff --git a/src/Humanizer/ChangeTense/VerbEndsWithY.cs b/src/Humanizer/ChangeTense/VerbEndsWithY.cs new file mode 100644 index 000000000..b61189660 --- /dev/null +++ b/src/Humanizer/ChangeTense/VerbEndsWithY.cs @@ -0,0 +1,20 @@ +namespace Humanizer +{ + class VerbEndsWithY : ChangeTenseBase + { + public VerbEndsWithY(string verb) + : base(verb) + { + } + + public override bool Applies() + { + return Verb.EndsWith("y"); + } + + public override string Apply() + { + return Verb.TrimEnd('y') + "ied"; + } + } +} \ No newline at end of file diff --git a/src/Humanizer/Humanizer.csproj b/src/Humanizer/Humanizer.csproj index 82bae64d2..dd3c084a8 100644 --- a/src/Humanizer/Humanizer.csproj +++ b/src/Humanizer/Humanizer.csproj @@ -71,8 +71,14 @@ + + + + + + - + True True diff --git a/src/Humanizer/Humanizer.csproj.DotSettings b/src/Humanizer/Humanizer.csproj.DotSettings index 7442acdd2..67f77d71a 100644 --- a/src/Humanizer/Humanizer.csproj.DotSettings +++ b/src/Humanizer/Humanizer.csproj.DotSettings @@ -1,4 +1,5 @@  + True True False True \ No newline at end of file From e205dd420ee417abff4bdff60542d09a205ca3f8 Mon Sep 17 00:00:00 2001 From: MehdiK Date: Tue, 21 Jan 2014 01:23:36 +0330 Subject: [PATCH 4/4] added the CatchAll rule --- src/Humanizer/ChangeTense/ChangeTenseBase.cs | 17 +++++++++++++++++ .../ChangeTense/EnglishTenseExtensions.cs | 9 +++++---- src/Humanizer/ChangeTense/VerbEndsWithY.cs | 2 +- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/Humanizer/ChangeTense/ChangeTenseBase.cs b/src/Humanizer/ChangeTense/ChangeTenseBase.cs index 77cf42ddf..c96ec31cb 100644 --- a/src/Humanizer/ChangeTense/ChangeTenseBase.cs +++ b/src/Humanizer/ChangeTense/ChangeTenseBase.cs @@ -18,4 +18,21 @@ protected ChangeTenseBase(string verb) public abstract bool Applies(); public abstract string Apply(); } + + class CatchAll : ChangeTenseBase + { + public CatchAll(string verb) : base(verb) + { + } + + public override bool Applies() + { + return true; + } + + public override string Apply() + { + return Verb + "ed"; + } + } } \ No newline at end of file diff --git a/src/Humanizer/ChangeTense/EnglishTenseExtensions.cs b/src/Humanizer/ChangeTense/EnglishTenseExtensions.cs index 0af545fcd..452182ca8 100644 --- a/src/Humanizer/ChangeTense/EnglishTenseExtensions.cs +++ b/src/Humanizer/ChangeTense/EnglishTenseExtensions.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; namespace Humanizer { @@ -192,7 +193,8 @@ private static string AppendEd(string present) new VerbEndsWithVowelAndY(present), new VerbEndsWithVowelAndConsonant(present), new VerbEndsWithE(present), - new VerbEndsWithY(present) + new VerbEndsWithY(present), + new CatchAll(present) }; foreach (var rule in rules) @@ -201,8 +203,7 @@ private static string AppendEd(string present) return rule.Apply(); } - // Catch all: + ed - return present + "ed"; + throw new ArgumentOutOfRangeException("present", "None of the defined rules apply to the provided verb"); } /// diff --git a/src/Humanizer/ChangeTense/VerbEndsWithY.cs b/src/Humanizer/ChangeTense/VerbEndsWithY.cs index b61189660..7f4b2e16d 100644 --- a/src/Humanizer/ChangeTense/VerbEndsWithY.cs +++ b/src/Humanizer/ChangeTense/VerbEndsWithY.cs @@ -9,7 +9,7 @@ public VerbEndsWithY(string verb) public override bool Applies() { - return Verb.EndsWith("y"); + return LastChar == 'y'; } public override string Apply()