public static bool AddReplacementEntry(this Dictionary <string, MultiReplacementEntry> list, string pattern1, string pattern2)
        {
            if (string.IsNullOrEmpty(pattern1) || pattern2 == null)
            {
                return(false);
            }

            var pattern1Builder = StringBuilderPool.Get(pattern1);
            ReplacementValueType type;
            var trailingUnderscore = pattern1Builder.EndsWith('_');

            if (pattern1Builder.StartsWith('_'))
            {
                if (trailingUnderscore)
                {
                    type = ReplacementValueType.Isol;
                    pattern1Builder.Remove(pattern1Builder.Length - 1, 1);
                }
                else
                {
                    type = ReplacementValueType.Ini;
                }

                pattern1Builder.Remove(0, 1);
            }
            else
            {
                if (trailingUnderscore)
                {
                    type = ReplacementValueType.Fin;
                    pattern1Builder.Remove(pattern1Builder.Length - 1, 1);
                }
                else
                {
                    type = ReplacementValueType.Med;
                }
            }

            pattern1Builder.Replace('_', ' ');

            pattern1 = StringBuilderPool.GetStringAndReturn(pattern1Builder);
            pattern2 = pattern2.Replace('_', ' ');

            // find existing entry
            if (list.TryGetValue(pattern1, out MultiReplacementEntry entry))
            {
                entry = entry.With(type, pattern2);
            }
            else
            {
                // make a new entry if none exists
                entry = new MultiReplacementEntry(pattern1, type, pattern2);
            }

            list[pattern1] = entry;

            return(true);
        }
        public MultiReplacementEntry With(ReplacementValueType type, string value)
        {
            var result = new MultiReplacementEntry(Pattern);

            switch (type)
            {
            case ReplacementValueType.Med:
                result.med  = value;
                result.ini  = ini;
                result.fin  = fin;
                result.isol = isol;
                break;

            case ReplacementValueType.Ini:
                result.med  = med;
                result.ini  = value;
                result.fin  = fin;
                result.isol = isol;
                break;

            case ReplacementValueType.Fin:
                result.med  = med;
                result.ini  = ini;
                result.fin  = value;
                result.isol = isol;
                break;

            case ReplacementValueType.Isol:
                result.med  = med;
                result.ini  = ini;
                result.fin  = fin;
                result.isol = value;
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(type));
            }

            return(result);
        }