2018-12-02 15:13:31 +00:00
# Documentation
`fx` can work in two modes: cli and interactive. To start interactive mode pipe into `fx` any JSON:
2018-12-13 05:43:12 +00:00
```bash
2018-12-02 15:13:31 +00:00
$ curl ... | fx
```
Or you can pass file argument as first parameter:
2018-12-13 05:43:12 +00:00
```bash
2018-12-02 15:13:31 +00:00
$ fx my.json
```
If any argument was passed, `fx` will apply it and prints to stdout.
## Anonymous function
Use an anonymous function as reducer which gets JSON and processes it:
2018-12-13 05:43:12 +00:00
```bash
2018-12-02 15:13:31 +00:00
$ echo '{"foo": [{"bar": "value"}]}' | fx 'x => x.foo[0].bar'
value
```
## Binding
If you don't pass anonymous function `param => ...` , code will be automatically transformed into anonymous function.
And you can get access to JSON by `this` keyword:
2018-12-13 05:43:12 +00:00
```bash
2018-12-02 15:13:31 +00:00
$ echo '{"foo": [{"bar": "value"}]}' | fx 'this.foo[0].bar'
value
```
## Dot
It is possible to omit `this` keyword:
2018-12-13 05:43:12 +00:00
```bash
2018-12-02 15:13:31 +00:00
$ echo '{"foo": [{"bar": "value"}]}' | fx .foo[0].bar
value
```
If single dot is passed, JSON will be processed without modification:
2018-12-13 05:43:12 +00:00
```bash
2018-12-02 15:13:31 +00:00
$ echo '{"foo": "bar"}' | fx .
{
"foo": "bar"
}
```
## Chain
You can pass any number of anonymous functions for reducing JSON:
2018-12-13 05:43:12 +00:00
```bash
2018-12-02 15:13:31 +00:00
$ echo '{"foo": [{"bar": "value"}]}' | fx 'x => x.foo' 'this[0]' 'this.bar'
value
```
## Generator
If passed code contains `yield` keyword, [generator expression ](https://github.com/sebmarkbage/ecmascript-generator-expression )
will be used:
2018-12-13 05:43:12 +00:00
```bash
2018-12-02 15:13:31 +00:00
$ curl ... | fx 'for (let user of this) if (user.login.startsWith("a")) yield user'
```
Access to JSON through `this` keyword:
2018-12-13 05:43:12 +00:00
```bash
2018-12-02 15:13:31 +00:00
$ echo '["a", "b"]' | fx 'yield* this'
[
"a",
"b"
]
```
2018-12-13 05:43:12 +00:00
```bash
2018-12-02 15:13:31 +00:00
$ echo '["a", "b"]' | fx 'yield* this; yield "c";'
[
"a",
"b",
"c"
]
```
## Update
You can update existing JSON using spread operator:
2018-12-13 05:43:12 +00:00
```bash
2018-12-02 15:13:31 +00:00
$ echo '{"count": 0}' | fx '{...this, count: 1}'
{
"count": 1
}
```
## Using packages
Use any npm package by installing it globally:
2018-12-13 05:43:12 +00:00
```bash
2018-12-02 15:13:31 +00:00
$ npm install -g lodash
$ cat package.json | fx 'require("lodash").keys(this.dependencies)'
```
## Using .fxrc
Create _.fxrc_ file in `$HOME` directory, and require any packages or define global functions.
For example, access all lodash methods without `_` prefix. Put in your `.fxrc` file:
```js
2018-12-12 03:40:13 +00:00
Object.assign(global, require('lodash/fp'))
2018-12-02 15:13:31 +00:00
```
And now you will be able to call all lodash methods. For example, see who's been committing to react recently:
2018-12-13 05:43:12 +00:00
```bash
2018-12-02 15:13:31 +00:00
curl 'https://api.github.com/repos/facebook/react/commits?per_page=100' \
2018-12-12 03:40:13 +00:00
| fx 'groupBy("commit.author.name")' 'mapValues(size)' toPairs 'sortBy(1)' reverse 'take(10)' fromPairs
2018-12-02 15:13:31 +00:00
```
> To be able require global modules make sure you have correct `NODE_PATH` env variable.
> ```bash
2019-02-19 13:51:14 +00:00
> export NODE_PATH=`npm root -g`
2018-12-02 15:13:31 +00:00
> ```
2018-12-26 07:34:24 +00:00
## Edit in place
Add next code to your _.fxrc_ file:
```js
2019-01-07 17:28:50 +00:00
const fs = require('fs')
2018-12-26 07:34:24 +00:00
global.save = json => {
fs.writeFileSync(process.argv[2], JSON.stringify(json, null, 2))
return json
}
```
Usage:
```bash
fx data.json '{...this, count: this.count+1}' save .count
```
2018-12-02 15:13:31 +00:00
## Formatting
If you need something different then JSON (for example arguments for xargs) do not return anything from reducer.
`undefined` value is printed into stderr by default.
2018-12-13 05:43:12 +00:00
```bash
2018-12-02 15:13:31 +00:00
echo '[]' | fx 'void 0'
undefined
```
2018-12-13 05:43:12 +00:00
```bash
2018-12-02 15:13:31 +00:00
echo '[1,2,3]' | fx 'this.forEach(x => console.log(x))' 2>/dev/null | xargs echo
1 2 3
```
## Other examples
Convert object to array:
2018-12-13 05:43:12 +00:00
```bash
2018-12-02 15:13:31 +00:00
$ cat package.json | fx 'Object.keys(this.dependencies)'
[
"@medv/prettyjson"
]
```
By the way, fx has shortcut for `Object.keys(this)` . Previous example can be rewritten as:
2018-12-13 05:43:12 +00:00
```bash
2018-12-02 15:13:31 +00:00
$ cat package.json | fx this.dependencies ?
```
2019-02-24 18:57:47 +00:00
## Streaming mode
`fx` supports line-delimited JSON and concatenated JSON streaming.
```bash
$ kubectl logs ... | fx .message
```
Sometimes it is necessary to omit some messages in JSON stream, or select only specified log messages.
For this purpose, `fx` has special helper `select` , pass function into it to select only some JSON messages.
```bash
$ kubectl logs ... | fx 'select(x => x.message.length > 40)' .message
```
2018-12-02 15:13:31 +00:00
## Interactive mode
Click on fields to expand or collapse JSON tree, use mouse wheel to scroll view.
Next commands available in interactive mode:
| Key | Command |
|-------------------------------|-------------------------|
| `q` or `Esc` or `Ctrl` +`c` | Exit |
| `e` /`E` | Expand/Collapse all |
| `g` /`G` | Goto top/bottom |
2018-12-04 19:34:54 +00:00
| `up` /`down` or `k/j` | Move cursor up/down |
| `left` /`right` or `h/l` | Expand/Collapse |
2018-12-03 05:14:41 +00:00
| `.` | Edit filter |
2018-12-15 07:14:44 +00:00
| `/` | Search |
| `n` | Goto next found pattern |
2018-12-03 05:14:41 +00:00
These commands are available when editing the filter:
| Key | Command |
|-------------------------------|-------------------------|
| `Enter` | Apply filter |
| `Ctrl` +`u` | Clear filter |
| `Ctrl` +`w` | Delete last part |
| `up` /`down` | Select autocomplete |
2018-12-02 15:13:31 +00:00
2018-12-15 07:14:44 +00:00
### Search
Press `/` and type regexp pattern to search in current JSON. Search work with currently applied filter.
Examples of pattern and corresponding regexp:
| Pattern | RegExp |
|------------|-------------|
| `/apple` | `/apple/ig` |
| `/apple/` | `/apple/` |
| `/apple/u` | `/apple/u` |
| `/\w+` | `/\w+/ig` |
2018-12-02 15:13:31 +00:00
### Selecting text
You may found what you can't just select text in fx. This is due the fact that all mouse events redirected to stdin. To be able select again you need instruct your terminal not to do it. This can be done by holding special keys while selecting:
2018-12-03 05:14:41 +00:00
| Key | Terminal |
2018-12-02 15:13:31 +00:00
|------------------|---------------|
| `Option` +`Mouse` | iTerm2, Hyper |
| `Fn` +`Mouse` | Terminal.app |
| `Shift` +`Mouse` | Linux |