Hunks.h 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. /*
  2. * Copyright (c) 2020, Itamar S. <itamar8910@gmail.com>
  3. * Copyright (c) 2023, Shannon Booth <shannon.ml.booth@gmail.com>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #pragma once
  8. #include <AK/Assertions.h>
  9. #include <AK/Format.h>
  10. #include <AK/String.h>
  11. #include <AK/StringView.h>
  12. #include <AK/Vector.h>
  13. namespace Diff {
  14. struct Range {
  15. size_t start_line { 0 };
  16. size_t number_of_lines { 0 };
  17. };
  18. struct HunkLocation {
  19. Range old_range;
  20. Range new_range;
  21. };
  22. struct Line {
  23. enum class Operation {
  24. Addition = '+',
  25. Removal = '-',
  26. Context = ' ',
  27. // NOTE: This should only be used when deconstructing a hunk into old and new lines (context format)
  28. Change = '!',
  29. };
  30. static constexpr Operation operation_from_symbol(char symbol)
  31. {
  32. switch (symbol) {
  33. case '+':
  34. return Operation::Addition;
  35. case '-':
  36. return Operation::Removal;
  37. case ' ':
  38. return Operation::Context;
  39. default:
  40. VERIFY_NOT_REACHED();
  41. }
  42. }
  43. Operation operation;
  44. String content;
  45. };
  46. struct Hunk {
  47. HunkLocation location;
  48. Vector<Line> lines;
  49. };
  50. ErrorOr<Vector<Hunk>> parse_hunks(StringView diff);
  51. HunkLocation parse_hunk_location(StringView location_line);
  52. };
  53. template<>
  54. struct AK::Formatter<Diff::Line::Operation> : Formatter<FormatString> {
  55. ErrorOr<void> format(FormatBuilder& builder, Diff::Line::Operation operation)
  56. {
  57. return Formatter<FormatString>::format(builder, "{}"sv, static_cast<char>(operation));
  58. }
  59. };
  60. template<>
  61. struct AK::Formatter<Diff::Line> : Formatter<FormatString> {
  62. ErrorOr<void> format(FormatBuilder& builder, Diff::Line const& line)
  63. {
  64. return Formatter<FormatString>::format(builder, "{}{}"sv, line.operation, line.content);
  65. }
  66. };
  67. template<>
  68. struct AK::Formatter<Diff::HunkLocation> : Formatter<FormatString> {
  69. static ErrorOr<void> format(FormatBuilder& format_builder, Diff::HunkLocation const& location)
  70. {
  71. auto& builder = format_builder.builder();
  72. TRY(builder.try_appendff("@@ -{}"sv, location.old_range.start_line));
  73. if (location.old_range.number_of_lines != 1)
  74. TRY(builder.try_appendff(",{}", location.old_range.number_of_lines));
  75. TRY(builder.try_appendff(" +{}", location.new_range.start_line));
  76. if (location.new_range.number_of_lines != 1)
  77. TRY(builder.try_appendff(",{}", location.new_range.number_of_lines));
  78. return builder.try_appendff(" @@");
  79. }
  80. };