~widelands-dev/widelands/trunk

7175.2.2 by fios at foramnagaidhlig
Added new textdomain for console help messages and unlocalized some console output
1
/*
11165 by The Widelands Bunnybot
Update copyright end year to 2025
2
 * Copyright (C) 2012-2025 by the Widelands Development Team
7175.2.2 by fios at foramnagaidhlig
Added new textdomain for console help messages and unlocalized some console output
3
 *
4
 * This program is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU General Public License
6
 * as published by the Free Software Foundation; either version 2
7
 * of the License, or (at your option) any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
10152 by The Widelands Bunnybot
Add check for missing copyright headers (#5223)
15
 * along with this program; if not, see <https://www.gnu.org/licenses/>.
7175.2.2 by fios at foramnagaidhlig
Added new textdomain for console help messages and unlocalized some console output
16
 *
17
 */
18
19
#include "wlapplication_messages.h"
20
9918 by The Widelands Bunnybot
Use shared_ptr for AddOnInfo (#4747)
21
#include <algorithm>
7175.2.2 by fios at foramnagaidhlig
Added new textdomain for console help messages and unlocalized some console output
22
#include <iostream>
9918 by The Widelands Bunnybot
Use shared_ptr for AddOnInfo (#4747)
23
#include <regex>
7175.2.2 by fios at foramnagaidhlig
Added new textdomain for console help messages and unlocalized some console output
24
25
#include "base/i18n.h"
10061 by The Widelands Bunnybot
Refactor String Assembly / Boost Format (#5081)
26
#include "base/string.h"
7175.2.2 by fios at foramnagaidhlig
Added new textdomain for console help messages and unlocalized some console output
27
9918 by The Widelands Bunnybot
Use shared_ptr for AddOnInfo (#4747)
28
constexpr size_t kIndent = 23;
29
constexpr size_t kTextWidth = 50;
30
31
#ifndef _WIN32
10121 by The Widelands Bunnybot
Tx String and CLI Help Fixes (#5179)
32
#ifdef USE_XDG
33
static const std::string kDefaultHomedir = "~/.local/share/widelands";
34
#else
9918 by The Widelands Bunnybot
Use shared_ptr for AddOnInfo (#4747)
35
static const std::string kDefaultHomedir = "~/.widelands";
10121 by The Widelands Bunnybot
Tx String and CLI Help Fixes (#5179)
36
#endif
9918 by The Widelands Bunnybot
Use shared_ptr for AddOnInfo (#4747)
37
#else
38
static const std::string kDefaultHomedir = "%USERPROFILE%\\.widelands";
39
#endif
40
41
/// Command line help
42
/// Title: unindented text in the line above
43
/// Key: the actual parameter
44
/// Hint: text after =
45
/// Help: Full text help
46
/// Verbose: Filter some config options (--help vs. --help-all)
47
static std::vector<Parameter> parameters;
48
void fill_parameter_vector() {
49
	i18n::Textdomain textdomain("widelands_console");
10892 by The Widelands Bunnybot
Allow loading last savegame/replay/edited map from the command line (CB #4470 / GH #6153)
50
51
	/** TRANSLATORS: Separator for alternative values for command line parameters */
52
	const std::string alternatives_format = _("%1$s|%2$s");
53
54
	// TODO(tothxa): Replace all uses and do this for true|false and others as well
55
	const std::string filename_placeholder = _("FILENAME");
56
57
	/** TRANSLATORS: Used instead of a file name indicating last savegame, replay or map.
58
	    Use '_' instead of spaces if you need multiple words and don't use punctuation marks
59
	 */
60
	const std::string lastused_word = _("last");
61
62
	const std::string file_or_last_placeholder =
63
	   format(alternatives_format, filename_placeholder, lastused_word);
64
11093 by The Widelands Bunnybot
170 files were automatically formatted.
65
	parameters = {
66
	   {_("Usage:"), _("widelands <option0>=<value0> ... <optionN>=<valueN>"), "--", "", false},
67
	   {"", _("widelands <save.wgf>/<replay.wry>"), "--", "", false},
68
	   /// Paths
69
	   {_("Options:"), "datadir", _("DIRNAME"),
70
	    _("Use the specified directory for the Widelands data files."), false},
71
	   {"", "homedir", _("DIRNAME"),
72
	    format(_("Use the specified directory for Widelands config files, savegames, and replays. "
73
	             "Default is `%s`."),
74
	           kDefaultHomedir),
75
	    false},
76
	   {"", "localedir", _("DIRNAME"),
77
	    _("Use the specified directory for the Widelands locale files."), false},
78
	   {"", "language",
79
	    /** TRANSLATORS: The … is not used on purpose to increase readability on monospaced terminals
80
	     */
81
	    _("[de_DE|sv_SE|...]"), _("Use the specified locale."), false},
82
	   {"", "skip_check_datadir_version", "",
83
	    _("Do not check whether the data directory to use is "
84
	      "compatible with this Widelands version."),
85
	    true},
86
	   /// Game setup
87
	   {"", "new_game_from_template", _("FILENAME"),
88
	    format(_("Create a new game directly with the settings configured in the given file. "
89
	             "An example can be found in `%s`."),
90
	           "data/templates/new_game_template"),
91
	    false},
92
	   {"", "scenario", _("FILENAME"),
93
	    _("Start the map `FILENAME` directly as a singleplayer scenario."), false},
94
	   {"", "loadgame", file_or_last_placeholder,
95
	    /** TRANSLATORS: %1 is translation for FILENAME,
96
	                     %2 is translation for "last" for last used file */
97
	    format(_("Load the savegame `%1$s` directly or the last saved game if `=%2$s` is used."),
98
	           filename_placeholder, lastused_word),
99
	    false},
100
	   {"", "replay", file_or_last_placeholder,
101
	    /** TRANSLATORS: %1 is translation for FILENAME,
102
	                     %2 is translation for "last" for last used file */
103
	    format(_("Load the replay `%1$s` directly or the last saved replay if `=%2$s` is used."),
104
	           filename_placeholder, lastused_word),
105
	    false},
106
	   {"", "editor", "",
107
	    /** TRANSLATORS: %1 is translation for FILENAME,
108
	                     %2 is translation for "last" for last used file */
109
	    format(_("Start the Widelands map editor directly. You can add `=%1$s` to directly load the "
110
	             "map `FILENAME` in the editor or `=%2$s` to load the last edited map."),
111
	           filename_placeholder, lastused_word),
112
	    false},
113
	   {"", "script", _("FILENAME"),
114
	    _("Run the given Lua script after initialization. Only valid with --scenario, --loadgame, "
115
	      "or "
116
	      "--editor."),
117
	    false},
11221 by The Widelands Bunnybot
Tools for saveloading compatibility testing (CB #4859 / GH #6497)
118
	   {"", "difficulty",
119
	    /** TRANSLATORS: A placeholder for a numerical value */
120
	    _("n"),
121
	    /** TRANSLATORS: `n` references a numerical placeholder */
122
	    _("Start the scenario with difficulty `n`. Only valid with --scenario."), false},
11093 by The Widelands Bunnybot
170 files were automatically formatted.
123
	   /// Misc
124
	   {"", "nosound", "", _("Start the game with sound disabled."), false},
125
	   /** TRANSLATORS: You may translate true/false, also as on/off or yes/no, but */
126
	   /** TRANSLATORS: it HAS TO BE CONSISTENT with the translation in the widelands textdomain. */
127
	   /** TRANSLATORS: * marks the default value */
128
	   {"", "play_intro_music", _("[true*|false]"),
129
	    _("Play the intro music at startup and show splash image until it ends."), true},
130
	   {"", "fail-on-lua-error", "", _("Force Widelands to crash when a Lua error occurs."), false},
11221 by The Widelands Bunnybot
Tools for saveloading compatibility testing (CB #4859 / GH #6497)
131
	   {"", "fail-on-errors", "",
132
	    _("Force Widelands to crash when a game or the editor terminates with an error."), false},
133
	   {"", "messagebox-timeout",
134
	    /** TRANSLATORS: Placeholder for a time value in seconds */
135
	    _("<seconds>"),
136
	    _("Automatically close modal message boxes after the given number of seconds time."), true},
11093 by The Widelands Bunnybot
170 files were automatically formatted.
137
	   {"", "replay_lifetime", _("n"), _("Delete replays automatically after `n` weeks."), true},
138
	   {"", "ai_training", "",
139
	    _("Enable AI training mode. See https://www.widelands.org/wiki/Ai%20Training/ for a full "
140
	      "description of the AI training logic."),
141
	    true},
142
	   {"", "auto_speed", "",
143
	    _("Constantly adjust the game speed automatically depending on AI delay. "
144
	      "Only to be used for AI testing or training (in conjunction with --ai_training)."),
145
	    true},
146
	   /* This is deliberately so long to discourage overusage */
147
	   {"", "enable_development_testing_tools", "",
148
	    _("Enable the Script Console and Cheating Mode."), true},
149
	   /// Saving options
150
	   {_("Game options:"), _("Note: New values will be written to the config file."), "--", "",
151
	    false},
152
	   {"", "autosave",
153
	    /** TRANSLATORS: A placeholder for a numerical value */
154
	    _("n"),
155
	    /** TRANSLATORS: `n` references a numerical placeholder */
156
	    _("Automatically save each `n` minutes."), false},
157
	   {"", "rolling_autosave", _("n"),
158
	    /** TRANSLATORS: `n` references a numerical placeholder */
159
	    _("Use `n` files for rolling autosaves."), true},
160
	   {"", "skip_autosave_on_inactivity", _("[true*|false]"),
161
	    _("Do not create an autosave when the user has been inactive since the last autosave."),
162
	    true},
163
	   {"", "nozip", "", _("Do not save files as binary zip archives."), false},
164
	   {"", "zip", "", _("Save files as binary zip archives."), false},
165
	   // The below comment is duplicated from above for the other case, when false is the default.
166
	   /** TRANSLATORS: You may translate true/false, also as on/off or yes/no, but */
167
	   /** TRANSLATORS: it HAS TO BE CONSISTENT with the translation in the widelands textdomain. */
168
	   /** TRANSLATORS: * marks the default value */
169
	   {"", "save_chat_history", _("[true|false*]"),
170
	    _("Whether to save the history of sent chat messages to a file."), true},
171
	   {"", "display_replay_filenames", _("[true*|false]"),
172
	    _("Show filenames in the replay screen."), true},
173
	   {"", "editor_player_menu_warn_too_many_players", _("[true*|false]"),
174
	    _("Whether a warning should be shown in the editor if there are too many players."), true},
175
	   /// Game options
176
	   {"", "pause_game_on_inactivity", _("n"),
177
	    /** TRANSLATORS: `n` references a numerical placeholder */
178
	    _("Pause the game after `n` minutes of user inactivity."), true},
179
	   {"", "auto_roadbuild_mode", _("[true*|false]"),
180
	    _("Start building a road after placing a flag."), true},
181
	   {"", "display_flags",
182
	    /** TRANSLATORS: The … character is not used on purpose to increase readability on monospaced
183
	       terminals */
184
	    _("[...]"), _("Bitmask of display flags to set for new games."), true},
9918 by The Widelands Bunnybot
Use shared_ptr for AddOnInfo (#4747)
185
#if 0  // TODO(matthiakl): Re-add training wheels code after v1.0
186
	{"",
187
	 "training_wheels",
188
	 _("[true*|false]"),
189
	 "",
190
	 true
191
	},
192
#endif
11093 by The Widelands Bunnybot
170 files were automatically formatted.
193
	   {"", "edge_scrolling", _("[true|false*]"),
194
	    _("Scroll when the mouse cursor is near the screen edge."), true},
195
	   {"", "invert_movement", _("[true|false*]"),
196
	    _("Invert click-and-drag map movement direction."), true},
197
	   {"", "numpad_diagonalscrolling", _("[true|false*]"),
198
	    _("Allow diagonal scrolling with the numeric keypad."), true},
199
	   {"", "game_clock", _("[true|false*]"), _("Display system time in the info panel."), true},
200
	   {"", "single_watchwin", _("[true|false*]"), _("Use single watchwindow mode."), true},
201
	   {"", "transparent_chat", _("[true*|false]"),
202
	    _("Show in-game chat with transparent background."), true},
203
	   {"", "toolbar_pos", _("[...]"), _("Bitmask to set the toolbar location and mode."), true},
204
	   /// Networking
205
	   {_("Networking:"), "metaserver", _("URI"),
206
	    _("Connect to a different metaserver for internet gaming."), false},
207
	   {"", "metaserverport", _("n"),
208
	    /** TRANSLATORS: `n` references a numerical placeholder */
209
	    _("Port number `n` of the metaserver for internet gaming."), false},
210
	   {"", "servername", _("[...]"), _("The name of the last hosted game."), true},
211
	   {"", "nickname", _("[...]"), _("The nickname used for LAN and online games."), true},
212
	   {"", "realname", _("[...]"), _("Name of map author."), true},
213
	   {"", "lasthost", _("[...]"), _("The last host connected to."), true},
214
	   {"", "registered", _("[true|false*]"),
215
	    _("Whether the used metaserver login is for a registered user."), true},
216
	   {"", "password_sha1", _("[...]"), _("The hashed password for online logins."), true},
217
	   {"", "addon_server_ip", _("IP"),
218
	    _("Connect to a different server address from the add-ons manager."), false},
219
	   {"", "addon_server_port", _("n"),
220
	    _("Connect to a different server port from the add-ons manager."), false},
221
	   {"", "write_syncstreams", "",
222
	    /** TRANSLATORS: A syncstream is a synchronization stream. Syncstreams are used in
223
	     * multiplayer
224
	     */
225
	    /** TRANSLATORS: games to make sure that there is no mismatch between the players. */
226
	    _("Create syncstream dump files to help debug network games."), true},
9975 by The Widelands Bunnybot
Add-Ons Webserver (#4934)
227
11093 by The Widelands Bunnybot
170 files were automatically formatted.
228
	   /// Interface options
229
	   {_("Graphic options:"), "fullscreen", "", _("Use the whole display for the game screen."),
230
	    false},
231
	   {"", "maximized", "", _("Start the game in a maximized window."), false},
232
	   {"", "xres",
233
	    /** TRANSLATORS: A placeholder for window width */
234
	    _("x"),
235
	    /** TRANSLATORS: `x` references a window width placeholder */
236
	    _("Width `x` of the window in pixel."), false},
237
	   {"", "yres",
238
	    /** TRANSLATORS: A placeholder for window height */
239
	    _("y"),
240
	    /** TRANSLATORS: `y` references a window height placeholder */
241
	    _("Height `y` of the window in pixel."), false},
242
	   {"", "sdl_cursor", _("[true*|false]"),
243
	    _("Whether to let the system draw the mouse cursor. Disable it only if the cursor doesn't "
244
	      "appear right, or if you want it to be visible in screenshots or screencasts."),
245
	    true},
246
	   {"", "tooltip_accessibility_mode", _("[true|false*]"), _("Whether to use sticky tooltips."),
247
	    true},
248
	   {"", "theme", _("DIRNAME"),
249
	    _("The path to the active UI theme, relative to the Widelands home directory."), false},
250
	   /// Window options
251
	   {_("Options for the internal window manager:"), "animate_map_panning", _("[true*|false]"),
252
	    _("Whether automatic map movements should be animated."), true},
253
	   {"", "border_snap_distance", _("n"),
254
	    /** TRANSLATORS: `n` references a numerical placeholder */
255
	    _("Move a window to the edge of the screen when the edge of the window comes within a "
256
	      "distance `n` from the edge of the screen."),
257
	    true},
258
	   {"", "dock_windows_to_edges", _("[true|false*]"),
259
	    _("Eliminate a window’s border towards the edge of the screen when the edge of the window "
260
	      "is "
261
	      "next to the edge of the screen."),
262
	    true},
263
	   {"", "panel_snap_distance", _("n"),
264
	    /** TRANSLATORS: `n` references a numerical placeholder */
265
	    _("Move a window to the edge of the panel when the edge of the window comes within "
266
	      "a distance of `n` from the edge of the panel."),
267
	    true},
268
	   /// Others
269
	   {_("Others:"), "verbose", "", _("Enable verbose debug messages"), false},
270
	   {"", "verbose-i18n", "",
271
	    _("Print all strings as they are translated. "
272
	      "This helps with tracing down bugs with internationalization."),
273
	    true},
274
	   {"", "version", "", _("Only print version and exit."), false},
275
	   {"", "help", "", _("Show this help."), false},
276
	   {"", "help-all", "", _("Show this help with all available config options."), false},
277
	   {"", _("<save.wgf>/<replay.wry>"), "--",
278
	    _("Load the given savegame or replay directly. Useful for .wgf/.wry file extension "
279
	      "association. Does not work with other options. Also see --loadgame/--replay."),
280
	    false}};
9918 by The Widelands Bunnybot
Use shared_ptr for AddOnInfo (#4747)
281
}
282
283
const std::vector<std::string> get_all_parameters() {
10898 by The Widelands Bunnybot
Refactor commandline handling (CB #4471 / GH #6154)
284
	std::vector<std::string> result;
285
	for (const Parameter& param : parameters) {
286
		// Filter out special entries
287
		if (param.hint_ != "--") {
288
			result.emplace_back(param.key_);
289
		}
290
	}
9918 by The Widelands Bunnybot
Use shared_ptr for AddOnInfo (#4747)
291
	return result;
292
}
293
294
bool is_parameter(const std::string& name) {
295
	auto result = std::find_if(
296
	   parameters.begin(), parameters.end(), [name](const Parameter& p) { return p.key_ == name; });
10898 by The Widelands Bunnybot
Refactor commandline handling (CB #4471 / GH #6154)
297
	return result != parameters.end() && result->hint_ != "--";
9918 by The Widelands Bunnybot
Use shared_ptr for AddOnInfo (#4747)
298
}
7175.2.2 by fios at foramnagaidhlig
Added new textdomain for console help messages and unlocalized some console output
299
10892 by The Widelands Bunnybot
Allow loading last savegame/replay/edited map from the command line (CB #4470 / GH #6153)
300
bool use_last(const std::string& filename_arg) {
301
	return i18n::is_translation_of(filename_arg, "last", "widelands_console");
302
}
303
7175.2.2 by fios at foramnagaidhlig
Added new textdomain for console help messages and unlocalized some console output
304
/**
305
 * Print usage information
306
 */
10276 by The Widelands Bunnybot
Reformat version string (remove markdown format) (#5385)
307
void show_usage(const std::string& build_ver_details, CmdLineVerbosity verbosity) {
9918 by The Widelands Bunnybot
Use shared_ptr for AddOnInfo (#4747)
308
	i18n::Textdomain textdomain("widelands_console");
7175.2.2 by fios at foramnagaidhlig
Added new textdomain for console help messages and unlocalized some console output
309
9918 by The Widelands Bunnybot
Use shared_ptr for AddOnInfo (#4747)
310
	std::cout << std::string(kIndent + kTextWidth, '=')
311
	          << std::endl
312
	          /** TRANSLATORS: %s = version information */
10276 by The Widelands Bunnybot
Reformat version string (remove markdown format) (#5385)
313
	          << format(_("This is Widelands version %s"), build_ver_details) << std::endl;
9918 by The Widelands Bunnybot
Use shared_ptr for AddOnInfo (#4747)
314
315
	if (verbosity != CmdLineVerbosity::None) {
316
		std::string indent_string = std::string(kIndent, ' ');
317
		bool multiline = true;
318
		for (const Parameter& param : parameters) {
319
			if (verbosity != CmdLineVerbosity::All && param.is_verbose_) {
320
				continue;
321
			}
322
323
			if (!param.title_.empty()) {
324
				std::cout << std::endl << param.title_ << std::endl;
325
			} else if (!multiline) {
326
				// Space out single line entries
327
				std::cout << std::endl;
328
			}
329
330
			std::string column = " ";
331
			if (param.hint_ == "--") {
332
				// option without dashes
333
				column += param.key_;
334
			} else {
335
				column += std::string("--") + param.key_;
336
				if (!param.hint_.empty()) {
337
					column += std::string("=") + param.hint_;
338
				}
339
			}
340
341
			std::cout << column;
342
			if (param.help_.empty()) {
343
				std::cout << std::endl;
344
				continue;
345
			}
346
347
			multiline = column.size() >= kIndent;
348
			if (multiline) {
349
				std::cout << std::endl << indent_string;
350
			} else {
351
				std::cout << std::string(kIndent - column.size(), ' ');
352
			}
353
354
			std::string help = param.help_;
355
			multiline |= help.size() > kTextWidth;
356
			while (help.size() > kTextWidth) {
357
				// Auto wrap lines wider than text width
358
				size_t space_idx = help.rfind(' ', kTextWidth);
359
				if (space_idx != std::string::npos) {
360
					std::cout << help.substr(0, space_idx) << std::endl << indent_string;
361
					help = help.substr(space_idx + 1);
362
				} else {
363
					break;
364
				}
365
			}
366
			std::cout << help << std::endl;
367
		}
368
	}
369
370
	std::cout << std::endl
371
	          << _("Bug reports? Suggestions? Check out the project website:\n"
9204 by The Widelands Bunnybot
Noordfrees: Launchpad mirror (#3766)\n\nMirrors all changes at widelands:master to lp:widelands (1d6b62c7619a182081e1c942ae533a95d6112044)
372
	               "        https://www.widelands.org/\n\n"
8048 by GunChleoc
Ran clang-format.
373
	               "Hope you enjoy this game!")
9918 by The Widelands Bunnybot
Use shared_ptr for AddOnInfo (#4747)
374
	          << std::endl;
7175.2.2 by fios at foramnagaidhlig
Added new textdomain for console help messages and unlocalized some console output
375
}