public BulletIndent(string indent = null, BulletIndent currentBulletIndent = null, int?level = null, List <string> bulletStyles = null) { if (indent == null) { // indicates an empty BulletIndent return; } this.bulletStyles = bulletStyles; string currentIndent = currentBulletIndent == null ? "" : currentBulletIndent.indent; this.indent = indent; if (currentBulletIndent == null) { // establish the first level this.level = level == null ? 0 : level; this.index = 0; this.parent = null; } else if (this.level == level || indent == currentIndent) { // staying on the same level this.level = currentBulletIndent.level; this.index = currentBulletIndent.index + 1; this.parent = currentBulletIndent.parent; this.styleInitializerLevel = currentBulletIndent.styleInitializerLevel; } else { // search for the same level BulletIndent matchingLevel = currentBulletIndent.parent; // used to find a previous level while (matchingLevel != null) { if ((level != null && matchingLevel.level == level) || indent == matchingLevel.indent) { // found a matching level, so this one is a continuation this.level = matchingLevel.level; this.index = matchingLevel.index + 1; this.parent = matchingLevel.parent; this.styleInitializerLevel = this.level; // don't honor style initializers above this level break; } else { matchingLevel = matchingLevel.parent; } } if (matchingLevel == null) { // create a new level this.level = level == null ? (currentBulletIndent.level + 1) : level; this.index = 0; this.parent = currentBulletIndent; this.styleInitializerLevel = currentBulletIndent.styleInitializerLevel; } } }
public BulletIndent clone() { // clone a BulletIndent that reflects the state BulletIndent cloneBulletIndent = new BulletIndent(); cloneBulletIndent.level = this.level; cloneBulletIndent.index = this.index; cloneBulletIndent.indent = this.indent; cloneBulletIndent.parent = this.parent; cloneBulletIndent.lastBullet = this.lastBullet; cloneBulletIndent.bulletStyles = this.bulletStyles; cloneBulletIndent.styleInitializerLevel = this.styleInitializerLevel; return(cloneBulletIndent); }
public string getBullet() { string bullet; List <string> bulletStyles = this.bulletStyles; if (bulletStyles == null || bulletStyles.Count == 0) { bullet = "(" + this.level + "." + this.index + ")"; // TODO: default bullet style } else { string bulletStyleText = bulletStyles[(int)(this.level < bulletStyles.Count ? this.level : bulletStyles.Count - 1)]; // support multiple numbers at one level by creating an array of styles that contain 0 or 1 number/letter/roman string concatenatedBullet = ""; string[] styleArray = Regex.Replace(bulletStyleText, @"(.*?(i\:[ivxldcm]+|i|I\:[IVXLDCM]+|I|1\:\d+|1|a\:[a-z]+|a|A\:[A-Z]+|A).\S*?)", "$1").Split('\x02'); BulletIndent currentBulletLevel = this; for (int i = styleArray.Length - 1; i >= 0 && currentBulletLevel != null; i--) { string bulletStyle = styleArray[i]; string padding = ""; if (new Regex(@"^ +").IsMatch(bulletStyle)) { padding = Regex.Replace(bulletStyle, @"^( +).*$", "$1"); bulletStyle = bulletStyle.Substring(padding.Length); } string prefix = ""; string postfix = ""; string bulletType = ""; // TODO: support styles like 'I.a.1.i', '1.1.1.1' or even '1:10.1.1.1' // TODO: consider allowing \: and \\ for legitimate: // support styles like 'i', 'i:iv', 'I', 'I:LV', '1', '1:13', 'a', 'a:d', 'A', 'A:AF' if (new Regex(@"^.*(i\:[ivxldcm]+|i|I\:[IVXLDCM]+|I|1\:\d+|1|a\:[a-z]+|a|A\:[A-Z]+|A).*$", RegexOptions.Singleline).IsMatch(bulletStyle)) { prefix = Regex.Replace(bulletStyle, @"^(.*?)(i\:[ivxldcm]+|i|I\:[IVXLDCM]+|I|1\:\d+|1|a\:[a-z]+|a|A\:[A-Z]+|A).*$", "$1"); postfix = Regex.Replace(bulletStyle, @"^.*?(i\:[ivxldcm]+|i|I\:[IVXLDCM]+|I|1\:\d+|1|a\:[a-z]+|a|A\:[A-Z]+|A)(.*)$", "$2"); bulletStyle = Regex.Replace(bulletStyle, @"^.*?(i\:[ivxldcm]+|i|I\:[IVXLDCM]+|I|1\:\d+|1|a\:[a-z]+|a|A\:[A-Z]+|A).*$", "$1"); bulletType = bulletStyle.Substring(0, 1); if (bulletStyle.Contains(":")) { if (this.styleInitializerLevel != null && currentBulletLevel.level > this.styleInitializerLevel) { // ignore the style initializer because we've already popped back to a level above this bulletStyle = bulletType; } else { // capture the style initializer, which is the value after the ":" bulletStyle = bulletStyle.Substring(bulletStyle.IndexOf(":") + 1); } } } else if (bulletStyle.Length > 1) { if ("(<#$%*.-=+`~[{_=+|'\"".Contains(bulletStyle.Substring(0, 1))) { prefix = bulletStyle.Substring(0, 1); bulletStyle = bulletStyle.Substring(1); } if (")>*]}.`~*-_=+|:'\"".Contains(bulletStyle.Substring(bulletStyle.Length - 1, 1))) { postfix = bulletStyle.Substring(bulletStyle.Length - 1, 1); bulletStyle = bulletStyle.Substring(0, bulletStyle.Length - 1); } } bullet = bulletStyle; if (bulletType.Length == 1) { switch (bulletType) { case "I": bullet = this.numberToRoman(currentBulletLevel.index + (bulletStyle != "I" ? this.romanToNumber(bulletStyle) : 1)); break; case "i": bullet = this.numberToRoman(currentBulletLevel.index + (bulletStyle != "i" ? this.romanToNumber(bulletStyle) : 1)).ToLower(); break; case "1": bullet = (currentBulletLevel.index + (bulletStyle != "1" ? Int32.Parse(bulletStyle) : 1)).ToString(); break; case "A": case "a": bullet = this.numberToAlphabet(currentBulletLevel.index + (bulletStyle.ToLower() != "a" ? this.alphabetToNumber(bulletStyle) : 1)); if (bulletType == "a") { bullet = bullet.ToLower(); } break; } if (padding.Length > 0 && bullet.Length < (padding.Length + 1)) { prefix = padding.Substring(0, padding.Length - bullet.Length + 1) + prefix; } bullet = prefix + bullet + postfix; currentBulletLevel = currentBulletLevel.parent; } concatenatedBullet = bullet + concatenatedBullet; } bullet = concatenatedBullet; } this.lastBullet = this.indent + bullet.Replace("\x01", ""); return(bullet); }