The Battle for Wesnoth  1.17.0-dev
commandline_options.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2011 - 2021
3  by Lukasz Dobrogowski <lukasz.dobrogowski@gmail.com>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 #include "commandline_options.hpp"
17 
18 #include "config.hpp"
19 #include "formatter.hpp"
20 #include "lexical_cast.hpp"
21 #include "log.hpp" // for logger, set_strict_severity, etc
22 #include "serialization/string_utils.hpp" // for split
23 
24 #include <boost/any.hpp> // for any
25 #include <boost/program_options/cmdline.hpp>
26 #include <boost/program_options/errors.hpp> // for validation_error, etc
27 #include <boost/program_options/parsers.hpp>
28 #include <boost/program_options/positional_options.hpp>
29 #include <boost/program_options/value_semantic.hpp> // for value, etc
30 #include <boost/program_options/variables_map.hpp> // for variables_map, etc
31 
32 #include <array>
33 #include <iostream> // for operator<<, basic_ostream, etc
34 
35 namespace po = boost::program_options;
36 
37 class two_strings : public std::pair<std::string,std::string> {};
38 
39 static void validate(boost::any& v, const std::vector<std::string>& values,
40  two_strings*, int)
41 {
42  two_strings ret_val;
43  if (values.size() != 2) {
44  throw po::validation_error(po::validation_error::invalid_option_value);
45  }
46  ret_val.first = values.at(0);
47  ret_val.second = values.at(1);
48  v = ret_val;
49 }
50 
52  : error(formatter() << "Invalid resolution \"" << resolution
53  << "\" (WIDTHxHEIGHT expected)")
54 {
55 }
56 
58  const std::string& expected_format)
59  : error(formatter() << "Invalid value set \"" << str
60  << "\" (" << expected_format << " expected)")
61 {
62 }
63 
64 
65 #ifdef _WIN32
66 #define IMPLY_WCONSOLE " Implies --wconsole."
67 #else
68 #define IMPLY_WCONSOLE
69 #endif // _WIN32
70 
71 
72 commandline_options::commandline_options(const std::vector<std::string>& args)
73  : bunzip2()
74  , bzip2()
75  , campaign()
76  , campaign_difficulty()
77  , campaign_scenario()
78  , campaign_skip_story(false)
79  , clock(false)
80  , core_id()
81  , data_path(false)
82  , data_dir()
83  , debug(false)
84  , debug_lua(false)
85  , strict_lua(false)
86  , allow_insecure(false)
87 #ifdef DEBUG_WINDOW_LAYOUT_GRAPHS
88  , debug_dot_domain()
89  , debug_dot_level()
90 #endif
91  , editor()
92  , fps(false)
93  , fullscreen(false)
94  , gunzip()
95  , gzip()
96  , help()
97  , language()
98  , log()
99  , load()
100  , logdomains()
101  , log_precise_timestamps(false)
102  , multiplayer(false)
103  , multiplayer_ai_config()
104  , multiplayer_algorithm()
105  , multiplayer_controller()
106  , multiplayer_era()
107  , multiplayer_exit_at_end()
108  , multiplayer_ignore_map_settings()
109  , multiplayer_label()
110  , multiplayer_parm()
111  , multiplayer_repeat()
112  , multiplayer_scenario()
113  , multiplayer_side()
114  , multiplayer_turns()
115  , max_fps()
116  , noaddons(false)
117  , nocache(false)
118  , nodelay(false)
119  , nogui(false)
120  , nobanner(false)
121  , nomusic(false)
122  , nosound(false)
123  , new_widgets(false)
124  , preprocess(false)
125  , preprocess_defines()
126  , preprocess_input_macros()
127  , preprocess_output_macros()
128  , preprocess_path()
129  , preprocess_target()
130  , resolution()
131  , rng_seed()
132  , server()
133  , username()
134  , password()
135  , render_image()
136  , render_image_dst()
137  , screenshot(false)
138  , screenshot_map_file()
139  , screenshot_output_file()
140  , script_file()
141  , plugin_file()
142  , script_unsafe_mode(false)
143  , strict_validation(false)
144  , test()
145  , unit_test()
146  , headless_unit_test(false)
147  , noreplaycheck(false)
148  , mptest(false)
149  , userconfig_path(false)
150  , userconfig_dir()
151  , userdata_path(false)
152  , userdata_dir()
153  , validcache(false)
154  , validate_core(false)
155  , validate_addon()
156  , validate_schema()
157  , validate_wml()
158  , validate_with()
159  , do_diff()
160  , do_patch()
161  , diff_left()
162  , diff_right()
163  , version(false)
164  , report(false)
165  , windowed(false)
166  , with_replay(false)
167  , translation_percent()
168  , args_(args.begin() + 1, args.end())
169  , args0_(*args.begin())
170  , all_()
171  , visible_()
172  , hidden_()
173 {
174  // When adding items don't forget to update doc/man/wesnoth.6
175  // Options are sorted alphabetically by --long-option.
176  po::options_description general_opts("General options");
177  general_opts.add_options()
178  ("all-translations", "Show all translations, even incomplete ones.")
179  ("bunzip2", po::value<std::string>(), "decompresses a file (<arg>.bz2) in bzip2 format and stores it without the .bz2 suffix. <arg>.bz2 will be removed.")
180  ("bzip2", po::value<std::string>(), "compresses a file (<arg>) in bzip2 format, stores it as <arg>.bz2 and removes <arg>.")
181  ("clock", "Adds the option to show a clock for testing the drawing timer.")
182  ("config-dir", po::value<std::string>(), "sets the path of the userdata directory to $HOME/<arg> or My Documents\\My Games\\<arg> for Windows. You can specify also an absolute path outside the $HOME or My Documents\\My Games directory. DEPRECATED: use userdata-dir instead.")
183  ("config-path", "prints the path of the userdata directory and exits. DEPRECATED: use userdata-path instead.")
184  ("core", po::value<std::string>(), "overrides the loaded core with the one whose id is specified.")
185  ("data-dir", po::value<std::string>(), "overrides the data directory with the one specified.")
186  ("data-path", "prints the path of the data directory and exits." IMPLY_WCONSOLE)
187  ("debug,d", "enables additional command mode options in-game.")
188  ("debug-lua", "enables some Lua debugging mechanisms")
189  ("strict-lua", "disallow deprecated Lua API calls")
190  ("allow-insecure", "Allows sending a plaintext password over an unencrypted connection. Should only ever be used for local testing.")
191 #ifdef DEBUG_WINDOW_LAYOUT_GRAPHS
192  ("debug-dot-level", po::value<std::string>(), "sets the level of the debug dot files. <arg> should be a comma separated list of levels. These files are used for debugging the widgets especially the for the layout engine. When enabled the engine will produce dot files which can be converted to images with the dot tool. Available levels: size (generate the size info of the widget), state (generate the state info of the widget).")
193  ("debug-dot-domain", po::value<std::string>(), "sets the domain of the debug dot files. <arg> should be a comma separated list of domains. See --debug-dot-level for more info. Available domains: show (generate the data when the dialog is about to be shown), layout (generate the data during the layout phase - might result in multiple files). The data can also be generated when the F12 is pressed in a dialog.")
194 #endif
195  ("editor,e", po::value<std::string>()->implicit_value(std::string()), "starts the in-game map editor directly. If file <arg> is specified, equivalent to -e --load <arg>.")
196  ("gunzip", po::value<std::string>(), "decompresses a file (<arg>.gz) in gzip format and stores it without the .gz suffix. <arg>.gz will be removed.")
197  ("gzip", po::value<std::string>(), "compresses a file (<arg>) in gzip format, stores it as <arg>.gz and removes <arg>.")
198  ("help,h", "prints this message and exits." IMPLY_WCONSOLE)
199  ("language,L", po::value<std::string>(), "uses language <arg> (symbol) this session. Example: --language ang_GB@latin")
200  ("load,l", po::value<std::string>(), "loads the save <arg> from the standard save game directory. When launching the map editor via -e, the map <arg> is loaded, relative to the current directory. If it is a directory, the editor will start with a load map dialog opened there.")
201  ("noaddons", "disables the loading of all add-ons.")
202  ("nocache", "disables caching of game data.")
203  ("nodelay", "runs the game without any delays.")
204  ("nomusic", "runs the game without music.")
205  ("nosound", "runs the game without sounds and music.")
206  ("password", po::value<std::string>(), "uses <password> when connecting to a server, ignoring other preferences.")
207  ("plugin", po::value<std::string>(), "(experimental) load a script which defines a wesnoth plugin. similar to --script below, but Lua file should return a function which will be run as a coroutine and periodically woken up with updates.")
208  ("render-image", po::value<two_strings>()->multitoken(), "takes two arguments: <image> <output>. Like screenshot, but instead of a map, takes a valid Wesnoth 'image path string' with image path functions, and writes it to a .png file." IMPLY_WCONSOLE)
209  ("report,R", "initializes game directories, prints build information suitable for use in bug reports, and exits." IMPLY_WCONSOLE)
210  ("rng-seed", po::value<unsigned int>(), "seeds the random number generator with number <arg>. Example: --rng-seed 0")
211  ("screenshot", po::value<two_strings>()->multitoken(), "takes two arguments: <map> <output>. Saves a screenshot of <map> to <output> without initializing a screen. Editor must be compiled in for this to work." IMPLY_WCONSOLE)
212  ("script", po::value<std::string>(), "(experimental) file containing a Lua script to control the client")
213  ("server,s", po::value<std::string>()->implicit_value(std::string()), "connects to the host <arg> if specified or to the first host in your preferences.")
214  ("strict-validation", "makes validation errors fatal")
215  ("translations-over", po::value<unsigned int>(), "Specify the standard for determining whether a translation is complete.")
216  ("unsafe-scripts", "makes the \'package\' package available to Lua scripts, so that they can load arbitrary packages. Do not do this with untrusted scripts! This action gives ua the same permissions as the Wesnoth executable.")
217  ("userconfig-dir", po::value<std::string>(), "sets the path of the user config directory to $HOME/<arg> or My Documents\\My Games\\<arg> for Windows. You can specify also an absolute path outside the $HOME or My Documents\\My Games directory. Defaults to $HOME/.config/wesnoth on X11 and to the userdata-dir on other systems.")
218  ("userconfig-path", "prints the path of the user config directory and exits.")
219  ("userdata-dir", po::value<std::string>(), "sets the path of the userdata directory to $HOME/<arg> or My Documents\\My Games\\<arg> for Windows. You can specify also an absolute path outside the $HOME or My Documents\\My Games directory.")
220  ("userdata-path", "prints the path of the userdata directory and exits." IMPLY_WCONSOLE)
221  ("username", po::value<std::string>(), "uses <username> when connecting to a server, ignoring other preferences.")
222  ("validcache", "assumes that the cache is valid. (dangerous)")
223  ("version,v", "prints the game's version number and exits.")
224  ("with-replay", "replays the file loaded with the --load option.")
225 #ifdef _WIN32
226  ("wconsole", "attaches a console window on startup (Windows only). Implied by any option that prints something and exits.")
227  ("wnoconsole", "don't attach a console window on startup (Windows only). Overrides options that imply --wconsole.")
228  ("wnoredirect", "disables standard redirection of logging to a file (Windows only), allowing the output to be piped to another command")
229 #endif // _WIN32
230  ;
231 
232  po::options_description campaign_opts("Campaign options");
233  campaign_opts.add_options()
234  ("campaign,c", po::value<std::string>()->implicit_value(std::string()), "goes directly to the campaign with id <arg>. A selection menu will appear if no id was specified.")
235  ("campaign-difficulty", po::value<int>(), "The difficulty of the specified campaign (1 to max). If none specified, the campaign difficulty selection widget will appear.")
236  ("campaign-scenario", po::value<std::string>(),"The id of the scenario from the specified campaign. The default is the first scenario.")
237  ("campaign-skip-story", "Skip [story] tags of the specified campaign.")
238  ;
239 
240  po::options_description display_opts("Display options");
241  display_opts.add_options()
242  ("fps", "displays the number of frames per second the game is currently running at, in a corner of the screen. Min/avg/max don't take the FPS limiter into account, act does.")
243  ("fullscreen,f", "runs the game in full screen mode.")
244  ("max-fps", po::value<int>(), "the maximum fps the game tries to run at. Values should be between 1 and 1000, the default is the display's refresh rate.")
245  ("new-widgets", "there is a new WIP widget toolkit this switch enables the new toolkit (VERY EXPERIMENTAL don't file bug reports since most are known). Parts of the library are deemed stable and will work without this switch.")
246  ("resolution,r", po::value<std::string>(), "sets the screen resolution. <arg> should have format XxY. Example: --resolution 800x600")
247  ("windowed,w", "runs the game in windowed mode.")
248  ;
249 
250  po::options_description logging_opts("Logging options");
251  logging_opts.add_options()
252  ("logdomains", po::value<std::string>()->implicit_value(std::string()), "lists defined log domains (only the ones containing <arg> filter if such is provided) and exits." IMPLY_WCONSOLE)
253  ("log-error", po::value<std::string>(), "sets the severity level of the specified log domain(s) to 'error'. <arg> should be given as a comma-separated list of domains, wildcards are allowed. Example: --log-error=network,gui/*,engine/enemies")
254  ("log-warning", po::value<std::string>(), "sets the severity level of the specified log domain(s) to 'warning'. Similar to --log-error.")
255  ("log-info", po::value<std::string>(), "sets the severity level of the specified log domain(s) to 'info'. Similar to --log-error.")
256  ("log-debug", po::value<std::string>(), "sets the severity level of the specified log domain(s) to 'debug'. Similar to --log-error.")
257  ("log-none", po::value<std::string>(), "sets the severity level of the specified log domain(s) to 'none'. Similar to --log-error.")
258  ("log-precise", "shows the timestamps in log output with more precision.")
259  ;
260 
261  po::options_description multiplayer_opts("Multiplayer options");
262  multiplayer_opts.add_options()
263  ("multiplayer,m", "Starts a multiplayer game. There are additional options that can be used as explained below:")
264  ("ai-config", po::value<std::vector<std::string>>()->composing(), "selects a configuration file to load for this side. <arg> should have format side:value")
265  ("algorithm", po::value<std::vector<std::string>>()->composing(), "selects a non-standard algorithm to be used by the AI controller for this side. <arg> should have format side:value")
266  ("controller", po::value<std::vector<std::string>>()->composing(), "selects the controller for this side. <arg> should have format side:value")
267  ("era", po::value<std::string>(), "selects the era to be played in by its id.")
268  ("exit-at-end", "exit Wesnoth at the end of the scenario.")
269  ("ignore-map-settings", "do not use map settings.")
270  ("label", po::value<std::string>(), "sets the label for AIs.") //TODO is the description precise? this option was undocumented before.
271  ("multiplayer-repeat", po::value<unsigned int>(), "repeats a multiplayer game after it is finished <arg> times.")
272  ("nogui", "runs the game without the GUI.")
273  ("parm", po::value<std::vector<std::string>>()->composing(), "sets additional parameters for this side. <arg> should have format side:name:value.")
274  ("scenario", po::value<std::string>(), "selects a multiplayer scenario. The default scenario is \"multiplayer_The_Freelands\".")
275  ("side", po::value<std::vector<std::string>>()->composing(), "selects a faction of the current era for this side by id. <arg> should have format side:value.")
276  ("turns", po::value<std::string>(), "sets the number of turns. By default no turn limit is set.")
277  ;
278 
279  po::options_description testing_opts("Testing options");
280  testing_opts.add_options()
281  ("test,t", po::value<std::string>()->implicit_value(std::string()), "runs the game in a small test scenario. If specified, scenario <arg> will be used instead.")
282  ("unit,u", po::value<std::vector<std::string>>(), "runs a unit test scenario. The GUI is not shown and the exit code of the program reflects the victory / defeat conditions of the scenario.\n\t0 - PASS\n\t1 - FAIL\n\t3 - FAIL (INVALID REPLAY)\n\t4 - FAIL (ERRORED REPLAY)\n\t5 - FAIL (BROKE STRICT)\n\t6 - FAIL (WML EXCEPTION)\n\tMultiple tests can be run by giving this option multiple times, in this case the test run will stop immediately after any test which doesn't PASS and the return code will be the status of the test that caused the stop.")
283  ("showgui", "don't run headlessly (for debugging a failing test)")
284  ("log-strict", po::value<std::string>(), "sets the strict level of the logger. any messages sent to log domains of this level or more severe will cause the unit test to fail regardless of the victory result.")
285  ("nobanner", "suppress startup banner.")
286  ("noreplaycheck", "don't try to validate replay of unit test.")
287  ("mp-test", "load the test mp scenarios.")
288  ;
289 
290  po::options_description parsing_opts("WML parsing options");
291  parsing_opts.add_options()
292  ("use-schema,S", po::value<std::string>(), "specify a schema to validate WML against (defaults to the core schema)")
293  ("validate,V", po::value<std::string>(), "validate a specified WML file against a schema" IMPLY_WCONSOLE)
294  ("validate-addon", po::value<std::string>(), "validate the specified addon's WML against the schema. Requires the user to play the campaign (in the GUI) to trigger the validation.")
295  ("validate-core", "validate the core WML against the schema")
296  ("validate-schema", po::value<std::string>(), "validate a specified WML schema" IMPLY_WCONSOLE)
297  ("diff,D", po::value<two_strings>()->multitoken(), "diff two preprocessed WML documents" IMPLY_WCONSOLE)
298  ("output,o", po::value<std::string>(), "output to specified file")
299  ("patch,P", po::value<two_strings>()->multitoken(), "apply a patch to a preprocessed WML document" IMPLY_WCONSOLE)
300  ("preprocess,p", po::value<two_strings>()->multitoken(), "requires two arguments: <file/folder> <target directory>. Preprocesses a specified file/folder. The preprocessed file(s) will be written in the specified target directory: a plain cfg file and a processed cfg file." IMPLY_WCONSOLE)
301  ("preprocess-defines", po::value<std::string>(), "comma separated list of defines to be used by '--preprocess' command. If 'SKIP_CORE' is in the define list the data/core won't be preprocessed. Example: --preprocess-defines=FOO,BAR")
302  ("preprocess-input-macros", po::value<std::string>(), "used only by the '--preprocess' command. Specifies source file <arg> that contains [preproc_define]s to be included before preprocessing.")
303  ("preprocess-output-macros", po::value<std::string>()->implicit_value(std::string()), "used only by the '--preprocess' command. Will output all preprocessed macros in the target file <arg>. If the file is not specified the output will be file '_MACROS_.cfg' in the target directory of preprocess's command.")
304  ;
305 
306  //hidden_.add_options()
307  // ("example-hidden-option", "")
308  // ;
309  visible_.add(general_opts).add(campaign_opts).add(display_opts).add(logging_opts).add(multiplayer_opts).add(testing_opts).add(parsing_opts);
310 
311  all_.add(visible_).add(hidden_);
312 
313  po::positional_options_description positional;
314  positional.add("data-dir",1);
315 
316  po::variables_map vm;
317  const int parsing_style = po::command_line_style::default_style ^ po::command_line_style::allow_guessing;
318  po::store(po::command_line_parser(args_).options(all_).positional(positional).style(parsing_style).run(),vm);
319 
320  if (vm.count("ai-config"))
321  multiplayer_ai_config = parse_to_uint_string_tuples_(vm["ai-config"].as<std::vector<std::string>>());
322  if (vm.count("algorithm"))
323  multiplayer_algorithm = parse_to_uint_string_tuples_(vm["algorithm"].as<std::vector<std::string>>());
324  if (vm.count("bunzip2"))
325  bunzip2 = vm["bunzip2"].as<std::string>();
326  if (vm.count("bzip2"))
327  bzip2 = vm["bzip2"].as<std::string>();
328  if (vm.count("campaign"))
329  campaign = vm["campaign"].as<std::string>();
330  if (vm.count("campaign-difficulty"))
331  campaign_difficulty = vm["campaign-difficulty"].as<int>();
332  if (vm.count("campaign-scenario"))
333  campaign_scenario = vm["campaign-scenario"].as<std::string>();
334  if (vm.count("campaign-skip-story"))
335  campaign_skip_story = true;
336  if (vm.count("clock"))
337  clock = true;
338  if (vm.count("core"))
339  core_id = vm["core"].as<std::string>();
340  if (vm.count("config-dir"))
341  userdata_dir = vm["config-dir"].as<std::string>(); //TODO: complain and remove
342  if (vm.count("config-path"))
343  userdata_path = true; //TODO: complain and remove
344  if (vm.count("controller"))
345  multiplayer_controller = parse_to_uint_string_tuples_(vm["controller"].as<std::vector<std::string>>());
346  if (vm.count("data-dir"))
347  data_dir = vm["data-dir"].as<std::string>();
348  if (vm.count("data-path"))
349  data_path = true;
350  if (vm.count("debug"))
351  debug = true;
352  if (vm.count("debug-lua"))
353  debug_lua = true;
354  if (vm.count("strict-lua"))
355  strict_lua = true;
356  if (vm.count("allow-insecure"))
357  allow_insecure = true;
358 #ifdef DEBUG_WINDOW_LAYOUT_GRAPHS
359  if (vm.count("debug-dot-domain")) {
360  debug_dot_domain = vm["debug-dot-domain"].as<std::string>();
361  }
362  if (vm.count("debug-dot-level")) {
363  debug_dot_level = vm["debug-dot-level"].as<std::string>();
364  }
365 #endif
366  if (vm.count("editor"))
367  editor = vm["editor"].as<std::string>();
368  if (vm.count("era"))
369  multiplayer_era = vm["era"].as<std::string>();
370  if (vm.count("exit-at-end"))
372  if (vm.count("fps"))
373  fps = true;
374  if (vm.count("fullscreen"))
375  fullscreen = true;
376  if (vm.count("gunzip"))
377  gunzip = vm["gunzip"].as<std::string>();
378  if (vm.count("gzip"))
379  gzip = vm["gzip"].as<std::string>();
380  if (vm.count("help"))
381  help = true;
382  if (vm.count("ignore-map-settings"))
384  if (vm.count("label"))
385  multiplayer_label = vm["label"].as<std::string>();
386  if (vm.count("language"))
387  language = vm["language"].as<std::string>();
388  if (vm.count("load"))
389  load = vm["load"].as<std::string>();
390  if (vm.count("log-error"))
391  parse_log_domains_(vm["log-error"].as<std::string>(),lg::err().get_severity());
392  if (vm.count("log-warning"))
393  parse_log_domains_(vm["log-warning"].as<std::string>(),lg::warn().get_severity());
394  if (vm.count("log-info"))
395  parse_log_domains_(vm["log-info"].as<std::string>(),lg::info().get_severity());
396  if (vm.count("log-debug"))
397  parse_log_domains_(vm["log-debug"].as<std::string>(),lg::debug().get_severity());
398  if (vm.count("log-none"))
399  parse_log_domains_(vm["log-none"].as<std::string>(),-1);
400  if (vm.count("logdomains"))
401  logdomains = vm["logdomains"].as<std::string>();
402  if (vm.count("log-precise"))
403  log_precise_timestamps = true;
404  if (vm.count("log-strict"))
405  parse_log_strictness(vm["log-strict"].as<std::string>());
406  if (vm.count("max-fps"))
407  max_fps = vm["max-fps"].as<int>();
408  if (vm.count("mp-test"))
409  mptest = true;
410  if (vm.count("multiplayer"))
411  multiplayer = true;
412  if (vm.count("multiplayer-repeat"))
413  multiplayer_repeat = vm["multiplayer-repeat"].as<unsigned int>();
414  if (vm.count("new-widgets"))
415  new_widgets = true;
416  if (vm.count("noaddons"))
417  noaddons = true;
418  if (vm.count("nocache"))
419  nocache = true;
420  if (vm.count("nodelay"))
421  nodelay = true;
422  if (vm.count("nomusic"))
423  nomusic = true;
424  if (vm.count("noreplaycheck"))
425  noreplaycheck = true;
426  if (vm.count("nosound"))
427  nosound = true;
428  if (vm.count("nogui"))
429  nogui = true;
430  if (vm.count("nobanner"))
431  nobanner = true;
432  if (vm.count("parm"))
433  multiplayer_parm = parse_to_uint_string_string_tuples_(vm["parm"].as<std::vector<std::string>>());
434  if (vm.count("preprocess"))
435  {
436  preprocess = true;
437  preprocess_path = vm["preprocess"].as<two_strings>().first;
438  preprocess_target = vm["preprocess"].as<two_strings>().second;
439  }
440  if (vm.count("diff"))
441  {
442  do_diff = true;
443  diff_left = vm["diff"].as<two_strings>().first;
444  diff_right = vm["diff"].as<two_strings>().second;
445  }
446  if (vm.count("patch"))
447  {
448  do_patch = true;
449  diff_left = vm["patch"].as<two_strings>().first;
450  diff_right = vm["patch"].as<two_strings>().second;
451  }
452  if (vm.count("output"))
453  {
454  output_file = vm["output"].as<std::string>();
455  }
456  if (vm.count("preprocess-defines"))
457  preprocess_defines = utils::split(vm["preprocess-defines"].as<std::string>(), ',');
458  if (vm.count("preprocess-input-macros"))
459  preprocess_input_macros = vm["preprocess-input-macros"].as<std::string>();
460  if (vm.count("preprocess-output-macros"))
461  preprocess_output_macros = vm["preprocess-output-macros"].as<std::string>();
462  if (vm.count("resolution"))
463  parse_resolution_(vm["resolution"].as<std::string>());
464  if (vm.count("rng-seed"))
465  rng_seed = vm["rng-seed"].as<unsigned int>();
466  if (vm.count("scenario"))
467  multiplayer_scenario = vm["scenario"].as<std::string>();
468  if (vm.count("render-image"))
469  {
470  render_image = vm["render-image"].as<two_strings>().first;
471  render_image_dst = vm["render-image"].as<two_strings>().second;
472  }
473  if (vm.count("screenshot"))
474  {
475  screenshot = true;
476  screenshot_map_file = vm["screenshot"].as<two_strings>().first;
477  screenshot_output_file = vm["screenshot"].as<two_strings>().second;
478  }
479  if (vm.count("script"))
480  script_file = vm["script"].as<std::string>();
481  if (vm.count("unsafe-scripts"))
482  script_unsafe_mode = true;
483  if (vm.count("plugin"))
484  plugin_file = vm["plugin"].as<std::string>();
485  if (vm.count("server"))
486  server = vm["server"].as<std::string>();
487  if (vm.count("username"))
488  username = vm["username"].as<std::string>();
489  if (vm.count("password"))
490  password = vm["password"].as<std::string>();
491  if (vm.count("report"))
492  report = true;
493  if (vm.count("side"))
494  multiplayer_side = parse_to_uint_string_tuples_(vm["side"].as<std::vector<std::string>>());
495  if (vm.count("test"))
496  test = vm["test"].as<std::string>();
497  if (vm.count("unit"))
498  {
499  unit_test = vm["unit"].as<std::vector<std::string>>();
500  headless_unit_test = true;
501  }
502  if (vm.count("showgui"))
503  headless_unit_test = false;
504  if (vm.count("noreplaycheck"))
505  noreplaycheck = true;
506  if (vm.count("turns"))
507  multiplayer_turns = vm["turns"].as<std::string>();
508  if (vm.count("strict-validation"))
509  strict_validation = true;
510  if (vm.count("userconfig-dir"))
511  userconfig_dir = vm["userconfig-dir"].as<std::string>();
512  if (vm.count("userconfig-path"))
513  userconfig_path = true;
514  if (vm.count("userdata-dir"))
515  userdata_dir = vm["userdata-dir"].as<std::string>();
516  if (vm.count("userdata-path"))
517  userdata_path = true;
518  if (vm.count("validcache"))
519  validcache = true;
520  // If you add a new validate-* option, remember the any_validation_option() function
521  if (vm.count("validate"))
522  validate_wml = vm["validate"].as<std::string>();
523  if (vm.count("validate-core"))
524  validate_core = true;
525  if (vm.count("validate-addon"))
526  validate_addon = vm["validate-addon"].as<std::string>();
527  if (vm.count("validate-schema"))
528  validate_schema = vm["validate-schema"].as<std::string>();
529  // If you add a new validate-* option, remember the any_validation_option() function
530  if (vm.count("use-schema"))
531  validate_with = vm["use-schema"].as<std::string>();;
532  if (vm.count("version"))
533  version = true;
534  if (vm.count("windowed"))
535  windowed = true;
536  if (vm.count("with-replay"))
537  with_replay = true;
538  if(vm.count("all-translations"))
540  else if(vm.count("translations-over"))
541  translation_percent = std::clamp<unsigned int>(vm["translations-over"].as<unsigned int>(), 0, 100);
542 }
543 
544 void commandline_options::parse_log_domains_(const std::string &domains_string, const int severity)
545 {
546  const std::vector<std::string> domains = utils::split(domains_string, ',');
547  for (const std::string& domain : domains)
548  {
549  if (!log)
550  log = std::vector<std::pair<int, std::string>>();
551  log->emplace_back(severity, domain);
552  }
553 }
554 
556  static const std::array<lg::logger const*, 4> loggers {{&lg::err(), &lg::warn(), &lg::info(), &lg::debug()}};
557  for (const lg::logger * l : loggers ) {
558  if (severity == l->get_name()) {
560  return ;
561  }
562  }
563  std::cerr << "Unrecognized argument to --log-strict : " << severity << " . \nDisabling strict mode logging." << std::endl;
565 }
566 
567 void commandline_options::parse_resolution_ ( const std::string& resolution_string )
568 {
569  const std::vector<std::string> tokens = utils::split(resolution_string, 'x');
570  if (tokens.size() != 2) {
571  throw bad_commandline_resolution(resolution_string);
572  }
573 
574  int xres, yres;
575 
576  try {
577  xres = std::stoi(tokens[0]);
578  yres = std::stoi(tokens[1]);
579  } catch(const std::invalid_argument &) {
580  throw bad_commandline_resolution(resolution_string);
581  }
582 
583  resolution = std::pair(xres, yres);
584 }
585 
586 std::vector<std::pair<unsigned int,std::string>> commandline_options::parse_to_uint_string_tuples_(const std::vector<std::string> &strings, char separator)
587 {
588  std::vector<std::pair<unsigned int,std::string>> vec;
589  const std::string& expected_format
590  = std::string() + "UINT" + separator + "STRING";
591 
592  for (const std::string &s : strings)
593  {
594  const std::vector<std::string> tokens = utils::split(s, separator);
595  if(tokens.size() != 2) {
596  throw bad_commandline_tuple(s, expected_format);
597  }
598 
599  unsigned int temp;
600  try {
601  temp = lexical_cast<unsigned int>(tokens[0]);
602  } catch (const bad_lexical_cast &) {
603  throw bad_commandline_tuple(s, expected_format);
604  }
605 
606  vec.emplace_back(temp, tokens[1]);
607  }
608  return vec;
609 }
610 
611 std::vector<std::tuple<unsigned int,std::string,std::string>> commandline_options::parse_to_uint_string_string_tuples_(const std::vector<std::string> &strings, char separator)
612 {
613  std::vector<std::tuple<unsigned int,std::string,std::string>> vec;
614  const std::string& expected_format
615  = std::string() + "UINT" + separator + "STRING" + separator + "STRING";
616 
617  for (const std::string &s : strings)
618  {
619  const std::vector<std::string> tokens = utils::split(s, separator);
620  if(tokens.size() != 3) {
621  throw bad_commandline_tuple(s, expected_format);
622  }
623 
624  unsigned int temp;
625  try {
626  temp = lexical_cast<unsigned int>(tokens[0]);
627  } catch (const bad_lexical_cast &) {
628  throw bad_commandline_tuple(s, expected_format);
629  }
630 
631  vec.emplace_back(temp, tokens[1], tokens[2]);
632  }
633  return vec;
634 }
635 
636 std::ostream& operator<<(std::ostream &os, const commandline_options& cmdline_opts)
637 {
638  os << "Usage: " << cmdline_opts.args0_ << " [<options>] [<data-directory>]\n";
639  os << cmdline_opts.visible_;
640  return os;
641 }
642 
644  config ret;
645  if (server) {
646  ret["server"] = *server;
647  }
648  if (username) {
649  ret["username"] = *username;
650  }
651  if (password) {
652  ret["password"] = *password;
653  }
654  return ret;
655 }
656 
658 {
660 }
bool log_precise_timestamps
True if –log-precise was given on the command line.
bool new_widgets
Do we wish to use the new library or not.
Definition: settings.cpp:25
std::vector< std::string > args_
std::optional< std::string > preprocess_path
Path to parse that was given to the –preprocess option.
std::optional< std::string > output_file
Output filename for WML diff or preprocessing.
std::optional< std::string > core_id
Non-empty if –core was given on the command line.
bool any_validation_option() const
True if the –validate or any of the –validate-* options are given.
std::optional< std::string > preprocess_output_macros
Non-empty if –preprocess-output-macros was given on the command line.
bool mptest
True if –mp-test was given on the command line.
static domain_map * domains
Definition: log.cpp:72
boost::program_options::options_description all_
bool nogui
True if –nogui was given on the command line.
bool script_unsafe_mode
Whether to load the "package" package for the scripting environment.
std::optional< std::string > test
Non-empty if –test was given on the command line.
std::optional< std::vector< std::pair< unsigned int, std::string > > > multiplayer_ai_config
Non-empty if –ai-config was given on the command line.
std::vector< game_tip > load(const config &cfg)
Loads the tips from a config.
Definition: tips.cpp:36
commandline_options(const std::vector< std::string > &args)
std::vector< std::tuple< unsigned int, std::string, std::string > > parse_to_uint_string_string_tuples_(const std::vector< std::string > &strings, char separator=':')
A helper function splitting vector of strings of format unsigned int:string:string to vector of tuple...
std::optional< std::string > password
Non-empty if –password was given on the command line.
boost::program_options::options_description hidden_
static l_noret error(LoadState *S, const char *why)
Definition: lundump.cpp:40
bool noaddons
True if –noaddons was given on the command line.
std::optional< unsigned int > translation_percent
Non-empty if –all-translations or –translations-over is given on the command line.
New lexcical_cast header.
logger & info()
Definition: log.cpp:89
void parse_log_domains_(const std::string &domains_string, const int severity)
bool userdata_path
True if –userdata-path was given on the command line.
bool multiplayer_ignore_map_settings
True if –ignore-map-settings was given at the command line.
std::optional< std::string > preprocess_target
Target (output) path that was given to the –preprocess option.
std::optional< std::string > preprocess_input_macros
Non-empty if –preprocess-input-macros was given on the command line.
std::optional< std::string > multiplayer_label
Non-empty if –label was given on the command line.
std::optional< std::vector< std::tuple< unsigned int, std::string, std::string > > > multiplayer_parm
Non-empty if –parm was given on the command line.
std::optional< std::string > userconfig_dir
Non-empty if –userconfig-dir was given on the command line.
bool fps
True if –fps was given on the command line.
std::vector< std::string > unit_test
Non-empty if –unit was given on the command line.
bool noreplaycheck
True if –noreplaycheck was given on the command line.
std::optional< std::string > load
Non-empty if –load was given on the command line.
std::optional< int > max_fps
Max FPS specified by –max-fps option.
void parse_resolution_(const std::string &resolution_string)
To lexical_cast(From value)
Lexical cast converts one type to another.
Definitions for the interface to Wesnoth Markup Language (WML).
bad_commandline_tuple(const std::string &str, const std::string &expected_format)
std::string diff_left
Files for diffing or patching.
#define IMPLY_WCONSOLE
bool preprocess
True if –preprocess was given on the command line.
bool with_replay
True if –with-replay was given on the command line.
bool headless_unit_test
True if –unit is used and –showgui is not present.
const config & options()
Definition: game.cpp:569
std::optional< std::string > render_image_dst
Output file to put rendered image path in.
bool report
True if –report was given on the command line.
std::optional< std::string > gzip
Non-empty if –gzip was given on the command line.
std::ostringstream wrapper.
Definition: formatter.hpp:39
bool nodelay
True if –nodelay was given on the command line.
std::optional< unsigned int > rng_seed
RNG seed specified by –rng-seed option.
std::optional< std::vector< std::pair< int, std::string > > > log
Contains parsed arguments of –log-* (e.g.
std::optional< std::string > validate_addon
Non-empty if –validate-addon was given on the command line.
bool fullscreen()
Definition: general.cpp:414
std::optional< int > campaign_difficulty
Non-empty if –campaign-difficulty was given on the command line.
bool windowed
True if –windowed was given on the command line.
std::optional< std::string > bunzip2
Non-empty if –bunzip2 was given on the command line.
std::vector< std::pair< unsigned int, std::string > > parse_to_uint_string_tuples_(const std::vector< std::string > &strings, char separator=':')
A helper function splitting vector of strings of format unsigned int:string to vector of tuples (unsi...
bool multiplayer
True if –multiplayer was given on the command line.
std::optional< std::vector< std::pair< unsigned int, std::string > > > multiplayer_algorithm
Non-empty if –algorithm was given on the command line.
Manage the empty-palette in the editor.
Definition: action.cpp:30
logger & debug()
Definition: log.cpp:95
bool clock
True if –clock was given on the command line.
bool userconfig_path
True if –userconfig-path was given on the command line.
severity
Definition: log.hpp:64
std::optional< std::string > bzip2
Non-empty if –bzip2 was given on the command line.
bool allow_insecure
Definition: game_config.cpp:97
bool nobanner
True if –nobanner was given on the command line.
std::optional< std::string > logdomains
Non-empty if –logdomains was given on the command line.
std::optional< std::string > render_image
Image path to render.
bool nomusic
True if –nomusic was given on the command line.
std::optional< std::string > multiplayer_era
Non-empty if –era was given on the command line.
std::optional< std::string > campaign
Non-empty if –campaign was given on the command line.
bool debug
True if –debug was given on the command line.
bool debug_lua
True if –debug-lua was given in the commandline.
bool nocache
True if –nocache was given on the command line.
logger & err()
Definition: log.cpp:77
bool allow_insecure
True if –allow-insecure was given in the commandline.
void set_strict_severity(int severity)
Definition: log.cpp:160
bool strict_lua
True if –strict-lua was given in the commandline.
bool new_widgets
True if –new-widgets was given on the command line.
std::optional< std::string > screenshot_output_file
Output file to put screenshot in.
std::optional< std::string > gunzip
Non-empty if –gunzip was given on the command line.
std::optional< std::vector< std::pair< unsigned int, std::string > > > multiplayer_side
Non-empty if –side was given on the command line.
static map_location::DIRECTION s
std::string password(const std::string &server, const std::string &login)
std::optional< std::string > userdata_dir
Non-empty if –userdata-dir was given on the command line.
std::string language()
Definition: general.cpp:505
bad_commandline_resolution(const std::string &resolution)
static void validate(boost::any &v, const std::vector< std::string > &values, two_strings *, int)
std::optional< std::string > script_file
File to load lua script from.
#define debug(x)
std::optional< std::string > username
Non-empty if –username was given on the command line.
std::optional< std::string > data_dir
Non-empty if –data-dir was given on the command line.
std::optional< std::string > multiplayer_scenario
Non-empty if –scenario was given on the command line.
bool campaign_skip_story
True if –skip-story was given on the command line.
std::string core_id()
Definition: general.cpp:323
void parse_log_strictness(const std::string &severity)
std::optional< std::string > server
Non-empty if –server was given on the command line.
bool data_path
True if –data-path was given on the command line.
bool screenshot
True if –screenshot was given on the command line.
logger & warn()
Definition: log.cpp:83
std::vector< std::string > split(const config_attribute_value &val)
bool version
True if –version was given on the command line.
bool validate_core
True if –validate-core was given on the command line.
std::optional< std::string > screenshot_map_file
Map file to make a screenshot of.
Standard logging facilities (interface).
std::optional< std::string > validate_with
Non-empty if –use-schema was given on the command line.
std::optional< std::string > validate_wml
Non-empty if –validate was given on the command line.
bool fullscreen
True if –fullscreen was given on the command line.
bool validcache
True if –validcache was given on the command line.
bool strict_validation
True if –strict-validation was given on the command line.
std::optional< std::string > multiplayer_turns
Non-empty if –turns was given on the command line.
point resolution()
Definition: general.cpp:393
std::optional< std::vector< std::string > > preprocess_defines
Defines that were given to the –preprocess option.
Definition: help.cpp:57
std::optional< unsigned int > multiplayer_repeat
Repeats specified by –multiplayer-repeat option.
bool nosound
True if –nosound was given on the command line.
std::optional< std::vector< std::pair< unsigned int, std::string > > > multiplayer_controller
Non-empty if –controller was given on the command line.
boost::program_options::options_description visible_
friend std::ostream & operator<<(std::ostream &os, const commandline_options &cmdline_opts)
To be used for printing help to the commandline.
bool multiplayer_exit_at_end
True if –exit-at-and was given on the command line.
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:61
std::optional< std::string > campaign_scenario
Non-empty if –campaign-scenario was given on the command line.
std::optional< std::string > validate_schema
Non-empty if –validate-schema was given on the command line.
int get_severity() const
Returns following values depending on the logger: error: 0 warn: 1 info: 2 debug: 3 See also the lg::...
Definition: log.hpp:162
std::optional< std::pair< int, int > > resolution
Pair of AxB values specified after –resolution.
Thrown when a lexical_cast fails.
std::optional< std::string > plugin_file
File to load a lua plugin (similar to a script) from.
std::optional< std::string > language
Non-empty if –language was given on the command line.