using System;
using System.Text;
using System.Collections.Generic;
public static class ClipboardFusionHelper
{
private static readonly string[] ExceptionsArray =
{
// Articles //
"a",
"an",
"the",
// Coordinating conjunctions //
"and",
"but",
"or",
"nor",
"for",
"yet",
"so",
// Postpositions //
"ago",
"apart",
"aside",
"aslant", //(archaic)
"away",
"hence",
"notwithstanding", //(also prepositional)
"on",
"short", //(also prepositional)
"through",
"withal",
// Single Word Prepositions //
"aboard",
"about",
"above",
"absent", //(law)
"across",
"cross", //(archaic)
"after",
"against",
// (poetic or archaic)
"'gainst",
"gainst",
// (archaic)
"again",
"gain",
"along",
"'long", //(abbreviation),
"alongst", //(archaic)
"alongside",
"amid",
//(poetic or archaic)
"amidst",
"mid",
"midst",
"among",
"amongst", //(in US English poetic or archaic)
//(abbreviations)
"'mong",
"mong",
"'mongst",
"apropos", //(rare for apropos of)
"apud", //(formal)
"around",
//(abbreviations)
"'round",
"round",
"as",
"astride",
"at",
"@", //(abbreviation)
"atop",
"ontop",
"bar",
"before",
//(dialectal or archaic)
"afore",
"tofore",
"behind",
"ahind", //(dialectal or archaic)
"below",
//(Scotland)
"ablow",
"allow",
"beneath",
"'neath", //(poetic)
"neath", //(poetic)
"beside",
"besides",
"between",
"atween", //(dialectal or archaic)
"beyond",
"ayond", //(dialectal or archaic)
"but",
"by",
"chez", //(rare)
"circa",
//(abbreviations)
"c. ",
"ca.",
"come",
"dehors", //(law)
"despite",
"spite", //(abbreviation)
"down",
"during",
"except",
"for",
"from",
"in",
"inside",
"into",
"less",
"like",
"minus",
"near",
"nearer", //(comparative),
"nearest", //(superlative)
"anear", //(archaic)
"notwithstanding", //(also postpositional)
"of",
"o'", //(poetic or eye-dialect)
"off",
"on",
"onto",
"opposite",
"out",
"outen", //(archaic or dialectal)
"outside",
"over",
"o'er", //(poetic)
"pace", //(formal)
"past",
"per",
"plus",
"post", //(often hyphenated)
"pre", //(often hyphenated)
"pro", //(often hyphenated)
"qua", //(formal)
"re", //(often used with colon)
"sans", //(formal)
"save",
"sauf", //(archaic)
"short",
"since",
"sithence", //(archaic)
"than",
"through",
"thru", //(abbreviation)
"throughout",
"thruout", //(abbreviation)
"till",
"to",
"toward",
"towards",
"under",
"underneath",
"unlike",
"until",
//(abbreviations)
"'til",
"til",
"unto",
"up",
"upon",
//(abbreviations)
"'pon",
"pon",
"upside",
"versus",
//(abbreviations)
"vs.",
"v.",
"via",
"vice", //(formal)
"vis-à-vis", //(formal)
"with",
//(abbreviations)
"w/",
"wi'",
"c?",
"within",
"w/i", //(abbreviation)
"without",
"w/o", //(abbreviation)
"worth",
};
private static string[] MultiWordExceptionArray =
{
// Two-word Prepositions //
"according to",
"across from",
"adjacent to",
"ahead of",
"along with",
"apart from",
"as for",
"as of",
"as per",
"as regards",
"aside from",
"back to",
"because of",
"close to",
"counter to",
"down on",
"due to",
"except for",
"far from",
"inside of",
"instead of",
"left of",
"near to",
"next to",
"opposite of",
"opposite to",
"other than",
"out from",
"out of",
"outside of",
"owing to",
"prior to",
"pursuant to",
"rather than",
"regardless of",
"right of",
"subsequent to",
"such as",
"thanks to",
"up to",
// Three-word Prepositions //
"as far as", //is one example of the many expressions which can be analyzed as as+adjective+as rather than a multiword preposition
"as opposed to",
"as soon as",
"as well as",
// Preposition + (article) + noun + preposition //
//English has many idiomatic expressions that act as prepositions that can be analyzed as a preposition followed by a noun (sometimes preceded by the definite or, occasionally, indefinite article) followed by another preposition.
"at the behest of",
"by means of",
"by virtue of",
"for the sake of",
"for lack of",
"for want of",
"in accordance with",
"in addition to",
"in case of",
"in front of",
"in lieu of",
"in place of",
"in point of",
"in spite of",
"on account of",
"on behalf of",
"on top of",
"with regard to", //(sometimes written as "w/r/t")
"with respect to",
"with a view to",
};
private static readonly string[] CaseSensitiveExceptionArray =
{
// OTHERS //
"SaaS",
"PaaS",
"B2B",
"AI",
};
private static readonly HashSet<string> Exceptions = new HashSet<string>(ExceptionsArray);
private static Dictionary<string, string> MultiWordExceptions;
private static Dictionary<string, string> CaseSensitiveExceptions;
public static string ProcessText(string text)
{
BFS.Clipboard.PasteText(ToTitleCaseSmart(BFS.Clipboard.CopyText()));
return null;
}
private static string ToTitleCaseSmart(string text)
{
// build multi-word exception dictionary
MultiWordExceptions = new Dictionary<string, string>();
foreach (string exception in MultiWordExceptionArray)
{
string key = "_" + exception.GetHashCode().ToString() + "_";
if (!MultiWordExceptions.ContainsKey(key))
MultiWordExceptions.Add(key, exception);
// replace exceptions with something we can easily look for and replace later
while (true)
{
int index = text.IndexOf(exception, StringComparison.OrdinalIgnoreCase);
if (index == -1)
break;
string modified = text.Substring(0, index);
modified += key;
modified += text.Substring(index + exception.Length);
text = modified;
}
}
// build case sensitive exceptions
CaseSensitiveExceptions = new Dictionary<string, string>();
foreach (string exception in CaseSensitiveExceptionArray)
{
string key = "_" + exception.GetHashCode().ToString() + "_";
if (!CaseSensitiveExceptions.ContainsKey(key))
CaseSensitiveExceptions.Add(key, exception);
// replace exceptions with something we can easily look for and replace later
text = text.Replace(exception, key);
}
// do the normal title case processing
Queue<string> words = new Queue<string>(System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(text.ToLowerInvariant()).Split(new char[] {' '}));
StringBuilder builder = new StringBuilder(words.Dequeue());
while (words.Count > 0)
{
string word = words.Dequeue();
string lower = word.ToLower();
builder.Append(" ");
if (Exceptions.Contains(lower))
builder.Append(lower);
else
builder.Append(word);
}
// go through and replace our other exceptions with the proper values
text = builder.ToString();
foreach (string key in MultiWordExceptions.Keys)
text = text.Replace(key, MultiWordExceptions[key]);
foreach (string key in CaseSensitiveExceptions.Keys)
text = text.Replace(key, CaseSensitiveExceptions[key]);
// return the result
return text;
}
}