2
* Copyright © 2012 Canonical Ltd.
4
* This program is free software: you can redistribute it and/or modify it
5
* under the terms of the GNU General Public License version 3,
6
* as published by the Free Software Foundation.
8
* This program is distributed in the hope that it will be useful,
9
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
* GNU General Public License for more details.
13
* You should have received a copy of the GNU General Public License
14
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16
* Authored by: Alan Griffiths <alan@octopull.co.uk>
19
#include "mir/options/program_option.h"
21
#include <boost/program_options/parsers.hpp>
26
namespace mo = mir::options;
27
namespace po = boost::program_options;
31
std::string parse_name(std::string name)
33
return name.substr(0, name.find_first_of(','));
37
mo::ProgramOption::ProgramOption()
41
void mo::ProgramOption::parse_arguments(
42
po::options_description const& desc,
46
// TODO: Don't allow unregistered options, once we allow better overriding of option parsing
47
po::store(po::command_line_parser(argc, argv).options(desc).allow_unregistered().run(), options);
51
void mo::ProgramOption::parse_environment(
52
po::options_description const& desc,
55
auto parsed_options = po::parse_environment(
57
[=](std::string const& from) -> std::string
59
auto const sizeof_prefix = strlen(prefix);
61
if (from.length() < sizeof_prefix || 0 != from.find(prefix)) return std::string();
63
std::string result(from, sizeof_prefix);
65
for(auto& ch : result)
67
if (ch == '_') ch = '-';
68
else ch = tolower(ch);
74
po::store(parsed_options, options);
77
void mo::ProgramOption::parse_file(
78
po::options_description const& config_file_desc,
79
std::string const& name)
81
std::string config_roots;
83
if (auto config_home = getenv("XDG_CONFIG_HOME"))
84
(config_roots = config_home) += ":";
85
else if (auto home = getenv("HOME"))
86
(config_roots = home) += "/.config:";
88
if (auto config_dirs = getenv("XDG_CONFIG_DIRS"))
89
config_roots += config_dirs;
91
config_roots += "/etc/xdg";
93
std::istringstream config_stream(config_roots);
95
/* Read options from config files */
96
for (std::string config_root; getline(config_stream, config_root, ':');)
98
auto const& filename = config_root + "/" + name;
102
std::ifstream file(filename);
103
po::store(po::parse_config_file(file, config_file_desc, true), options);
105
catch (const po::error& error)
107
std::cerr << "ERROR in " << filename << ": " << error.what() << std::endl;
114
bool mo::ProgramOption::is_set(char const* name) const
116
return options.count(parse_name(name));
120
bool mo::ProgramOption::get(char const* name, bool default_) const
122
auto const parsed_name = parse_name(name);
123
if (options.count(parsed_name))
125
return options[parsed_name].as<bool>();
131
std::string mo::ProgramOption::get(char const* name, char const* default_) const
133
auto const parsed_name = parse_name(name);
134
if (options.count(parsed_name))
136
return options[parsed_name].as<std::string>();
142
int mo::ProgramOption::get(char const* name, int default_) const
144
auto const parsed_name = parse_name(name);
145
if (options.count(parsed_name))
147
return options[parsed_name].as<int>();
153
boost::any const& mo::ProgramOption::get(char const* name) const
155
auto const parsed_name = parse_name(name);
156
if (options.count(parsed_name))
158
return options[parsed_name].value();
161
static boost::any const default_;