Skip to content

Commit

Permalink
cli: Implement --arg, --argjson and --rawfile
Browse files Browse the repository at this point in the history
  • Loading branch information
wader committed Sep 12, 2021
1 parent 962d84d commit f5ffd32
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 24 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,5 @@
"editor.formatOnSave": true,
"cSpell.allowCompoundWords": true,
"cSpell.enabled": true,
"files.trimTrailingWhitespace": true,
}
7 changes: 5 additions & 2 deletions doc/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ Tool, language and decoders for exploring binary data.
For more information see https://github.com/wader/fq

Usage: fq [OPTIONS] [--] [EXPR] [FILE...]
--compact,-c Compact output
--arg NAME VALUE Set variable $NAME to string VALUE
--argjson NAME JSON Set variable $NAME to JSON
--compact-output,-c Compact output
--decode,-d NAME Decode format (probe)
--file,-f PATH Read EXPR from file
--formats Show supported formats
--from-file,-f PATH Read EXPR from file
--help,-h Show help
--include-path,-L PATH Include search path
--join-output,-j No newline between outputs
Expand All @@ -20,6 +22,7 @@ Usage: fq [OPTIONS] [--] [EXPR] [FILE...]
--options Show all options
--raw-input,-R Read raw input strings (don't decode)
--raw-output,-r Raw string output (without quotes)
--rawfile NAME PATH Set variable $NAME to string content of file
--repl,-i Interactive REPL
--slurp,-s Read (slurp) all inputs into an array
--version,-v Show version (dev)
Expand Down
10 changes: 9 additions & 1 deletion pkg/interp/args.jq
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ def args_parse($args; $opts):
)
elif $opt.array then
_parse($new_args; $flagmap; ($r | .parsed[$optname] += [$value]))
elif $opt.pairs then
_parse($new_args; $flagmap; ($r | .parsed[$optname] += [$value]))
else
_parse($new_args; $flagmap; ($r | .parsed[$optname] = $value))
end;
Expand Down Expand Up @@ -55,6 +57,12 @@ def args_parse($args; $opts):
else
_parse_with_arg($args[2:]; $optname; $args[1]; $opt)
end
elif $opt.pairs then
if ($args | length) > 2 then
_parse_with_arg($args[3:]; $optname; [$args[1], $args[2]]; $opt)
else
error("\($arg): needs two argument")
end
else
if $assign_i then error("\($arg): takes no argument")
else _parse_without_arg($args[1:]; $optname)
Expand Down Expand Up @@ -96,7 +104,7 @@ def args_help_text($opts):
, .short
] | map(select(strings)) | join(",")
) +
( .string // .array // .object
( .string // .array // .object // .pairs
| if . then " \(.)"
else ""
end
Expand Down
92 changes: 71 additions & 21 deletions pkg/interp/interp.jq
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,13 @@ include "funcs";
include "args";
include "query";

# will include all per format specific function etc
# generated decode functions per format
include "@format/decode";
# include per format specific functions
include "@format/all";

# optional user init
include "@config/init?";


# def readline: #:: [a]| => string
# Read a line.

# def readline($prompt): #:: [a]|(string) => string
# Read a line with prompt.

# def readline($prompt; $completion): #:: [a]|(string;string) => string
# $prompt is prompt to show.
# $completion name of completion function [a](string) => [string],
# it will be called with same input as readline and a string argument being the
# current line from start to current cursor position. Should return possible completions.

# try to be same exit codes as jq
# TODO: jq seems to halt processing inputs on JSON decode error but not IO errors,
# seems strange.
Expand Down Expand Up @@ -52,6 +39,8 @@ def _build_default_options:
( (null | stdout) as $stdout
| {
addrbase: 16,
arg: [],
argjson: [],
arraytruncate: 50,
bitsformat: "snippet",
bytecolors: "0-0xff=brightwhite,0=brightblack,32-126:9-13=white",
Expand Down Expand Up @@ -87,6 +76,7 @@ def _build_default_options:
join_string: "\n",
linebytes: (if $stdout.is_terminal then [intdiv(intdiv($stdout.width; 8); 2) * 2, 4] | max else 16 end),
null_input: false,
rawfile: [],
raw_output: ($stdout.is_terminal | not),
raw_string: false,
repl: false,
Expand Down Expand Up @@ -114,18 +104,31 @@ def _tonumber:
try tonumber catch null;

def _tostring:
if . != null then "\"\(.)\"" | fromjson end;

def _toarray:
if . != null then
( fromjson
| if type != "array" then null end
( "\"\(.)\""
| try
( fromjson
| if type != "string" then error end
)
catch null
)
end;

def _toarray(f):
try
( fromjson
| if type == "array" and (all(f) | not) then null end
)
catch null;

def _is_string_pair:
type == "array" and length == 2 and all(type == "string");

def _to_options:
( {
addrbase: (.addrbase | _tonumber),
arg: (.arg | _toarray(_is_string_pair)),
argjson: (.argjson | _toarray(_is_string_pair)),
arraytruncate: (.arraytruncate | _tonumber),
bitsformat: (.bitsformat | _tostring),
bytecolors: (.bytecolors | _tostring),
Expand All @@ -138,11 +141,12 @@ def _to_options:
displaybytes: (.displaybytes | _tonumber),
expr: (.expr | _tostring),
expr_file: (.expr_file | _tostring),
filename: (.filenames | _toarray),
filename: (.filenames | _toarray(type == "string")),
include_path: (.include_path | _tostring),
join_string: (.join_string | _tostring),
linebytes: (.linebytes | _tonumber),
null_input: (.null_input | _toboolean),
rawfile: (.rawfile| _toarray(_is_string_pair)),
raw_output: (.raw_output | _toboolean),
raw_string: (.raw_string | _toboolean),
repl: (.repl | _toboolean),
Expand Down Expand Up @@ -458,6 +462,16 @@ def _main:
);
def _opts($version):
{
"arg": {
long: "--arg",
description: "Set variable $NAME to string VALUE",
pairs: "NAME VALUE"
},
"argjson": {
long: "--argjson",
description: "Set variable $NAME to JSON",
pairs: "NAME JSON"
},
"compact": {
short: "-c",
long: "--compact-output",
Expand Down Expand Up @@ -531,6 +545,11 @@ def _main:
description: "Read raw input strings (don't decode)",
bool: true
},
"rawfile": {
long: "--rawfile",
description: "Set variable $NAME to string content of file",
pairs: "NAME PATH"
},
"raw_string": {
short: "-r",
# for jq compat, is called raw string internally, "raw output" is if
Expand Down Expand Up @@ -580,6 +599,18 @@ def _main:
| _options_stack(
[ $args_opts
+ ( {
argjson: (
( $args_opts.argjson
| if . then map(
( . as $a
| .[1] |=
try fromjson
catch error("--argjson \($a[0]): \(.)")
)
)
end
)
),
expr: (
( $args_opts.expr_file
| if . then
Expand Down Expand Up @@ -612,6 +643,17 @@ def _main:
end
)
),
rawfile: (
( $args_opts.rawfile
| if . then
( map(.[1] |=
try (open | tobytes | tostring)
catch halt_error(_exit_code_args_error)
)
)
end
)
),
raw_string: (
if $args_opts.raw_string
or $args_opts.join_output
Expand Down Expand Up @@ -652,6 +694,14 @@ def _main:
_finally(
( _include_paths($opts.include_path) as $_
| _input_filenames($opts.filenames) as $_ # store inputs
| _variables(
( $opts.arg +
$opts.argjson +
$opts.rawfile
| map({key: .[0], value: .[1]})
| from_entries
)
)
| ( def _inputs:
( if $opts.null_input then null
# note jq --slurp --raw-string is special, will be just
Expand Down
6 changes: 6 additions & 0 deletions pkg/interp/testdata/args.fqtest
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ Tool, language and decoders for exploring binary data.
For more information see https://github.com/wader/fq

Usage: fq [OPTIONS] [--] [EXPR] [FILE...]
--arg NAME VALUE Set variable $NAME to string VALUE
--argjson NAME JSON Set variable $NAME to JSON
--compact-output,-c Compact output
--decode,-d NAME Decode format (probe)
--formats Show supported formats
Expand All @@ -22,6 +24,7 @@ Usage: fq [OPTIONS] [--] [EXPR] [FILE...]
--options Show all options
--raw-input,-R Read raw input strings (don't decode)
--raw-output,-r Raw string output (without quotes)
--rawfile NAME PATH Set variable $NAME to string content of file
--repl,-i Interactive REPL
--slurp,-s Read (slurp) all inputs into an array
--version,-v Show version (dev)
Expand Down Expand Up @@ -114,6 +117,8 @@ xing Xing header
$ fq --options
{
"addrbase": 16,
"arg": [],
"argjson": [],
"arraytruncate": 50,
"bitsformat": "snippet",
"bytecolors": "0-0xff=brightwhite,0=brightblack,32-126:9-13=white",
Expand All @@ -136,6 +141,7 @@ $ fq --options
"null_input": false,
"raw_output": false,
"raw_string": false,
"rawfile": [],
"repl": false,
"show_formats": false,
"show_help": false,
Expand Down
3 changes: 3 additions & 0 deletions pkg/interp/testdata/options.fqtest
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
$ fq -n options
{
"addrbase": 16,
"arg": [],
"argjson": [],
"arraytruncate": 50,
"bitsformat": "snippet",
"bytecolors": "0-0xff=brightwhite,0=brightblack,32-126:9-13=white",
Expand All @@ -23,6 +25,7 @@ $ fq -n options
"null_input": true,
"raw_output": false,
"raw_string": false,
"rawfile": [],
"repl": false,
"show_formats": false,
"show_help": false,
Expand Down

0 comments on commit f5ffd32

Please sign in to comment.