/// <summary> /// Parses the string and updates the state accordingly. /// </summary> /// <param name="input">The text to process.</param> /// <returns>The text, ready for formatting.</returns> /// This method modifies the text because it removes some /// syntax stuff. Maybe the states themselves should handle /// their own syntax and remove it? private string HandleFormattingState(string input) { for (int i = 0; i < s_registeredStates.Count; i++) { Type type = s_registeredStates[i]; if (IsFormatterStateEnabled(type)) { FormatterStateAttribute att = s_registeredStatesAttributes[i]; Match m = Regex.Match(input, att.Pattern); if (m.Success) { FormatterState formatterState = (FormatterState)Activator.CreateInstance(type, this); return(formatterState.Consume(input, m)); } } } // Default, when no block is specified, we ask the current state, or // use the paragraph state. if (CurrentState != null) { if (CurrentState.FallbackFormattingState != null) { FormatterState formatterState = (FormatterState)Activator.CreateInstance(CurrentState.FallbackFormattingState, this); ChangeState(formatterState); } // else, the current state doesn't want to be superceded by // a new one. We'll leave him be. } else { ChangeState(new States.ParagraphFormatterState(this)); } return(input); }
internal static string GetConsumedInput(List <Type> disabledFormatterStates, string input, TextileFormatter instance) { for (int i = 0; i < s_registeredStates.Count; i++) { Type type = s_registeredStates[i]; if (!disabledFormatterStates.Contains(type)) { FormatterStateAttribute att = s_registeredStatesAttributes[i]; Match m = Regex.Match(input, att.Pattern); if (m.Success) { FormatterState formatterState = (FormatterState)Activator.CreateInstance(type, instance); return(formatterState.Consume(input, m)); } } } return(null); }
/// <summary> /// Gets the type of a candidate formatter state for the given input and look-ahead input. /// </summary> /// <param name="input"></param> /// <param name="inputLookAhead"></param> /// <param name="match"></param> /// <param name="lookAheadMatch"></param> /// <returns></returns> public Type GetCandidateFormatterStateType(string input, string inputLookAhead, out Match match, out Match lookAheadMatch) { for (int i = 0; i < _formatterStates.Count; i++) { Type type = _formatterStates[i]; FormatterStateAttribute attribute = _formatterStateAttributes[i]; // Match the current line. Match m = null; if (attribute.Regex != null) { m = attribute.Regex.Match(input); } if (m == null || m.Success) { // If the current line matches, optionally match // the next line (if that formatter state needs the look-ahead // line to know if it's a candidate). Match m2 = null; if (attribute.LookAheadRegex != null) { if (string.IsNullOrEmpty(inputLookAhead)) // This could be null if we're processing the last line. { continue; } m2 = attribute.LookAheadRegex.Match(inputLookAhead); if (!m2.Success) { continue; } } // Seems good! match = m; lookAheadMatch = m2; return(type); } } match = null; lookAheadMatch = null; return(null); }
public static void RegisterFormatterState(Type formatterStateType) { if (!formatterStateType.IsSubclassOf(typeof(FormatterState))) { throw new ArgumentException("The formatter state must be a sub-public class of FormatterStateBase."); } if (formatterStateType.GetConstructor(new Type[] { typeof(TextileFormatter) }) == null) { throw new ArgumentException("The formatter state must have a constructor that takes a TextileFormatter reference."); } FormatterStateAttribute att = FormatterStateAttribute.Get(formatterStateType); if (att == null) { throw new ArgumentException("The formatter state must have the FormatterStateAttribute."); } s_registeredStates.Add(formatterStateType); s_registeredStatesAttributes.Add(att); }