Skip to content
Open
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
27 changes: 26 additions & 1 deletion Inflector.sln
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
# Visual Studio 14
VisualStudioVersion = 14.0.23107.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Inflector", "Inflector\Inflector.csproj", "{D5677360-4354-4BA3-9E23-DB169C22BEAB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Inflector.Tests", "Inflector.Tests\Inflector.Tests.csproj", "{48D42B49-DAA7-47BB-9DC2-9BF2013C48C0}"
Expand All @@ -11,6 +13,13 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Inflector45", "Inflector45\
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InflectorRT", "InflectorRT\InflectorRT.csproj", "{8DA0D24A-BD73-411E-90D3-BAD6056C1DF9}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "InflectorCore", "InflectorCore\InflectorCore.xproj", "{0795EB68-F83C-4065-BCB1-3BF3D521C8DD}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{5D7DF9FF-D706-4A4C-8AA7-54143BA07035}"
ProjectSection(SolutionItems) = preProject
global.json = global.json
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -79,6 +88,22 @@ Global
{8DA0D24A-BD73-411E-90D3-BAD6056C1DF9}.Release|x64.Build.0 = Release|x64
{8DA0D24A-BD73-411E-90D3-BAD6056C1DF9}.Release|x86.ActiveCfg = Release|x86
{8DA0D24A-BD73-411E-90D3-BAD6056C1DF9}.Release|x86.Build.0 = Release|x86
{0795EB68-F83C-4065-BCB1-3BF3D521C8DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0795EB68-F83C-4065-BCB1-3BF3D521C8DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0795EB68-F83C-4065-BCB1-3BF3D521C8DD}.Debug|ARM.ActiveCfg = Debug|Any CPU
{0795EB68-F83C-4065-BCB1-3BF3D521C8DD}.Debug|ARM.Build.0 = Debug|Any CPU
{0795EB68-F83C-4065-BCB1-3BF3D521C8DD}.Debug|x64.ActiveCfg = Debug|Any CPU
{0795EB68-F83C-4065-BCB1-3BF3D521C8DD}.Debug|x64.Build.0 = Debug|Any CPU
{0795EB68-F83C-4065-BCB1-3BF3D521C8DD}.Debug|x86.ActiveCfg = Debug|Any CPU
{0795EB68-F83C-4065-BCB1-3BF3D521C8DD}.Debug|x86.Build.0 = Debug|Any CPU
{0795EB68-F83C-4065-BCB1-3BF3D521C8DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0795EB68-F83C-4065-BCB1-3BF3D521C8DD}.Release|Any CPU.Build.0 = Release|Any CPU
{0795EB68-F83C-4065-BCB1-3BF3D521C8DD}.Release|ARM.ActiveCfg = Release|Any CPU
{0795EB68-F83C-4065-BCB1-3BF3D521C8DD}.Release|ARM.Build.0 = Release|Any CPU
{0795EB68-F83C-4065-BCB1-3BF3D521C8DD}.Release|x64.ActiveCfg = Release|Any CPU
{0795EB68-F83C-4065-BCB1-3BF3D521C8DD}.Release|x64.Build.0 = Release|Any CPU
{0795EB68-F83C-4065-BCB1-3BF3D521C8DD}.Release|x86.ActiveCfg = Release|Any CPU
{0795EB68-F83C-4065-BCB1-3BF3D521C8DD}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
245 changes: 245 additions & 0 deletions InflectorCore/Inflector.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
using System.Collections.Generic;
#if NET45 || NETFX_CORE
using System.Runtime.CompilerServices;
#endif
using System.Text.RegularExpressions;

namespace Inflector
{
public static class Inflector
{
#region Default Rules

static Inflector()
{
AddPlural("$", "s");
AddPlural("s$", "s");
AddPlural("(ax|test)is$", "$1es");
AddPlural("(octop|vir|alumn|fung)us$", "$1i");
AddPlural("(alias|status)$", "$1es");
AddPlural("(bu)s$", "$1ses");
AddPlural("(buffal|tomat|volcan)o$", "$1oes");
AddPlural("([ti])um$", "$1a");
AddPlural("sis$", "ses");
AddPlural("(?:([^f])fe|([lr])f)$", "$1$2ves");
AddPlural("(hive)$", "$1s");
AddPlural("([^aeiouy]|qu)y$", "$1ies");
AddPlural("(x|ch|ss|sh)$", "$1es");
AddPlural("(matr|vert|ind)ix|ex$", "$1ices");
AddPlural("([m|l])ouse$", "$1ice");
AddPlural("^(ox)$", "$1en");
AddPlural("(quiz)$", "$1zes");

AddSingular("s$", "");
AddSingular("(n)ews$", "$1ews");
AddSingular("([ti])a$", "$1um");
AddSingular("((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$", "$1$2sis");
AddSingular("(^analy)ses$", "$1sis");
AddSingular("([^f])ves$", "$1fe");
AddSingular("(hive)s$", "$1");
AddSingular("(tive)s$", "$1");
AddSingular("([lr])ves$", "$1f");
AddSingular("([^aeiouy]|qu)ies$", "$1y");
AddSingular("(s)eries$", "$1eries");
AddSingular("(m)ovies$", "$1ovie");
AddSingular("(x|ch|ss|sh)es$", "$1");
AddSingular("([m|l])ice$", "$1ouse");
AddSingular("(bus)es$", "$1");
AddSingular("(o)es$", "$1");
AddSingular("(shoe)s$", "$1");
AddSingular("(cris|ax|test)es$", "$1is");
AddSingular("(octop|vir|alumn|fung)i$", "$1us");
AddSingular("(alias|status)es$", "$1");
AddSingular("^(ox)en", "$1");
AddSingular("(vert|ind)ices$", "$1ex");
AddSingular("(matr)ices$", "$1ix");
AddSingular("(quiz)zes$", "$1");

AddIrregular("person", "people");
AddIrregular("man", "men");
AddIrregular("child", "children");
AddIrregular("sex", "sexes");
AddIrregular("move", "moves");
AddIrregular("goose", "geese");
AddIrregular("alumna", "alumnae");

AddUncountable("equipment");
AddUncountable("information");
AddUncountable("rice");
AddUncountable("money");
AddUncountable("species");
AddUncountable("series");
AddUncountable("fish");
AddUncountable("sheep");
AddUncountable("deer");
AddUncountable("aircraft");
}

#endregion

private class Rule
{
private readonly Regex _regex;
private readonly string _replacement;

public Rule(string pattern, string replacement)
{
_regex = new Regex(pattern, RegexOptions.IgnoreCase);
_replacement = replacement;
}

public string Apply(string word)
{
if (!_regex.IsMatch(word))
{
return null;
}

return _regex.Replace(word, _replacement);
}
}

private static void AddIrregular(string singular, string plural)
{
AddPlural("(" + singular[0] + ")" + singular.Substring(1) + "$", "$1" + plural.Substring(1));
AddSingular("(" + plural[0] + ")" + plural.Substring(1) + "$", "$1" + singular.Substring(1));
}

private static void AddUncountable(string word)
{
_uncountables.Add(word.ToLower());
}

private static void AddPlural(string rule, string replacement)
{
_plurals.Add(new Rule(rule, replacement));
}

private static void AddSingular(string rule, string replacement)
{
_singulars.Add(new Rule(rule, replacement));
}

private static readonly List<Rule> _plurals = new List<Rule>();
private static readonly List<Rule> _singulars = new List<Rule>();
private static readonly List<string> _uncountables = new List<string>();

public static string Pluralize(this string word)
{
return ApplyRules(_plurals, word);
}

public static string Singularize(this string word)
{
return ApplyRules(_singulars, word);
}

#if NET45 || NETFX_CORE
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
private static string ApplyRules(List<Rule> rules, string word)
{
string result = word;

if (!_uncountables.Contains(word.ToLower()))
{
for (int i = rules.Count - 1; i >= 0; i--)
{
if ((result = rules[i].Apply(word)) != null)
{
break;
}
}
}

return result;
}

public static string Titleize(this string word)
{
return Regex.Replace(Humanize(Underscore(word)), @"\b([a-z])",
delegate(Match match)
{
return match.Captures[0].Value.ToUpper();
});
}

public static string Humanize(this string lowercaseAndUnderscoredWord)
{
return Capitalize(Regex.Replace(lowercaseAndUnderscoredWord, @"_", " "));
}

public static string Pascalize(this string lowercaseAndUnderscoredWord)
{
return Regex.Replace(lowercaseAndUnderscoredWord, "(?:^|_)(.)",
delegate(Match match)
{
return match.Groups[1].Value.ToUpper();
});
}

public static string Camelize(this string lowercaseAndUnderscoredWord)
{
return Uncapitalize(Pascalize(lowercaseAndUnderscoredWord));
}

public static string Underscore(this string pascalCasedWord)
{
return Regex.Replace(
Regex.Replace(
Regex.Replace(pascalCasedWord, @"([A-Z]+)([A-Z][a-z])", "$1_$2"), @"([a-z\d])([A-Z])",
"$1_$2"), @"[-\s]", "_").ToLower();
}

public static string Capitalize(this string word)
{
return word.Substring(0, 1).ToUpper() + word.Substring(1).ToLower();
}

public static string Uncapitalize(this string word)
{
return word.Substring(0, 1).ToLower() + word.Substring(1);
}

public static string Ordinalize(this string numberString)
{
return Ordanize(int.Parse(numberString), numberString);
}

public static string Ordinalize(this int number)
{
return Ordanize(number, number.ToString());
}

#if NET45 || NETFX_CORE
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
private static string Ordanize(int number, string numberString)
{
int nMod100 = number % 100;

if (nMod100 >= 11 && nMod100 <= 13)
{
return numberString + "th";
}

switch (number % 10)
{
case 1:
return numberString + "st";
case 2:
return numberString + "nd";
case 3:
return numberString + "rd";
default:
return numberString + "th";
}
}


public static string Dasherize(this string underscoredWord)
{
return underscoredWord.Replace('_', '-');
}
}
}
20 changes: 20 additions & 0 deletions InflectorCore/InflectorCore.xproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>

<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>0795eb68-f83c-4065-bcb1-3bf3d521c8dd</ProjectGuid>
<RootNamespace>InflectorCore</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
</PropertyGroup>

<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>
22 changes: 22 additions & 0 deletions InflectorCore/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"version": "1.0.0-*",
"description": "InflectorCore Class Library",
"authors": [ "Szymon" ],
"tags": [ "" ],
"projectUrl": "",
"licenseUrl": "",

"dependencies": {
"System.Collections": "4.0.10-beta-23019",
"System.Linq": "4.0.0-beta-23019",
"System.Threading": "4.0.10-beta-23019",
"System.Runtime": "4.0.10-beta-23019",
"Microsoft.CSharp": "4.0.0-beta-23019",
"System.Text.RegularExpressions": "4.0.10-beta-23019"
},

"frameworks": {
"dnx462": { },
"dnxcore50": { }
}
}
Loading