Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue38fix #43

Merged
merged 6 commits into from
Jan 1, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 69 additions & 6 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,12 +133,75 @@ TimeSpan.FromDays(14).Humanize() => "2 weeks"
###Inflector methods
There are also a few inflector methods:

* Pluralize: pluralizes the provided input considering irregular words; e.g. `"Man".Pluralize()` => `"Men"` & `"string".Pluralize()` => `"strings"`
* Singularize: singularizes the provided input considering irregular words; e.g. `"Men".Singularize()` => `"Man"` & `"strings".Singularize()` => `"string"`
* Ordinalize numbers: turns a number into an ordinal string used to denote the position in an ordered sequence such as 1st, 2nd, 3rd, 4th; e.g. `1.Ordinalize()` => `"1st"`, `5.Ordinalize()` => `"5th"`
* Ordinalize strings: Turns a number into an ordinal number used to denote the position in an ordered sequence such as 1st, 2nd, 3rd, 4th; e.g. `"21".Ordinalize()` => `"21st"`
* Underscore: separates the input words with underscore; e.g. `"SomeTitle".Underscore()` => `"some_title"`
* Dasherize: replaces underscores with dashes in the string; e.g. `"some_title".Dasherize()` => `"some-title"`
####Pluralize
`Pluralize` pluralizes the provided input while taking irregular and uncountable words into consideration:

```C#
"Man".Pluralize() => "Men"
"string".Pluralize() => "strings"
```

Normally you would call `Pluralize` on a singular word but if you're unsure about the singularity of the word you can call the method with the optional `plurality` argument:

```C#
"Men".Pluralize(Plurality.CouldBeEither) => "Men"
"Man".Pluralize(Plurality.CouldBeEither) => "Men"
"string".Pluralize(Plurality.CouldBeEither) => "strings"
```

####Singularize
`Singularize` singularizes the provided input while taking irregular and uncountable words into consideration:

```C#
"Men".Singularize() => "Man"
"strings".Singularize() => "string"
```

Normally you would call `Singularize` on a plural word but if you're unsure about the pluralit of the word you can call the method with the optional `plurality` argument:

```C#
"Men".Singularize(Plurality.CouldBeEither) => "Man"
"Man".Singularize(Plurality.CouldBeEither) => "Man"
"strings".Singularize(Plurality.CouldBeEither) => "string"
```

####ToQuantity
Many times you want to call `Singularize` and `Pluralize` to prefix a word with a number; e.g. "2 requests", "3 men". `ToQuantity` prefixes the provided word with the number and accordingly pluralizes or singularizes the word:

```C#
"case".ToQuantity(0) => "0 cases"
"case".ToQuantity(1) => "1 case"
"case".ToQuantity(5) => "5 cases"
"man".ToQuantity(0) => "0 men"
"man".ToQuantity(1) => "1 man"
"man".ToQuantity(2) => "2 men"
```

`ToQuantity` has smarts to figure out whether your input word is plural or singular and changes or leaves it depending on the input quantity:

```C#
"men.ToQuantity(2) => "2 men"
"process".ToQuantity(2) => "2 processes"
"process".ToQuantity(1) => "1 process"
"processes".ToQuantity(2) => "2 processes"
"processes".ToQuantity(1) => "1 process"
```

####Ordinalize numbers & strings
`Ordinalize` turns a number into an ordinal string used to denote the position in an ordered sequence such as 1st, 2nd, 3rd, 4th:

```C#
1.Ordinalize() => "1st"
5.Ordinalize() => "5th"
```

You can also call `Ordinalize` on a numeric string and achieve the same result: `"21".Ordinalize()` => `"21st"`

####Underscore
`Underscore` separates the input words with underscore; e.g. `"SomeTitle".Underscore()` => `"some_title"`

####Dasherize
`Dasherize` replaces underscores with dashes in the string; e.g. `"some_title".Dasherize()` => `"some-title"`

###Fluent Date
Humanizer provides a fluent API to deal with `DateTime` and `TimeSpan` as follows:
Expand Down
42 changes: 40 additions & 2 deletions src/Humanizer.Tests/InflectorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,26 @@ public void Pluralize()
{
foreach (var pair in TestData)
{
Assert.Equal(pair.Key.Pluralize(), pair.Value);
Assert.Equal(pair.Value, pair.Key.Pluralize());
}
}

[Fact]
public void PluralizeAlreadyPluralWord()
{
foreach (var pair in TestData)
{
Assert.Equal(pair.Value, pair.Value.Pluralize(Plurality.Plural));
}
}

[Fact]
public void PluralizeWordsWithUnknownPlurality()
{
foreach (var pair in TestData)
{
Assert.Equal(pair.Value, pair.Value.Pluralize(Plurality.CouldBeEither));
Assert.Equal(pair.Value, pair.Key.Pluralize(Plurality.CouldBeEither));
}
}

Expand All @@ -22,7 +41,26 @@ public void Singularize()
{
foreach (var pair in TestData)
{
Assert.Equal(pair.Value.Singularize(), pair.Key);
Assert.Equal(pair.Key, pair.Value.Singularize());
}
}

