1
1
mirror of https://github.com/wader/fq.git synced 2024-12-23 13:22:58 +03:00

cli: Better filenames in errors

This commit is contained in:
Mattias Wadman 2021-08-18 18:47:13 +02:00
parent 394e2b3837
commit 0dd848de6c
8 changed files with 44 additions and 31 deletions

View File

@ -38,7 +38,7 @@ func (i *Interp) makeFunctions(registry *registry.Registry) []Function {
{[]string{"tty"}, 0, 0, i.tty, nil}, {[]string{"tty"}, 0, 0, i.tty, nil},
{[]string{"readline"}, 0, 2, i.readline, nil}, {[]string{"readline"}, 0, 2, i.readline, nil},
{[]string{"eval"}, 1, 1, nil, i.eval}, {[]string{"eval"}, 1, 2, nil, i.eval},
{[]string{"stdout"}, 0, 0, nil, i.stdout}, {[]string{"stdout"}, 0, 0, nil, i.stdout},
{[]string{"stderr"}, 0, 0, nil, i.stderr}, {[]string{"stderr"}, 0, 0, nil, i.stderr},
@ -246,12 +246,20 @@ func (i *Interp) readline(c interface{}, a []interface{}) interface{} {
} }
func (i *Interp) eval(c interface{}, a []interface{}) gojq.Iter { func (i *Interp) eval(c interface{}, a []interface{}) gojq.Iter {
var err error
src, err := toString(a[0]) src, err := toString(a[0])
if err != nil { if err != nil {
return gojq.NewIter(fmt.Errorf("src: %w", err)) return gojq.NewIter(fmt.Errorf("src: %w", err))
} }
var filenameHint string
if len(a) >= 2 {
filenameHint, err = toString(a[1])
if err != nil {
return gojq.NewIter(fmt.Errorf("filename hint: %w", err))
}
}
iter, err := i.Eval(i.evalContext.ctx, ScriptMode, c, src, i.evalContext.stdout) iter, err := i.Eval(i.evalContext.ctx, ScriptMode, c, src, filenameHint, i.evalContext.stdout)
if err != nil { if err != nil {
return gojq.NewIter(err) return gojq.NewIter(err)
} }

View File

@ -54,10 +54,11 @@ type compileError struct {
func (ce compileError) Value() interface{} { func (ce compileError) Value() interface{} {
return map[string]interface{}{ return map[string]interface{}{
"error": ce.err.Error(), "error": ce.err.Error(),
"what": ce.what, "what": ce.what,
"line": ce.pos.Line, "filename": ce.filename,
"column": ce.pos.Column, "line": ce.pos.Line,
"column": ce.pos.Column,
} }
} }
func (ee compileError) Error() string { func (ee compileError) Error() string {
@ -540,7 +541,7 @@ func (i *Interp) Main(ctx context.Context, stdout io.Writer, version string) err
return nil return nil
} }
func (i *Interp) Eval(ctx context.Context, mode RunMode, c interface{}, src string, stdout Output) (gojq.Iter, error) { func (i *Interp) Eval(ctx context.Context, mode RunMode, c interface{}, src string, filename string, stdout Output) (gojq.Iter, error) {
var err error var err error
// TODO: did not work // TODO: did not work
// nq := &(*q) // nq := &(*q)
@ -549,9 +550,10 @@ func (i *Interp) Eval(ctx context.Context, mode RunMode, c interface{}, src stri
if err != nil { if err != nil {
p := queryErrorPosition(err) p := queryErrorPosition(err)
return nil, compileError{ return nil, compileError{
err: err, err: err,
what: "parse", what: "parse",
pos: p, filename: filename,
pos: p,
} }
} }
@ -692,7 +694,7 @@ func (i *Interp) Eval(ctx context.Context, mode RunMode, c interface{}, src stri
return nil, compileError{ return nil, compileError{
err: err, err: err,
what: "parse", what: "parse",
filename: filename, filename: filenamePart,
pos: p, pos: p,
} }
} }
@ -712,9 +714,10 @@ func (i *Interp) Eval(ctx context.Context, mode RunMode, c interface{}, src stri
if err != nil { if err != nil {
p := queryErrorPosition(err) p := queryErrorPosition(err)
return nil, compileError{ return nil, compileError{
err: err, err: err,
what: "compile", what: "compile",
pos: p, filename: filename,
pos: p,
} }
} }
@ -752,7 +755,7 @@ func (i *Interp) EvalFunc(ctx context.Context, mode RunMode, c interface{}, name
/// _args to mark variable as internal and hide it from completion /// _args to mark variable as internal and hide it from completion
// {input: ..., args: [...]} | .args as {args: $_args} | .input | name[($_args[0]; ...)] // {input: ..., args: [...]} | .args as {args: $_args} | .input | name[($_args[0]; ...)]
trampolineExpr := fmt.Sprintf(". as {args: $_args} | .input | %s%s", name, argExpr) trampolineExpr := fmt.Sprintf(". as {args: $_args} | .input | %s%s", name, argExpr)
iter, err := i.Eval(ctx, mode, trampolineInput, trampolineExpr, stdout) iter, err := i.Eval(ctx, mode, trampolineInput, trampolineExpr, "", stdout)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -169,9 +169,9 @@ def _eval_is_compile_error: type == "object" and .error != null and .what != nul
def _eval_compile_error_tostring: def _eval_compile_error_tostring:
"\(.filename // "src"):\(.line):\(.column): \(.error)"; "\(.filename // "src"):\(.line):\(.column): \(.error)";
def _eval($e; f; on_error; on_compile_error): def _eval($e; $filename; f; on_error; on_compile_error):
( _default_options(_build_default_options) as $_ ( _default_options(_build_default_options) as $_
| try eval($e) | f | try eval($e; $filename) | f
catch catch
if _eval_is_compile_error then on_compile_error if _eval_is_compile_error then on_compile_error
else on_error else on_error
@ -184,7 +184,7 @@ def _repl_on_error:
| (_error_str | println) | (_error_str | println)
); );
def _repl_on_compile_error: _repl_on_error; def _repl_on_compile_error: _repl_on_error;
def _repl_eval($e): _eval($e; _repl_display; _repl_on_error; _repl_on_compile_error); def _repl_eval($e): _eval($e; "repl"; _repl_display; _repl_on_error; _repl_on_compile_error);
# run read-eval-print-loop # run read-eval-print-loop
def repl($opts; iter): #:: a|(Opts) => @ def repl($opts; iter): #:: a|(Opts) => @
@ -231,8 +231,8 @@ def _cli_expr_on_compile_error:
| halt_error(_exit_code_compile_error) | halt_error(_exit_code_compile_error)
); );
# _cli_expr_eval halts on compile errors # _cli_expr_eval halts on compile errors
def _cli_expr_eval($e; f): _eval($e; f; _cli_expr_on_error; _cli_expr_on_compile_error); def _cli_expr_eval($e; $filename; f): _eval($e; $filename; f; _cli_expr_on_error; _cli_expr_on_compile_error);
def _cli_expr_eval($e): _eval($e; .; _cli_expr_on_error; _cli_expr_on_compile_error); def _cli_expr_eval($e; $filename): _eval($e; $filename; .; _cli_expr_on_error; _cli_expr_on_compile_error);
# next valid input # next valid input
def input: def input:
@ -450,10 +450,12 @@ def _main:
( { null_input: ($parsed_args.null_input == true) } ( { null_input: ($parsed_args.null_input == true) }
| if $parsed_args.file then | if $parsed_args.file then
( .expr = ($parsed_args.file | open | string) ( .expr = ($parsed_args.file | open | string)
| .expr_filename = $parsed_args.file
| .filenames = $rest | .filenames = $rest
) )
else else
( .expr = ($rest[0] // ".") ( .expr = ($rest[0] // ".")
| .expr_filename = "arg"
| .filenames = $rest[1:] | .filenames = $rest[1:]
) )
end end
@ -462,7 +464,7 @@ def _main:
elif .filenames == [] then elif .filenames == [] then
.filenames = ["-"] .filenames = ["-"]
end end
| . as {$expr, $filenames, $null_input} | . as {$expr, $expr_filename, $filenames, $null_input}
| _include_paths([ | _include_paths([
$parsed_args.include_path // empty $parsed_args.include_path // empty
]) as $_ ]) as $_
@ -472,10 +474,10 @@ def _main:
else inputs else inputs
end end
# will iterate zero or more inputs # will iterate zero or more inputs
| if $parsed_args.repl then [_cli_expr_eval($expr)] | repl({}; .[]) | if $parsed_args.repl then [_cli_expr_eval($expr; $expr_filename)] | repl({}; .[])
else else
( _cli_last_expr_error(null) as $_ ( _cli_last_expr_error(null) as $_
| _cli_expr_eval($expr; _repl_display) | _cli_expr_eval($expr; $expr_filename; _repl_display)
) )
end end
) )

View File

@ -15,11 +15,11 @@ exitcode: 123
$ fq -n invalid $ fq -n invalid
exitcode: 3 exitcode: 3
stderr: stderr:
error: src:1:0: function not defined: invalid/0 error: arg:1:0: function not defined: invalid/0
$ fq -n "(" $ fq -n "("
exitcode: 3 exitcode: 3
stderr: stderr:
error: src:1:2: unexpected token <EOF> error: arg:1:2: unexpected token <EOF>
$ fq . non-existing $ fq . non-existing
exitcode: 2 exitcode: 2
stderr: stderr:

View File

@ -5,4 +5,4 @@ $ fq -L /library -n 'include "a"; a'
$ fq -L /wrong -n 'include "a"; a' $ fq -L /wrong -n 'include "a"; a'
exitcode: 3 exitcode: 3
stderr: stderr:
error: src:1:0: open a.jq: file does not exist error: arg:1:0: open a.jq: file does not exist

View File

@ -54,11 +54,11 @@ error: /non-existing: file not found
$ fq -d raw '(' /a /b /c $ fq -d raw '(' /a /b /c
exitcode: 3 exitcode: 3
stderr: stderr:
error: src:1:2: unexpected token <EOF> error: arg:1:2: unexpected token <EOF>
$ fq -d raw bla /a /b /c $ fq -d raw bla /a /b /c
exitcode: 3 exitcode: 3
stderr: stderr:
error: src:1:0: function not defined: bla/0 error: arg:1:0: function not defined: bla/0
$ fq -d raw '1+"a"' /a /b /c $ fq -d raw '1+"a"' /a /b /c
exitcode: 5 exitcode: 5
stderr: stderr:

View File

@ -2,9 +2,9 @@ $ fq -i
null> 1+1 null> 1+1
2 2
null> ( null> (
error: src:1:2: unexpected token <EOF> error: repl:1:2: unexpected token <EOF>
null> abc null> abc
error: src:1:0: function not defined: abc/0 error: repl:1:0: function not defined: abc/0
null> 1+"a" null> 1+"a"
error: cannot add: number (1) and string ("a") error: cannot add: number (1) and string ("a")
null> 1 | repl null> 1 | repl

View File

@ -19,7 +19,7 @@ null> $a
"aa" "aa"
null> var("a"; empty) null> var("a"; empty)
null> $a null> $a
error: src:1:0: variable not defined: $a error: repl:1:0: variable not defined: $a
null> var null> var
{ {
"bb": "bb" "bb": "bb"