Serenity Operating System
at master 119 lines 3.8 kB view raw
1/* 2 * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <AK/JsonArray.h> 8#include <AK/JsonObject.h> 9#include <AK/JsonValue.h> 10#include <AK/StringBuilder.h> 11#include <LibCore/ArgsParser.h> 12#include <LibCore/File.h> 13#include <LibCore/System.h> 14#include <LibMain/Main.h> 15#include <unistd.h> 16 17static bool use_color = false; 18static void print(StringView name, JsonValue const&, Vector<DeprecatedString>& trail); 19 20static StringView color_name = ""sv; 21static StringView color_index = ""sv; 22static StringView color_brace = ""sv; 23static StringView color_bool = ""sv; 24static StringView color_null = ""sv; 25static StringView color_string = ""sv; 26static StringView color_off = ""sv; 27 28ErrorOr<int> serenity_main(Main::Arguments arguments) 29{ 30 TRY(Core::System::pledge("stdio rpath tty")); 31 32 if (isatty(STDOUT_FILENO)) 33 use_color = true; 34 35 TRY(Core::System::pledge("stdio rpath")); 36 37 Core::ArgsParser args_parser; 38 args_parser.set_general_help("Print each value in a JSON file with its fully expanded key."); 39 40 StringView path; 41 args_parser.add_option(use_color, "Colorize output (default on tty)", "colorize", 'c'); 42 args_parser.add_option(Core::ArgsParser::Option { 43 Core::ArgsParser::OptionArgumentMode::None, 44 "Monochrome (don't colorize output)", 45 "monochrome", 46 'm', 47 nullptr, 48 [](StringView s) { 49 VERIFY(s.is_empty()); 50 use_color = false; 51 return true; 52 }, 53 }); 54 args_parser.add_positional_argument(path, "Input", "input", Core::ArgsParser::Required::No); 55 args_parser.parse(arguments); 56 57 auto file = TRY(Core::File::open_file_or_standard_stream(path, Core::File::OpenMode::Read)); 58 59 TRY(Core::System::pledge("stdio")); 60 61 auto file_contents = TRY(file->read_until_eof()); 62 auto json = TRY(JsonValue::from_string(file_contents)); 63 64 if (use_color) { 65 color_name = "\033[33;1m"sv; 66 color_index = "\033[35;1m"sv; 67 color_brace = "\033[36m"sv; 68 color_bool = "\033[32;1m"sv; 69 color_string = "\033[31;1m"sv; 70 color_null = "\033[34;1m"sv; 71 color_off = "\033[0m"sv; 72 } 73 74 Vector<DeprecatedString> trail; 75 print("json"sv, json, trail); 76 return 0; 77} 78 79static void print(StringView name, JsonValue const& value, Vector<DeprecatedString>& trail) 80{ 81 for (size_t i = 0; i < trail.size(); ++i) 82 out("{}", trail[i]); 83 84 out("{}{}{} = ", color_name, name, color_off); 85 86 if (value.is_object()) { 87 outln("{}{{}}{};", color_brace, color_off); 88 trail.append(DeprecatedString::formatted("{}{}{}.", color_name, name, color_off)); 89 value.as_object().for_each_member([&](auto& on, auto& ov) { print(on, ov, trail); }); 90 trail.take_last(); 91 return; 92 } 93 if (value.is_array()) { 94 outln("{}[]{};", color_brace, color_off); 95 trail.append(DeprecatedString::formatted("{}{}{}", color_name, name, color_off)); 96 for (size_t i = 0; i < value.as_array().size(); ++i) { 97 auto element_name = DeprecatedString::formatted("{}{}[{}{}{}{}{}]{}", color_off, color_brace, color_off, color_index, i, color_off, color_brace, color_off); 98 print(element_name, value.as_array()[i], trail); 99 } 100 trail.take_last(); 101 return; 102 } 103 switch (value.type()) { 104 case JsonValue::Type::Null: 105 out("{}", color_null); 106 break; 107 case JsonValue::Type::Bool: 108 out("{}", color_bool); 109 break; 110 case JsonValue::Type::String: 111 out("{}", color_string); 112 break; 113 default: 114 out("{}", color_index); 115 break; 116 } 117 118 outln("{}{};", value.serialized<StringBuilder>(), color_off); 119}