Skip to content

Commit

Permalink
Create a JqRepl struct to encapsualte state
Browse files Browse the repository at this point in the history
This is the main guts of our repl and provides us a place to start
adding methods and features.
  • Loading branch information
ashb committed May 26, 2016
1 parent cf7b132 commit 90aa9b7
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 54 deletions.
114 changes: 114 additions & 0 deletions jqrepl.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package jqrepl

import (
"fmt"
"io"

"github.com/ashb/jqrepl/jq"
"gopkg.in/chzyer/readline.v1"
)

type JqRepl struct {
programCounter int
promptTemplate string
reader *readline.Instance
libJq *jq.Jq
input *jq.Jv
}

func New() (*JqRepl, error) {
repl := JqRepl{
promptTemplate: "\033[0;36m%3d »\033[0m",
}
var err error
repl.reader, err = readline.New(repl.currentPrompt())
if err != nil {
return nil, err
}

repl.libJq, err = jq.New()
if err != nil {
repl.reader.Close()
return nil, err
}

return &repl, nil
}

func (repl *JqRepl) Close() {
repl.reader.Close()
repl.libJq.Close()
if repl.input != nil {
repl.input.Free()
}
}

func (repl *JqRepl) currentPrompt() string {
return fmt.Sprintf(repl.promptTemplate, repl.programCounter)
}

// JvInput returns the current input the JQ program will operate on
func (repl *JqRepl) JvInput() *jq.Jv {
return repl.input
}

func (repl *JqRepl) SetJvInput(input *jq.Jv) {
if repl.input != nil {
repl.input.Free()
}
repl.input = input
}

func (repl *JqRepl) Loop() {
for {
repl.reader.SetPrompt(repl.currentPrompt())

line, err := repl.reader.Readline()
if err == io.EOF {
break
} else if err == readline.ErrInterrupt {
// Stop the streaming of any results - if we were
continue
} else if err != nil {
panic(fmt.Errorf("%#v", err))
}

repl.programCounter++
repl.RunProgram(line)
}
}

func (repl *JqRepl) Error(err error) {
fmt.Fprintf(repl.reader.Stderr(), "\033[0;31m%s\033[0m\n", err)
}

func (repl *JqRepl) Output(o *jq.Jv) {
fmt.Fprintln(repl.reader.Stdout(), o.Dump(jq.JvPrintPretty|jq.JvPrintSpace1|jq.JvPrintColour))
}

func (repl *JqRepl) RunProgram(program string) {
chanIn, chanOut, chanErr := repl.libJq.Start(program)
inCopy := repl.JvInput().Copy()

// Run until the channels are closed
for chanErr != nil && chanOut != nil {
select {
case e, ok := <-chanErr:
if !ok {
chanErr = nil
} else {
repl.Error(e)
}
case o, ok := <-chanOut:
if !ok {
chanOut = nil
} else {
repl.Output(o)
}
case chanIn <- inCopy:
// We've sent our input, close the channel to tell Jq we're done
close(chanIn)
chanIn = nil
}
}
}
61 changes: 7 additions & 54 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,82 +3,35 @@
package main

import (
"fmt"
"io"

"github.com/ashb/jqrepl"
"github.com/ashb/jqrepl/jq"

"gopkg.in/chzyer/readline.v1"
)

func main() {
prompt := "\033[0;36m»\033[0m "
l, err := readline.New(prompt)
repl, err := jqrepl.New()

if err != nil {
// TODO: don't use panic
panic(err)
}

libjq, err := jq.New()
if err != nil {
// TODO: don't use panic
panic(err)
}
defer libjq.Close()
defer repl.Close()

input, err := jq.JvFromJSONString(`
{ "simple": 123,
"nested": {
"a": [1,2,"a"],
"b": true,
"c": null
}
},
"non_printable": "\ud83c\uddec\ud83c\udde7"
}`)
if err != nil {
// TODO: don't use panic
panic(err)
}

defer input.Free()

for {
line, err := l.Readline()
if err == io.EOF {
break
} else if err == readline.ErrInterrupt {
// Stop the streaming.
continue
} else if err != nil {
panic(fmt.Errorf("%#v", err))
}

chanIn, chanOut, chanErr := libjq.Start(line)
inCopy := input.Copy()

// Run until the channels are closed
for chanErr != nil && chanOut != nil {
select {
case e, ok := <-chanErr:
if !ok {
chanErr = nil
} else {
fmt.Printf("\033[0;31m%s\033[0m\n", e)
}
case o, ok := <-chanOut:
if !ok {
chanOut = nil
} else {
fmt.Printf("// Read from output %v %#v\n", o.Kind(), ok)
fmt.Println(o.ToGoVal())
}
case chanIn <- inCopy:
// We've sent our input, close the channel to tell Jq we're done
close(chanIn)
chanIn = nil
}
}
}
repl.SetJvInput(input)

libjq.Close()
repl.Loop()
}

0 comments on commit 90aa9b7

Please sign in to comment.