pub(super) const ENV_VAR_NAME: &str = "$__bashkit_env__";
pub(super) const PUBLIC_ENV_VAR_NAME: &str = "$ENV";
pub(super) const FILENAME_VAR_NAME: &str = "$__bashkit_filename__";
pub(super) const LINENO_VAR_NAME: &str = "$__bashkit_lineno__";
pub(super) const ARGS_VAR_NAME: &str = "$ARGS";
pub(super) const JQ_COMPAT_DEFS: &str = r#"
def setpath(p; v):
if (p | length) == 0 then v
else p[0] as $k |
(if . == null then
if ($k | type) == "number" then [] else {} end
else . end) |
.[$k] |= setpath(p[1:]; v)
end;
def leaf_paths: paths(scalars);
def match(re; flags):
matches(re; flags)[] |
.[0] as $m |
{ offset: $m.offset, length: $m.length, string: $m.string,
captures: [.[1:][] | { offset: .offset, length: .length, string: .string,
name: (if has("name") then .name else null end) }] };
def match(re): match(re; "");
def scan(re; flags):
matches(re; if (flags | test("g")) then flags else "g" + flags end)[]
| .[0].string;
def scan(re): scan(re; "");
def @tsv:
[.[] |
if type == "string" then
(split("\\") | join("\\\\"))
| (split("\t") | join("\\t"))
| (split("\r") | join("\\r"))
| (split("\n") | join("\\n"))
elif type == "number" or type == "boolean" then tostring
elif . == null then ""
else error("\(type) (\(tojson)) is not valid in a tsv row")
end
] | join("\t");
def @csv:
[.[] |
if type == "string" then
"\"" + (split("\"") | join("\"\"")) + "\""
elif type == "number" or type == "boolean" then tostring
elif . == null then ""
else error("\(type) (\(tojson)) is not valid in a csv row")
end
] | join(",");
"#;
pub(super) fn build_compat_prefix() -> String {
format!(
"{JQ_COMPAT_DEFS}\n\
def env: {ENV_VAR_NAME};\n\
def input_filename: {FILENAME_VAR_NAME};\n\
def input_line_number: {LINENO_VAR_NAME};\n"
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn build_compat_prefix_includes_setpath() {
let prefix = build_compat_prefix();
assert!(prefix.contains("def setpath"));
}
#[test]
fn build_compat_prefix_includes_env_def() {
let prefix = build_compat_prefix();
assert!(prefix.contains("def env: $__bashkit_env__"));
}
#[test]
fn build_compat_prefix_includes_filename_def() {
let prefix = build_compat_prefix();
assert!(prefix.contains("def input_filename: $__bashkit_filename__"));
}
#[test]
fn build_compat_prefix_includes_lineno_def() {
let prefix = build_compat_prefix();
assert!(prefix.contains("def input_line_number: $__bashkit_lineno__"));
}
#[test]
fn tsv_rejects_arrays_in_compat_def() {
assert!(JQ_COMPAT_DEFS.contains("is not valid in a tsv row"));
}
#[test]
fn csv_rejects_arrays_in_compat_def() {
assert!(JQ_COMPAT_DEFS.contains("is not valid in a csv row"));
}
#[test]
fn scan_avoids_double_g_in_compat_def() {
assert!(JQ_COMPAT_DEFS.contains(r#"flags | test("g")"#));
}
}