using System;
using System.Text;
using System.Text.RegularExpressions;
namespace Eminent.MsBuild.Tasks
{
///
/// Various string utility methods.
///
public class StringUtility
{
private static readonly Regex _singleRegex1 = new Regex("(?[^aeiou])y$", RegexOptions.Compiled);
private static readonly Regex _singleRegex2 = new Regex("(?[aeiou]y)$", RegexOptions.Compiled);
private static readonly Regex _singleRegex3 = new Regex("(?[sxzh])$", RegexOptions.Compiled);
private static readonly Regex _singleRegex4 = new Regex("(?[^sxzhy])$", RegexOptions.Compiled);
private static readonly Regex _pluralRegex1 = new Regex("(?[^aeiou])ies$", RegexOptions.Compiled);
private static readonly Regex _pluralRegex2 = new Regex("(?[aeiou]y)s$", RegexOptions.Compiled);
private static readonly Regex _pluralRegex3 = new Regex("(?[sxzh])es$", RegexOptions.Compiled);
private static readonly Regex _pluralRegex4 = new Regex("(?[^sxzhy])s$", RegexOptions.Compiled);
private static readonly Regex _splitNameRegex = new Regex(@"[\W_]+", RegexOptions.Compiled);
private static readonly String[] _invariants = {"alias", "news", "sheep", "status"};
private StringUtility()
{
}
///
/// Determines if a string is an invariant item
///
///
///
public static bool IsInvariant(string value)
{
// cycle thorough all of the invariants
foreach( string s in _invariants ) {
if( value.ToLower().EndsWith(s.ToLower()) ) {
return true;
}
}
return false;
}
///
/// Determines if a string is in plural form based on some simple rules.
///
///
///
public static bool IsPlural(string value)
{
// handle invariants
if( IsInvariant(value) ) {
return true;
}
if (_pluralRegex1.IsMatch(value) || _pluralRegex2.IsMatch(value) || _pluralRegex3.IsMatch(value) || _pluralRegex4.IsMatch(value))
{
return true;
}
else
{
return false;
}
}
///
/// Determines if a string is in singular form based on some simple rules.
///
///
///
public static bool IsSingular(string value)
{
// handle invariants
if (IsInvariant(value)) {
return true;
}
return !IsPlural(value);
}
///
/// Converts a string to plural based on some simple rules.
///
///
///
public static string ToPlural(string value)
{
// handle invariants
if (IsInvariant(value)) {
return value;
}
if (!IsSingular(value)) return value;
if (_singleRegex1.IsMatch(value))
{
return _singleRegex1.Replace(value, "${keep}ies");
}
else if (_singleRegex2.IsMatch(value))
{
return _singleRegex2.Replace(value, "${keep}s");
}
else if (_singleRegex3.IsMatch(value))
{
return _singleRegex3.Replace(value, "${keep}es");
}
else if (_singleRegex4.IsMatch(value))
{
return _singleRegex4.Replace(value, "${keep}s");
}
return value;
}
///
/// Converts a string to singular based on some simple rules.
///
///
///
public static string ToSingular(string value)
{
// handle invariants
if (IsInvariant(value)) {
return value;
}
if (!IsPlural(value)) return value;
if (_pluralRegex1.IsMatch(value))
{
return _pluralRegex1.Replace(value, "${keep}y");
}
else if (_pluralRegex2.IsMatch(value))
{
return _pluralRegex2.Replace(value, "${keep}");
}
else if (_pluralRegex3.IsMatch(value))
{
return _pluralRegex3.Replace(value, "${keep}");
}
else if (_pluralRegex4.IsMatch(value))
{
return _pluralRegex4.Replace(value, "${keep}");
}
return value;
}
///
/// Converts a string to use camelCase.
///
///
///
public static string ToCamelCase(string value)
{
if (value == null || value.Length == 0)
return value;
string output = ToPascalCase(value);
if (output.Length > 2)
return char.ToLower(output[0]) + output.Substring(1);
else
return output.ToLower();
}
///
/// Converts a string to Proper Case. This is an alias for ToPascalCase
///
/// string to convert
/// The string converted to Proper Case
public static string ToProperCase(string value)
{
return ToPascalCase(value);
}
///
/// Converts a string to use PascalCase.
///
/// Text to convert
///
public static string ToPascalCase(string value)
{
if (value == null || value.Length == 0)
return value;
string[] names = _splitNameRegex.Split(value);
StringBuilder output = new StringBuilder();
if (names.Length > 1)
{
foreach(string name in names)
{
if (name.Length > 1)
{
output.Append(char.ToUpper(name[0]));
output.Append(name.Substring(1).ToLower());
}
else
{
output.Append(name);
}
}
}
else if (value.Length > 1)
{
output.Append(char.ToUpper(value[0]));
output.Append(value.Substring(1));
}
else
{
output.Append(value.ToUpper());
}
return output.ToString();
}
///
/// Takes a NameIdentifier and spaces it out into words "Name Identifier".
///
///
///
public static string ToSpacedWords(string value)
{
StringBuilder spacedName = new StringBuilder();
for (int i = 0; i < value.Length; i++)
{
if (i > 0 && i < value.Length - 1 && Char.IsUpper(value[i]))
{
spacedName.Append(" ");
}
spacedName.Append(value[i]);
}
return spacedName.ToString();
}
///
/// Remove any non-word characters from a name (word characters are a-z, A-Z, 0-9, _)
/// so that it may be used in code
///
/// name to be cleaned
/// Cleaned up object name
public static string GetCleanName(string name)
{
return Regex.Replace(name, @"[\W]", "");
}
///
/// Return a tab
///
public static string Tab()
{
return Tab(1);
}
///
/// Return a specified number of tabs
///
/// Number of tabs
/// n tabs
public static string Tab(int n)
{
return new String('\t', n);
}
///
/// Return a newline
///
public static string Newline()
{
return Newline(1);
}
///
/// Return a specified number of newlines
///
/// Number of newlines
/// n tabs
public static string Newline(int n)
{
String result = string.Empty;
for( int i = 0; i < n; i++ ) {
result += Environment.NewLine;
}
return result;
}
///
/// Return a newline and the specified number of tabs
///
/// Number of tabs
/// newline with specified number of tabs
public static string NewlineAndTabs(int n)
{
return (Newline() + Tab(n));
}
///
/// Checks the string for any characters present
///
/// String to check
/// True if characters are present, otherwise false
public static bool HasCharacters(string name)
{
return Regex.IsMatch(name, @"[a-zA-Z]");
}
///
/// Checks the string for any numerics present
///
/// String to check
/// True if numerics are present, otherwise false
public static bool HasNumerics(string name)
{
return Regex.IsMatch(name, @"[0-9]");
}
///
/// Checks the string to see if it starts with a numeric
///
/// String to check
/// True if string starts with a numeric, otherwise false
public static bool StartsWithNumeric(string name)
{
return Regex.IsMatch(name, @"^[0-9]+");
}
///
/// Checks the string to see if it starts with a character
///
/// String to check
/// True if string starts with a character, otherwise false
public static bool StartsWithCharacter(string name)
{
return Regex.IsMatch(name, @"^[a-zA-Z]+");
}
///
/// Checks the string to see if it is a valid variable name
///
/// String to check
/// True if string is a valid variable name, otherwise false
/// Checks for (_ | {AlphaCharacter})({WordCharacter})*
public static bool IsValidVariableName(string name)
{
return Regex.IsMatch(name, @"(_ | [a-zA-Z])([a-zA-Z_0-9])*");
}
///
/// Wraps long lines at the specified column number breaking on the specified break
/// character.
///
///
///
/// the character for the language that indicates a line continuation
/// The character that should be used for breaking the string
/// a wrapped line
public static string WrapLongLines(string text, System.Int32 columnNumber, string lineContinuationCharacter, char breakCharacter)
{
return WrapLongLines(text, columnNumber, lineContinuationCharacter, breakCharacter, 4);
}
///
/// Wraps long lines at the specified column number breaking on the specified break
/// character.
///
///
///
/// the character for the language that indicates a line continuation
/// The character that should be used for breaking the string
/// Number of tabs to indent the wrapped lines
/// a wrapped line
public static string WrapLongLines(string text, System.Int32 columnNumber, string lineContinuationCharacter, char breakCharacter, int tabs)
{
// if the line is less than column number just return it
if( text.Length <= columnNumber ) {
return text;
}
StringBuilder result = new StringBuilder();
System.Int32 stringLength = text.Length;
string subString;
System.Int32 startPosition = 0;
// loop through ever column number characters
while( startPosition < stringLength ) {
// check if the startPosition + columnNumber is greater than the stringLength
if( (startPosition + columnNumber) > stringLength ) {
// the substring is less than the columnNumber we're at the
// last part so just add it and exit
subString = text.Substring(startPosition);
result.Append(subString);
break;
}
// get the substring we're working with
subString = text.Substring(startPosition, columnNumber);
// not at the end so get the position of the last space
System.Int32 lastBreak = subString.LastIndexOf(breakCharacter);
lastBreak++;
// check that we got one
result.Append(subString.Substring(0, lastBreak));
result.Append(lineContinuationCharacter);
result.Append(Newline());
result.Append(Tab(tabs));
// set the next position
startPosition += lastBreak;
}
return result.ToString();
}
}
}