forked from Archives/fx
Compare commits
No commits in common. 'master' and '22.0.8' have entirely different histories.
@ -1,66 +0,0 @@
|
||||
# Documentation
|
||||
|
||||
The **fx** can work in two modes: as a reducer or an interactive viewer.
|
||||
|
||||
To start the interactive mode pipe a JSON into **fx**:
|
||||
|
||||
```sh
|
||||
$ curl ... | fx
|
||||
```
|
||||
|
||||
Or you can pass a filename as the first parameter:
|
||||
|
||||
```sh
|
||||
$ fx data.json
|
||||
```
|
||||
|
||||
## Reducers
|
||||
|
||||
Use [JavaScript](js.md), [Python](python.md), or [Ruby](ruby.md).
|
||||
|
||||
## Streaming mode
|
||||
|
||||
The **fx** supports line-delimited JSON streaming or concatenated JSON streaming.
|
||||
|
||||
```sh
|
||||
$ echo '
|
||||
> {"message": "hello"}
|
||||
> {"message": "world!"}
|
||||
> ' | fx .message
|
||||
hello
|
||||
world!
|
||||
```
|
||||
|
||||
## Interactive mode
|
||||
|
||||
Type `?` to see the full list of available shortcuts while in the interactive mode.
|
||||
|
||||
### Search
|
||||
|
||||
Press `/` and type regexp pattern to search in the current JSON.
|
||||
Search is performed on the internal representation of the JSON without newlines.
|
||||
|
||||
Type `n` to jump to the next result, and `N` to the previous
|
||||
|
||||
### Selecting text
|
||||
|
||||
You can't just select text in fx. This is due to the fact that all mouse events are
|
||||
redirected to stdin. To be able to select again you need to instruct your terminal
|
||||
not to do it. This can be done by holding special keys while selecting:
|
||||
|
||||
| Key | Terminal |
|
||||
|------------------|---------------|
|
||||
| `Option`+`Mouse` | iTerm2, Hyper |
|
||||
| `Fn`+`Mouse` | Terminal.app |
|
||||
| `Shift`+`Mouse` | Linux |
|
||||
|
||||
|
||||
## Configs
|
||||
|
||||
Next configs available for **fx** via environment variables.
|
||||
|
||||
| Name | Values | Description |
|
||||
|----------------|-----------------------------------------------------|-------------------------------------------------------|
|
||||
| `FX_LANG` | `js` (default), `node`, `python`, `python3`, `ruby` | Reducer type. |
|
||||
| `FX_THEME` | `0` (disable colors), `1` (default), `2..9` | Color theme. |
|
||||
| `FX_SHOW_SIZE` | `true` or `false` (default) | Show size of arrays and object in collapsed previews. |
|
Binary file not shown.
Before Width: | Height: | Size: 411 KiB |
@ -1,120 +0,0 @@
|
||||
# JavaScript Reducers
|
||||
|
||||
If any additional arguments were passed, fx converts them into a function which
|
||||
takes the JSON as an argument named `x`.
|
||||
|
||||
By default, fx uses builtin JavaScript VM ([goja](https://github.com/dop251/goja)),
|
||||
but also can be used with node.
|
||||
|
||||
```sh
|
||||
export FX_LANG=js # Default
|
||||
```
|
||||
|
||||
Or for usage with node:
|
||||
|
||||
```sh
|
||||
export FX_LANG=node
|
||||
```
|
||||
|
||||
An example of anonymous function used as a reducer:
|
||||
```sh
|
||||
$ echo '{"foo": [{"bar": "value"}]}' | fx 'x => x.foo[0].bar'
|
||||
value
|
||||
```
|
||||
|
||||
The same reducer function can be simplified to:
|
||||
|
||||
```sh
|
||||
$ echo '{"foo": [{"bar": "value"}]}' | fx 'x.foo[0].bar'
|
||||
value
|
||||
```
|
||||
|
||||
Each argument treated as a reducer function.
|
||||
|
||||
```sh
|
||||
$ echo '{"foo": [{"bar": "value"}]}' | fx 'x.foo' 'x[0]' 'x.bar'
|
||||
value
|
||||
```
|
||||
|
||||
Update JSON using the spread operator:
|
||||
|
||||
```sh
|
||||
$ echo '{"name": "fx", "count": 0}' | fx '{...this, count: 1}'
|
||||
{
|
||||
"name": "fx",
|
||||
"count": 1
|
||||
}
|
||||
```
|
||||
|
||||
## Dot
|
||||
|
||||
Fx supports simple JS-like syntax for accessing data, which can be used with any `FX_LANG`.
|
||||
|
||||
```sh
|
||||
$ echo '{"foo": [{"bar": "value"}]}' | fx .foo[0].bar
|
||||
value
|
||||
```
|
||||
|
||||
## .fxrc.js
|
||||
|
||||
Create _.fxrc.js_ file in `$HOME` directory, and define some useful functions.
|
||||
|
||||
```js
|
||||
// .fxrc.js
|
||||
function upper(s) {
|
||||
return s.toUpperCase()
|
||||
}
|
||||
```
|
||||
|
||||
```sh
|
||||
$ cat data.json | fx .name upper
|
||||
ANTON
|
||||
```
|
||||
|
||||
## Node
|
||||
|
||||
```sh
|
||||
export FX_LANG=node
|
||||
```
|
||||
|
||||
Use any npm package by installing it globally. Create _.fxrc.js_ file in `$HOME`
|
||||
directory, and require any packages or define global functions. For example,
|
||||
to access all lodash methods without `_` prefix, put next line into your
|
||||
_.fxrc.js_ file:
|
||||
|
||||
```js
|
||||
Object.assign(global, require('lodash/fp'))
|
||||
```
|
||||
|
||||
And now you will be able to call all lodash methods. For example, see who's been
|
||||
committing to react recently:
|
||||
|
||||
```sh
|
||||
curl 'https://api.github.com/repos/facebook/react/commits?per_page=100' \
|
||||
| fx 'groupBy("commit.author.name")' 'mapValues(size)' toPairs 'sortBy(1)' reverse 'take(10)' fromPairs
|
||||
```
|
||||
|
||||
> To be able to require global modules make sure you have correct `NODE_PATH` env variable.
|
||||
> ```sh
|
||||
> export NODE_PATH=`npm root -g`
|
||||
> ```
|
||||
|
||||
The _.fxrc.js_ file supports both: `import` and `require`.
|
||||
|
||||
```js
|
||||
// .fxrc.js
|
||||
import 'zx/globals'
|
||||
const _ = require('lodash')
|
||||
```
|
||||
|
||||
> If you want to use _.fxrc.js_ for both `FX_LANG=js` and `FX_LANG=node`,
|
||||
> separate parts by `// nodejs:` comment:
|
||||
> ```js
|
||||
> // .fxrc.js
|
||||
> function upper(s) {
|
||||
> return s.toUpperCase()
|
||||
> }
|
||||
> // nodejs:
|
||||
> import 'zx/globals'
|
||||
> const _ = require('lodash')
|
||||
> ```
|
@ -1,27 +0,0 @@
|
||||
# Python Reducers
|
||||
|
||||
If any additional arguments was passed, **fx** converts it to a function which
|
||||
takes the JSON as an argument named `x`.
|
||||
|
||||
```sh
|
||||
export FX_LANG=python
|
||||
```
|
||||
Or
|
||||
```sh
|
||||
export FX_LANG=python3
|
||||
```
|
||||
|
||||
Example:
|
||||
|
||||
```sh
|
||||
fx data.json '[x["age"] + i for i in range(10)]'
|
||||
```
|
||||
|
||||
## Dot
|
||||
|
||||
Fx supports simple syntax for accessing data, which can be used with any `FX_LANG`.
|
||||
|
||||
```sh
|
||||
$ echo '{"foo": [{"bar": "value"}]}' | fx .foo[0].bar
|
||||
value
|
||||
```
|
@ -1,23 +0,0 @@
|
||||
# Ruby Reducers
|
||||
|
||||
If any additional arguments was passed, **fx** converts it to a function which
|
||||
takes the JSON as an argument named `x`.
|
||||
|
||||
```sh
|
||||
export FX_LANG=ruby
|
||||
```
|
||||
|
||||
Example:
|
||||
|
||||
```sh
|
||||
fx data.json 'x.to_a.map {|x| x[1]}'
|
||||
```
|
||||
|
||||
## Dot
|
||||
|
||||
Fx supports simple syntax for accessing data, which can be used with any `FX_LANG`.
|
||||
|
||||
```sh
|
||||
$ echo '{"foo": [{"bar": "value"}]}' | fx .foo[0].bar
|
||||
value
|
||||
```
|
Before Width: | Height: | Size: 659 KiB After Width: | Height: | Size: 659 KiB |
@ -0,0 +1,19 @@
|
||||
# Reducers
|
||||
|
||||
Fx takes a few arguments after the file name, and converts them to a reducer.
|
||||
|
||||
## Node
|
||||
|
||||
Access all lodash (or ramda, etc) methods by using [.fxrc](#using-fxrc) file.
|
||||
|
||||
```bash
|
||||
$ fx data.json 'groupBy("commit.committer.name")' 'mapValues(_.size)'
|
||||
```
|
||||
|
||||
## Python
|
||||
|
||||
TODO
|
||||
|
||||
## Ruby
|
||||
|
||||
TODO
|
@ -1,98 +0,0 @@
|
||||
package reducer
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
. "github.com/antonmedv/fx/pkg/json"
|
||||
. "github.com/antonmedv/fx/pkg/theme"
|
||||
"github.com/dop251/goja"
|
||||
)
|
||||
|
||||
//go:embed js.js
|
||||
var templateJs string
|
||||
|
||||
func js(args []string, fxrc string) string {
|
||||
rs := "\n"
|
||||
for i, a := range args {
|
||||
rs += " try {"
|
||||
switch {
|
||||
case flatMapRegex.MatchString(a):
|
||||
code := fold(strings.Split(a, "[]"))
|
||||
rs += fmt.Sprintf(
|
||||
`
|
||||
x = (
|
||||
%v
|
||||
)(x)
|
||||
`, code)
|
||||
|
||||
case strings.HasPrefix(a, ".["):
|
||||
rs += fmt.Sprintf(
|
||||
`
|
||||
x = function ()
|
||||
{ return this%v }
|
||||
.call(x)
|
||||
`, a[1:])
|
||||
|
||||
case strings.HasPrefix(a, "."):
|
||||
rs += fmt.Sprintf(
|
||||
`
|
||||
x = function ()
|
||||
{ return this%v }
|
||||
.call(x)
|
||||
`, a)
|
||||
|
||||
default:
|
||||
rs += fmt.Sprintf(
|
||||
`
|
||||
let f = function ()
|
||||
{ return %v }
|
||||
.call(x)
|
||||
x = typeof f === 'function' ? f(x) : f
|
||||
`, a)
|
||||
}
|
||||
// Generate a beautiful error message.
|
||||
rs += " } catch (e) {\n"
|
||||
pre, post, pointer := trace(args, i)
|
||||
rs += fmt.Sprintf(
|
||||
" throw `\\n ${%q} ${%q} ${%q}\\n %v\\n\\n${e.stack || e}`\n",
|
||||
pre, a, post, pointer,
|
||||
)
|
||||
rs += " }\n"
|
||||
}
|
||||
|
||||
return fmt.Sprintf(templateJs, fxrc, rs)
|
||||
}
|
||||
|
||||
func CreateJS(args []string, fxrc string) (*goja.Runtime, goja.Callable, error) {
|
||||
vm := goja.New()
|
||||
_, err := vm.RunString(js(args, fxrc))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
fn, ok := goja.AssertFunction(vm.Get("reduce"))
|
||||
if !ok {
|
||||
panic("Not a function")
|
||||
}
|
||||
return vm, fn, nil
|
||||
}
|
||||
|
||||
func ReduceJS(vm *goja.Runtime, reduce goja.Callable, input interface{}, theme Theme) int {
|
||||
value, err := reduce(goja.Undefined(), vm.ToValue(Stringify(input)))
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return 1
|
||||
}
|
||||
output := value.String()
|
||||
dec := json.NewDecoder(strings.NewReader(output))
|
||||
dec.UseNumber()
|
||||
object, err := Parse(dec)
|
||||
if err != nil {
|
||||
fmt.Print(output)
|
||||
return 0
|
||||
}
|
||||
Echo(object, theme)
|
||||
return 0
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
// .fxrc.js %v
|
||||
|
||||
function reduce(input) {
|
||||
let x = JSON.parse(input)
|
||||
|
||||
// Reducers %v
|
||||
if (typeof x === 'undefined') {
|
||||
return 'null'
|
||||
} else {
|
||||
return JSON.stringify(x)
|
||||
}
|
||||
}
|
@ -1,215 +0,0 @@
|
||||
package reducer
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"unicode"
|
||||
|
||||
. "github.com/antonmedv/fx/pkg/dict"
|
||||
. "github.com/antonmedv/fx/pkg/json"
|
||||
)
|
||||
|
||||
type state int
|
||||
|
||||
const (
|
||||
start state = iota
|
||||
unknown
|
||||
propOrIndex
|
||||
prop
|
||||
index
|
||||
indexEnd
|
||||
number
|
||||
doubleQuote
|
||||
doubleQuoteEscape
|
||||
singleQuote
|
||||
singleQuoteEscape
|
||||
)
|
||||
|
||||
func SplitSimplePath(args []string) ([]interface{}, bool) {
|
||||
path := make([]interface{}, 0)
|
||||
for _, arg := range args {
|
||||
s := ""
|
||||
state := start
|
||||
for _, ch := range arg {
|
||||
switch state {
|
||||
|
||||
case start:
|
||||
switch {
|
||||
case ch == 'x':
|
||||
state = unknown
|
||||
case ch == '.':
|
||||
state = propOrIndex
|
||||
default:
|
||||
return path, false
|
||||
}
|
||||
|
||||
case unknown:
|
||||
switch {
|
||||
case ch == '.':
|
||||
state = prop
|
||||
s = ""
|
||||
case ch == '[':
|
||||
state = index
|
||||
s = ""
|
||||
default:
|
||||
return path, false
|
||||
}
|
||||
|
||||
case propOrIndex:
|
||||
switch {
|
||||
case isProp(ch):
|
||||
state = prop
|
||||
s = string(ch)
|
||||
case ch == '[':
|
||||
state = index
|
||||
default:
|
||||
return path, false
|
||||
}
|
||||
|
||||
case prop:
|
||||
switch {
|
||||
case isProp(ch):
|
||||
s += string(ch)
|
||||
case ch == '.':
|
||||
state = prop
|
||||
path = append(path, s)
|
||||
s = ""
|
||||
case ch == '[':
|
||||
state = index
|
||||
path = append(path, s)
|
||||
s = ""
|
||||
default:
|
||||
return path, false
|
||||
}
|
||||
|
||||
case index:
|
||||
switch {
|
||||
case unicode.IsDigit(ch):
|
||||
state = number
|
||||
s = string(ch)
|
||||
case ch == '"':
|
||||
state = doubleQuote
|
||||
s = ""
|
||||
case ch == '\'':
|
||||
state = singleQuote
|
||||
s = ""
|
||||
default:
|
||||
return path, false
|
||||
}
|
||||
|
||||
case indexEnd:
|
||||
switch {
|
||||
case ch == ']':
|
||||
state = unknown
|
||||
default:
|
||||
return path, false
|
||||
}
|
||||
|
||||
case number:
|
||||
switch {
|
||||
case unicode.IsDigit(ch):
|
||||
s += string(ch)
|
||||
case ch == ']':
|
||||
state = unknown
|
||||
n, err := strconv.Atoi(s)
|
||||
if err != nil {
|
||||
return path, false
|
||||
}
|
||||
path = append(path, n)
|
||||
s = ""
|
||||
default:
|
||||
return path, false
|
||||
}
|
||||
|
||||
case doubleQuote:
|
||||
switch ch {
|
||||
case '"':
|
||||
state = indexEnd
|
||||
path = append(path, s)
|
||||
s = ""
|
||||
case '\\':
|
||||
state = doubleQuoteEscape
|
||||
default:
|
||||
s += string(ch)
|
||||
}
|
||||
|
||||
case doubleQuoteEscape:
|
||||
switch ch {
|
||||
case '"':
|
||||
state = doubleQuote
|
||||
s += string(ch)
|
||||
default:
|
||||
return path, false
|
||||
}
|
||||
|
||||
case singleQuote:
|
||||
switch ch {
|
||||
case '\'':
|
||||
state = indexEnd
|
||||
path = append(path, s)
|
||||
s = ""
|
||||
case '\\':
|
||||
state = singleQuoteEscape
|
||||
s += string(ch)
|
||||
default:
|
||||
s += string(ch)
|
||||
}
|
||||
|
||||
case singleQuoteEscape:
|
||||
switch ch {
|
||||
case '\'':
|
||||
state = singleQuote
|
||||
s += string(ch)
|
||||
default:
|
||||
return path, false
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(s) > 0 {
|
||||
if state == prop {
|
||||
path = append(path, s)
|
||||
} else {
|
||||
return path, false
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return path, true
|
||||
}
|
||||
|
||||
func isProp(ch rune) bool {
|
||||
return unicode.IsLetter(ch) || unicode.IsDigit(ch) || ch == '_' || ch == '$'
|
||||
}
|
||||
|
||||
func GetBySimplePath(object interface{}, path []interface{}) interface{} {
|
||||
for _, get := range path {
|
||||
switch get := get.(type) {
|
||||
case string:
|
||||
switch o := object.(type) {
|
||||
case *Dict:
|
||||
object = o.Values[get]
|
||||
case string:
|
||||
if get == "length" {
|
||||
object = Number(strconv.Itoa(len([]rune(o))))
|
||||
} else {
|
||||
object = nil
|
||||
}
|
||||
case Array:
|
||||
if get == "length" {
|
||||
object = Number(strconv.Itoa(len(o)))
|
||||
} else {
|
||||
object = nil
|
||||
}
|
||||
default:
|
||||
object = nil
|
||||
}
|
||||
case int:
|
||||
switch o := object.(type) {
|
||||
case Array:
|
||||
object = o[get]
|
||||
default:
|
||||
object = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return object
|
||||
}
|
@ -1,137 +0,0 @@
|
||||
package reducer
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func Test_splitPath(t *testing.T) {
|
||||
tests := []struct {
|
||||
args []string
|
||||
want []interface{}
|
||||
}{
|
||||
{
|
||||
args: []string{},
|
||||
want: []interface{}{},
|
||||
},
|
||||
{
|
||||
args: []string{"."},
|
||||
want: []interface{}{},
|
||||
},
|
||||
{
|
||||
args: []string{"x"},
|
||||
want: []interface{}{},
|
||||
},
|
||||
{
|
||||
args: []string{".foo"},
|
||||
want: []interface{}{"foo"},
|
||||
},
|
||||
{
|
||||
args: []string{"x.foo"},
|
||||
want: []interface{}{"foo"},
|
||||
},
|
||||
{
|
||||
args: []string{"x[42]"},
|
||||
want: []interface{}{42},
|
||||
},
|
||||
{
|
||||
args: []string{".[42]"},
|
||||
want: []interface{}{42},
|
||||
},
|
||||
{
|
||||
args: []string{".42"},
|
||||
want: []interface{}{"42"},
|
||||
},
|
||||
{
|
||||
args: []string{".физ"},
|
||||
want: []interface{}{"физ"},
|
||||
},
|
||||
{
|
||||
args: []string{".foo.bar"},
|
||||
want: []interface{}{"foo", "bar"},
|
||||
},
|
||||
{
|
||||
args: []string{".foo", ".bar"},
|
||||
want: []interface{}{"foo", "bar"},
|
||||
},
|
||||
{
|
||||
args: []string{".foo[42]"},
|
||||
want: []interface{}{"foo", 42},
|
||||
},
|
||||
{
|
||||
args: []string{".foo[42].bar"},
|
||||
want: []interface{}{"foo", 42, "bar"},
|
||||
},
|
||||
{
|
||||
args: []string{".foo[1][2]"},
|
||||
want: []interface{}{"foo", 1, 2},
|
||||
},
|
||||
{
|
||||
args: []string{".foo[\"bar\"]"},
|
||||
want: []interface{}{"foo", "bar"},
|
||||
},
|
||||
{
|
||||
args: []string{".foo[\"bar\\\"\"]"},
|
||||
want: []interface{}{"foo", "bar\""},
|
||||
},
|
||||
{
|
||||
args: []string{".foo['bar']['baz\\'']"},
|
||||
want: []interface{}{"foo", "bar", "baz\\'"},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(strings.Join(tt.args, " "), func(t *testing.T) {
|
||||
path, ok := SplitSimplePath(tt.args)
|
||||
require.Equal(t, tt.want, path)
|
||||
require.True(t, ok)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_splitPath_negative(t *testing.T) {
|
||||
tests := []struct {
|
||||
args []string
|
||||
}{
|
||||
{
|
||||
args: []string{"./"},
|
||||
},
|
||||
{
|
||||
args: []string{"x/"},
|
||||
},
|
||||
{
|
||||
args: []string{"1+1"},
|
||||
},
|
||||
{
|
||||
args: []string{"x[42"},
|
||||
},
|
||||
{
|
||||
args: []string{".i % 2"},
|
||||
},
|
||||
{
|
||||
args: []string{"x[for x]"},
|
||||
},
|
||||
{
|
||||
args: []string{"x['y'."},
|
||||
},
|
||||
{
|
||||
args: []string{"x[0?"},
|
||||
},
|
||||
{
|
||||
args: []string{"x[\"\\u"},
|
||||
},
|
||||
{
|
||||
args: []string{"x['\\n"},
|
||||
},
|
||||
{
|
||||
args: []string{"x[9999999999999999999999999999999999999]"},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(strings.Join(tt.args, " "), func(t *testing.T) {
|
||||
path, ok := SplitSimplePath(tt.args)
|
||||
require.False(t, ok, path)
|
||||
})
|
||||
}
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
package reducer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
. "github.com/antonmedv/fx/pkg/json"
|
||||
. "github.com/antonmedv/fx/pkg/theme"
|
||||
)
|
||||
|
||||
func Echo(object interface{}, theme Theme) {
|
||||
if s, ok := object.(string); ok {
|
||||
fmt.Println(s)
|
||||
} else {
|
||||
fmt.Println(PrettyPrint(object, 1, theme))
|
||||
}
|
||||
}
|
||||
|
||||
func trace(args []string, i int) (pre, post, pointer string) {
|
||||
pre = strings.Join(args[:i], " ")
|
||||
if len(pre) > 20 {
|
||||
pre = "..." + pre[len(pre)-20:]
|
||||
}
|
||||
post = strings.Join(args[i+1:], " ")
|
||||
if len(post) > 20 {
|
||||
post = post[:20] + "..."
|
||||
}
|
||||
pointer = fmt.Sprintf(
|
||||
"%v %v %v",
|
||||
strings.Repeat(" ", len(pre)),
|
||||
strings.Repeat("^", len(args[i])),
|
||||
strings.Repeat(" ", len(post)),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
var flatMapRegex = regexp.MustCompile("^(\\.\\w*)+\\[]")
|
||||
|
||||
func fold(s []string) string {
|
||||
if len(s) == 1 {
|
||||
return "x => x" + s[0]
|
||||
}
|
||||
obj := s[0]
|
||||
if obj == "." {
|
||||
obj = "x"
|
||||
} else {
|
||||
obj = "x" + obj
|
||||
}
|
||||
return fmt.Sprintf("x => Object.values(%v).flatMap(%v)", obj, fold(s[1:]))
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
. "github.com/antonmedv/fx/pkg/json"
|
||||
. "github.com/antonmedv/fx/pkg/reducer"
|
||||
. "github.com/antonmedv/fx/pkg/theme"
|
||||
"github.com/dop251/goja"
|
||||
)
|
||||
|
||||
func stream(dec *json.Decoder, object interface{}, lang string, args []string, theme Theme, fxrc string) int {
|
||||
var vm *goja.Runtime
|
||||
var fn goja.Callable
|
||||
var err error
|
||||
if lang == "js" {
|
||||
vm, fn, err = CreateJS(args, fxrc)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return 1
|
||||
}
|
||||
}
|
||||
for {
|
||||
if object != nil {
|
||||
if lang == "js" {
|
||||
ReduceJS(vm, fn, object, theme)
|
||||
} else {
|
||||
Reduce(object, lang, args, theme, fxrc)
|
||||
}
|
||||
}
|
||||
object, err = Parse(dec)
|
||||
if err == io.EOF {
|
||||
return 0
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Println("JSON Parse Error:", err.Error())
|
||||
return 1
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,3 @@
|
||||
package main
|
||||
|
||||
const version = "24.0.0"
|
||||
const version = "22.0.0"
|
||||
|
Loading…
Reference in New Issue