/// <summary>
        /// Determines what to do when an Invalid Selector is found.
        ///
        /// Returns True if we should just continue; False if we should skip this item.
        /// </summary>
        private bool OnInvalidSelector(string format, CustomFormatInfo info, PlaceholderInfo placeholder)
        {
            string invalidSelector = format.Substring(placeholder.selectorStart, placeholder.selectorLength);

            string message;

            switch (InvalidSelectorAction)
            {
            case ErrorAction.ThrowError:
                //  Let's give a detailed description of the error:
                message = FormatEx(
                    ("Invalid Format String.\\n" +
                     ("Could not evaluate \"{0}\": \"{1}\" is not a member of {2}.\\n" +
                      ("The error occurs at position {3} of the following format string:\\n" + "{4}"))),
                    invalidSelector, info.Selector, info.CurrentType, placeholder.placeholderStart, format);
                throw new ArgumentException(message, invalidSelector);

            case ErrorAction.OutputErrorInResult:
                //  Let's put the placeholder back,
                //  along with the error.
                //  Example: {Person.Name.ABC}  becomes  {Person.Name.ABC:(Error: "ABC" is not a member of String)}
                message = ("{" + (FormatEx("{0}:(Error: \"{1}\" is not a member of {2})", invalidSelector,
                                           info.Selector, info.CurrentType) + "}"));
                info.WriteError(message, placeholder);
                return(false);

            case ErrorAction.Ignore:
                //  Allow formatting to continue!
                break;
            }
            return(true);
        }
        private static void _GetDefaultOutput(object sender, ExtendFormatEventArgs e)
        {
            CustomFormatInfo info = e.FormatInfo;

            //  Let's see if there are nested items:
            if (info.HasNested)
            {
                info.CustomFormatNested();
                return;
            }

            //  Let's do the default formatting:
            //  We will try using IFormatProvider, IFormattable, and if all else fails, ToString.
            //  (This code was adapted from the built-in String.Format code)
            if (info.Provider != null)
            {
                //  Use the provider to see if a CustomFormatter is available:
                ICustomFormatter formatter = info.Provider.GetFormat(typeof(ICustomFormatter)) as ICustomFormatter;
                if (formatter != null)
                {
                    info.Write(formatter.Format(info.Format, info.Current, info.Provider));
                    return;
                }
            }

            //  Now try to format the object, using its own built-in formatting if possible:
            if (info.Current is IFormattable)
            {
                info.Write(((IFormattable)info.Current).ToString(info.Format, info.Provider));
            }
            else
            {
                info.Write(info.Current.ToString());
            }
        }
Пример #3
0
        private void DoTimeStringFormat(object sender, ExtendFormatEventArgs e)
        {
            CustomFormatInfo info = e.FormatInfo;

            if (info.CurrentIsTimeSpan)
            {
                info.Write(TimestringPlugin.ToTimeString((TimeSpan)info.Current, info.Format, _formattingOptions));
            }
            else if (info.CurrentIsDate && info.FormatStartsWith("timestring"))
            {
                info.Write(TimestringPlugin.ToTimeString(DateTime.Now.Subtract((DateTime)info.Current), info.Format.Substring(10), _formattingOptions));
            }
        }
        /// <summary>
        /// Determines what to do when an Invalid Selector is found.
        /// </summary>
        private void OnInvalidFormat(string format, CustomFormatInfo info, PlaceholderInfo placeholder, Exception ex)
        {
            string selector      = format.Substring(placeholder.selectorStart, placeholder.selectorLength);
            string invalidFormat = format.Substring(placeholder.formatStart, placeholder.formatLength);
            string errorMessage  = ex.Message;

            if (ex is FormatException)
            {
                errorMessage = FormatEx("\"{0}\" is not a valid format specifier for {1}", invalidFormat,
                                        info.CurrentType);
            }

            string message;

            switch (InvalidFormatAction)
            {
            case ErrorAction.ThrowError:
                //  Let's give a detailed description of the error:
                message = FormatEx(
                    ("Invalid Format String.\\n" +
                     ("Could not evaluate {{0}} because {1}.\\n" +
                      ("The error occurs at position {2} of the following format string:\\n" + "{3}"))), selector,
                    errorMessage, placeholder.placeholderStart, format);
                throw new ArgumentException(message, invalidFormat, ex);

            case ErrorAction.OutputErrorInResult:
                //  Let's put the placeholder back,
                //  along with the error.
                //  Example: {Person.Birthday:x}  becomes  {Person.Birthday:(Error: "x" is an invalid format specifier)}
                message = ("{" + (FormatEx("{0}:(Error: {1})", selector, errorMessage) + "}"));
                info.WriteError(message, placeholder);
                break;

            case ErrorAction.Ignore:
                //  Allow formatting to continue!
                break;
            }
        }
