configuration: support multiple configuration files
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#include <algorithm>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
#include <iostream>
|
||||
@@ -27,6 +28,7 @@
|
||||
#include "config.h"
|
||||
#include "mpdpp.h"
|
||||
#include "settings.h"
|
||||
#include "utility/string.h"
|
||||
|
||||
namespace po = boost::program_options;
|
||||
|
||||
@@ -37,23 +39,45 @@ namespace {
|
||||
|
||||
const char *env_home;
|
||||
|
||||
std::string xdg_config_home()
|
||||
{
|
||||
std::string result;
|
||||
const char *env_xdg_config_home = getenv("XDG_CONFIG_HOME");
|
||||
if (env_xdg_config_home == nullptr)
|
||||
result = "~/.config/ncmpcpp/";
|
||||
else
|
||||
{
|
||||
result = env_xdg_config_home;
|
||||
if (!result.empty() && result.back() != '/')
|
||||
result += "/";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void expand_home(std::string &path)
|
||||
{
|
||||
assert(env_home != nullptr);
|
||||
if (!path.empty() && path[0] == '~')
|
||||
path.replace(0, 1, env_home);
|
||||
}
|
||||
|
||||
bool configure(int argc, char **argv)
|
||||
{
|
||||
std::string bindings_path, config_path;
|
||||
const std::vector<std::string> default_config_paths = {
|
||||
"~/.ncmpcpp/config",
|
||||
xdg_config_home() + "config"
|
||||
};
|
||||
|
||||
std::string bindings_path;
|
||||
std::vector<std::string> config_paths;
|
||||
|
||||
po::options_description options("Options");
|
||||
options.add_options()
|
||||
("host,h", po::value<std::string>()->default_value("localhost"), "connect to server at host")
|
||||
("port,p", po::value<int>()->default_value(6600), "connect to server at port")
|
||||
("config,c", po::value<std::string>(&config_path)->default_value("~/.ncmpcpp/config"), "specify configuration file")
|
||||
("config,c", po::value<std::vector<std::string>>(&config_paths)->default_value(default_config_paths, join<std::string>(default_config_paths, " AND ")), "specify configuration file(s)")
|
||||
("bindings,b", po::value<std::string>(&bindings_path)->default_value("~/.ncmpcpp/bindings"), "specify bindings file")
|
||||
("screen,s", po::value<std::string>(), "specify initial screen")
|
||||
("slave-screen,S", po::value<std::string>(), "specify initial slave screen")
|
||||
@@ -120,7 +144,6 @@ bool configure(int argc, char **argv)
|
||||
}
|
||||
|
||||
po::notify(vm);
|
||||
|
||||
// get home directory
|
||||
env_home = getenv("HOME");
|
||||
if (env_home == nullptr)
|
||||
@@ -130,8 +153,8 @@ bool configure(int argc, char **argv)
|
||||
}
|
||||
|
||||
// read configuration
|
||||
expand_home(config_path);
|
||||
if (Config.read(config_path) == false)
|
||||
std::for_each(config_paths.begin(), config_paths.end(), expand_home);
|
||||
if (Config.read(config_paths) == false)
|
||||
exit(1);
|
||||
|
||||
// if bindings file was not specified, use the one from main directory.
|
||||
|
||||
@@ -173,7 +173,7 @@ option_parser::worker buffer(NC::Buffer &arg, ValueT &&value, TransformT &&map)
|
||||
|
||||
}
|
||||
|
||||
bool Configuration::read(const std::string &config_path)
|
||||
bool Configuration::read(const std::vector<std::string> &config_paths)
|
||||
{
|
||||
std::string mpd_host;
|
||||
unsigned mpd_port;
|
||||
@@ -653,8 +653,16 @@ bool Configuration::read(const std::string &config_path)
|
||||
active_window_border, NC::Border::Red
|
||||
));
|
||||
|
||||
std::ifstream f(config_path);
|
||||
return p.run(f);
|
||||
return std::all_of(
|
||||
config_paths.begin(),
|
||||
config_paths.end(),
|
||||
[&p](const std::string &config_path) {
|
||||
std::ifstream f(config_path);
|
||||
if (f.is_open())
|
||||
std::clog << "Reading configuration from " << config_path << "...\n";
|
||||
return p.run(f);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/* vim: set tabstop=4 softtabstop=4 shiftwidth=4 noexpandtab : */
|
||||
|
||||
@@ -53,7 +53,7 @@ struct Configuration
|
||||
: playlist_disable_highlight_delay(0), visualizer_sync_interval(0)
|
||||
{ }
|
||||
|
||||
bool read(const std::string &config_path);
|
||||
bool read(const std::vector<std::string> &config_paths);
|
||||
|
||||
std::string ncmpcpp_directory;
|
||||
std::string lyrics_directory;
|
||||
|
||||
@@ -106,8 +106,18 @@ struct option_parser
|
||||
m_defined = true;
|
||||
}
|
||||
|
||||
bool defined() const { return m_defined; }
|
||||
void run_default() const { m_default(); }
|
||||
bool defined() const
|
||||
{
|
||||
return m_defined;
|
||||
}
|
||||
|
||||
void run_default()
|
||||
{
|
||||
if (m_defined)
|
||||
throw std::runtime_error("option already defined");
|
||||
m_default();
|
||||
m_defined = true;
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_defined;
|
||||
|
||||
@@ -32,8 +32,8 @@ template <size_t N> size_t const_strlen(const char (&)[N]) {
|
||||
}
|
||||
|
||||
// it's present in boost for std::string, but we want more general version.
|
||||
template <typename CollectionT, typename StringT>
|
||||
StringT join(CollectionT &&collection, StringT &&separator)
|
||||
template <typename StringT, typename CollectionT>
|
||||
StringT join(const CollectionT &collection, const StringT &separator)
|
||||
{
|
||||
StringT result;
|
||||
auto first = std::begin(collection), last = std::end(collection);
|
||||
|
||||
Reference in New Issue
Block a user