2021-11-30 14:23:20 +03:00
|
|
|
# is here to be defined as early as possible to allow debugging
|
2022-01-05 23:36:22 +03:00
|
|
|
# TODO: move some _* to builtin.jq etc?
|
|
|
|
|
|
|
|
def stdin_tty: null | _stdin;
|
|
|
|
def stdout_tty: null | _stdout;
|
|
|
|
|
|
|
|
def print: tostring | _stdout;
|
|
|
|
def println: ., "\n" | print;
|
|
|
|
def printerr: tostring | _stderr;
|
|
|
|
def printerrln: ., "\n" | printerr;
|
|
|
|
|
2022-02-21 00:25:46 +03:00
|
|
|
def _debug($name):
|
|
|
|
( (([$name, .] | tojson) | printerrln)
|
2021-11-30 14:23:20 +03:00
|
|
|
, .
|
|
|
|
);
|
2022-02-21 00:25:46 +03:00
|
|
|
|
|
|
|
# jq compat
|
|
|
|
def debug: _debug("DEBUG");
|
2021-11-30 14:23:20 +03:00
|
|
|
def debug(f): . as $c | f | debug | $c;
|
2022-02-21 00:25:46 +03:00
|
|
|
|
2022-01-07 13:01:28 +03:00
|
|
|
# jq compat, output to compact json to stderr and let input thru
|
|
|
|
def stderr:
|
|
|
|
( (tojson | printerr)
|
|
|
|
, .
|
|
|
|
);
|
2021-11-30 14:23:20 +03:00
|
|
|
|
2022-02-20 23:48:01 +03:00
|
|
|
# try to be same exit codes as jq
|
|
|
|
# TODO: jq seems to halt processing inputs on JSON decode error but not IO errors,
|
|
|
|
# seems strange.
|
|
|
|
# jq '(' <(echo 1) <(echo 2) ; echo $? => 3 and no inputs processed
|
|
|
|
# jq '.' missing <(echo 2) ; echo $? => 2 and continues process inputs
|
|
|
|
# jq '.' <(echo 'a') <(echo 123) ; echo $? => 4 and stops process inputs
|
|
|
|
# jq '.' missing <(echo 'a') <(echo 123) ; echo $? => 2 ???
|
|
|
|
# jq '"a"+.' <(echo '"a"') <(echo 1) ; echo $? => 5
|
|
|
|
# jq '"a"+.' <(echo 1) <(echo '"a"') ; echo $? => 0
|
|
|
|
def _exit_code_args_error: 2;
|
|
|
|
def _exit_code_input_io_error: 2;
|
|
|
|
def _exit_code_compile_error: 3;
|
|
|
|
def _exit_code_input_decode_error: 4;
|
|
|
|
def _exit_code_expr_error: 5;
|
|
|
|
|
2021-09-23 19:35:04 +03:00
|
|
|
def _global_var($k): _global_state[$k];
|
|
|
|
def _global_var($k; f): _global_state(_global_state | .[$k] |= f) | .[$k];
|
|
|
|
|
|
|
|
def _include_paths: _global_var("include_paths");
|
|
|
|
def _include_paths(f): _global_var("include_paths"; f);
|
|
|
|
|
|
|
|
def _options_stack: _global_var("options_stack");
|
|
|
|
def _options_stack(f): _global_var("options_stack"; f);
|
|
|
|
|
|
|
|
def _cli_last_expr_error: _global_var("cli_last_expr_error");
|
|
|
|
def _cli_last_expr_error(f): _global_var("cli_last_expr_error"; f);
|
|
|
|
|
|
|
|
def _input_filename: _global_var("input_filename");
|
|
|
|
def _input_filename(f): _global_var("input_filename"; f);
|
|
|
|
|
|
|
|
def _input_filenames: _global_var("input_filenames");
|
|
|
|
def _input_filenames(f): _global_var("input_filenames"; f);
|
|
|
|
|
|
|
|
def _input_strings: _global_var("input_strings");
|
|
|
|
def _input_strings(f): _global_var("input_strings"; f);
|
|
|
|
|
|
|
|
def _input_strings_lines: _global_var("input_strings_lines");
|
|
|
|
def _input_strings_lines(f): _global_var("input_strings_lines"; f);
|
|
|
|
|
|
|
|
def _input_io_errors: _global_var("input_io_errors");
|
|
|
|
def _input_io_errors(f): _global_var("input_io_errors"; f);
|
|
|
|
|
|
|
|
def _input_decode_errors: _global_var("input_decode_errors");
|
|
|
|
def _input_decode_errors(f): _global_var("input_decode_errors"; f);
|
|
|
|
|
2022-02-21 00:25:46 +03:00
|
|
|
def _slurps: _global_var("slurps");
|
|
|
|
def _slurps(f): _global_var("slurps"; f);
|
2021-09-23 19:35:04 +03:00
|
|
|
|
2022-02-21 00:25:46 +03:00
|
|
|
# call f and finally eval fin even if empty or error.
|
2022-02-24 20:39:01 +03:00
|
|
|
# _finally(1; debug)
|
|
|
|
# _finally(null; debug)
|
|
|
|
# _finally(error("a"); debug)
|
|
|
|
# _finally(empty; debug)
|
|
|
|
# _finally(1,2,3; debug)
|
|
|
|
# _finally({a:1}; debug)
|
2021-08-19 19:11:37 +03:00
|
|
|
def _finally(f; fin):
|
2022-02-24 20:39:01 +03:00
|
|
|
try
|
|
|
|
( f
|
|
|
|
, (fin | empty)
|
|
|
|
)
|
|
|
|
catch
|
|
|
|
( fin as $_
|
|
|
|
| error
|
|
|
|
);
|
2020-06-08 03:29:51 +03:00
|
|
|
|
2021-09-22 22:08:36 +03:00
|
|
|
# TODO: figure out a saner way to force int
|
|
|
|
def _to_int: (. % (. + 1));
|
|
|
|
|
2021-10-30 02:17:14 +03:00
|
|
|
# integer division
|
|
|
|
# inspried by https://github.com/itchyny/gojq/issues/63#issuecomment-765066351
|
|
|
|
def _intdiv($a; $b):
|
|
|
|
( ($a | _to_int) as $a
|
|
|
|
| ($b | _to_int) as $b
|
|
|
|
| ($a - ($a % $b)) / $b
|
|
|
|
);
|
|
|
|
|
|
|
|
# valid jq identifier, start with alpha or underscore then zero or more alpha, num or underscore
|
|
|
|
def _is_ident: type == "string" and test("^[a-zA-Z_][a-zA-Z_0-9]*$");
|
|
|
|
# escape " and \
|
|
|
|
def _escape_ident: gsub("(?<g>[\\\\\"])"; "\\\(.g)");
|
|
|
|
|
|
|
|
# format number with fixed number of decimals
|
|
|
|
def _numbertostring($decimals):
|
|
|
|
( . as $n
|
|
|
|
| [ (. % (. + 1)) # truncate to integer
|
|
|
|
, "."
|
|
|
|
, foreach range($decimals) as $_ (1; . * 10; ($n * .) % 10)
|
|
|
|
]
|
|
|
|
| join("")
|
|
|
|
);
|
|
|
|
|
2021-08-19 19:11:37 +03:00
|
|
|
def _repeat_break(f):
|
|
|
|
try repeat(f)
|
2021-09-04 02:43:56 +03:00
|
|
|
catch
|
|
|
|
if . == "break" then empty
|
|
|
|
else error
|
|
|
|
end;
|
2021-08-19 19:11:37 +03:00
|
|
|
|
2021-09-28 00:11:18 +03:00
|
|
|
def _recurse_break(f):
|
|
|
|
try recurse(f)
|
|
|
|
catch
|
|
|
|
if . == "break" then empty
|
|
|
|
else error
|
|
|
|
end;
|
|
|
|
|
2021-09-23 19:35:04 +03:00
|
|
|
def _is_scalar:
|
|
|
|
type |. != "array" and . != "object";
|
2021-10-07 14:35:48 +03:00
|
|
|
|
2021-11-01 14:57:55 +03:00
|
|
|
def _is_context_canceled_error: . == "context canceled";
|
|
|
|
|
2022-02-21 00:25:46 +03:00
|
|
|
def _error_str($contexts): (["error"] + $contexts + [.]) | join(": ");
|
|
|
|
def _error_str: _error_str([]);
|