TextDiffer.cs 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344
  1. using System.Collections.Immutable;
  2. namespace Masuit.Tools.TextDiff;
  3. public readonly record struct TextDiffer(DiffOperation Operation, string Text)
  4. {
  5. public static TextDiffer Empty => new(DiffOperation.Equal, string.Empty);
  6. public bool IsEmpty => Text.Length == 0;
  7. public static TextDiffer Equal(ReadOnlySpan<char> text) => Create(DiffOperation.Equal, text.ToString());
  8. public static TextDiffer Insert(ReadOnlySpan<char> text) => Create(DiffOperation.Insert, text.ToString());
  9. public static TextDiffer Delete(ReadOnlySpan<char> text) => Create(DiffOperation.Delete, text.ToString());
  10. internal static TextDiffer Create(DiffOperation operation, string text) => new(operation, text);
  11. internal TextDiffer Replace(string text) => this with { Text = text };
  12. internal TextDiffer Append(string text) => this with { Text = Text + text };
  13. internal TextDiffer Prepend(string text) => this with { Text = text + Text };
  14. /// <summary>
  15. /// 比较两段文本并生成差异信息
  16. /// </summary>
  17. /// <param name="text1"></param>
  18. /// <param name="text2"></param>
  19. /// <param name="timeoutInSeconds">比较超时时间,单位:秒,0表示不超时</param>
  20. /// <param name="checklines">如果为false,则不要先运行行级差异来识别更改的区域。如果为true,则运行一个速度稍快但不太理想的差异</param>
  21. /// <returns></returns>
  22. public static ImmutableList<TextDiffer> Compute(string text1, string text2, float timeoutInSeconds = 0f, bool checklines = true)
  23. {
  24. using var cts = timeoutInSeconds <= 0
  25. ? new CancellationTokenSource()
  26. : new CancellationTokenSource(TimeSpan.FromSeconds(timeoutInSeconds));
  27. return Compute(text1, text2, checklines, timeoutInSeconds > 0, cts.Token);
  28. }
  29. public static ImmutableList<TextDiffer> Compute(string text1, string text2, bool checkLines, bool optimizeForSpeed, CancellationToken token)
  30. => DiffAlgorithm.Compute(text1, text2, checkLines, optimizeForSpeed, token).ToImmutableList();
  31. public bool IsLargeDelete(int size) => Operation == DiffOperation.Delete && Text.Length > size;
  32. public override string ToString()
  33. {
  34. var prettyText = Text.Replace('\n', '\u00b6');
  35. return "Diff(" + Operation + ",\"" + prettyText + "\")";
  36. }
  37. }