diff --git a/README.rst b/README.rst index 215c456..83e8ed2 100644 --- a/README.rst +++ b/README.rst @@ -13,10 +13,12 @@ duckargs |duck| |tests_badge| |cov_badge| |version_badge| |license_badge| The purpose of ``duckargs`` is to save some typing whenever you want to quickly -create a python program that accepts command line arguments. Just run ``duckargs`` -with the arguments that you want your program to accept, with example values for -options, and ``duckargs`` will generate the python code for a program that uses -``argparse`` to handle those arguments. +create a python program or C program that accepts command line arguments. Just run +``duckargs`` (generates python), ``duckargs-python`` (also generates python) or +``duckargs-c`` (generates C) +with the arguments that you want your program to accept, with example values provided +to options, and ``duckargs`` will generate the code for a program that handles those +options/arguments. Install ======= @@ -30,13 +32,13 @@ Install with pip (python 3x required): Example ======= -Run duckargs from the command line via ``duckargs`` or ``python -m duckargs``, followed -by whatever arguments/options/flags you want your program to accept, and ``duckargs`` -will print the corresponding python code. For example: +To generate python code, run duckargs from the command line via ``duckargs`` or ``duckargs-python``, +followed by whatever arguments/options/flags you want your program to accept, and duckargs will +print the corresponding python code. For example: :: - $ duckargs positional_arg1 positional_arg2 -i --int-val 4 -f 3.3 -f --file FILE -F --otherfile FILE -a -b -c + $ duckargs positional_arg1 positional_arg2 -i --int-val 4 -e 3.3 -f --file FILE -F --otherfile FILE -a -b -c The output of the above command looks like this: @@ -45,7 +47,7 @@ The output of the above command looks like this: .. code:: python # Generated by duckargs, invoked with the following arguments: - # positional_arg1 positional_arg2 -i --int-val 4 -f 3.3 -f --file FILE -F --otherfile FILE -a -b -c + # positional_arg1 positional_arg2 -i --int-val 4 -e 3.3 -f --file FILE -F --otherfile FILE -a -b -c import argparse @@ -56,7 +58,7 @@ The output of the above command looks like this: parser.add_argument('positional_arg1', help='a string') parser.add_argument('positional_arg2', help='a string') parser.add_argument('-i', '--int-val', default=4, type=int, help='an int value') - parser.add_argument('-f', default=3.3, type=float, help='a float value') + parser.add_argument('-e', default=3.3, type=float, help='a float value') parser.add_argument('-f', '--file', default=None, type=argparse.FileType(), help='a filename') parser.add_argument('-F', '--otherfile', default=None, type=argparse.FileType(), help='a filename') parser.add_argument('-a', action='store_true', help='a flag') @@ -67,7 +69,7 @@ The output of the above command looks like this: print(args.positional_arg1) print(args.positional_arg2) print(args.int_val) - print(args.f) + print(args.e) print(args.file) print(args.otherfile) print(args.a) @@ -77,6 +79,153 @@ The output of the above command looks like this: if __name__ == "__main__": main() +For generating C code, the process is the same, except you should call ``duckargs-c`` +instead of ``duckargs-python``: + +:: + + $ duckargs-c positional_arg1 positional_arg2 -i --int-val 4 -f 3.3 -f --file FILE -F --otherfile FILE -a -b -c + + // Generated by duckargs, invoked with the following arguments: + // positional_arg1 positional_arg2 -i --int-val 4 -e 3.3 -f --file FILE -F --otherfile FILE -a -b -c + + #include + #include + #include + #include + + static char *positional_arg1 = "positional_arg1"; + static char *positional_arg2 = "positional_arg2"; + static long int int_val = 4; + static float e = 3.3; + static char *file = NULL; + static char *otherfile = NULL; + static bool a = false; + static bool b = false; + static bool c = false; + + static struct option long_options[] = + { + {"int-val", required_argument, NULL, 'i'}, + {"file", required_argument, NULL, 'f'}, + {"otherfile", required_argument, NULL, 'F'}, + {NULL, 0, NULL, 0} + }; + + void print_usage(void) + { + printf("\n"); + printf("program_name [OPTIONS] positional_arg1 positional_arg2\n\n"); + printf("-i --int-val [int] An int value (default: %ld)\n", int_val); + printf("-e [float] A float value (default: %.2f)\n", e); + printf("-f --file FILE A filename (default: %s)\n", file ? file : "null"); + printf("-F --otherfile FILE A filename (default: %s)\n", otherfile ? otherfile : "null"); + printf("-a A flag\n"); + printf("-b A flag\n"); + printf("-c A flag\n"); + printf("\n"); + } + + int parse_args(int argc, char *argv[]) + { + char *endptr = NULL; + int ch; + + while ((ch = getopt_long(argc, argv, "i:e:f:F:abc", long_options, NULL)) != -1) + { + switch (ch) + { + case 'i': + { + int_val = strtol(optarg, &endptr, 0); + if (endptr && (*endptr != '\0')) + { + printf("Option '-i' requires an integer argument\n"); + return -1; + } + break; + } + case 'e': + { + e = strtof(optarg, &endptr); + if (endptr == optarg) + { + printf("Option '-e' requires a floating-point argument\n"); + return -1; + } + break; + } + case 'f': + { + file = optarg; + break; + } + case 'F': + { + otherfile = optarg; + break; + } + case 'a': + { + a = true; + break; + } + case 'b': + { + b = true; + break; + } + case 'c': + { + c = true; + break; + } + } + } + + if (argc < (optind + 2)) + { + printf("Missing positional arguments\n"); + return -1; + } + + positional_arg1 = argv[optind]; + optind++; + + positional_arg2 = argv[optind]; + optind++; + + return 0; + } + + int main(int argc, char *argv[]) + { + if (argc < 2) + { + print_usage(); + return -1; + } + + int ret = parse_args(argc, argv); + if (0 != ret) + { + return ret; + } + + printf("positional_arg1: %s\n", positional_arg1); + printf("positional_arg2: %s\n", positional_arg2); + printf("int_val: %ld\n", int_val); + printf("e: %.4f\n", e); + printf("file: %s\n", file); + printf("otherfile: %s\n", otherfile); + printf("a: %s\n", a ? "true" : "false"); + printf("b: %s\n", b ? "true" : "false"); + printf("c: %s\n", c ? "true" : "false"); + + return 0; + } + + Comma-separated choices for option argument ===========================================