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

cli: Implement --arg, --argjson and --rawfile

This commit is contained in:
Mattias Wadman 2021-09-06 23:42:05 +02:00
parent 962d84dc68
commit f5ffd32096
6 changed files with 95 additions and 24 deletions

View File

@ -139,4 +139,5 @@
"editor.formatOnSave": true,
"cSpell.allowCompoundWords": true,
"cSpell.enabled": true,
"files.trimTrailingWhitespace": true,
}

View File

@ -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
@ -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)

View File

@ -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;
@ -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)
@ -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

View File

@ -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.
@ -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",
@ -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,
@ -114,18 +104,31 @@ def _tonumber:
try tonumber catch null;
def _tostring:
if . != null then "\"\(.)\"" | fromjson end;
def _toarray:
if . != null then
( "\"\(.)\""
| try
( fromjson
| if type != "array" then null end
| 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),
@ -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),
@ -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",
@ -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
@ -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
@ -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
@ -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

View File

@ -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
@ -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)
@ -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",
@ -136,6 +141,7 @@ $ fq --options
"null_input": false,
"raw_output": false,
"raw_string": false,
"rawfile": [],
"repl": false,
"show_formats": false,
"show_help": false,

View File

@ -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",
@ -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,