1
1
mirror of https://github.com/wader/fq.git synced 2024-11-23 00:57:15 +03:00

interp,repl: Improved eval and output interrupt

repl now rewrites query to do implicit display inside the sub eval.
This makes it possible to interrupt eval and output in a better and faster way.

Make JSON encoder fail early on errors.

Add more interrupt tests.
This commit is contained in:
Mattias Wadman 2022-03-11 16:22:23 +01:00
parent dd52e85411
commit 41551de331
6 changed files with 54 additions and 20 deletions

View File

@ -205,6 +205,10 @@ func (e *Encoder) encodeArray(vs []interface{}) {
e.writeByte('[', e.colors.Array)
e.depth += e.indent
for i, v := range vs {
if e.wErr != nil {
return
}
if i > 0 {
e.writeByte(',', e.colors.Array)
}
@ -237,6 +241,10 @@ func (e *Encoder) encodeMap(vs map[string]interface{}) {
return kvs[i].key < kvs[j].key
})
for i, kv := range kvs {
if e.wErr != nil {
return
}
if i > 0 {
e.writeByte(',', e.colors.Object)
}

View File

@ -31,6 +31,13 @@ expect "123"
send "\x03"
expect "mp3> "
# test interrupt multiple outputs implicit display
send "range(100000)\n"
expect "123"
# ctrl-c
send "\x03"
expect "mp3> "
# test interrupt big json output
send "\[range(100000)\] | d\n"
expect "123"
@ -38,6 +45,13 @@ expect "123"
send "\x03"
expect "mp3> "
# test interrupt big json output implicit display
send "\[range(100000)\]\n"
expect "123"
# ctrl-c
send "\x03"
expect "mp3> "
# test exit
# ctrl-d
send "\x04"

View File

@ -17,6 +17,13 @@ def _eval_error_function_not_defined($name; $args):
"function not defined: \($name)/\($args | length)"
);
# if catch_query . -> try (.) catch .catch_query
# if input_query . -> .input_query | .
# if ... | <.slurp.> -> .slurp({slurp: "<slurp>", slurp_args: [arg query ast], orig: orig query ast, rewrite: rewritten query})
# else if .output_query -> . | .output_query
#
# ex ... | slurp -> <slurp>({...})
# ex no slurp: . -> try (.input_query | . | .output_query) catch .catch_query
def _eval_query_rewrite($opts):
_query_fromtostring(
( . as $orig_query
@ -35,10 +42,9 @@ def _eval_query_rewrite($opts):
# try (1+1) catch vs try 1 + 1 catch
_query_try(. | _query_query; $opts.catch_query)
end
| _query_pipe(
$opts.input_query // _query_ident;
.
)
| if $opts.input_query then
_query_pipe($opts.input_query; .)
end
| if $slurp then
_query_func(
$slurp;
@ -61,6 +67,8 @@ def _eval_query_rewrite($opts):
)
]
)
elif $opts.output_query then
_query_pipe(.; $opts.output_query)
end
)
);

View File

@ -194,5 +194,6 @@ def _help($arg0; $topic):
( _repl_slurp_eval($query.rewrite) as $outputs
| "value help"
, $outputs
| display
)
end;

View File

@ -918,6 +918,8 @@ func (i *Interp) Eval(ctx context.Context, c interface{}, expr string, opts Eval
// gojq ctx cancel will not return ok=false, just cancelled error
if !ok {
runCtxCancelFn()
} else if _, ok := v.(error); ok {
runCtxCancelFn()
}
return v, ok
})

View File

@ -211,18 +211,26 @@ def _repl_on_compile_error:
end
| println
);
def _repl_eval($expr; on_error; on_compile_error; $slurps):
def _repl_display:
display(_display_default_opts);
def _repl_eval($expr; on_error; on_compile_error):
eval(
$expr;
{ slurps: $slurps,
{ slurps:
{ repl: "_repl_slurp",
help: "_help_slurp",
slurp: "_slurp"
},
# input to repl is always array of values to iterate
input_query: (_query_ident | _query_iter), # .[]
catch_query: _query_func("_repl_on_expr_error")
# each input should be evaluted separatel like with cli, so catch and just print errors
catch_query: _query_func("_repl_on_expr_error"),
# run display in sub eval so it can be interrupted
output_query: _query_func("_repl_display")
};
on_error;
on_compile_error
);
def _repl_eval($expr; on_error; on_compile_error):
_repl_eval($expr; on_error; on_compile_error; null);
# run read-eval-print-loop
# input is array of inputs to iterate
@ -242,17 +250,10 @@ def _repl($opts):
);
def _repl_loop:
try
( _display_default_opts as $default_opts
| _repl_eval(
_read_expr;
_repl_on_error;
_repl_on_compile_error;
{ repl: "_repl_slurp",
help: "_help_slurp",
slurp: "_slurp"
}
)
| display($default_opts)
_repl_eval(
_read_expr;
_repl_on_error;
_repl_on_compile_error
)
catch
if . == "interrupt" then empty