Commit 7b204649e3

Jay Weisskopf <jay@jayschwa.net>
2018-09-26 02:13:02
stage1: Added `zig help` to show usage on stdout
This will make it easier to do things like `zig help | grep something`. Invalid arguments will now display a short notice for `zig help` instead of showing the full usage information. This will make it easier to see the actual error.
1 parent 2e562a5
Changed files (1)
src/main.cpp
@@ -16,14 +16,22 @@
 
 #include <stdio.h>
 
-static int usage(const char *arg0) {
-    fprintf(stderr, "Usage: %s [command] [options]\n"
+static int print_error_usage(const char *arg0) {
+    fprintf(stderr, "See `%s help` for detailed usage information\n", arg0);
+    return EXIT_FAILURE;
+}
+
+static int print_full_usage(const char *arg0) {
+    fprintf(stdout,
+        "Usage: %s [command] [options]\n"
+        "\n"
         "Commands:\n"
         "  build                        build project from build.zig\n"
         "  build-exe [source]           create executable from source or object files\n"
         "  build-lib [source]           create library from source or object files\n"
         "  build-obj [source]           create object from source or assembly\n"
         "  builtin                      show the source code of that @import(\"builtin\")\n"
+        "  help                         show this usage information\n"
         "  id                           print the base64-encoded compiler id\n"
         "  init-exe                     initialize a `zig build` application in the cwd\n"
         "  init-lib                     initialize a `zig build` library in the cwd\n"
@@ -33,6 +41,7 @@ static int usage(const char *arg0) {
         "  test [source]                create and run a test build\n"
         "  version                      print version number and exit\n"
         "  zen                          print zen of zig and exit\n"
+        "\n"
         "Compile Options:\n"
         "  --assembly [source]          add assembly file to build\n"
         "  --cache-dir [path]           override the cache directory\n"
@@ -63,6 +72,7 @@ static int usage(const char *arg0) {
         "  -dirafter [dir]              same as -isystem but do it last\n"
         "  -isystem [dir]               add additional search path for other .h files\n"
         "  -mllvm [arg]                 forward an arg to LLVM's option processing\n"
+        "\n"
         "Link Options:\n"
         "  --dynamic-linker [path]      set the path to ld.so\n"
         "  --each-lib-rpath             add rpath for each used dynamic library\n"
@@ -87,13 +97,14 @@ static int usage(const char *arg0) {
         "  --ver-major [ver]            dynamic library semver major version\n"
         "  --ver-minor [ver]            dynamic library semver minor version\n"
         "  --ver-patch [ver]            dynamic library semver patch version\n"
+        "\n"
         "Test Options:\n"
         "  --test-filter [text]         skip tests that do not match filter\n"
         "  --test-name-prefix [text]    add prefix to all tests\n"
         "  --test-cmd [arg]             specify test execution command one arg at a time\n"
         "  --test-cmd-bin               appends test binary path to test cmd args\n"
     , arg0);
-    return EXIT_FAILURE;
+    return EXIT_SUCCESS;
 }
 
 static const char *ZIG_ZEN = "\n"
@@ -144,15 +155,16 @@ static int print_target_list(FILE *f) {
 }
 
 enum Cmd {
-    CmdInvalid,
+    CmdNone,
     CmdBuild,
     CmdBuiltin,
+    CmdHelp,
     CmdRun,
+    CmdTargets,
     CmdTest,
+    CmdTranslateC,
     CmdVersion,
     CmdZen,
-    CmdTranslateC,
-    CmdTargets,
 };
 
 static const char *default_zig_cache_name = "zig-cache";
@@ -251,7 +263,7 @@ int main(int argc, char **argv) {
         if (init_kind != InitKindNone) {
             if (argc >= 3) {
                 fprintf(stderr, "Unexpected extra argument: %s\n", argv[2]);
-                return usage(arg0);
+                return print_error_usage(arg0);
             }
             Buf *cmd_template_path = buf_alloc();
             os_path_join(get_zig_special_dir(), buf_create_from_str(init_cmd), cmd_template_path);
@@ -326,7 +338,7 @@ int main(int argc, char **argv) {
         }
     }
 
-    Cmd cmd = CmdInvalid;
+    Cmd cmd = CmdNone;
     EmitFileType emit_file_type = EmitFileTypeBinary;
     const char *in_file = nullptr;
     const char *out_file = nullptr;
@@ -547,7 +559,7 @@ int main(int argc, char **argv) {
             } else if (strcmp(arg, "--pkg-begin") == 0) {
                 if (i + 2 >= argc) {
                     fprintf(stderr, "Expected 2 arguments after --pkg-begin\n");
-                    return usage(arg0);
+                    return print_error_usage(arg0);
                 }
                 CliPkg *new_cur_pkg = allocate<CliPkg>(1);
                 i += 1;
@@ -565,7 +577,7 @@ int main(int argc, char **argv) {
                 cur_pkg = cur_pkg->parent;
             } else if (i + 1 >= argc) {
                 fprintf(stderr, "Expected another argument after %s\n", arg);
-                return usage(arg0);
+                return print_error_usage(arg0);
             } else {
                 i += 1;
                 if (strcmp(arg, "--output") == 0) {
@@ -581,7 +593,7 @@ int main(int argc, char **argv) {
                         color = ErrColorOff;
                     } else {
                         fprintf(stderr, "--color options are 'auto', 'on', or 'off'\n");
-                        return usage(arg0);
+                        return print_error_usage(arg0);
                     }
                 } else if (strcmp(arg, "--cache") == 0) {
                     if (strcmp(argv[i], "auto") == 0) {
@@ -592,7 +604,7 @@ int main(int argc, char **argv) {
                         enable_cache = CacheOptOff;
                     } else {
                         fprintf(stderr, "--cache options are 'auto', 'on', or 'off'\n");
-                        return usage(arg0);
+                        return print_error_usage(arg0);
                     }
                 } else if (strcmp(arg, "--emit") == 0) {
                     if (strcmp(argv[i], "asm") == 0) {
@@ -603,7 +615,7 @@ int main(int argc, char **argv) {
                         emit_file_type = EmitFileTypeLLVMIr;
                     } else {
                         fprintf(stderr, "--emit options are 'asm', 'bin', or 'llvm-ir'\n");
-                        return usage(arg0);
+                        return print_error_usage(arg0);
                     }
                 } else if (strcmp(arg, "--name") == 0) {
                     out_name = argv[i];
@@ -672,10 +684,10 @@ int main(int argc, char **argv) {
                     test_exec_args.append(argv[i]);
                 } else {
                     fprintf(stderr, "Invalid argument: %s\n", arg);
-                    return usage(arg0);
+                    return print_error_usage(arg0);
                 }
             }
-        } else if (cmd == CmdInvalid) {
+        } else if (cmd == CmdNone) {
             if (strcmp(arg, "build-exe") == 0) {
                 cmd = CmdBuild;
                 out_type = OutTypeExe;
@@ -685,6 +697,8 @@ int main(int argc, char **argv) {
             } else if (strcmp(arg, "build-lib") == 0) {
                 cmd = CmdBuild;
                 out_type = OutTypeLib;
+            } else if (strcmp(arg, "help") == 0) {
+                cmd = CmdHelp;
             } else if (strcmp(arg, "run") == 0) {
                 cmd = CmdRun;
                 out_type = OutTypeExe;
@@ -703,7 +717,7 @@ int main(int argc, char **argv) {
                 cmd = CmdBuiltin;
             } else {
                 fprintf(stderr, "Unrecognized command: %s\n", arg);
-                return usage(arg0);
+                return print_error_usage(arg0);
             }
         } else {
             switch (cmd) {
@@ -719,16 +733,17 @@ int main(int argc, char **argv) {
                         }
                     } else {
                         fprintf(stderr, "Unexpected extra parameter: %s\n", arg);
-                        return usage(arg0);
+                        return print_error_usage(arg0);
                     }
                     break;
                 case CmdBuiltin:
+                case CmdHelp:
                 case CmdVersion:
                 case CmdZen:
                 case CmdTargets:
                     fprintf(stderr, "Unexpected extra parameter: %s\n", arg);
-                    return usage(arg0);
-                case CmdInvalid:
+                    return print_error_usage(arg0);
+                case CmdNone:
                     zig_unreachable();
             }
         }
@@ -751,19 +766,19 @@ int main(int argc, char **argv) {
         if (target_arch) {
             if (parse_target_arch(target_arch, &target->arch)) {
                 fprintf(stderr, "invalid --target-arch argument\n");
-                return usage(arg0);
+                return print_error_usage(arg0);
             }
         }
         if (target_os) {
             if (parse_target_os(target_os, &target->os)) {
                 fprintf(stderr, "invalid --target-os argument\n");
-                return usage(arg0);
+                return print_error_usage(arg0);
             }
         }
         if (target_environ) {
             if (parse_target_environ(target_environ, &target->env_type)) {
                 fprintf(stderr, "invalid --target-environ argument\n");
-                return usage(arg0);
+                return print_error_usage(arg0);
             }
         }
     }
@@ -785,13 +800,13 @@ int main(int argc, char **argv) {
         {
             if (cmd == CmdBuild && !in_file && objects.length == 0 && asm_files.length == 0) {
                 fprintf(stderr, "Expected source file argument or at least one --object or --assembly argument.\n");
-                return usage(arg0);
+                return print_error_usage(arg0);
             } else if ((cmd == CmdTranslateC || cmd == CmdTest || cmd == CmdRun) && !in_file) {
                 fprintf(stderr, "Expected source file argument.\n");
-                return usage(arg0);
+                return print_error_usage(arg0);
             } else if (cmd == CmdBuild && out_type == OutTypeObj && objects.length != 0) {
                 fprintf(stderr, "When building an object file, --object arguments are invalid.\n");
-                return usage(arg0);
+                return print_error_usage(arg0);
             }
 
             assert(cmd != CmdBuild || out_type != OutTypeUnknown);
@@ -820,7 +835,7 @@ int main(int argc, char **argv) {
 
             if (need_name && buf_out_name == nullptr) {
                 fprintf(stderr, "--name [name] not provided and unable to infer\n\n");
-                return usage(arg0);
+                return print_error_usage(arg0);
             }
 
             Buf *zig_root_source_file = (cmd == CmdTranslateC) ? nullptr : in_file_buf;
@@ -1012,6 +1027,8 @@ int main(int argc, char **argv) {
                 zig_unreachable();
             }
         }
+    case CmdHelp:
+        return print_full_usage(arg0);
     case CmdVersion:
         printf("%s\n", ZIG_VERSION_STRING);
         return EXIT_SUCCESS;
@@ -1020,7 +1037,8 @@ int main(int argc, char **argv) {
         return EXIT_SUCCESS;
     case CmdTargets:
         return print_target_list(stdout);
-    case CmdInvalid:
-        return usage(arg0);
+    case CmdNone:
+        fprintf(stderr, "Zig programming language\n");
+        return print_error_usage(arg0);
     }
 }