Skip to content

Commit b7783ca

Browse files
authored
Merge pull request #5181 from Feoramund/fix-5167
Make `odin help` more precise
2 parents bf0b69b + 2c25a72 commit b7783ca

File tree

1 file changed

+80
-22
lines changed

1 file changed

+80
-22
lines changed

src/main.cpp

Lines changed: 80 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -278,10 +278,10 @@ gb_internal void usage(String argv0, String argv1 = {}) {
278278
print_usage_line(1, " One must contain the program's entry point, all must be in the same package.");
279279
print_usage_line(1, "run Same as 'build', but also then runs the newly compiled executable.");
280280
print_usage_line(1, "bundle Bundles a directory in a specific layout for that platform.");
281-
print_usage_line(1, "check Parses, and type checks a directory of .odin files.");
281+
print_usage_line(1, "check Parses and type checks a directory of .odin files.");
282282
print_usage_line(1, "strip-semicolon Parses, type checks, and removes unneeded semicolons from the entire program.");
283283
print_usage_line(1, "test Builds and runs procedures with the attribute @(test) in the initial package.");
284-
print_usage_line(1, "doc Generates documentation on a directory of .odin files.");
284+
print_usage_line(1, "doc Generates documentation from a directory of .odin files.");
285285
print_usage_line(1, "version Prints version.");
286286
print_usage_line(1, "report Prints information useful to reporting a bug.");
287287
print_usage_line(1, "root Prints the root path where Odin looks for the builtin collections.");
@@ -2221,20 +2221,30 @@ gb_internal void remove_temp_files(lbGenerator *gen) {
22212221
}
22222222

22232223

2224-
gb_internal void print_show_help(String const arg0, String command, String optional_flag = {}) {
2224+
gb_internal int print_show_help(String const arg0, String command, String optional_flag = {}) {
2225+
bool help_resolved = false;
2226+
bool printed_usage_header = false;
2227+
bool printed_flags_header = false;
2228+
22252229
if (command == "help" && optional_flag.len != 0 && optional_flag[0] != '-') {
22262230
command = optional_flag;
22272231
optional_flag = {};
22282232
}
22292233

2230-
print_usage_line(0, "%.*s is a tool for managing Odin source code.", LIT(arg0));
2231-
print_usage_line(0, "Usage:");
2232-
print_usage_line(1, "%.*s %.*s [arguments]", LIT(arg0), LIT(command));
2233-
print_usage_line(0, "");
2234-
defer (print_usage_line(0, ""));
2235-
2234+
auto const print_usage_header_once = [&help_resolved, &printed_usage_header, arg0, command]() {
2235+
if (printed_usage_header) {
2236+
return;
2237+
}
2238+
print_usage_line(0, "%.*s is a tool for managing Odin source code.", LIT(arg0));
2239+
print_usage_line(0, "Usage:");
2240+
print_usage_line(1, "%.*s %.*s [arguments]", LIT(arg0), LIT(command));
2241+
print_usage_line(0, "");
2242+
help_resolved = true;
2243+
printed_usage_header = true;
2244+
};
22362245

22372246
if (command == "build") {
2247+
print_usage_header_once();
22382248
print_usage_line(1, "build Compiles directory of .odin files as an executable.");
22392249
print_usage_line(2, "One must contain the program's entry point, all must be in the same package.");
22402250
print_usage_line(2, "Use `-file` to build a single file instead.");
@@ -2243,35 +2253,48 @@ gb_internal void print_show_help(String const arg0, String command, String optio
22432253
print_usage_line(3, "odin build <dir> Builds package in <dir>.");
22442254
print_usage_line(3, "odin build filename.odin -file Builds single-file package, must contain entry point.");
22452255
} else if (command == "run") {
2256+
print_usage_header_once();
22462257
print_usage_line(1, "run Same as 'build', but also then runs the newly compiled executable.");
22472258
print_usage_line(2, "Append an empty flag and then the args, '-- <args>', to specify args for the output.");
22482259
print_usage_line(2, "Examples:");
22492260
print_usage_line(3, "odin run . Builds and runs package in current directory.");
22502261
print_usage_line(3, "odin run <dir> Builds and runs package in <dir>.");
22512262
print_usage_line(3, "odin run filename.odin -file Builds and runs single-file package, must contain entry point.");
22522263
} else if (command == "check") {
2264+
print_usage_header_once();
22532265
print_usage_line(1, "check Parses and type checks directory of .odin files.");
22542266
print_usage_line(2, "Examples:");
22552267
print_usage_line(3, "odin check . Type checks package in current directory.");
22562268
print_usage_line(3, "odin check <dir> Type checks package in <dir>.");
22572269
print_usage_line(3, "odin check filename.odin -file Type checks single-file package, must contain entry point.");
22582270
} else if (command == "test") {
2271+
print_usage_header_once();
22592272
print_usage_line(1, "test Builds and runs procedures with the attribute @(test) in the initial package.");
22602273
} else if (command == "doc") {
2274+
print_usage_header_once();
22612275
print_usage_line(1, "doc Generates documentation from a directory of .odin files.");
22622276
print_usage_line(2, "Examples:");
22632277
print_usage_line(3, "odin doc . Generates documentation on package in current directory.");
22642278
print_usage_line(3, "odin doc <dir> Generates documentation on package in <dir>.");
22652279
print_usage_line(3, "odin doc filename.odin -file Generates documentation on single-file package.");
22662280
} else if (command == "version") {
2281+
print_usage_header_once();
22672282
print_usage_line(1, "version Prints version.");
22682283
} else if (command == "strip-semicolon") {
2284+
print_usage_header_once();
22692285
print_usage_line(1, "strip-semicolon");
22702286
print_usage_line(2, "Parses and type checks .odin file(s) and then removes unneeded semicolons from the entire project.");
22712287
} else if (command == "bundle") {
2288+
print_usage_header_once();
22722289
print_usage_line(1, "bundle <platform> Bundles a directory in a specific layout for that platform");
22732290
print_usage_line(2, "Supported platforms:");
22742291
print_usage_line(3, "android");
2292+
} else if (command == "report") {
2293+
print_usage_header_once();
2294+
print_usage_line(1, "report Prints information useful to reporting a bug.");
2295+
} else if (command == "root") {
2296+
print_usage_header_once();
2297+
print_usage_line(1, "root Prints the root path where Odin looks for the builtin collections.");
22752298
}
22762299

22772300
bool doc = command == "doc";
@@ -2293,13 +2316,10 @@ gb_internal void print_show_help(String const arg0, String command, String optio
22932316
check = true;
22942317
}
22952318

2296-
print_usage_line(0, "");
2297-
print_usage_line(1, "Flags");
2298-
print_usage_line(0, "");
22992319

23002320

23012321

2302-
auto const print_flag = [&optional_flag](char const *flag) -> bool {
2322+
auto const print_flag = [&optional_flag, &help_resolved, &printed_flags_header, print_usage_header_once](char const *flag) -> bool {
23032323
if (optional_flag.len != 0) {
23042324
String f = make_string_c(flag);
23052325
isize i = string_index_byte(f, ':');
@@ -2310,6 +2330,14 @@ gb_internal void print_show_help(String const arg0, String command, String optio
23102330
return false;
23112331
}
23122332
}
2333+
print_usage_header_once();
2334+
if (!printed_flags_header) {
2335+
print_usage_line(0, "");
2336+
print_usage_line(1, "Flags");
2337+
print_usage_line(0, "");
2338+
printed_flags_header = true;
2339+
}
2340+
help_resolved = true;
23132341
print_usage_line(0, "");
23142342
print_usage_line(1, flag);
23152343
return true;
@@ -2867,6 +2895,21 @@ gb_internal void print_show_help(String const arg0, String command, String optio
28672895
print_usage_line(2, "If this is omitted, the terminal will prompt you to provide it.");
28682896
}
28692897
}
2898+
2899+
if (!help_resolved) {
2900+
usage(arg0);
2901+
print_usage_line(0, "");
2902+
if (command == "help") {
2903+
print_usage_line(0, "'%.*s' is not a recognized flag.", LIT(optional_flag));
2904+
} else {
2905+
print_usage_line(0, "'%.*s' is not a recognized command.", LIT(command));
2906+
}
2907+
return 1;
2908+
}
2909+
2910+
print_usage_line(0, "");
2911+
2912+
return 0;
28702913
}
28712914

28722915
gb_internal void print_show_unused(Checker *c) {
@@ -3239,6 +3282,16 @@ int main(int arg_count, char const **arg_ptr) {
32393282
String run_args_string = {};
32403283
isize last_non_run_arg = args.count;
32413284

3285+
for_array(i, args) {
3286+
if (args[i] == "--") {
3287+
break;
3288+
}
3289+
if (args[i] == "-help" || args[i] == "--help") {
3290+
build_context.show_help = true;
3291+
return print_show_help(args[0], command);
3292+
}
3293+
}
3294+
32423295
bool run_output = false;
32433296
if (command == "run" || command == "test") {
32443297
if (args.count < 3) {
@@ -3332,6 +3385,10 @@ int main(int arg_count, char const **arg_ptr) {
33323385
return 1;
33333386
#endif
33343387
} else if (command == "version") {
3388+
if (args.count != 2) {
3389+
usage(args[0]);
3390+
return 1;
3391+
}
33353392
build_context.command_kind = Command_version;
33363393
gb_printf("%.*s version %.*s", LIT(args[0]), LIT(ODIN_VERSION));
33373394

@@ -3346,6 +3403,10 @@ int main(int arg_count, char const **arg_ptr) {
33463403
gb_printf("\n");
33473404
return 0;
33483405
} else if (command == "report") {
3406+
if (args.count != 2) {
3407+
usage(args[0]);
3408+
return 1;
3409+
}
33493410
build_context.command_kind = Command_bug_report;
33503411
print_bug_report_help();
33513412
return 0;
@@ -3354,8 +3415,7 @@ int main(int arg_count, char const **arg_ptr) {
33543415
usage(args[0]);
33553416
return 1;
33563417
} else {
3357-
print_show_help(args[0], args[1], args[2]);
3358-
return 0;
3418+
return print_show_help(args[0], args[1], args[2]);
33593419
}
33603420
} else if (command == "bundle") {
33613421
if (args.count < 4) {
@@ -3371,6 +3431,10 @@ int main(int arg_count, char const **arg_ptr) {
33713431
}
33723432
init_filename = args[3];
33733433
} else if (command == "root") {
3434+
if (args.count != 2) {
3435+
usage(args[0]);
3436+
return 1;
3437+
}
33743438
gb_printf("%.*s", LIT(odin_root_dir()));
33753439
return 0;
33763440
} else if (command == "clear-cache") {
@@ -3386,11 +3450,6 @@ int main(int arg_count, char const **arg_ptr) {
33863450

33873451
init_filename = copy_string(permanent_allocator(), init_filename);
33883452

3389-
if (init_filename == "-help" ||
3390-
init_filename == "--help") {
3391-
build_context.show_help = true;
3392-
}
3393-
33943453
if (init_filename.len > 0 && !build_context.show_help) {
33953454
// The command must be build, run, test, check, or another that takes a directory or filename.
33963455
if (!path_is_directory(init_filename)) {
@@ -3441,8 +3500,7 @@ int main(int arg_count, char const **arg_ptr) {
34413500
}
34423501

34433502
if (build_context.show_help) {
3444-
print_show_help(args[0], command);
3445-
return 0;
3503+
return print_show_help(args[0], command);
34463504
}
34473505

34483506
if (command == "bundle") {

0 commit comments

Comments
 (0)