mirror of
https://github.com/wader/fq.git
synced 2024-12-23 13:22:58 +03:00
interp: add topath/0 and make todescription return null if there is none
Move out more code from funcs.jq
This commit is contained in:
parent
07c7daaf92
commit
07b421011f
@ -161,11 +161,12 @@ notable is support for arbitrary-precision integers.
|
|||||||
- `delta/0`, `delta_by/1`, array with difference between all consecutive pairs.
|
- `delta/0`, `delta_by/1`, array with difference between all consecutive pairs.
|
||||||
- `chunk/1`, split array or string into even chunks
|
- `chunk/1`, split array or string into even chunks
|
||||||
- Adds some decode value specific functions:
|
- Adds some decode value specific functions:
|
||||||
- `root/0` return tree root for value
|
- `root/0` tree root for value
|
||||||
- `buffer_root/0` return root value of buffer for value
|
- `buffer_root/0` root value of buffer for value
|
||||||
- `format_root/0` return root value of format for value
|
- `format_root/0` root value of format for value
|
||||||
- `parent/0` return parent value
|
- `parent/0` parent value
|
||||||
- `parents/0` output parents of value
|
- `parents/0` output parents of value
|
||||||
|
- `topath/0` path of value. Use `path_to_expr` to get a string representation.
|
||||||
- `tovalue/0`, `tovalue/1` symbolic value if available otherwise actual value
|
- `tovalue/0`, `tovalue/1` symbolic value if available otherwise actual value
|
||||||
- `toactual/0` actual value (decoded etc)
|
- `toactual/0` actual value (decoded etc)
|
||||||
- `tosym/0` symbolic value (mapped etc)
|
- `tosym/0` symbolic value (mapped etc)
|
||||||
|
4
pkg/interp/bufferrange.jq
Normal file
4
pkg/interp/bufferrange.jq
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
def tobitsrange: _tobitsrange;
|
||||||
|
def tobytesrange: _tobitsrange(8);
|
||||||
|
def tobits: _tobitsrange(1; false);
|
||||||
|
def tobytes: _tobitsrange(8; false);
|
@ -6,67 +6,6 @@ def debug:
|
|||||||
);
|
);
|
||||||
def debug(f): . as $c | f | debug | $c;
|
def debug(f): . as $c | f | debug | $c;
|
||||||
|
|
||||||
# TODO: introspect and show doc, reflection somehow?
|
|
||||||
def help:
|
|
||||||
( "Type jq expression to evaluate"
|
|
||||||
, "\\t Auto completion"
|
|
||||||
, "Up/Down History"
|
|
||||||
, "^C Interrupt execution"
|
|
||||||
, "... | repl Start a new REPL"
|
|
||||||
, "^D Exit REPL"
|
|
||||||
) | println;
|
|
||||||
|
|
||||||
# null input means done, otherwise {approx_read_bytes: 123, total_size: 123}
|
|
||||||
# TODO: decode provide even more detailed progress, post-process sort etc?
|
|
||||||
def _decode_progress:
|
|
||||||
# _input_filenames is remaning files to read
|
|
||||||
( (_input_filenames | length) as $inputs_len
|
|
||||||
| ( options.filenames | length) as $filenames_len
|
|
||||||
| _ansi.clear_line
|
|
||||||
, "\r"
|
|
||||||
, if . != null then
|
|
||||||
( if $filenames_len > 1 then
|
|
||||||
"\($filenames_len - $inputs_len)/\($filenames_len) \(_input_filename) "
|
|
||||||
else empty
|
|
||||||
end
|
|
||||||
, "\((.approx_read_bytes / .total_size * 100 | _numbertostring(1)))%"
|
|
||||||
)
|
|
||||||
else empty
|
|
||||||
end
|
|
||||||
| stderr
|
|
||||||
);
|
|
||||||
|
|
||||||
def decode($name; $decode_opts):
|
|
||||||
( options as $opts
|
|
||||||
| (null | stdout) as $stdout
|
|
||||||
| _decode(
|
|
||||||
$name;
|
|
||||||
$opts +
|
|
||||||
{
|
|
||||||
_progress: (
|
|
||||||
if $opts.decode_progress and $opts.repl and $stdout.is_terminal then
|
|
||||||
"_decode_progress"
|
|
||||||
else null
|
|
||||||
end
|
|
||||||
),
|
|
||||||
} +
|
|
||||||
$decode_opts
|
|
||||||
)
|
|
||||||
);
|
|
||||||
def decode($name): decode($name; {});
|
|
||||||
def decode: decode(options.decode_format; {});
|
|
||||||
|
|
||||||
def tovalue($opts): _tovalue(options($opts));
|
|
||||||
def tovalue: _tovalue({});
|
|
||||||
def toactual: _decode_value(._actual);
|
|
||||||
def tosym: _decode_value(._sym);
|
|
||||||
def todescription: _decode_value(._description);
|
|
||||||
|
|
||||||
def tobitsrange: _tobitsrange;
|
|
||||||
def tobytesrange: _tobitsrange(8);
|
|
||||||
def tobits: _tobitsrange(1; false);
|
|
||||||
def tobytes: _tobitsrange(8; false);
|
|
||||||
|
|
||||||
def display($opts): _display(options($opts));
|
def display($opts): _display(options($opts));
|
||||||
def display: display({});
|
def display: display({});
|
||||||
def d($opts): display($opts);
|
def d($opts): display($opts);
|
||||||
@ -87,25 +26,6 @@ def hexdump: hexdump({display_bytes: 0});
|
|||||||
def hd($opts): hexdump($opts);
|
def hd($opts): hexdump($opts);
|
||||||
def hd: hexdump;
|
def hd: hexdump;
|
||||||
|
|
||||||
def format: _decode_value(._format; null);
|
|
||||||
|
|
||||||
def root: _decode_value(._root);
|
|
||||||
def buffer_root: _decode_value(._buffer_root);
|
|
||||||
def format_root: _decode_value(._format_root);
|
|
||||||
def parent: _decode_value(._parent);
|
|
||||||
def parents:
|
|
||||||
# TODO: refactor, _while_break?
|
|
||||||
( _decode_value(._parent)
|
|
||||||
| if . == null then empty
|
|
||||||
else
|
|
||||||
_recurse_break(
|
|
||||||
( ._parent
|
|
||||||
| if . == null then error("break") end
|
|
||||||
)
|
|
||||||
)
|
|
||||||
end
|
|
||||||
);
|
|
||||||
|
|
||||||
# overload match to support buffers
|
# overload match to support buffers
|
||||||
def _orig_match($val): match($val);
|
def _orig_match($val): match($val);
|
||||||
def _orig_match($regex; $flags): match($regex; $flags);
|
def _orig_match($regex; $flags): match($regex; $flags);
|
||||||
@ -420,9 +340,3 @@ def diff($a; $b):
|
|||||||
if $a == $b then empty else {a: $a, b: $b} end
|
if $a == $b then empty else {a: $a, b: $b} end
|
||||||
end
|
end
|
||||||
);
|
);
|
||||||
|
|
||||||
def in_bits_range($p):
|
|
||||||
select(._start <= $p and $p < ._stop);
|
|
||||||
def in_bytes_range($p):
|
|
||||||
select(._start/8 <= $p and $p < ._stop/8);
|
|
||||||
|
|
||||||
|
@ -33,9 +33,11 @@ import (
|
|||||||
|
|
||||||
//go:embed interp.jq
|
//go:embed interp.jq
|
||||||
//go:embed internal.jq
|
//go:embed internal.jq
|
||||||
|
//go:embed options.jq
|
||||||
|
//go:embed value.jq
|
||||||
|
//go:embed bufferrange.jq
|
||||||
//go:embed funcs.jq
|
//go:embed funcs.jq
|
||||||
//go:embed grep.jq
|
//go:embed grep.jq
|
||||||
//go:embed options.jq
|
|
||||||
//go:embed args.jq
|
//go:embed args.jq
|
||||||
//go:embed query.jq
|
//go:embed query.jq
|
||||||
//go:embed repl.jq
|
//go:embed repl.jq
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
include "internal";
|
include "internal";
|
||||||
include "options";
|
include "options";
|
||||||
|
include "value";
|
||||||
|
include "bufferrange";
|
||||||
include "funcs";
|
include "funcs";
|
||||||
include "grep";
|
include "grep";
|
||||||
include "args";
|
include "args";
|
||||||
|
@ -226,6 +226,16 @@ def _repl($opts): #:: a|(Opts) => @
|
|||||||
def _repl_slurp($opts): _repl($opts);
|
def _repl_slurp($opts): _repl($opts);
|
||||||
def _repl_slurp: _repl({});
|
def _repl_slurp: _repl({});
|
||||||
|
|
||||||
|
# TODO: introspect and show doc, reflection somehow?
|
||||||
|
def help:
|
||||||
|
( "Type jq expression to evaluate"
|
||||||
|
, "\\t Auto completion"
|
||||||
|
, "Up/Down History"
|
||||||
|
, "^C Interrupt execution"
|
||||||
|
, "... | repl Start a new REPL"
|
||||||
|
, "^D Exit REPL"
|
||||||
|
) | println;
|
||||||
|
|
||||||
# just gives error, call appearing last will be renamed to _repl_slurp
|
# just gives error, call appearing last will be renamed to _repl_slurp
|
||||||
def repl($_):
|
def repl($_):
|
||||||
if options.repl then error("repl must be last")
|
if options.repl then error("repl must be last")
|
||||||
|
22
pkg/interp/testdata/value.fqtest
vendored
22
pkg/interp/testdata/value.fqtest
vendored
@ -29,13 +29,25 @@ $ fq -d mp3 '.headers[0][]' /test.mp3
|
|||||||
0x20| 00 00 00 00 00 00 00 00 00 00 | .......... |.headers[0].padding: raw bits (all zero)
|
0x20| 00 00 00 00 00 00 00 00 00 00 | .......... |.headers[0].padding: raw bits (all zero)
|
||||||
# TODO: proper buffer_root test
|
# TODO: proper buffer_root test
|
||||||
$ fq -d mp3 -i . /test.mp3
|
$ fq -d mp3 -i . /test.mp3
|
||||||
mp3> . | (root, buffer_root, format_root, parent | ._path | path_to_expr), [parents | ._path | path_to_expr]
|
mp3> .frames[0].header.mpeg_version | (topath | path_to_expr), tovalue, toactual, tosym, todescription
|
||||||
"."
|
".frames[0].header.mpeg_version"
|
||||||
|
"1"
|
||||||
|
3
|
||||||
|
"1"
|
||||||
|
"MPEG Version 1"
|
||||||
|
mp3> .frames[0].header.bitrate | (topath | path_to_expr), tovalue, toactual, tosym, todescription
|
||||||
|
".frames[0].header.bitrate"
|
||||||
|
56000
|
||||||
|
4
|
||||||
|
56000
|
||||||
|
null
|
||||||
|
mp3> . | (root, buffer_root, format_root, parent | try topath | path_to_expr catch .), [parents | topath | path_to_expr]
|
||||||
"."
|
"."
|
||||||
"."
|
"."
|
||||||
"."
|
"."
|
||||||
|
"expected a decode value but got: null (null)"
|
||||||
[]
|
[]
|
||||||
mp3> .headers[0].magic | (root, buffer_root, format_root, parent | ._path | path_to_expr), [parents | ._path | path_to_expr]
|
mp3> .headers[0].magic | (root, buffer_root, format_root, parent | topath | path_to_expr), [parents | topath | path_to_expr]
|
||||||
"."
|
"."
|
||||||
"."
|
"."
|
||||||
".headers[0]"
|
".headers[0]"
|
||||||
@ -45,7 +57,7 @@ mp3> .headers[0].magic | (root, buffer_root, format_root, parent | ._path | path
|
|||||||
".headers",
|
".headers",
|
||||||
"."
|
"."
|
||||||
]
|
]
|
||||||
mp3> .frames[0].side_info.granules[1] | (root, buffer_root, format_root, parent | ._path | path_to_expr), [parents | ._path | path_to_expr]
|
mp3> .frames[0].side_info.granules[1] | (root, buffer_root, format_root, parent | topath | path_to_expr), [parents | topath | path_to_expr]
|
||||||
"."
|
"."
|
||||||
"."
|
"."
|
||||||
".frames[0]"
|
".frames[0]"
|
||||||
@ -231,7 +243,7 @@ mp3> ._sym
|
|||||||
null
|
null
|
||||||
mp3> ._description
|
mp3> ._description
|
||||||
"/test.mp3"
|
"/test.mp3"
|
||||||
mp3> ._path
|
mp3> topath
|
||||||
[]
|
[]
|
||||||
mp3> ._bits
|
mp3> ._bits
|
||||||
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
|
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|
|
||||||
|
4
pkg/interp/testdata/value_array.fqtest
vendored
4
pkg/interp/testdata/value_array.fqtest
vendored
@ -153,8 +153,8 @@ null
|
|||||||
"null"
|
"null"
|
||||||
0
|
0
|
||||||
mp3> .headers._description | ., type, length?
|
mp3> .headers._description | ., type, length?
|
||||||
""
|
null
|
||||||
"string"
|
"null"
|
||||||
0
|
0
|
||||||
mp3> .headers._path | ., type, length?
|
mp3> .headers._path | ., type, length?
|
||||||
[
|
[
|
||||||
|
4
pkg/interp/testdata/value_boolean.fqtest
vendored
4
pkg/interp/testdata/value_boolean.fqtest
vendored
@ -57,8 +57,8 @@ null
|
|||||||
"null"
|
"null"
|
||||||
0
|
0
|
||||||
mp3> .headers[0].flags.unsynchronisation._description | ., type, length?
|
mp3> .headers[0].flags.unsynchronisation._description | ., type, length?
|
||||||
""
|
null
|
||||||
"string"
|
"null"
|
||||||
0
|
0
|
||||||
mp3> .headers[0].flags.unsynchronisation._path | ., type, length?
|
mp3> .headers[0].flags.unsynchronisation._path | ., type, length?
|
||||||
[
|
[
|
||||||
|
4
pkg/interp/testdata/value_json_array.fqtest
vendored
4
pkg/interp/testdata/value_json_array.fqtest
vendored
@ -71,8 +71,8 @@ null
|
|||||||
"null"
|
"null"
|
||||||
0
|
0
|
||||||
json> (.)._description | ., type, length?
|
json> (.)._description | ., type, length?
|
||||||
""
|
null
|
||||||
"string"
|
"null"
|
||||||
0
|
0
|
||||||
json> (.)._path | ., type, length?
|
json> (.)._path | ., type, length?
|
||||||
[]
|
[]
|
||||||
|
4
pkg/interp/testdata/value_json_object.fqtest
vendored
4
pkg/interp/testdata/value_json_object.fqtest
vendored
@ -61,8 +61,8 @@ null
|
|||||||
"null"
|
"null"
|
||||||
0
|
0
|
||||||
json> (.)._description | ., type, length?
|
json> (.)._description | ., type, length?
|
||||||
""
|
null
|
||||||
"string"
|
"null"
|
||||||
0
|
0
|
||||||
json> (.)._path | ., type, length?
|
json> (.)._path | ., type, length?
|
||||||
[]
|
[]
|
||||||
|
4
pkg/interp/testdata/value_number.fqtest
vendored
4
pkg/interp/testdata/value_number.fqtest
vendored
@ -58,8 +58,8 @@ null
|
|||||||
"null"
|
"null"
|
||||||
0
|
0
|
||||||
mp3> .headers[0].version._description | ., type, length?
|
mp3> .headers[0].version._description | ., type, length?
|
||||||
""
|
null
|
||||||
"string"
|
"null"
|
||||||
0
|
0
|
||||||
mp3> .headers[0].version._path | ., type, length?
|
mp3> .headers[0].version._path | ., type, length?
|
||||||
[
|
[
|
||||||
|
4
pkg/interp/testdata/value_object.fqtest
vendored
4
pkg/interp/testdata/value_object.fqtest
vendored
@ -74,8 +74,8 @@ null
|
|||||||
"null"
|
"null"
|
||||||
0
|
0
|
||||||
mp3> .headers[0].flags._description | ., type, length?
|
mp3> .headers[0].flags._description | ., type, length?
|
||||||
""
|
null
|
||||||
"string"
|
"null"
|
||||||
0
|
0
|
||||||
mp3> .headers[0].flags._path | ., type, length?
|
mp3> .headers[0].flags._path | ., type, length?
|
||||||
[
|
[
|
||||||
|
@ -350,8 +350,14 @@ func (dvb decodeValueBase) JQValueKey(name string) interface{} {
|
|||||||
case "_description":
|
case "_description":
|
||||||
switch vv := dv.V.(type) {
|
switch vv := dv.V.(type) {
|
||||||
case decode.Compound:
|
case decode.Compound:
|
||||||
|
if vv.Description == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return vv.Description
|
return vv.Description
|
||||||
case decode.Scalar:
|
case decode.Scalar:
|
||||||
|
if vv.Description == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return vv.Description
|
return vv.Description
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
|
71
pkg/interp/value.jq
Normal file
71
pkg/interp/value.jq
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
# null input means done, otherwise {approx_read_bytes: 123, total_size: 123}
|
||||||
|
# TODO: decode provide even more detailed progress, post-process sort etc?
|
||||||
|
def _decode_progress:
|
||||||
|
# _input_filenames is remaning files to read
|
||||||
|
( (_input_filenames | length) as $inputs_len
|
||||||
|
| ( options.filenames | length) as $filenames_len
|
||||||
|
| _ansi.clear_line
|
||||||
|
, "\r"
|
||||||
|
, if . != null then
|
||||||
|
( if $filenames_len > 1 then
|
||||||
|
"\($filenames_len - $inputs_len)/\($filenames_len) \(_input_filename) "
|
||||||
|
else empty
|
||||||
|
end
|
||||||
|
, "\((.approx_read_bytes / .total_size * 100 | _numbertostring(1)))%"
|
||||||
|
)
|
||||||
|
else empty
|
||||||
|
end
|
||||||
|
| stderr
|
||||||
|
);
|
||||||
|
|
||||||
|
def decode($name; $decode_opts):
|
||||||
|
( options as $opts
|
||||||
|
| (null | stdout) as $stdout
|
||||||
|
| _decode(
|
||||||
|
$name;
|
||||||
|
$opts +
|
||||||
|
{
|
||||||
|
_progress: (
|
||||||
|
if $opts.decode_progress and $opts.repl and $stdout.is_terminal then
|
||||||
|
"_decode_progress"
|
||||||
|
else null
|
||||||
|
end
|
||||||
|
),
|
||||||
|
} +
|
||||||
|
$decode_opts
|
||||||
|
)
|
||||||
|
);
|
||||||
|
def decode($name): decode($name; {});
|
||||||
|
def decode: decode(options.decode_format; {});
|
||||||
|
|
||||||
|
def topath: _decode_value(._path);
|
||||||
|
def tovalue($opts): _tovalue(options($opts));
|
||||||
|
def tovalue: _tovalue({});
|
||||||
|
def toactual: _decode_value(._actual);
|
||||||
|
def tosym: _decode_value(._sym);
|
||||||
|
def todescription: _decode_value(._description);
|
||||||
|
|
||||||
|
# TODO: rename?
|
||||||
|
def format: _decode_value(._format; null);
|
||||||
|
|
||||||
|
def root: _decode_value(._root);
|
||||||
|
def buffer_root: _decode_value(._buffer_root);
|
||||||
|
def format_root: _decode_value(._format_root);
|
||||||
|
def parent: _decode_value(._parent);
|
||||||
|
def parents:
|
||||||
|
# TODO: refactor, _while_break?
|
||||||
|
( _decode_value(._parent)
|
||||||
|
| if . == null then empty
|
||||||
|
else
|
||||||
|
_recurse_break(
|
||||||
|
( ._parent
|
||||||
|
| if . == null then error("break") end
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
);
|
||||||
|
|
||||||
|
def in_bits_range($p):
|
||||||
|
select(._start <= $p and $p < ._stop);
|
||||||
|
def in_bytes_range($p):
|
||||||
|
select(._start/8 <= $p and $p < ._stop/8);
|
Loading…
Reference in New Issue
Block a user