pax_global_header00006660000000000000000000000064134363543020014515gustar00rootroot0000000000000052 comment=1c70bda212c5200f25bb893e7ced9e79c3aa233a arg/000077500000000000000000000000001343635430200116325ustar00rootroot00000000000000arg/LICENSE000066400000000000000000000020751343635430200126430ustar00rootroot00000000000000MIT License Copyright 2019 Bruce Hill Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. arg/Makefile000066400000000000000000000013731343635430200132760ustar00rootroot00000000000000PREFIX= CC=cc CFLAGS=-O3 -std=gnu99 all: arg clean: rm arg arg: arg.c $(CC) arg.c $(CFLAGS) -o arg install: arg @prefix="$(PREFIX)"; \ if [[ ! $$prefix ]]; then \ read -p $$'\033[1mWhere do you want to install? (default: /usr/local) \033[0m' prefix; \ fi; \ if [[ ! $$prefix ]]; then \ prefix="/usr/local"; \ fi; \ mkdir -pv $$prefix/bin $$prefix/share/man/man1 \ && cp -v arg $$prefix/bin/ \ && cp -v arg.1 $$prefix/share/man/man1/ uninstall: @prefix="$(PREFIX)"; \ if [[ ! $$prefix ]]; then \ read -p $$'\033[1mWhere do you want to uninstall from? (default: /usr/local) \033[0m' prefix; \ fi; \ if [[ ! $$prefix ]]; then \ prefix="/usr/local"; \ fi; \ echo "Deleting..."; \ rm -rvf $$prefix/bin/arg $$prefix/share/man/man1/arg.1 arg/README.md000066400000000000000000000032141343635430200131110ustar00rootroot00000000000000# arg - A simple command line argument parser This is a simple tool with a simple job: figure out the value of a single command line argument. Tools like `getopt` and `getopts` are unnecessarily complex and difficult to use, while also not supporting common use cases well. Parsing an argument in a shell script shouldn't require a tutorial or dozen lines of shell code! To quote the `getopt` manpage: > Each shellscript has to carry complex code to parse arguments halfway > correcty (like the example presented here). A better getopt-like tool would > move much of the complexity into the tool and keep the client shell scripts > simpler. ## Usage Simply run: `arg `. `` can be anything, like `-f`, `-flag`, `--flag`, or `flag`. If the flag occurs among the rest of the command line arguments, `arg` will print the flag's value (if any) and exit successfully, otherwise, it will fail (exit status 1). In a shell script, this would look like: ``` #!/bin/sh dir=`arg --dir "$@" || arg -d "$@" || echo "$HOME/Downloads"` if ! server=`arg --server "$@" || arg -s "$@"`; then echo "No server provided :(" && exit 1 fi if arg --verbose "$@" || arg -v "$@"; then echo "Downloading to $dir" fi curl "$server/file.zip" > "$dir/file.zip" ``` The flag's value may be of the form `=` or ` `. Single-letter flags will also match when grouped with other single letter flags, but will not have a value (e.g. `arg -b -abc foo` will succeed without printing anything). When using `arg` in a shell script, it is best to use quotes around `$@`, as in `arg --foo "$@"`, so arguments with spaces will be forwarded correctly. arg/arg.1000066400000000000000000000036601343635430200124720ustar00rootroot00000000000000.\" Manpage for arg. .\" Contact bruce@bruce-hill.com to correct errors or typos. .TH man 8 "14 February 2019" "1.0" "arg man page" .SH NAME arg \- A minimalist command line argument parser .SH SYNOPSIS .B arg .I flag .I ... .SH DESCRIPTION This is a handy tool for parsing out a single argument from a list of command line arguments. .SH INPUT The first argument must be a flag (for example \fB-f\fR, \fB--foo\fR, or \fBfoo\fR). This flag will be searched for among the remaining arguments. .SH OUTPUT AND RETURN If the flag is found, the program will exit successfully (exit status 0), otherwise the program will fail (exit status 1). A flag is found if: .RS 4 .HP 2 \fB-\fR one of the extra arguments is an exact match: \fBarg --foo .. \fI--foo\fB []\fR .HP 2 \fB-\fR one of the exact arguments begins with the flag followed by an '=' sign: \fBarg --foo .. \fI--foo=\fB[]\fR .HP 2 \fB-\fR or the flag is a single dash followed by a single letter, and the letter is found clustered with other letters after a single dash: \fBarg -f .. -x\fIf\fBy\fR If a value is found, the value is printed to stdout. .RE .SH EXAMPLES The primary use case of this program is for shell scripting, as a much simpler and easier to use alternative to getopt. Here are some simple shell script examples: .TP .B if foo=`arg --foo "$@"`; then echo "foo is '$foo'"; fi If \fI--foo=value\fR or \fI--foo value\fR are in the arguments, the shell script will print "foo is 'value'". Note: it is important to put quotes around \fB$@\fR to ensure that arguments with spaces get passed correctly. .TP .B if arg -v "$@" || arg --verbose "$@"; then echo "Verbose!"; fi Prints "Verbose!" if the shell script was run with either \fI-v\fR or \fI--verbose\fR. .TP .B prefix=`arg prefix "$@" || echo "/usr/local"` Sets prefix to the value of the \fIprefix\fR flag the user pased in, or if no such flag was passed, \fI/usr/local\fR. .SH AUTHOR Bruce Hill (bruce@bruce-hill.com) arg/arg.c000066400000000000000000000032301343635430200125450ustar00rootroot00000000000000/* * arg - A simple C program by Bruce Hill for parsing command line arguments * Licensed under the MIT license (see LICENSE for details). * * Example: arg --foo a b --foo=blah --baz -xyz * - Prints "blah" and exits with success * Example: arg --nope a b --foo=blah --baz -xyz * - Prints nothing and exits with failure * Example: arg -y a b --foo=blah --baz -xyz * - Prints nothing and exits with success */ #include #include const int EXIT_SUCCESS = 0; const int EXIT_NO_MATCH = 1; const int EXIT_BAD_USAGE = -1; int main(int argc, char **argv) { char *flag = argv[1]; if (!flag) { fprintf(stderr, "Usage: arg ...\n"); return EXIT_BAD_USAGE; } size_t flaglen = strlen(flag); int ischarflag = flag[0] == '-' && flaglen == 2; for (int i = 2; i < argc; i++) { char *arg = argv[i]; if (strncmp(arg, flag, flaglen) == 0) { if (arg[flaglen] == '\0') { // --flag ... if (argv[i+1] && argv[i+1][0] != '-') // --flag puts(argv[i+1]); // value of the flag return EXIT_SUCCESS; } else if (arg[flaglen] == '=') { // --flag= puts(&arg[flaglen+1]); return EXIT_SUCCESS; } } if (ischarflag && arg[0] == '-' && arg[1] != '-') { // If flag is single-character, e.g. -f, look for it among other // single character flags like -xfy. for (char *c = &arg[1]; *c; c++) { if (*c == flag[1]) return EXIT_SUCCESS; } } } return EXIT_NO_MATCH; }