mirror of
https://github.com/wader/fq.git
synced 2024-11-23 09:56:07 +03:00
interp: Cleanup, use BufferRange for _open, progress for all decode
This commit is contained in:
parent
08142063b3
commit
67898cb44a
@ -1,8 +1,5 @@
|
||||
package flac
|
||||
|
||||
// TODO: 24 bit picture length truncate warning
|
||||
// TODO: Cuesheet
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
|
@ -20,7 +20,7 @@ type BufferRange struct {
|
||||
unit int
|
||||
}
|
||||
|
||||
func bufferViewFromBuffer(bb *bitio.Buffer, unit int) BufferRange {
|
||||
func newBufferRangeFromBuffer(bb *bitio.Buffer, unit int) BufferRange {
|
||||
return BufferRange{
|
||||
bb: bb,
|
||||
r: ranges.Range{Start: 0, Len: bb.Len()},
|
||||
|
@ -4,8 +4,8 @@
|
||||
| to_entries[]
|
||||
# TODO: nicer way to skip "all" which also would override builtin all/*
|
||||
| select(.key != "all")
|
||||
| "def \(.key)($opts): _decode(\(.key | tojson); $opts);"
|
||||
, "def \(.key): _decode(\(.key | tojson); {});"
|
||||
| "def \(.key)($opts): decode(\(.key | tojson); $opts);"
|
||||
, "def \(.key): decode(\(.key | tojson); {});"
|
||||
)
|
||||
, ( _registry.formats[]
|
||||
| select(.files)
|
||||
|
@ -124,7 +124,7 @@ func makeStringBitBufTransformFn(
|
||||
}
|
||||
outBB := bitio.NewBufferFromBytes(buf.Bytes(), -1)
|
||||
|
||||
return bufferViewFromBuffer(outBB, 8)
|
||||
return newBufferRangeFromBuffer(outBB, 8)
|
||||
default:
|
||||
bb, err := toBuffer(c)
|
||||
if err != nil {
|
||||
@ -170,7 +170,7 @@ func makeBitBufTransformFn(fn func(r io.Reader) (io.Reader, error)) func(c inter
|
||||
|
||||
outBB := bitio.NewBufferFromBytes(outBuf.Bytes(), -1)
|
||||
|
||||
return bufferViewFromBuffer(outBB, 8)
|
||||
return newBufferRangeFromBuffer(outBB, 8)
|
||||
}
|
||||
}
|
||||
|
||||
@ -192,7 +192,7 @@ func makeHashFn(fn func() (hash.Hash, error)) func(c interface{}, a []interface{
|
||||
|
||||
outBB := bitio.NewBufferFromBytes(h.Sum(nil), -1)
|
||||
|
||||
return bufferViewFromBuffer(outBB, 8)
|
||||
return newBufferRangeFromBuffer(outBB, 8)
|
||||
}
|
||||
}
|
||||
|
||||
@ -473,24 +473,21 @@ func (i *Interp) history(c interface{}, a []interface{}) interface{} {
|
||||
return vs
|
||||
}
|
||||
|
||||
type bitBufFile struct {
|
||||
gojq.JQValue
|
||||
|
||||
bb *bitio.Buffer
|
||||
filename string
|
||||
|
||||
type openFile struct {
|
||||
BufferRange
|
||||
filename string
|
||||
progressFn progressreadseeker.ProgressFn
|
||||
}
|
||||
|
||||
var _ ToBufferView = (*bitBufFile)(nil)
|
||||
var _ ToBufferView = (*openFile)(nil)
|
||||
|
||||
func (bbf *bitBufFile) Display(w io.Writer, opts Options) error {
|
||||
_, err := fmt.Fprintln(w, bbf.JQValue.JQValueToString())
|
||||
func (of *openFile) Display(w io.Writer, opts Options) error {
|
||||
_, err := fmt.Fprintf(w, "<openFile %q>\n", of.filename)
|
||||
return err
|
||||
}
|
||||
|
||||
func (bbf *bitBufFile) ToBufferView() (BufferRange, error) {
|
||||
return bufferViewFromBuffer(bbf.bb, 8), nil
|
||||
func (of *openFile) ToBufferView() (BufferRange, error) {
|
||||
return newBufferRangeFromBuffer(of.bb, 8), nil
|
||||
}
|
||||
|
||||
// def open: #:: string| => buffer
|
||||
@ -541,8 +538,7 @@ func (i *Interp) _open(c interface{}, a []interface{}) interface{} {
|
||||
bEnd = int64(len(buf))
|
||||
}
|
||||
|
||||
bbf := &bitBufFile{
|
||||
JQValue: gojqextra.String(fmt.Sprintf("<bitBufFile %s>", path)),
|
||||
bbf := &openFile{
|
||||
filename: path,
|
||||
}
|
||||
|
||||
@ -581,7 +577,7 @@ func (i *Interp) _decode(c interface{}, a []interface{}) interface{} {
|
||||
// would be nice to move all progress code into decode but it might be
|
||||
// tricky to keep track of absolute positions in the underlaying readers
|
||||
// when it uses BitBuf slices, maybe only in Pos()?
|
||||
if bbf, ok := c.(*bitBufFile); ok {
|
||||
if bbf, ok := c.(*openFile); ok {
|
||||
opts.Filename = bbf.filename
|
||||
|
||||
if opts.Progress != "" {
|
||||
@ -732,7 +728,7 @@ func (i *Interp) _toBitsRange(c interface{}, a []interface{}) interface{} {
|
||||
|
||||
if !r {
|
||||
bb, _ := bv.toBuffer()
|
||||
return bufferViewFromBuffer(bb, unit)
|
||||
return newBufferRangeFromBuffer(bb, unit)
|
||||
}
|
||||
|
||||
return bv
|
||||
|
@ -16,6 +16,45 @@ def help:
|
||||
, "^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; $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
|
||||
)
|
||||
}
|
||||
)
|
||||
);
|
||||
def decode($name): decode($name; {});
|
||||
def decode: decode(options.decode_format; {});
|
||||
|
||||
|
||||
def display($opts): _display($opts);
|
||||
def display: _display({});
|
||||
def d($opts): _display($opts);
|
||||
@ -66,34 +105,7 @@ def match($regex; $flags): if _is_buffer then _bits_match($regex; $flags) else _
|
||||
def formats:
|
||||
_registry.formats;
|
||||
|
||||
# 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
|
||||
);
|
||||
|
||||
def _esc: "\u001b";
|
||||
def _ansi:
|
||||
{
|
||||
clear_line: "\(_esc)[2K",
|
||||
};
|
||||
|
||||
# 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("")
|
||||
);
|
||||
def intdiv(a; b): _intdiv(a; b);
|
||||
|
||||
# TODO: escape for safe key names
|
||||
# path ["a", 1, "b"] -> "a[1].b"
|
||||
|
@ -45,6 +45,35 @@ def _finally(f; fin):
|
||||
# TODO: figure out a saner way to force int
|
||||
def _to_int: (. % (. + 1));
|
||||
|
||||
# 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
|
||||
);
|
||||
|
||||
def _esc: "\u001b";
|
||||
def _ansi:
|
||||
{
|
||||
clear_line: "\(_esc)[2K",
|
||||
};
|
||||
|
||||
# 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("")
|
||||
);
|
||||
|
||||
def _repeat_break(f):
|
||||
try repeat(f)
|
||||
catch
|
||||
|
@ -358,7 +358,7 @@ func toBufferView(v interface{}) (BufferRange, error) {
|
||||
if err != nil {
|
||||
return BufferRange{}, err
|
||||
}
|
||||
return bufferViewFromBuffer(bb, 8), nil
|
||||
return newBufferRangeFromBuffer(bb, 8), nil
|
||||
}
|
||||
}
|
||||
|
||||
@ -546,7 +546,6 @@ func (i *Interp) Eval(ctx context.Context, c interface{}, src string, srcFilenam
|
||||
return []*gojq.Query{i.initFqQuery}, nil
|
||||
},
|
||||
load: func(name string) (*gojq.Query, error) {
|
||||
// log.Printf("name: %#+v\n", name)
|
||||
if err := ctx.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
include "internal";
|
||||
include "options";
|
||||
include "funcs";
|
||||
include "grep";
|
||||
include "options";
|
||||
include "args";
|
||||
include "repl";
|
||||
# generated decode functions per format and format helpers
|
||||
@ -24,45 +24,6 @@ def _exit_code_compile_error: 3;
|
||||
def _exit_code_input_decode_error: 4;
|
||||
def _exit_code_expr_error: 5;
|
||||
|
||||
|
||||
# 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; $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
|
||||
)
|
||||
}
|
||||
)
|
||||
);
|
||||
def decode($name): decode($name; {});
|
||||
def decode: decode(options.decode_format; {});
|
||||
|
||||
# next valid input
|
||||
def input:
|
||||
def _input($opts; f):
|
||||
|
@ -58,8 +58,8 @@ def _build_default_dynamic_options:
|
||||
( (null | stdout) as $stdout
|
||||
| {
|
||||
# TODO: intdiv 2 * 2 to get even number, nice or maybe not needed?
|
||||
display_bytes: (if $stdout.is_terminal then [intdiv(intdiv($stdout.width; 8); 2) * 2, 4] | max else 16 end),
|
||||
line_bytes: (if $stdout.is_terminal then [intdiv(intdiv($stdout.width; 8); 2) * 2, 4] | max else 16 end),
|
||||
display_bytes: (if $stdout.is_terminal then [_intdiv(_intdiv($stdout.width; 8); 2) * 2, 4] | max else 16 end),
|
||||
line_bytes: (if $stdout.is_terminal then [_intdiv(_intdiv($stdout.width; 8); 2) * 2, 4] | max else 16 end),
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -108,7 +108,7 @@ func makeDecodeValue(dv *decode.Value) interface{} {
|
||||
case []byte:
|
||||
// TODO: not sure about this
|
||||
// TODO: only synthentic value without range?
|
||||
return bufferViewFromBuffer(bitio.NewBufferFromBytes(vv, -1), 8)
|
||||
return newBufferRangeFromBuffer(bitio.NewBufferFromBytes(vv, -1), 8)
|
||||
case []interface{}:
|
||||
return decodeValue{
|
||||
JQValue: gojqextra.Array(vv),
|
||||
|
Loading…
Reference in New Issue
Block a user