예제 #1
0
        /// <summary>
        /// Parses the specified text representing a misspelling transform
        /// operation.
        /// </summary>
        /// <param name="text">The text.</param>
        /// <returns>operation, or null if invalid text</returns>
        public static MspOperation Parse(string text)
        {
            if (string.IsNullOrWhiteSpace(text))
            {
                return(null);
            }

            Match m = _opRegex.Match(text);

            if (!m.Success)
            {
                return(null);
            }

            MspOperation operation = new MspOperation
            {
                RangeA = new TextRange(
                    ParseRangeNumber(m.Groups["ras"].Value),
                    ParseRangeNumber(m.Groups["ral"].Value)),
                ValueA = m.Groups["va"].Length > 0 ? m.Groups["va"].Value : null,
                RangeB = new TextRange(
                    ParseRangeNumber(m.Groups["rbs"].Value),
                    ParseRangeNumber(m.Groups["rbl"].Value)),
                ValueB = m.Groups["vb"].Length > 0 ? m.Groups["vb"].Value : null,
                Tag    = m.Groups["tag"].Length > 0 ? m.Groups["tag"].Value : null,
                Note   = m.Groups["note"].Length > 0 ? m.Groups["note"].Value : null
            };

            DetermineOperator(m.Groups["op"].Value, operation);

            // range B is allowed only for move/swap
            if (operation._operator != MspOperator.Move &&
                operation._operator != MspOperator.Swap)
            {
                operation.RangeB = TextRange.Empty;
            }

            // value B is allowed only for insert/replace/swap
            if (operation._operator != MspOperator.Insert &&
                operation._operator != MspOperator.Replace &&
                operation._operator != MspOperator.Swap)
            {
                operation.ValueB = null;
            }

            return(operation);
        }
        /// <summary>
        /// Get all the pins exposed by the implementor.
        /// </summary>
        /// <remarks>If operations have tags, the operations with tags are
        /// grouped by them, and a pin is returned for each group, with its name
        /// equal to <c>fr.msp</c> + the grouped operations tag, and its value
        /// equal to the count of such operations. These pins are sorted
        /// by their name.</remarks>
        /// <returns>pins</returns>
        public IEnumerable <DataPin> GetDataPins()
        {
            if (Operations?.Count == 0)
            {
                return(Enumerable.Empty <DataPin>());
            }

            var groups = from s in Operations
                         let o = MspOperation.Parse(s)
                                 where o?.Tag != null
                                 group o by o.Tag
                                 into g
                                 select g;

            return(from g in groups
                   orderby g.Key
                   select new DataPin
            {
                Name = PartBase.FR_PREFIX + $"msp.{g.Key}",
                Value = g.Count().ToString(CultureInfo.InvariantCulture)
            });
        }
