mirror of
https://github.com/wader/fq.git
synced 2024-12-24 22:05:31 +03:00
cae288e6be
json, yaml, toml, xml, html, csv are now normal formats and most of them also particiate in probing (not html and csv). Also fixes a bunch of bugs in to/fromxml, to/fromjq etc.
181 lines
4.3 KiB
Plaintext
181 lines
4.3 KiB
Plaintext
include "internal";
|
|
include "options";
|
|
include "binary";
|
|
include "decode";
|
|
|
|
def intdiv(a; b): _intdiv(a; b);
|
|
|
|
def trim: capture("^\\s*(?<str>.*?)\\s*$"; "").str;
|
|
|
|
# does +1 and [:1] as " "*0 is null
|
|
def rpad($s; $w): . + ($s * ($w+1-length))[1:];
|
|
|
|
# add missing group/0 function
|
|
# https://github.com/stedolan/jq/issues/2444
|
|
def group: group_by(.);
|
|
|
|
# like group but groups streaks based on condition
|
|
def streaks_by(f):
|
|
( . as $a
|
|
| length as $l
|
|
| if $l == 0 then []
|
|
else
|
|
( [ foreach $a[] as $v (
|
|
{cf: ($a[0] | f), index: 0, start: 0, extract: null};
|
|
( ($v | f) as $vf
|
|
| (.index == 0 or (.cf == $vf)) as $equal
|
|
| if $equal then
|
|
( .extract = null
|
|
)
|
|
else
|
|
( .cf = $vf
|
|
| .extract = [.start, .index]
|
|
| .start = .index
|
|
)
|
|
end
|
|
| .index += 1
|
|
);
|
|
( if .extract then .extract else empty end
|
|
, if .index == $l then [.start, .index] else empty end
|
|
)
|
|
)
|
|
]
|
|
| map($a[.[0]:.[1]])
|
|
)
|
|
end
|
|
);
|
|
# [1, 2, 2, 3] => [[1], [2, 2], [3]]
|
|
def streaks: streaks_by(.);
|
|
|
|
# same as group_by but counts, array or pairs with [value, count]
|
|
def count_by(exp):
|
|
group_by(exp) | map([(.[0] | exp), length]);
|
|
def count: count_by(.);
|
|
|
|
# array of result of applying f on all consecutive pairs
|
|
def delta_by(f):
|
|
( . as $a
|
|
| if length < 1 then []
|
|
else
|
|
[ range(length-1) as $i
|
|
| {a: $a[$i], b: $a[$i+1]}
|
|
| f
|
|
]
|
|
end
|
|
);
|
|
# array of minus between all consecutive pairs
|
|
def delta: delta_by(.b - .a);
|
|
|
|
# split array or string into even chunks, except maybe the last
|
|
def chunk($size):
|
|
if length == 0 then []
|
|
else
|
|
[ ( range(
|
|
( (length / $size)
|
|
| ceil
|
|
| if . == 0 then 1 end
|
|
)
|
|
) as $i
|
|
| .[$i * $size:($i + 1) * $size]
|
|
)
|
|
]
|
|
end;
|
|
|
|
# [{a: 123, ...}, ...]
|
|
# colmap maps something into [col, ...]
|
|
# render maps [{column: 0, string: "coltext", maxwidth: 12}, ..] into a row
|
|
def table(colmap; render):
|
|
def _column_widths:
|
|
[ . as $rs
|
|
| range($rs[0] | length) as $i
|
|
| [$rs[] | colmap | (.[$i] | length)]
|
|
| max
|
|
];
|
|
if length == 0 then ""
|
|
else
|
|
( _column_widths as $cw
|
|
| . as $rs
|
|
| ( $rs[]
|
|
| . as $r
|
|
| [ range($r | length) as $i
|
|
| ($r | colmap | {column: $i, string: .[$i], maxwidth: $cw[$i]})
|
|
]
|
|
| render
|
|
)
|
|
)
|
|
end;
|
|
|
|
# TODO: rename keys and add more, ascii/utf8/utf16/codepoint name?, le/be, signed/unsigned?
|
|
# TODO: move?
|
|
def iprint:
|
|
{
|
|
bin: "0b\(toradix(2))",
|
|
oct: "0o\(toradix(8))",
|
|
dec: "\(.)",
|
|
hex: "0x\(toradix(16))",
|
|
str: (try ([.] | implode) catch null),
|
|
};
|
|
|
|
# produce a/b pairs for diffing values
|
|
def diff($a; $b):
|
|
( ( $a | type) as $at
|
|
| ( $b | type) as $bt
|
|
| if $at != $bt then {a: $a, b: $b}
|
|
elif ($at == "array" or $at == "object") then
|
|
( [ ((($a | keys) + ($b | keys)) | unique)[] as $k
|
|
| {
|
|
($k | tostring):
|
|
( [($a | has($k)), ($b | has($k))]
|
|
| if . == [true, true] then diff($a[$k]; $b[$k])
|
|
elif . == [true, false] then {a: $a[$k]}
|
|
elif . == [false, true] then {b: $b[$k]}
|
|
else empty # TODO: can't happen? error?
|
|
end
|
|
)
|
|
}
|
|
]
|
|
| add
|
|
| if . == null then empty end
|
|
)
|
|
else
|
|
if $a == $b then empty else {a: $a, b: $b} end
|
|
end
|
|
);
|
|
|
|
def paste:
|
|
if _is_completing | not then
|
|
( [ _repeat_break(
|
|
try _stdin(64*1024)
|
|
catch if . == "eof" then error("break") end
|
|
)
|
|
]
|
|
| join("")
|
|
)
|
|
end;
|
|
|
|
# very simple markdown to text converter
|
|
# assumes very basic markdown as input
|
|
def _markdown_to_text:
|
|
( .
|
|
# ```
|
|
# code
|
|
# ```
|
|
# -> code
|
|
| gsub("\\n```\\n"; "\n"; "m")
|
|
# #, ##, ###, ... -> #
|
|
| gsub("(?<line>\\n)?#+(?<title>.*)\\n"; "\(.line // "")#\(.title)\n"; "m")
|
|
# [title](url) -> title (url)
|
|
| gsub("\\[(?<title>.*)\\]\\((?<url>.*)\\)"; "\(.title) (\(.url))")
|
|
# `code` -> code
|
|
| gsub("`(?<code>.*)`"; .code)
|
|
);
|
|
|
|
def expr_to_path: _expr_to_path;
|
|
def path_to_expr: _path_to_expr;
|
|
|
|
def torepr:
|
|
( format as $f
|
|
| if $f == null then error("value is not a format root") end
|
|
| _format_func($f; "torepr")
|
|
);
|