Skip to content

Instantly share code, notes, and snippets.

@danbst danbst/README.md
Last active Dec 5, 2018

Embed
What would you like to do?
nixq - jq but with Nix syntax

nixq - jq but with Nix syntax

Familliar syntax and all of <nixpkgs/lib> and builtins in your hands.

Now going through jq tutorial:

Identity filter

$ # jq
$ curl 'https://api.github.com/repos/stedolan/jq/commits?per_page=5' | jq '.'
$ # nixq
$ curl 'https://api.github.com/repos/stedolan/jq/commits?per_page=5' | nixq '_'

First element

$ # jq
$ ... | jq '.[0]'
$ # nixq, multiple versions
$ ... | nixq '_0'
$ ... | nixq 'elemAt _ 0'
$ ... | nixq 'head _'

Select several fields from first element, including some nested

$ # jq
$ jq '.[0] | {message: .commit.message, name: .commit.committer.name}'
$ # nixq
$ nixq 'with _0; { message = commit.message; name = commit.committer.name; }'

Same, but for all elements

$ # jq
$ jq '.[] | {message: .commit.message, name: .commit.committer.name}'
$ # nixq, unfortunately, can't do that in same fashion. But see next example

Same, but wrap result into a list, so it will be a valid JSON

$ # jq
$ jq '[.[] | {message: .commit.message, name: .commit.committer.name}]'
$ # nixq
$ nixq 'map (_: with _.commit; { message = message; name = committer.name; }) _'

Now the most complex expression from tutorial, don't know how to describe it in short

$ # jq
$ jq '[.[] | {message: .commit.message, name: .commit.committer.name, parents: [.parents[].html_url]}]'
$ # nixq
$ nixq 'map (_: { 
    message = _.commit.message;
    name = _.commit.committer.name;
    parents = map (_: _.html_url) _.parents;
  }) _'
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p jq nixUnstable
input=$(</dev/stdin)
prelude="
with import <nixpkgs/lib>;
with builtins;
let
_ = fromJSON ''$input'';
_0 = head _;
_1 = head _0;
_2 = head _1;
in $@
"
nix eval --json "($prelude)" | jq ".[0]"
@charles-dyfis-net

This comment has been minimized.

Copy link

commented Nov 19, 2018

in $@ doesn't make much sense inside a string-assignment context in shell. It effectively gets coerced to $*, but makes the reader scratch their heads trying to figure out if it's in a context where it could be expanded into multiple words first. :)

...to be a little more clear about what I mean by multiple words...

set -- "first word" "second word" "third word"
printf '%s\n' "START$@END"

runs the command:

printf '%s\n' 'STARTfirst word' 'second word' 'third wordEND'

...retaining the original element separators. In assigning a value to a single string, you can't have separators at all.


I'd strongly suggest requiring a query to be passed as exactly one string, and making any other usage an explicit error. That way there's no magic going on behind the user's back in terms of how their arguments are or aren't reassembled (which is often particularly surprising if a user is trying to run a query involving quotes, which $@ or $* will discard when used as here).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.