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(); } } }