Skip to content

Commit 79a15c2

Browse files
committed
Generate completion files and CLIOptions array at compile time
1 parent 96eb67e commit 79a15c2

File tree

12 files changed

+293
-248
lines changed

12 files changed

+293
-248
lines changed

.clang-format-ignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
# ignore vendored libraries:
22
./external/**/*
3+
./resources/completion.*.in

application/CMakeLists.txt

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -183,12 +183,27 @@ f3d_embed_file(
183183
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/F3DConfig.h.in"
184184
"${CMAKE_CURRENT_BINARY_DIR}/F3DConfig.h")
185185

186+
set(_ENABLED_CONDITIONALS)
187+
if(F3D_MODULE_RAYTRACING)
188+
list(APPEND _ENABLED_CONDITIONALS "F3D_MODULE_RAYTRACING")
189+
endif()
190+
if(F3D_MODULE_DMON)
191+
list(APPEND _ENABLED_CONDITIONALS "F3D_MODULE_DMON")
192+
endif()
193+
if(F3D_MODULE_UI)
194+
list(APPEND _ENABLED_CONDITIONALS "F3D_MODULE_UI")
195+
endif()
196+
186197
add_custom_command(
187198
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/F3DCLIOptions.h"
188-
COMMAND ${CMAKE_COMMAND} -D srcDir=${CMAKE_SOURCE_DIR} -D binaryDir=${CMAKE_CURRENT_BINARY_DIR} -P ${CMAKE_SOURCE_DIR}/cmake/f3dCLIOpts.cmake
199+
COMMAND ${CMAKE_COMMAND}
200+
-D "F3D_SOURCE_DIR=${CMAKE_SOURCE_DIR}"
201+
-D "F3D_BINARY_DIR=${CMAKE_BINARY_DIR}"
202+
-D "ENABLED_CONDITIONALS=${_ENABLED_CONDITIONALS}"
203+
-P "${CMAKE_SOURCE_DIR}/cmake/f3dCLIOptions.cmake"
189204
DEPENDS
190-
${CMAKE_SOURCE_DIR}/resources/cli-options.schema.json
191-
${CMAKE_SOURCE_DIR}/resources/cli-options.json
205+
"${CMAKE_SOURCE_DIR}/resources/cli-options.schema.json"
206+
"${CMAKE_SOURCE_DIR}/resources/cli-options.json"
192207
VERBATIM
193208
)
194209