Пример #5
0
        private static void FormatConditional(object sender, ExtendFormatEventArgs e)
        {
            CustomFormatInfo info = e.FormatInfo;

            // See if the format string contains un-nested "|":
            string[] parameters = Core.ParsingServices.SplitNested(info.Format, '|');
            if (parameters.Length == 1)
            {
                return; // There are no splits.
            }


            int paramCount = parameters.Length;
            int paramIndex = 0; // Determines which parameter to use in the result


            // See if there are any (optional) conditions:
            bool conditionResult = false;

            if (info.CurrentIsNumber && TryEvaluateCondition(ref parameters[0], info.Current, ref conditionResult))
            {
                // parameters(0) contained a "conditional statement"
                // If the conditional statement was False, then
                // we will move on to the next parameters
                while (!conditionResult)
                {
                    if (paramIndex == parameters.Length - 1)
                    {
                        break;
                    }

                    paramIndex += 1;

                    if (!TryEvaluateCondition(ref parameters[paramIndex], info.Current, ref conditionResult))
                    {
                        // (couldn't evaluate the conditional statement, which means it's an "else" statement
                        break;
                    }
                }
            }
            else
            {
                // Determine the Current item's Type:
                if (info.CurrentIsNumber)
                {
                    // Number: Neg|Zero|One|Many  or  Zero|One|Many/Neg  or  One|Many/Neg/Zero
                    var arg = Convert.ToDecimal(info.Current);
                    if (arg < 0m)
                    {
                        paramIndex = -4;
                    }
                    else if (arg == 0m)
                    {
                        paramIndex = -3;
                    }
                    else if (0m < arg && arg <= 1m)
                    {
                        paramIndex = -2;
                    }
                    else
                    {
                        paramIndex = -1;
                    }

                    paramIndex = paramIndex + paramCount;

                    if (paramIndex < 0)
                    {
                        paramIndex = paramCount - 1;
                    }
                }
                else if (info.CurrentIsBoolean)
                {
                    // Bool: True|False
                    bool arg = (bool)info.Current;
                    if (!arg)
                    {
                        paramIndex = 1;
                    }
                }
                else if (info.CurrentIsDate)
                {
                    // Date: Past|Present|Future   or   Past/Present|Future
                    System.DateTime arg = (DateTime)info.Current;
                    if (paramCount == 3 && arg.Date == DateTime.Today)
                    {
                        paramIndex = 1;
                    }
                    else if (arg > DateTime.Now)
                    {
                        paramIndex = paramCount - 1;
                    }
                }
                else if (info.CurrentIsTimeSpan)
                {
                    // TimeSpan: Negative|Zero|Positive  or  Negative/Zero|Positive
                    TimeSpan arg = (TimeSpan)info.Current;
                    if (paramCount == 3 && arg == TimeSpan.Zero)
                    {
                        paramIndex = 1;
                    }
                    else if (arg.CompareTo(TimeSpan.Zero) == 1)
                    {
                        paramIndex = paramCount - 1;
                    }
                }
                else if (info.CurrentIsString)
                {
                    // String: Value|NullOrEmpty
                    var arg = (string)info.Current;
                    if (string.IsNullOrEmpty(arg))
                    {
                        paramIndex = 1;
                    }
                }
                else
                {
                    // Object: Something|Nothing
                    object arg = info.Current;
                    if (arg == null)
                    {
                        paramIndex = 1;
                    }
                }
            }


            // Now, output the selected parameter:
            if (parameters[paramIndex].Contains("{"))
            {
                // The format has nested items, so let's evaluate those now:
                info.SetFormat(parameters[paramIndex], true);
                info.CustomFormatNested();
            }
            else
            {
                // The format doesn't have nested items so let's just write the selected parameter:
                info.Write(parameters[paramIndex]);
            }
        }
        /// <summary>
        /// Does the actual work.
        /// </summary>
        internal void FormatExInternal(CustomFormatInfo info)
        {
            if (info.Current == null && info.Arguments.Length >= 1)
            {
                info.Current = info.Arguments[0];
            }

            //  We need to store the Format and the Current items and keep them in this context
            string format  = info.Format;
            object current = info.Current;


            // ' Here is the regular expression to use for parsing the Format string:
            // Static R As New Regex( _
            //   "{  ([0-9A-Za-z_.\[\]()]*)   (?:    :  ( (?:    (?<open>{)     |     (?<nest-open>})     |     [^{}]+     )*? ) (?(open)(?!))  )?  }" _
            //   , RegexOptions.IgnorePatternWhitespace Or RegexOptions.Compiled)
            //   {  (      Selectors     )   (Optnl :           {  Nested                         }     or      Format                         )   }


            int             lastAppendedIndex = 0;
            PlaceholderInfo placeholder       = null;

            while (NextPlaceholder(format, lastAppendedIndex, format.Length, ref placeholder))
            {
                //  Write the text in-between placeholders:
                info.WriteRegularText(format, lastAppendedIndex, (placeholder.placeholderStart - lastAppendedIndex));
                lastAppendedIndex = placeholder.placeholderStart + placeholder.placeholderLength;

                //  Evaluate the source by evaluating each argSelector:
                info.Current = current; //  Restore the current scope
                //bool isFirstSelector = true; // TODO: Remove this variable if it never gets used again
                int selectorIndex = -1;

                foreach (string selector in placeholder.selectors)
                {
                    selectorIndex++;
                    info.SetSelector(selector, selectorIndex);
                    //  Raise the ExtendCustomSource event to allow custom source evaluation:
                    OnExtendSourceEvent(new ExtendSourceEventArgs(info));

                    //  Make sure that the selector has been handled:
                    if (!info.Handled)
                    {
                        break;
                    }
                    //isFirstSelector = false;
                }

                //  Handle errors:
                if (!info.Handled)
                {
                    //  If the ExtendCustomSource event wasn't handled,
                    //  then the Selector could not be evaluated.
                    if (!OnInvalidSelector(format, info, placeholder))
                    {
                        continue;
                    }
                }

                string argFormat = format.Substring(placeholder.formatStart, placeholder.formatLength);
                info.SetFormat(argFormat, placeholder.hasNested);

                try {
                    //  Raise the ExtendCustomFormat event to allow custom formatting:
                    OnExtendFormatEvent(new ExtendFormatEventArgs(info));
                }
                catch (Exception ex) {
                    //  Handle errors:
                    OnInvalidFormat(format, info, placeholder, ex);
                }
            }
            //  Write the substring between the last bracket and the end of the string:
            info.WriteRegularText(format, lastAppendedIndex, (format.Length - lastAppendedIndex));
        }
