From efa4bdbfcd1489527bcf6f20a49c9a3bca8bbf6b Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 20 Apr 2017 17:34:47 +0200 Subject: [PATCH] Improve nix show-config --json In particular, show descriptions. This could be used for manpage generation etc. --- src/libstore/globals.cc | 5 +++++ src/libutil/config.cc | 38 ++++++++++++++++++++++++++++++++ src/libutil/config.hh | 8 +++++++ src/libutil/json.cc | 49 ++++++++++++++--------------------------- src/libutil/json.hh | 11 +++------ src/nix/show-config.cc | 3 +-- 6 files changed, 71 insertions(+), 43 deletions(-) diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc index 3242ef9d6..953bf6aaa 100644 --- a/src/libstore/globals.cc +++ b/src/libstore/globals.cc @@ -89,6 +89,11 @@ template<> std::string BaseSetting::to_string() else abort(); } +template<> void BaseSetting::toJSON(JSONPlaceholder & out) +{ + AbstractSetting::toJSON(out); +} + void MaxBuildJobsSetting::set(const std::string & str) { if (str == "auto") value = std::max(1U, std::thread::hardware_concurrency()); diff --git a/src/libutil/config.cc b/src/libutil/config.cc index 72b6cf806..62c6433c7 100644 --- a/src/libutil/config.cc +++ b/src/libutil/config.cc @@ -1,5 +1,6 @@ #include "config.hh" #include "args.hh" +#include "json.hh" namespace nix { @@ -103,6 +104,17 @@ void Config::resetOverriden() s.second.setting->overriden = false; } +void Config::toJSON(JSONObject & out) +{ + for (auto & s : _settings) + if (!s.second.isAlias) { + JSONObject out2(out.object(s.first)); + out2.attr("description", s.second.setting->description); + JSONPlaceholder out3(out2.placeholder("value")); + s.second.setting->toJSON(out3); + } +} + AbstractSetting::AbstractSetting( const std::string & name, const std::string & description, @@ -111,6 +123,17 @@ AbstractSetting::AbstractSetting( { } +void AbstractSetting::toJSON(JSONPlaceholder & out) +{ + out.write(to_string()); +} + +template +void BaseSetting::toJSON(JSONPlaceholder & out) +{ + out.write(value); +} + template<> void BaseSetting::set(const std::string & str) { value = str; @@ -161,6 +184,13 @@ template<> std::string BaseSetting::to_string() return concatStringsSep(" ", value); } +template<> void BaseSetting::toJSON(JSONPlaceholder & out) +{ + JSONList list(out.list()); + for (auto & s : value) + list.elem(s); +} + template<> void BaseSetting::set(const std::string & str) { value = tokenizeString(str); @@ -171,12 +201,20 @@ template<> std::string BaseSetting::to_string() return concatStringsSep(" ", value); } +template<> void BaseSetting::toJSON(JSONPlaceholder & out) +{ + JSONList list(out.list()); + for (auto & s : value) + list.elem(s); +} + template class BaseSetting; template class BaseSetting; template class BaseSetting; template class BaseSetting; template class BaseSetting; template class BaseSetting; +template class BaseSetting; void PathSetting::set(const std::string & str) { diff --git a/src/libutil/config.hh b/src/libutil/config.hh index 130f59e2b..919621091 100644 --- a/src/libutil/config.hh +++ b/src/libutil/config.hh @@ -9,6 +9,8 @@ namespace nix { class Args; class AbstractSetting; +class JSONPlaceholder; +class JSONObject; /* A class to simplify providing configuration settings. The typical use is to inherit Config and add Setting members: @@ -56,6 +58,8 @@ public: void applyConfigFile(const Path & path, bool fatal = false); void resetOverriden(); + + void toJSON(JSONObject & out); }; class AbstractSetting @@ -90,6 +94,8 @@ protected: virtual std::string to_string() = 0; + virtual void toJSON(JSONPlaceholder & out); + bool isOverriden() { return overriden; } }; @@ -122,6 +128,8 @@ public: void set(const std::string & str) override; std::string to_string() override; + + void toJSON(JSONPlaceholder & out) override; }; template diff --git a/src/libutil/json.cc b/src/libutil/json.cc index 6023d1d4f..b8b8ef9c8 100644 --- a/src/libutil/json.cc +++ b/src/libutil/json.cc @@ -19,51 +19,34 @@ void toJSON(std::ostream & str, const char * start, const char * end) str << '"'; } -void toJSON(std::ostream & str, const std::string & s) -{ - toJSON(str, s.c_str(), s.c_str() + s.size()); -} - void toJSON(std::ostream & str, const char * s) { if (!s) str << "null"; else toJSON(str, s, s + strlen(s)); } -void toJSON(std::ostream & str, unsigned long long n) +template<> void toJSON(std::ostream & str, const int & n) { str << n; } +template<> void toJSON(std::ostream & str, const unsigned int & n) { str << n; } +template<> void toJSON(std::ostream & str, const long & n) { str << n; } +template<> void toJSON(std::ostream & str, const unsigned long & n) { str << n; } +template<> void toJSON(std::ostream & str, const long long & n) { str << n; } +template<> void toJSON(std::ostream & str, const unsigned long long & n) { str << n; } +template<> void toJSON(std::ostream & str, const float & n) { str << n; } + +template<> void toJSON(std::ostream & str, const std::string & s) { - str << n; + toJSON(str, s.c_str(), s.c_str() + s.size()); } -void toJSON(std::ostream & str, unsigned long n) -{ - str << n; -} - -void toJSON(std::ostream & str, long n) -{ - str << n; -} - -void toJSON(std::ostream & str, unsigned int n) -{ - str << n; -} - -void toJSON(std::ostream & str, int n) -{ - str << n; -} - -void toJSON(std::ostream & str, double f) -{ - str << f; -} - -void toJSON(std::ostream & str, bool b) +template<> void toJSON(std::ostream & str, const bool & b) { str << (b ? "true" : "false"); } +template<> void toJSON(std::ostream & str, const std::nullptr_t & b) +{ + str << "null"; +} + JSONWriter::JSONWriter(std::ostream & str, bool indent) : state(new JSONState(str, indent)) { diff --git a/src/libutil/json.hh b/src/libutil/json.hh index 03eecb732..595e9bbe3 100644 --- a/src/libutil/json.hh +++ b/src/libutil/json.hh @@ -7,15 +7,10 @@ namespace nix { void toJSON(std::ostream & str, const char * start, const char * end); -void toJSON(std::ostream & str, const std::string & s); void toJSON(std::ostream & str, const char * s); -void toJSON(std::ostream & str, unsigned long long n); -void toJSON(std::ostream & str, unsigned long n); -void toJSON(std::ostream & str, long n); -void toJSON(std::ostream & str, unsigned int n); -void toJSON(std::ostream & str, int n); -void toJSON(std::ostream & str, double f); -void toJSON(std::ostream & str, bool b); + +template +void toJSON(std::ostream & str, const T & n); class JSONWriter { diff --git a/src/nix/show-config.cc b/src/nix/show-config.cc index ba39e2bb2..aade2adea 100644 --- a/src/nix/show-config.cc +++ b/src/nix/show-config.cc @@ -31,8 +31,7 @@ struct CmdShowConfig : Command if (json) { // FIXME: use appropriate JSON types (bool, ints, etc). JSONObject jsonObj(std::cout, true); - for (auto & s : settings.getSettings()) - jsonObj.attr(s.first, s.second); + settings.toJSON(jsonObj); } else { for (auto & s : settings.getSettings()) std::cout << s.first + " = " + s.second + "\n";