예제 #3
0
        private static void DetermineOperator(string text, MspOperation operation)
        {
            switch (text)
            {
            case "=":
                if (operation.ValueB == null)
                {
                    operation.Operator = MspOperator.Delete;
                    break;
                }
                operation.Operator = operation.RangeA.Length == 0?
                                     MspOperator.Insert : MspOperator.Replace;
                break;

            case ">":
                operation.Operator = MspOperator.Move;
                break;

            case "~":
                operation.Operator = MspOperator.Swap;
                break;
            }
        }
        /// <summary>
        /// Get all the pins exposed by the implementor.
        /// </summary>
        /// <param name="item">The optional item. The item with its parts
        /// can optionally be passed to this method for those parts requiring
        /// to access further data.</param>
        /// <remarks>If operations have tags, the operations with tags are
        /// grouped by them, and a pin is returned for each group, with its name
        /// equal to <c>fr.msp</c> + the grouped operations tag, and its value
        /// equal to the count of such operations. These pins are sorted
        /// by their name.
        /// <para>Also, if <paramref name="item"/> is received and it has
        /// a base text part and an orthography layer part, two additional pins
        /// are returned: <c>fr.orthography-txt</c> with the original orthography
        /// got from the base text, and <c>fr.orthography.std</c> with the
        /// <see cref="Standard"/> orthography from this fragment.</para>
        /// </remarks>
        /// <returns>pins</returns>
        public IEnumerable <DataPin> GetDataPins(IItem item = null)
        {
            List <DataPin> pins = new List <DataPin>();

            if (Operations?.Count > 0)
            {
                var groups = from s in Operations
                             let o = MspOperation.Parse(s)
                                     where o?.Tag != null
                                     group o by o.Tag
                                     into g
                                     select g;

                pins.AddRange(
                    from g in groups
                    orderby g.Key
                    select new DataPin
                {
                    Name  = PartBase.FR_PREFIX + $"msp.{g.Key}",
                    Value = g.Count().ToString(CultureInfo.InvariantCulture)
                });
            }

            if (item != null)
            {
                // get the base text part
                IPart textPart = item.Parts
                                 .Find(p => p.RoleId == PartBase.BASE_TEXT_ROLE_ID);
                if (textPart == null)
                {
                    return(pins);
                }

                // get the orthography layer
                TagAttribute attr = GetType().GetTypeInfo()
                                    .GetCustomAttribute <TagAttribute>();
                Regex roleIdRegex = new Regex("^" + attr.Tag + "(?::.+)?$");

                IHasFragments <OrthographyLayerFragment> layerPart =
                    item.Parts.Find(p => p.RoleId != null &&
                                    roleIdRegex.IsMatch(p.RoleId))
                    as IHasFragments <OrthographyLayerFragment>;
                if (layerPart == null)
                {
                    return(pins);
                }

                string baseText = layerPart.GetTextAt(textPart, Location);
                if (baseText != null)
                {
                    pins.Add(new DataPin
                    {
                        Name  = PartBase.FR_PREFIX + "orthography-txt",
                        Value = baseText
                    });
                    pins.Add(new DataPin
                    {
                        Name  = PartBase.FR_PREFIX + "orthography-std",
                        Value = Standard
                    });
                }
            }

            return(pins);
        }
예제 #5
0
        private void DetectMoves(List <Tuple <Diff, MspOperation> > mspDiffs)
        {
            // first look for INS..DEL
            for (int i = 0; i < mspDiffs.Count; i++)
            {
                // for each INS:
                if (mspDiffs[i].Item2?.Operator == MspOperator.Insert)
                {
                    MspOperation ins = mspDiffs[i].Item2;

                    // find a DEL with the same value
                    var nextDel = mspDiffs
                                  .Skip(i + 1)
                                  .FirstOrDefault(t =>
                                                  t.Item2?.Operator == MspOperator.Delete &&
                                                  t.Item2.ValueA == ins.ValueB);

                    // if found, assume a MOV from DEL to INS
                    if (nextDel != null)
                    {
                        int          nextDelIndex = mspDiffs.IndexOf(nextDel);
                        MspOperation del          = mspDiffs[nextDelIndex].Item2;

                        mspDiffs[nextDelIndex] = Tuple.Create(mspDiffs[nextDelIndex].Item1,
                                                              new MspOperation
                        {
                            Operator = MspOperator.Move,
                            RangeA   = del.RangeA,
                            RangeB   = ins.RangeA,
                            ValueA   = del.ValueA
                        });
                        mspDiffs.RemoveAt(i--);
                    }
                }
            }

            // then look for DEL..INS
            for (int i = 0; i < mspDiffs.Count; i++)
            {
                // for each DEL:
                if (mspDiffs[i].Item2?.Operator == MspOperator.Delete)
                {
                    // find an INS with the same value
                    MspOperation del     = mspDiffs[i].Item2;
                    var          nextIns = mspDiffs
                                           .Skip(i + 1)
                                           .FirstOrDefault(t =>
                                                           t.Item2?.Operator == MspOperator.Insert &&
                                                           t.Item2.ValueB == del.ValueA);

                    // if found, assume a MOV from DEL to INS
                    if (nextIns != null)
                    {
                        MspOperation ins          = nextIns.Item2;
                        int          nextInsIndex = mspDiffs.IndexOf(nextIns);

                        mspDiffs[i] = Tuple.Create(mspDiffs[i].Item1,
                                                   new MspOperation
                        {
                            Operator = MspOperator.Move,
                            RangeA   = del.RangeA,
                            RangeB   = ins.RangeA,
                            ValueA   = del.ValueA
                        });
                        mspDiffs.RemoveAt(nextInsIndex);
                    }
                }
            }
        }