summaryrefslogtreecommitdiffstats
path: root/cmd/jp/main.go
blob: c603f685eb3de8b950c5be995cf1c81976af0e80 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"os"
	"reflect"

	"github.com/sgreben/jp/pkg/jp/primitives"
	"github.com/sgreben/jp/pkg/terminal"

	"github.com/sgreben/jp/pkg/jsonpath"
)

type configuration struct {
	Box      primitives.Box
	X        string
	Y        string
	XY       string
	PlotType enumVar
}

const plotTypeLine = "line"
const plotTypeBar = "bar"
const plotTypeScatter = "scatter"
const plotTypeHist = "hist"

var config = configuration{
	PlotType: enumVar{
		Value: plotTypeLine,
		Choices: []string{
			plotTypeLine,
			plotTypeBar,
		},
	},
}

var xPattern *jsonpath.JSONPath
var yPattern *jsonpath.JSONPath
var xyPattern *jsonpath.JSONPath

func init() {
	flag.Var(&config.PlotType, "type", fmt.Sprintf("Plot type. One of %v", config.PlotType.Choices))
	flag.StringVar(&config.X, "x", "", "x values (JSONPath expression)")
	flag.StringVar(&config.Y, "y", "", "y values (JSONPath expression)")
	flag.StringVar(&config.XY, "xy", "", "x,y value pairs (JSONPath expression). Overrides -x and -y if given.")
	flag.IntVar(&config.Box.Width, "width", 0, "Plot width (default 0 (auto))")
	flag.IntVar(&config.Box.Height, "height", 0, "Plot height (default 0 (auto))")
	flag.Parse()
	log.SetOutput(os.Stderr)

	var err error
	xPattern = jsonpath.New("x")
	err = xPattern.Parse(fmt.Sprintf("{%s}", config.X))
	if err != nil {
		log.Fatal(err)
	}
	yPattern = jsonpath.New("y")
	err = yPattern.Parse(fmt.Sprintf("{%s}", config.Y))
	if err != nil {
		log.Fatal(err)
	}
	if config.XY != "" {
		xyPattern = jsonpath.New("xy")
		err = xyPattern.Parse(fmt.Sprintf("{%s}", config.XY))
		if err != nil {
			log.Fatal(err)
		}
	}
	if config.Box.Width == 0 {
		config.Box.Width = terminal.Width()
	}
	if config.Box.Height == 0 {
		config.Box.Height = terminal.Height() - 1
	}
}

func match(in interface{}, p *jsonpath.JSONPath) [][]reflect.Value {
	out, err := p.FindResults(in)
	if err != nil {
		log.Println(err)
	}
	return out
}

func main() {
	var in interface{}
	dec := json.NewDecoder(os.Stdin)
	err := dec.Decode(&in)
	if err != nil {
		log.Println(err)
	}
	fmt.Println()
	var x, y [][]reflect.Value
	if xyPattern != nil {
		x, y = split(match(in, xyPattern))
	} else {
		x = match(in, xPattern)
		y = match(in, yPattern)
	}
	switch config.PlotType.Value {
	case plotTypeLine:
		fmt.Print(linePlot(x, y, config.Box))
	case plotTypeBar:
		fmt.Print(barPlot(x, y, config.Box))
	}

}