Add $ARGS, --args and --jsonargs (fix #1345)
This commit is contained in:
1 parent
e8abc0a2f6
commit
66fb962a66
1 file changed
+78
-36
+78
-36
@@ -41,7 +41,7 @@ static const char* progname;
|
||||
* For a longer help message we could use a better option parsing
|
||||
* strategy, one that lets stack options.
|
||||
*/
|
||||
static void usage(int code) {
|
||||
static void usage(int code, int keep_it_short) {
|
||||
FILE *f = stderr;
|
||||
|
||||
if (code == 0)
|
||||
@@ -49,7 +49,9 @@ static void usage(int code) {
|
||||
|
||||
int ret = fprintf(f,
|
||||
"jq - commandline JSON processor [version %s]\n"
|
||||
"\nUsage:\n\n\t%s [options] <jq filter> [file...]\n\n"
|
||||
"\nUsage:\t%s [options] <jq filter> [file...]\n"
|
||||
"\t%s [options] --args <jq filter> [strings...]\n"
|
||||
"\t%s [options] --jsonargs <jq filter> [JSON_TEXTS...]\n\n"
|
||||
"jq is a tool for processing JSON inputs, applying the given filter to\n"
|
||||
"its JSON text inputs and producing the filter's results as JSON on\n"
|
||||
"standard output.\n\n"
|
||||
@@ -59,7 +61,14 @@ static void usage(int code) {
|
||||
"For more advanced filters see the jq(1) manpage (\"man jq\")\n"
|
||||
"and/or https://stedolan.github.io/jq\n\n"
|
||||
"Example:\n\n\t$ echo '{\"foo\": 0}' | jq .\n"
|
||||
"\t{\n\t\t\"foo\": 0\n\t}\n\n"
|
||||
"\t{\n\t\t\"foo\": 0\n\t}\n\n",
|
||||
JQ_VERSION, progname, progname, progname);
|
||||
if (keep_it_short) {
|
||||
fprintf(f,
|
||||
"For a listing of options, use %s --help.\n",
|
||||
progname);
|
||||
} else {
|
||||
(void) fprintf(f,
|
||||
"Some of the options include:\n"
|
||||
" -c compact instead of pretty-printed output;\n"
|
||||
" -n use `null` as the single input value;\n"
|
||||
@@ -74,7 +83,13 @@ static void usage(int code) {
|
||||
" --arg a v set variable $a to value <v>;\n"
|
||||
" --argjson a v set variable $a to JSON value <v>;\n"
|
||||
" --slurpfile a f set variable $a to an array of JSON texts read from <f>;\n"
|
||||
"\nSee the manpage for more options.\n", JQ_VERSION, progname);
|
||||
" --args remaining arguments are string arguments, not files;\n"
|
||||
" --jsonargs remaining arguments are JSON arguments, not files;\n"
|
||||
" -- terminates argument processing;\n\n"
|
||||
"Named arguments are also available as $ARGS.named[], while\n"
|
||||
"positional arguments are available as $ARGS.positional[].\n"
|
||||
"\nSee the manpage for more options.\n");
|
||||
}
|
||||
exit((ret < 0 && code == 0) ? 2 : code);
|
||||
}
|
||||
|
||||
@@ -200,7 +215,8 @@ int main(int argc, char* argv[]) {
|
||||
int parser_flags = 0;
|
||||
int nfiles = 0;
|
||||
int badwrite;
|
||||
jv program_arguments = jv_array();
|
||||
jv ARGS = jv_array(); /* positional arguments */
|
||||
jv program_arguments = jv_object(); /* named arguments */
|
||||
|
||||
#ifdef WIN32
|
||||
fflush(stdout);
|
||||
@@ -234,21 +250,35 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
jq_util_input_state *input_state = jq_util_input_init(NULL, NULL); // XXX add err_cb
|
||||
|
||||
int further_args_are_files = 0;
|
||||
int further_args_are_strings = 0;
|
||||
int further_args_are_json = 0;
|
||||
int args_done = 0;
|
||||
int jq_flags = 0;
|
||||
size_t short_opts = 0;
|
||||
jv lib_search_paths = jv_null();
|
||||
for (int i=1; i<argc; i++, short_opts = 0) {
|
||||
if (further_args_are_files) {
|
||||
if (args_done) {
|
||||
if (further_args_are_strings) {
|
||||
ARGS = jv_array_append(ARGS, jv_string(argv[i]));
|
||||
} else if (further_args_are_json) {
|
||||
ARGS = jv_array_append(ARGS, jv_parse(argv[i]));
|
||||
} else {
|
||||
jq_util_input_add_input(input_state, argv[i]);
|
||||
nfiles++;
|
||||
}
|
||||
} else if (!strcmp(argv[i], "--")) {
|
||||
if (!program) usage(2);
|
||||
further_args_are_files = 1;
|
||||
if (!program) usage(2, 1);
|
||||
args_done = 1;
|
||||
} else if (!isoptish(argv[i])) {
|
||||
if (program) {
|
||||
if (further_args_are_strings) {
|
||||
ARGS = jv_array_append(ARGS, jv_string(argv[i]));
|
||||
} else if (further_args_are_json) {
|
||||
ARGS = jv_array_append(ARGS, jv_parse(argv[i]));
|
||||
} else {
|
||||
jq_util_input_add_input(input_state, argv[i]);
|
||||
nfiles++;
|
||||
}
|
||||
} else {
|
||||
program = argv[i];
|
||||
}
|
||||
@@ -294,7 +324,7 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
if (isoption(argv[i], 0, "unbuffered", &short_opts)) {
|
||||
options |= UNBUFFERED_OUTPUT;
|
||||
if (!short_opts) continue;
|
||||
continue;
|
||||
}
|
||||
if (isoption(argv[i], 'S', "sort-keys", &short_opts)) {
|
||||
options |= SORTED_OUTPUT;
|
||||
@@ -319,7 +349,7 @@ int main(int argc, char* argv[]) {
|
||||
if (isoption(argv[i], 0, "tab", &short_opts)) {
|
||||
dumpopts &= ~JV_PRINT_INDENT_FLAGS(7);
|
||||
dumpopts |= JV_PRINT_TAB | JV_PRINT_PRETTY;
|
||||
if (!short_opts) continue;
|
||||
continue;
|
||||
}
|
||||
if (isoption(argv[i], 0, "indent", &short_opts)) {
|
||||
if (i >= argc - 1) {
|
||||
@@ -334,53 +364,60 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
dumpopts |= JV_PRINT_INDENT_FLAGS(indent);
|
||||
i++;
|
||||
if (!short_opts) continue;
|
||||
continue;
|
||||
}
|
||||
if (isoption(argv[i], 0, "seq", &short_opts)) {
|
||||
options |= SEQ;
|
||||
if (!short_opts) continue;
|
||||
continue;
|
||||
}
|
||||
if (isoption(argv[i], 0, "stream", &short_opts)) {
|
||||
parser_flags |= JV_PARSE_STREAMING;
|
||||
if (!short_opts) continue;
|
||||
continue;
|
||||
}
|
||||
if (isoption(argv[i], 0, "stream-errors", &short_opts)) {
|
||||
parser_flags |= JV_PARSE_STREAM_ERRORS;
|
||||
if (!short_opts) continue;
|
||||
continue;
|
||||
}
|
||||
if (isoption(argv[i], 'e', "exit-status", &short_opts)) {
|
||||
options |= EXIT_STATUS;
|
||||
if (!short_opts) continue;
|
||||
}
|
||||
// FIXME: For --arg* we should check that the varname is acceptable
|
||||
if (isoption(argv[i], 0, "args", &short_opts)) {
|
||||
further_args_are_strings = 1;
|
||||
further_args_are_json = 0;
|
||||
continue;
|
||||
}
|
||||
if (isoption(argv[i], 0, "jsonargs", &short_opts)) {
|
||||
further_args_are_strings = 0;
|
||||
further_args_are_json = 1;
|
||||
continue;
|
||||
}
|
||||
if (isoption(argv[i], 0, "arg", &short_opts)) {
|
||||
if (i >= argc - 2) {
|
||||
fprintf(stderr, "%s: --arg takes two parameters (e.g. --arg varname value)\n", progname);
|
||||
die();
|
||||
}
|
||||
jv arg = jv_object();
|
||||
arg = jv_object_set(arg, jv_string("name"), jv_string(argv[i+1]));
|
||||
arg = jv_object_set(arg, jv_string("value"), jv_string(argv[i+2]));
|
||||
program_arguments = jv_array_append(program_arguments, arg);
|
||||
if (!jv_object_has(jv_copy(program_arguments), jv_string(argv[i+1])))
|
||||
program_arguments = jv_object_set(program_arguments, jv_string(argv[i+1]), jv_string(argv[i+2]));
|
||||
i += 2; // skip the next two arguments
|
||||
if (!short_opts) continue;
|
||||
continue;
|
||||
}
|
||||
if (isoption(argv[i], 0, "argjson", &short_opts)) {
|
||||
if (i >= argc - 2) {
|
||||
fprintf(stderr, "%s: --argjson takes two parameters (e.g. --argjson varname text)\n", progname);
|
||||
die();
|
||||
}
|
||||
if (!jv_object_has(jv_copy(program_arguments), jv_string(argv[i+1]))) {
|
||||
jv v = jv_parse(argv[i+2]);
|
||||
if (!jv_is_valid(v)) {
|
||||
fprintf(stderr, "%s: invalid JSON text passed to --argjson\n", progname);
|
||||
die();
|
||||
}
|
||||
jv arg = jv_object();
|
||||
arg = jv_object_set(arg, jv_string("name"), jv_string(argv[i+1]));
|
||||
arg = jv_object_set(arg, jv_string("value"), v);
|
||||
program_arguments = jv_array_append(program_arguments, arg);
|
||||
program_arguments = jv_object_set(program_arguments, jv_string(argv[i+1]), v);
|
||||
}
|
||||
i += 2; // skip the next two arguments
|
||||
if (!short_opts) continue;
|
||||
continue;
|
||||
}
|
||||
if (isoption(argv[i], 0, "argfile", &short_opts) ||
|
||||
isoption(argv[i], 0, "slurpfile", &short_opts)) {
|
||||
@@ -393,36 +430,34 @@ int main(int argc, char* argv[]) {
|
||||
fprintf(stderr, "%s: --%s takes two parameters (e.g. --%s varname filename)\n", progname, which, which);
|
||||
die();
|
||||
}
|
||||
jv arg = jv_object();
|
||||
arg = jv_object_set(arg, jv_string("name"), jv_string(argv[i+1]));
|
||||
if (!jv_object_has(jv_copy(program_arguments), jv_string(argv[i+1]))) {
|
||||
jv data = jv_load_file(argv[i+2], 0);
|
||||
if (!jv_is_valid(data)) {
|
||||
data = jv_invalid_get_msg(data);
|
||||
fprintf(stderr, "%s: Bad JSON in --%s %s %s: %s\n", progname, which,
|
||||
argv[i+1], argv[i+2], jv_string_value(data));
|
||||
jv_free(data);
|
||||
jv_free(arg);
|
||||
ret = 2;
|
||||
goto out;
|
||||
}
|
||||
if (isoption(argv[i], 0, "argfile", &short_opts) &&
|
||||
if (strcmp(which, "argfile") == 0 &&
|
||||
jv_get_kind(data) == JV_KIND_ARRAY && jv_array_length(jv_copy(data)) == 1)
|
||||
data = jv_array_get(data, 0);
|
||||
arg = jv_object_set(arg, jv_string("value"), data);
|
||||
program_arguments = jv_array_append(program_arguments, arg);
|
||||
program_arguments = jv_object_set(program_arguments, jv_string(argv[i+1]), data);
|
||||
}
|
||||
i += 2; // skip the next two arguments
|
||||
if (!short_opts) continue;
|
||||
continue;
|
||||
}
|
||||
if (isoption(argv[i], 0, "debug-dump-disasm", &short_opts)) {
|
||||
options |= DUMP_DISASM;
|
||||
if (!short_opts) continue;
|
||||
continue;
|
||||
}
|
||||
if (isoption(argv[i], 0, "debug-trace", &short_opts)) {
|
||||
jq_flags |= JQ_DEBUG_TRACE;
|
||||
if (!short_opts) continue;
|
||||
continue;
|
||||
}
|
||||
if (isoption(argv[i], 'h', "help", &short_opts)) {
|
||||
usage(0);
|
||||
usage(0, 0);
|
||||
if (!short_opts) continue;
|
||||
}
|
||||
if (isoption(argv[i], 'V', "version", &short_opts)) {
|
||||
@@ -489,7 +524,7 @@ int main(int argc, char* argv[]) {
|
||||
program = ".";
|
||||
#endif
|
||||
|
||||
if (!program) usage(2);
|
||||
if (!program) usage(2, 1);
|
||||
|
||||
if (options & FROM_FILE) {
|
||||
char *program_origin = strdup(program);
|
||||
@@ -507,11 +542,17 @@ int main(int argc, char* argv[]) {
|
||||
goto out;
|
||||
}
|
||||
jq_set_attr(jq, jv_string("PROGRAM_ORIGIN"), jq_realpath(jv_string(dirname(program_origin))));
|
||||
ARGS = JV_OBJECT(jv_string("positional"), ARGS,
|
||||
jv_string("named"), jv_copy(program_arguments));
|
||||
program_arguments = jv_object_set(program_arguments, jv_string("ARGS"), jv_copy(ARGS));
|
||||
compiled = jq_compile_args(jq, skip_shebang(jv_string_value(data)), jv_copy(program_arguments));
|
||||
free(program_origin);
|
||||
jv_free(data);
|
||||
} else {
|
||||
jq_set_attr(jq, jv_string("PROGRAM_ORIGIN"), jq_realpath(jv_string("."))); // XXX is this good?
|
||||
ARGS = JV_OBJECT(jv_string("positional"), ARGS,
|
||||
jv_string("named"), jv_copy(program_arguments));
|
||||
program_arguments = jv_object_set(program_arguments, jv_string("ARGS"), jv_copy(ARGS));
|
||||
compiled = jq_compile_args(jq, program, jv_copy(program_arguments));
|
||||
}
|
||||
if (!compiled){
|
||||
@@ -576,6 +617,7 @@ out:
|
||||
ret = 2;
|
||||
}
|
||||
|
||||
jv_free(ARGS);
|
||||
jv_free(program_arguments);
|
||||
jq_util_input_free(&input_state);
|
||||
jq_teardown(&jq);
|
||||
|
||||
Reference in new issue
Block a user