configuration: support multiple configuration files
This commit is contained in:
1
NEWS
1
NEWS
@@ -9,6 +9,7 @@ ncmpcpp-0.7 (????-??-??)
|
||||
* List filtering has been removed due to the major part of its functionality overlapping with find forward/backward.
|
||||
* Find backward/forward function is now incremental.
|
||||
* Support for 256 colors and customization of background colors has been added.
|
||||
* Multiple configuration files via command line arguments are now accepted. In addition, by default ncmpcpp attempts to read both $HOME/.ncmpcpp/config and $XDG_CONFIG_HOME/ncmpcpp/config (in this order).
|
||||
|
||||
ncmpcpp-0.6.2 (????-??-??)
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
####################################################
|
||||
## this is example configuration file, copy it to ##
|
||||
## ~/.ncmpcpp/config and set up your preferences ##
|
||||
####################################################
|
||||
##############################################################
|
||||
## This is the example configuration file. Copy it to ##
|
||||
## $HOME/.ncmpcpp/config or $XDG_CONFIG_HOME/ncmpcpp/config ##
|
||||
## and set up your preferences. ##
|
||||
##############################################################
|
||||
#
|
||||
##### directories ######
|
||||
##
|
||||
|
||||
@@ -31,7 +31,7 @@ Display help.
|
||||
Display version information.
|
||||
.TP
|
||||
.SH "CONFIGURATION"
|
||||
When ncmpcpp starts, it tries to read user's settings from the ~/.ncmpcpp/config file. If no user's configuration is found, ncmpcpp uses its default configuration. An example configuration file containing all default values is provided with ncmpcpp and can be usually found in /usr/share/doc/ncmpcpp (exact location may depend on used distribution or configure prefix).
|
||||
When ncmpcpp starts, it tries to read user's settings from $HOME/.ncmpcpp/config and $XDG_CONFIG_HOME/ncmpcpp/config files. If no configuration is found, ncmpcpp uses its default configuration. An example configuration file containing all default values is provided with ncmpcpp and can be usually found in /usr/share/doc/ncmpcpp (exact location may depend on used distribution or configure prefix).
|
||||
|
||||
Note: Configuration option values can either be enclosed in quotation marks or not.
|
||||
- If they are enclosed, the leftmost and the rightmost quotation marks are treated as delimiters, therefore it is not necessary to escape quotation marks you use within the value itself.
|
||||
|
||||
@@ -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
|
||||
));
|
||||
|
||||
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