Serenity Operating System
1/*
2 * Copyright (c) 2021, Mustafa Quraish <mustafa@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <LibCore/ArgsParser.h>
8#include <LibCore/File.h>
9#include <LibCore/System.h>
10#include <LibDiff/Generator.h>
11#include <LibMain/Main.h>
12#include <unistd.h>
13
14ErrorOr<int> serenity_main(Main::Arguments arguments)
15{
16 TRY(Core::System::pledge("stdio rpath"));
17
18 Core::ArgsParser parser;
19 DeprecatedString filename1;
20 DeprecatedString filename2;
21
22 parser.add_positional_argument(filename1, "First file to compare", "file1", Core::ArgsParser::Required::Yes);
23 parser.add_positional_argument(filename2, "Second file to compare", "file2", Core::ArgsParser::Required::Yes);
24 parser.parse(arguments);
25
26 auto file1 = TRY(Core::File::open(filename1, Core::File::OpenMode::Read));
27 auto file2 = TRY(Core::File::open(filename2, Core::File::OpenMode::Read));
28
29 bool color_output = TRY(Core::System::isatty(STDOUT_FILENO));
30
31 auto hunks = Diff::from_text(TRY(file1->read_until_eof()), TRY(file2->read_until_eof()));
32 for (auto const& hunk : hunks) {
33 auto original_start = hunk.original_start_line;
34 auto target_start = hunk.target_start_line;
35 auto num_added = hunk.added_lines.size();
36 auto num_removed = hunk.removed_lines.size();
37
38 StringBuilder sb;
39 // Source line(s)
40 sb.appendff("{}", original_start);
41 if (num_removed > 1)
42 sb.appendff(",{}", original_start + num_removed - 1);
43
44 // Action
45 if (num_added > 0 && num_removed > 0)
46 sb.append('c');
47 else if (num_added > 0)
48 sb.append('a');
49 else
50 sb.append('d');
51
52 // Target line(s)
53 sb.appendff("{}", target_start);
54 if (num_added > 1)
55 sb.appendff(",{}", target_start + num_added - 1);
56
57 outln("Hunk: {}", sb.to_deprecated_string());
58 for (auto const& line : hunk.removed_lines) {
59 if (color_output)
60 outln("\033[31;1m< {}\033[0m", line);
61 else
62 outln("< {}", line);
63 }
64 if (num_added > 0 && num_removed > 0)
65 outln("---");
66 for (auto const& line : hunk.added_lines) {
67 if (color_output)
68 outln("\033[32;1m> {}\033[0m", line);
69 else
70 outln("> {}", line);
71 }
72 }
73
74 return hunks.is_empty() ? 0 : 1;
75}