@@ -333,13 +348,13 @@ if(UNIX AND NOT APPLE AND NOT ANDROID)
333348
DESTINATION "${f3d_resources_dir}"
334349
COMPONENT shellext
335350
)
336-
install(FILES "${F3D_SOURCE_DIR}/resources/completion.bash"
351+
install(FILES "${CMAKE_BINARY_DIR}/completion.bash"
337352
DESTINATION "share/bash-completion/completions" COMPONENT shellext
338353
RENAME "f3d")
339-
install(FILES "${F3D_SOURCE_DIR}/resources/completion.zsh"
354+
install(FILES "${CMAKE_BINARY_DIR}/completion.zsh"
340355
DESTINATION "share/zsh/site-functions" COMPONENT shellext
341356
RENAME "_f3d")
342-
install(FILES "${F3D_SOURCE_DIR}/resources/completion.fish"
357+
install(FILES "${CMAKE_BINARY_DIR}/completion.fish"
343358
DESTINATION "share/fish/vendor_completions.d" COMPONENT shellext
344359
RENAME "f3d.fish")
345360
install(FILES "${F3D_SOURCE_DIR}/resources/app.f3d.F3D.metainfo.xml"

application/F3DCLIOptions.h.in

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,40 @@
22
#define F3DCLIOptions_h
33

44
#include <string_view>
5+
#include <vector>
56

67
namespace F3D
78
{
8-
constexpr std::string_view CLI_OPTIONS_JSON = R"END(@CLI_OPTIONS_JSON@)END";
9+
/**
10+
* A struct to configure a complete cxxopts CLI options
11+
* F3D uses exclusively string options except for a few true boolean option (eg: `--version`)
12+
* LongName: The long name, eg: `axis`
13+
* ShortName: The short name, eg: `x`
14+
* HelpText: The help text, for display only when using `--help`
15+
* ValueHelper: Used in help but also to discrimate between boolean option or not
16+
* ImplicitValue: The implicit value when option is provided without a value
17+
*/
18+
struct CLIOption
19+
{
20+
std::string_view LongName;
21+
std::string_view ShortName;
22+
std::string_view HelpText;
23+
std::string_view ValueHelper;
24+
std::string_view ImplicitValue;
25+
};
26+
27+
/**
28+
* A struct to group option into categories
29+
*/
30+
struct CLIGroup
31+
{
32+
std::string_view GroupName;
33+
std::vector<CLIOption> Options;
34+
};
35+
36+
// clang-format off
37+
@F3D_CLI_OPTIONS_CPP@
38+
// clang-format on
939
}
1040

1141
#endif

application/F3DOptionsTools.cxx

Lines changed: 7 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -25,96 +25,6 @@ namespace fs = std::filesystem;
2525

2626
namespace
2727
{
28-
/**
29-
* A struct to configure a complete cxxopts CLI options
30-
* F3D uses exclusively string options except for a few true boolean option (eg: `--version`)
31-
* LongName: The long name, eg: `axis`
32-
* ShortName: The short name, eg: `x`
33-
* HelpText: The help text, for display only when using `--help`
34-
* ValueHelper: Used in help but also to discrimate between boolean option or not
35-
* ImplicitValue: The implicit value when option is provided without a value
36-
*/
37-
struct CLIOption
38-
{
39-
std::string LongName;
40-
std::string ShortName;
41-
std::string HelpText;
42-
std::string ValueHelper;
43-
std::string ImplicitValue;
44-
};
45-
46-
/**
47-
* A struct to group option into categories
48-
*/
49-
struct CLIGroup
50-
{
51-
std::string GroupName;
52-
std::vector<CLIOption> Options;
53-
};
54-
55-
//----------------------------------------------------------------------------
56-
/**
57-
* Get all F3D CLI options except `--input`, `--define`, and `--reset`.
58-
* Order of groups (in JSON) matters in the context of `--help`.
59-
*/
60-
[[nodiscard]] std::vector<CLIGroup> GetAllCLIOptions()
61-
{
62-
const auto cliOptionsJson = nlohmann::json::parse(F3D::CLI_OPTIONS_JSON);
63-
64-
auto parseCliOptionJson = [](const nlohmann::json& cliOptionJson) -> CLIOption
65-
{
66-
CLIOption cliOption;
67-
cliOption.LongName = cliOptionJson["longName"];
68-
cliOption.ShortName = cliOptionJson["shortName"];
69-
cliOption.HelpText = cliOptionJson["helpText"];
70-
cliOption.ValueHelper = cliOptionJson["valueHelper"];
71-
cliOption.ImplicitValue = cliOptionJson["implicitValue"];
72-
return cliOption;
73-
};
74-
75-
auto parseCliGroupJson = [&parseCliOptionJson](const nlohmann::json& cliGroupJson) -> CLIGroup
76-
{
77-
CLIGroup cliGroup;
78-
cliGroup.GroupName = cliGroupJson["name"];
79-
for (const auto& cliOptionJson : cliGroupJson["options"])
80-
{
81-
#ifndef F3D_MODULE_DMON
82-
if (cliOptionJson.value("conditional", "") == "F3D_MODULE_DMON")
83-
{
84-
continue;
85-
}
86-
#endif
87-
#ifndef F3D_MODULE_UI
88-
if (cliGroupJson.value("conditional", "") == "F3D_MODULE_UI")
89-
{
90-
continue;
91-
}
92-
#endif
93-
if (cliGroup.GroupName == "Applicative" &&
94-
std::set<std::string>{ "input", "define", "reset" }.count(cliOptionJson["longName"]) != 0)
95-
{
96-
continue;
97-
}
98-
cliGroup.Options.push_back(parseCliOptionJson(cliOptionJson));
99-
}
100-
return cliGroup;
101-
};
102-
103-
std::vector<CLIGroup> cliOptions;
104-
for (const auto& cliGroupJson : cliOptionsJson["groups"])
105-
{
106-
#ifndef F3D_MODULE_RAYTRACING
107-
if (cliGroupJson.value("conditional", "") == "F3D_MODULE_RAYTRACING")
108-
{
109-
continue;
110-
}
111-
#endif
112-
cliOptions.push_back(parseCliGroupJson(cliGroupJson));
113-
}
114-
115-
return cliOptions;
116-
}
117-
11828
/**
11929
* True boolean options need to be filtered out in ParseCLIOptions
12030
* Also filter out special options like `define` and `reset`
@@ -139,8 +49,7 @@ std::string CollapseName(const std::string_view& longName, const std::string_vie
13949
}
14050

14151
//----------------------------------------------------------------------------
142-
void PrintHelp(const std::string& execName, const cxxopts::Options& cxxOptions,
143-
const std::vector<CLIGroup>& cliOptions)
52+
void PrintHelp(const std::string& execName, const cxxopts::Options& cxxOptions)
14453
{
14554
const std::array<std::pair<std::string, std::string>, 4> examples = { {
14655
{ execName + " file.vtu -xtgans",
@@ -153,9 +62,9 @@ void PrintHelp(const std::string& execName, const cxxopts::Options& cxxOptions,
15362
} };
15463

15564
f3d::log::setUseColoring(false);
156-
std::vector<std::string> orderedCLIGroupNames(cliOptions.size());
157-
std::transform(cliOptions.cbegin(), cliOptions.cend(), orderedCLIGroupNames.begin(),
158-
[](const ::CLIGroup& cliGroup) { return cliGroup.GroupName; });
65+
std::vector<std::string> orderedCLIGroupNames(F3D::CLIOptions.size());
66+
std::transform(F3D::CLIOptions.cbegin(), F3D::CLIOptions.cend(), orderedCLIGroupNames.begin(),
67+
[](const F3D::CLIGroup& cliGroup) { return cliGroup.GroupName; });
15968
f3d::log::info(cxxOptions.help(orderedCLIGroupNames));
16069
f3d::log::info("\nExamples:");
16170
for (const auto& [cmd, desc] : examples)
@@ -372,14 +281,12 @@ F3DOptionsTools::OptionsDict F3DOptionsTools::ParseCLIOptions(
372281
std::vector<std::string> resets;
373282
auto cxxoptsResets = cxxopts::value<std::vector<std::string>>(resets);
374283

375-
auto CLIOptions = GetAllCLIOptions();
376-
377284
try
378285
{
379286
cxxopts::Options cxxOptions(execName, F3D::AppTitle);
380287
cxxOptions.custom_help("[OPTIONS...]");
381288

382-
for (const ::CLIGroup& optionGroup : CLIOptions)
289+
for (const F3D::CLIGroup& optionGroup : F3D::CLIOptions)
383290
{
384291
auto group = cxxOptions.add_options(std::string(optionGroup.GroupName));
385292

@@ -392,7 +299,7 @@ F3DOptionsTools::OptionsDict F3DOptionsTools::ParseCLIOptions(
392299
}
393300

394301
// Add each option to cxxopts
395-
for (const ::CLIOption& cliOption : optionGroup.Options)
302+
for (const F3D::CLIOption& cliOption : optionGroup.Options)
396303
{
397304
if (cliOption.ValueHelper.empty())
398305
{
@@ -468,7 +375,7 @@ F3DOptionsTools::OptionsDict F3DOptionsTools::ParseCLIOptions(
468375
// Check boolean options and log them if any
469376
if (result.count("help") > 0)
470377
{
471-
::PrintHelp(execName, cxxOptions, CLIOptions);
378+
::PrintHelp(execName, cxxOptions);
472379
throw F3DExNoProcess("help requested");
473380
}
474381
if (result.count("version") > 0)

0 commit comments

Comments
 (0)