[Fact]
public void SingularizeAlreadySingularWord()
{
foreach (var pair in TestData)
{
Assert.Equal(pair.Key, pair.Key.Singularize(Plurality.Singular));
}
}

[Fact]
public void SingularizeWordsWithUnknownSingularity()
{
foreach (var pair in TestData)
{
Assert.Equal(pair.Key, pair.Key.Singularize(Plurality.CouldBeEither));
Assert.Equal(pair.Key, pair.Value.Singularize(Plurality.CouldBeEither));
}
}

Expand Down
6 changes: 5 additions & 1 deletion src/Humanizer.Tests/ToQuantityTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,18 @@ namespace Humanizer.Tests
{
public class ToQuantityTests
{

[Theory]
[InlineData("case", 0, "0 cases")]
[InlineData("case", 1, "1 case")]
[InlineData("case", 5, "5 cases")]
[InlineData("man", 0, "0 men")]
[InlineData("man", 1, "1 man")]
[InlineData("man", 2, "2 men")]
[InlineData("men", 2, "2 men")]
[InlineData("process", 2, "2 processes")]
[InlineData("process", 1, "1 process")]
[InlineData("processes", 2, "2 processes")]
[InlineData("processes", 1, "1 process")]
public void ToQuantity(string word, int quatity, string expected)
{
Assert.Equal(expected, word.ToQuantity(quatity));
Expand Down
61 changes: 56 additions & 5 deletions src/Humanizer/InflectorExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,25 @@

namespace Humanizer
{
/// <summary>
/// Provides hint for Humanizer as to whether a word is singular, plural or with unknown plurality
/// </summary>
public enum Plurality
{
/// <summary>
/// The word is singular
/// </summary>
Singular,
/// <summary>
/// The word is plural
/// </summary>
Plural,
/// <summary>
/// I am unsure of the plurality
/// </summary>
CouldBeEither
}

/// <summary>
/// Inflector extensions
/// </summary>
Expand Down Expand Up @@ -124,25 +143,57 @@ private static void AddSingular(string rule, string replacement)
/// Pluralizes the provided input considering irregular words
/// </summary>
/// <param name="word">Word to be pluralized</param>
/// <param name="plurality">Normally you call Pluralize on singular words; but if you're unsure call it with Plurality.CouldBeEither</param>
/// <returns></returns>
public static string Pluralize(this string word)
public static string Pluralize(this string word, Plurality plurality = Plurality.Singular)
{
return ApplyRules(Plurals, word);
if (plurality == Plurality.Plural)
return word;

var result = ApplyRules(Plurals, word);

if (plurality == Plurality.Singular)
return result;

var asSingular = ApplyRules(Singulars, word);
var asSingularAsPlural = ApplyRules(Plurals, asSingular);
if (asSingular != null && asSingular != word && asSingular + "s" != word && asSingularAsPlural == word && result != word)
return word;

return result;
}

/// <summary>
/// Singularizes the provided input considering irregular words
/// </summary>
/// <param name="word">Word to be singularized</param>
/// <param name="plurality">Normally you call Singularize on plural words; but if you're unsure call it with Plurality.CouldBeEither</param>
/// <returns></returns>
public static string Singularize(this string word)
public static string Singularize(this string word, Plurality plurality = Plurality.Plural)
{
return ApplyRules(Singulars, word);
if (plurality == Plurality.Singular)
return word;

var result = ApplyRules(Singulars, word);

if (plurality == Plurality.Plural)
return result;

// the Plurality is unknown so we should check all possibilities
var asPlural = ApplyRules(Plurals, word);
var asPluralAsSingular = ApplyRules(Singulars, asPlural);
if (asPlural != word && word+"s" != asPlural && asPluralAsSingular == word && result != word)
return word;

return result ?? word;
}

private static string ApplyRules(List<Rule> rules, string word)
{
string result = word;
if (word == null)
return null;

var result = word;

if (!Uncountables.Contains(word.ToLower()))
{
Expand Down
18 changes: 11 additions & 7 deletions src/Humanizer/ToQuantityExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,21 @@
public static class ToQuantityExtensions
{
/// <summary>
/// "request".ToQuantity(0) => "0 requests", "request".ToQuantity(1) => "1 request", "request".ToQuantity(2) => "2 requests"
/// Prefixes the provided word with the number and accordingly pluralizes or singularizes the word
/// </summary>
/// <param name="input"></param>
/// <param name="quantity"></param>
/// <param name="input">The word to be prefixes</param>
/// <param name="quantity">The quantity of the word</param>
/// <example>
/// "request".ToQuantity(0) => "0 requests"
/// "request".ToQuantity(1) => "1 request"
/// "request".ToQuantity(2) => "2 requests"
/// "men".ToQuantity(2) => "2 men"
/// "men".ToQuantity(1) => "1 man"
/// </example>
/// <returns></returns>
public static string ToQuantity(this string input, int quantity)
{
if (quantity == 1)
return string.Format("{0} {1}", quantity, input);

return string.Format("{0} {1}", quantity, input.Pluralize());
return string.Format("{0} {1}", quantity, quantity == 1 ? input.Singularize(Plurality.CouldBeEither) : input.Pluralize(Plurality.CouldBeEither));
}
}
}