Пример #7
0
        private void DoArrayFormatting(object sender, ExtendFormatEventArgs e)
        {
            CustomFormatInfo info = e.FormatInfo;
            // This method needs the Highest priority so that it comes before Strings.Format.Conditional.vb
            ICollection items = info.Current as ICollection;

            if (items == null)
            {
                return;
            }


            // The SplitString function is in the file Strings.Format.Conditional.vb:
            string[] split = Core.ParsingServices.SplitNested(info.Format, '|', 3);
            string   format = split[0];
            string   spacer = null, lastSpacer = null;

            if (split.Length >= 2)
            {
                spacer = split[1];
            }
            else
            {
                spacer = " "; // At least put a space between items by default
            }


            if (split.Length >= 3)
            {
                lastSpacer = split[2];
            }

            if (!info.HasNested)
            {
                format = "{:" + format + "}";
            }



            int itemCount = -1;

            if (lastSpacer != null)
            {
                itemCount = items.Count;
            }

            int oldCollectionIndex = CollectionIndex;

            // In case we have nested arrays, we might need to restore the CollectionIndex
            CollectionIndex = -1;
            foreach (object item in items)
            {
                CollectionIndex += 1;
                // Keep track of the index

                // If it isn't the first item, then write the spacer:
                if (CollectionIndex > 0)
                {
                    // Write either the spacer or lastSpacer:
                    if (itemCount == -1 || CollectionIndex < itemCount - 1)
                    {
                        info.Write(spacer);
                    }
                    else
                    {
                        info.Write(lastSpacer);
                    }
                }

                // Write the format for this item:
                info.Current = item;
                info.SetFormat(format, info.HasNested);
                info.CustomFormatNested();
            }
            CollectionIndex = oldCollectionIndex;
            // Restore the CollectionIndex
        }