Compare commits

..

No commits in common. 'master' and '1.2.0' have entirely different histories.

@ -1,4 +1,3 @@
# This repository is no longer to develop.
# tson # tson
`tson` is JSON viewer and editor written in Go. `tson` is JSON viewer and editor written in Go.
This tool displays JSON as a tree and you can search and edit key or values. This tool displays JSON as a tree and you can search and edit key or values.
@ -27,37 +26,11 @@ $ curl -X POST http://gorilla/likes/regist | tson
$ tson -url http://gorilla/likes/json $ tson -url http://gorilla/likes/json
``` ```
### Use `tson` as a library in your application
You can use tson in your application as following.
```go
package main
import (
"fmt"
tson "github.com/skanehira/tson/lib"
)
func main() {
j := []byte(`{"name":"gorilla"}`)
// tson.Edit([]byte) will return []byte, error
res, err := tson.Edit(j)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(res))
}
```
## Keybinding ## Keybinding
### JSON tree ### JSON tree
| key | description | | key | description |
|--------|--------------------------------| |--------|---------------------------------------------|
| j | move down | | j | move down |
| k | move up | | k | move up |
| g | move to the top | | g | move to the top |
@ -73,15 +46,14 @@ func main() {
| a | add new node | | a | add new node |
| A | add new value | | A | add new value |
| d | clear children nodes | | d | clear children nodes |
| e | edit json with $EDITOR | | e | edit json with $EDITOR(only when use --url) |
| q | quit tson |
| Enter | edit node | | Enter | edit node |
| / or f | search nodes | | / | search nodes |
| ? | show helps | | ? | show helps |
| space | expand/collaspe children nodes | | space | expand/collaspe children nodes |
| ctrl-j | move to next parent node | | ctrl-j | move to next parent node |
| ctrk-k | move to next previous node | | ctrk-k | move to next previous node |
| ctrl-c | quit tson | | ctrl-c | exit tson |
### help ### help
| key | description | | key | description |

@ -3,13 +3,11 @@ module github.com/skanehira/tson
go 1.13 go 1.13
require ( require (
github.com/creack/pty v1.1.11 github.com/creack/pty v1.1.9
github.com/gdamore/tcell v1.3.0 github.com/gdamore/tcell v1.3.0
github.com/gofrs/uuid v3.2.0+incompatible github.com/gofrs/uuid v3.2.0+incompatible
github.com/lucasb-eyer/go-colorful v1.0.3 // indirect
github.com/mattn/go-runewidth v0.0.6 // indirect
github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/go-homedir v1.1.0
github.com/rivo/tview v0.0.0-20191129065140-82b05c9fb329 github.com/rivo/tview v0.0.0-20190324182152-8a9e26fab0ff
github.com/rivo/uniseg v0.1.0 // indirect
golang.org/x/crypto v0.0.0-20191029031824-8986dd9e96cf golang.org/x/crypto v0.0.0-20191029031824-8986dd9e96cf
golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9 // indirect
) )

@ -1,22 +1,23 @@
github.com/DATA-DOG/go-sqlmock v1.3.3 h1:CWUqKXe0s8A2z6qCgkP4Kru7wC11YoAnoupUKFDnH08=
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w=
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
github.com/gdamore/tcell v1.3.0 h1:r35w0JBADPZCVQijYebl6YMWWtHRqVEGt7kL2eBADRM= github.com/gdamore/tcell v1.3.0 h1:r35w0JBADPZCVQijYebl6YMWWtHRqVEGt7kL2eBADRM=
github.com/gdamore/tcell v1.3.0/go.mod h1:Hjvr+Ofd+gLglo7RYKxxnzCBmev3BzsS67MebKS4zMM= github.com/gdamore/tcell v1.3.0/go.mod h1:Hjvr+Ofd+gLglo7RYKxxnzCBmev3BzsS67MebKS4zMM=
github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE= github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE=
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/lucasb-eyer/go-colorful v1.0.2 h1:mCMFu6PgSozg9tDNMMK3g18oJBX7oYGrC09mS6CXfO4=
github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s= github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s=
github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac= github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y=
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.6 h1:V2iyH+aX9C5fsYCpK60U8BYIvmhqxuOL3JZcqc1NB7k=
github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/rivo/tview v0.0.0-20191129065140-82b05c9fb329 h1:MubHhHJ4mB0A5wMcc2am0/51RydztIDoumyOd0r0yBw= github.com/rivo/tview v0.0.0-20190324182152-8a9e26fab0ff h1:GrQgx8/nVONecTx4oGQ6O78pD8lVehvpQqeHGGPrCQM=
github.com/rivo/tview v0.0.0-20191129065140-82b05c9fb329/go.mod h1:/rBeY22VG2QprWnEqG57IBC8biVu3i0DOIjRLc9I8H0= github.com/rivo/tview v0.0.0-20190324182152-8a9e26fab0ff/go.mod h1:J4W+hErFfITUbyFAEXizpmkuxX7ZN56dopxHB4XQhMw=
github.com/rivo/tview v0.0.0-20191018125527-685bf6da76c2 h1:GVXSfgXOMAeLvFH7IrpY3yYM8H3YekZEFcZ14q9gQXM=
github.com/rivo/tview v0.0.0-20191018125527-685bf6da76c2/go.mod h1:/rBeY22VG2QprWnEqG57IBC8biVu3i0DOIjRLc9I8H0=
github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY= github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
@ -24,11 +25,13 @@ golang.org/x/crypto v0.0.0-20191029031824-8986dd9e96cf h1:fnPsqIDRbCSgumaMCRpoIo
golang.org/x/crypto v0.0.0-20191029031824-8986dd9e96cf/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20191029031824-8986dd9e96cf/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756 h1:9nuHUbU8dRnRRfj9KjWUVrJeoexdbeMjttk6Oh1rD10=
golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191018095205-727590c5006e h1:ZtoklVMHQy6BFRHkbG6JzK+S6rX82//Yeok1vMlizfQ=
golang.org/x/sys v0.0.0-20191018095205-727590c5006e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191018095205-727590c5006e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9 h1:ZBzSG/7F4eNKz2L3GE9o300RX0Az1Bw5HF7PDraD+qU= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=

@ -150,7 +150,6 @@ func (g *Gui) LoadJSON() {
log.Println(fmt.Sprintf("can't open file: %s", err)) log.Println(fmt.Sprintf("can't open file: %s", err))
return err return err
} }
defer file.Close()
i, err := UnMarshalJSON(file) i, err := UnMarshalJSON(file)
if err != nil { if err != nil {
@ -216,7 +215,7 @@ func (g *Gui) SaveJSONToFile(file string) error {
enc := json.NewEncoder(&buf) enc := json.NewEncoder(&buf)
enc.SetIndent("", " ") enc.SetIndent("", " ")
if err := enc.Encode(g.MakeJSON(g.Tree.OriginRoot)); err != nil { if err := enc.Encode(g.makeJSON(g.Tree.GetRoot())); err != nil {
log.Println(fmt.Sprintf("can't marshal json: %s", err)) log.Println(fmt.Sprintf("can't marshal json: %s", err))
return err return err
} }
@ -229,7 +228,7 @@ func (g *Gui) SaveJSONToFile(file string) error {
return nil return nil
} }
func (g *Gui) MakeJSON(node *tview.TreeNode) interface{} { func (g *Gui) makeJSON(node *tview.TreeNode) interface{} {
ref := node.GetReference().(Reference) ref := node.GetReference().(Reference)
children := node.GetChildren() children := node.GetChildren()
@ -237,25 +236,22 @@ func (g *Gui) MakeJSON(node *tview.TreeNode) interface{} {
case Object: case Object:
i := make(map[string]interface{}) i := make(map[string]interface{})
for _, n := range children { for _, n := range children {
i[n.GetText()] = g.MakeJSON(n) i[n.GetText()] = g.makeJSON(n)
} }
return i return i
case Array: case Array:
var i []interface{} var i []interface{}
for _, n := range children { for _, n := range children {
i = append(i, g.MakeJSON(n)) i = append(i, g.makeJSON(n))
} }
return i return i
case Key: case Key:
if len(node.GetChildren()) == 0 {
return ""
}
v := node.GetChildren()[0] v := node.GetChildren()[0]
if v.GetReference().(Reference).JSONType == Value { if v.GetReference().(Reference).JSONType == Value {
return g.parseValue(v) return g.parseValue(v)
} }
return map[string]interface{}{ return map[string]interface{}{
node.GetText(): g.MakeJSON(v), node.GetText(): g.makeJSON(v),
} }
} }
@ -343,14 +339,14 @@ func (g *Gui) NaviPanel() {
} }
func (g *Gui) EditWithEditor() { func (g *Gui) EditWithEditor() {
g.App.Suspend(func() {
f, err := ioutil.TempFile("", "tson") f, err := ioutil.TempFile("", "tson")
if err != nil { if err != nil {
log.Println(fmt.Sprintf("can't create temp file: %s", err)) log.Println(fmt.Sprintf("can't create temp file: %s", err))
g.Message(err.Error(), "main", func() {}) g.Message(err.Error(), "main", func() {})
return return
} }
f.Close()
defer os.RemoveAll(f.Name())
if err := g.SaveJSONToFile(f.Name()); err != nil { if err := g.SaveJSONToFile(f.Name()); err != nil {
log.Println(fmt.Sprintf("can't write to temp file: %s", err)) log.Println(fmt.Sprintf("can't write to temp file: %s", err))
@ -358,21 +354,15 @@ func (g *Gui) EditWithEditor() {
return return
} }
if b := g.App.Suspend(func() {
editor := os.Getenv("EDITOR") editor := os.Getenv("EDITOR")
if editor == "" { if editor == "" {
msg := fmt.Sprint("$EDITOR is empty") log.Println(fmt.Sprintf("$EDITOR is empty: %s", err))
log.Println(msg) g.Message(err.Error(), "main", func() {})
g.Message(msg, "main", func() {})
return return
} }
var args []string cmd := exec.Command(editor, f.Name())
if editor == "vim" {
args = append(args, []string{"-c", "set ft=json", f.Name()}...)
} else {
args = append(args, f.Name())
}
cmd := exec.Command(editor, args...)
// Start the command with a pty. // Start the command with a pty.
ptmx, err := pty.Start(cmd) ptmx, err := pty.Start(cmd)
@ -381,11 +371,7 @@ func (g *Gui) EditWithEditor() {
return return
} }
// Make sure to close the pty at the end. // Make sure to close the pty at the end.
defer func() { defer func() { _ = ptmx.Close() }() // Best effort.
if err := ptmx.Close(); err != nil {
log.Printf("can't close pty: %s", err)
}
}()
// Handle pty size. // Handle pty size.
ch := make(chan os.Signal, 1) ch := make(chan os.Signal, 1)
@ -406,23 +392,14 @@ func (g *Gui) EditWithEditor() {
g.Message(err.Error(), "main", func() {}) g.Message(err.Error(), "main", func() {})
return return
} }
defer func() { defer func() { _ = terminal.Restore(int(os.Stdin.Fd()), oldState) }() // Best effort.
if err := terminal.Restore(int(os.Stdin.Fd()), oldState); err != nil {
log.Printf("can't restore terminal: %s", err)
}
}()
// Copy stdin to the pty and the pty to stdout. // Copy stdin to the pty and the pty to stdout.
go io.Copy(ptmx, os.Stdin) go func() {
io.Copy(os.Stdout, ptmx) io.Copy(ptmx, os.Stdin)
}()
f, err = os.Open(f.Name()) io.Copy(os.Stdout, ptmx)
if err != nil {
log.Println(fmt.Sprintf("can't open file: %s", err))
g.Message(err.Error(), "main", func() {})
return
}
defer f.Close()
i, err := UnMarshalJSON(f) i, err := UnMarshalJSON(f)
if err != nil { if err != nil {
@ -431,9 +408,12 @@ func (g *Gui) EditWithEditor() {
return return
} }
os.RemoveAll(f.Name())
g.Tree.UpdateView(g, i) g.Tree.UpdateView(g, i)
}) }); !b {
log.Println(fmt.Sprintf("can't edit: %s", err))
g.Message(err.Error(), "main", func() {})
return
}
} }
func UnMarshalJSON(in io.Reader) (interface{}, error) { func UnMarshalJSON(in io.Reader) (interface{}, error) {

@ -38,16 +38,15 @@ var (
addNewNode = fmt.Sprintf(RedColor, "a", " add new node") addNewNode = fmt.Sprintf(RedColor, "a", " add new node")
addNewValue = fmt.Sprintf(RedColor, "A", " add new value") addNewValue = fmt.Sprintf(RedColor, "A", " add new value")
clearChildrenNodes = fmt.Sprintf(RedColor, "d", " clear children nodes") clearChildrenNodes = fmt.Sprintf(RedColor, "d", " clear children nodes")
editNodes = fmt.Sprintf(RedColor, "e", " edit json with $EDITOR") editNodes = fmt.Sprintf(RedColor, "e", " edit json with $EDITOR(only when use --url)")
quitTson = fmt.Sprintf(RedColor, "q", " quit tson")
editNodeValue = fmt.Sprintf(RedColor, "Enter", "edit current node") editNodeValue = fmt.Sprintf(RedColor, "Enter", "edit current node")
searchNodes = fmt.Sprintf(RedColor, "/ or f", " search nodes") searchNodes = fmt.Sprintf(RedColor, "/", " search nodes")
toggleExpandNodes = fmt.Sprintf(RedColor, "space", " expand/collaspe nodes") toggleExpandNodes = fmt.Sprintf(RedColor, "space", " expand/collaspe nodes")
moveNextParentNode = fmt.Sprintf(RedColor, "ctrl-j", "move to next parent node") moveNextParentNode = fmt.Sprintf(RedColor, "ctrl-j", "move to next parent node")
movePreParentNode = fmt.Sprintf(RedColor, "ctrl-k", "move to previous parent node") movePreParentNode = fmt.Sprintf(RedColor, "ctrl-k", "move to previous parent node")
treeNavi = strings.Join([]string{hideNode, collaspeAllNode, expandNode, expandAllNode, treeNavi = strings.Join([]string{hideNode, collaspeAllNode, expandNode, expandAllNode,
readFile, saveFile, addNewNode, addNewValue, clearChildrenNodes, editNodeValue, searchNodes, readFile, saveFile, addNewNode, addNewValue, clearChildrenNodes, editNodeValue, searchNodes,
moveNextParentNode, movePreParentNode, editNodes, quitTson}, "\n") moveNextParentNode, movePreParentNode, editNodes}, "\n")
) )
type Navi struct { type Navi struct {

@ -2,6 +2,7 @@ package gui
import ( import (
"fmt" "fmt"
"log"
"reflect" "reflect"
"strconv" "strconv"
"strings" "strings"
@ -9,11 +10,12 @@ import (
"github.com/gdamore/tcell" "github.com/gdamore/tcell"
"github.com/gofrs/uuid" "github.com/gofrs/uuid"
"github.com/rivo/tview" "github.com/rivo/tview"
"golang.org/x/crypto/ssh/terminal"
) )
const ( const (
moveNext int = iota + 1 moveToNext int = iota + 1
movePre moveToPre
) )
type Tree struct { type Tree struct {
@ -62,25 +64,28 @@ func (t *Tree) AddNode(node interface{}) []*tview.TreeNode {
newNode.SetReference(Reference{ID: id, JSONType: Key}) newNode.SetReference(Reference{ID: id, JSONType: Key})
} }
log.Printf("key:%v value:%v value_kind:%v", k, v, newNode.GetReference())
nodes = append(nodes, newNode) nodes = append(nodes, newNode)
} }
case []interface{}: case []interface{}:
for _, v := range node { for _, v := range node {
id := uuid.Must(uuid.NewV4()).String() id := uuid.Must(uuid.NewV4()).String()
switch v.(type) { switch n := v.(type) {
case map[string]interface{}: case map[string]interface{}:
r := reflect.ValueOf(n)
if r.Kind() != reflect.Slice {
objectNode := tview.NewTreeNode("{object}"). objectNode := tview.NewTreeNode("{object}").
SetChildren(t.AddNode(v)).SetReference(Reference{ID: id, JSONType: Object}) SetChildren(t.AddNode(v)).SetReference(Reference{ID: id, JSONType: Object})
log.Printf("value:%v value_kind:%v", v, "object")
nodes = append(nodes, objectNode) nodes = append(nodes, objectNode)
case []interface{}: }
arrayNode := tview.NewTreeNode("{array}").
SetChildren(t.AddNode(v)).SetReference(Reference{ID: id, JSONType: Array})
nodes = append(nodes, arrayNode)
default: default:
nodes = append(nodes, t.AddNode(v)...) nodes = append(nodes, t.AddNode(v)...)
} }
} }
default: default:
log.Printf("value:%v value_kind:%v", node, "value")
ref := reflect.ValueOf(node) ref := reflect.ValueOf(node)
var valueType ValueType var valueType ValueType
switch ref.Kind() { switch ref.Kind() {
@ -98,6 +103,7 @@ func (t *Tree) AddNode(node interface{}) []*tview.TreeNode {
} }
} }
log.Printf("value_type:%v", valueType)
id := uuid.Must(uuid.NewV4()).String() id := uuid.Must(uuid.NewV4()).String()
nodes = append(nodes, t.NewNodeWithLiteral(node). nodes = append(nodes, t.NewNodeWithLiteral(node).
SetReference(Reference{ID: id, JSONType: Value, ValueType: valueType})) SetReference(Reference{ID: id, JSONType: Value, ValueType: valueType}))
@ -147,7 +153,7 @@ func (t *Tree) SetKeybindings(g *Gui) {
g.LoadJSON() g.LoadJSON()
case 's': case 's':
g.SaveJSON() g.SaveJSON()
case '/', 'f': case '/':
g.Search() g.Search()
case 'a': case 'a':
g.AddNode() g.AddNode()
@ -156,19 +162,19 @@ func (t *Tree) SetKeybindings(g *Gui) {
case '?': case '?':
g.NaviPanel() g.NaviPanel()
case 'e': case 'e':
if terminal.IsTerminal(0) {
g.EditWithEditor() g.EditWithEditor()
}
case ' ': case ' ':
current := t.GetCurrentNode() current := t.GetCurrentNode()
current.SetExpanded(!current.IsExpanded()) current.SetExpanded(!current.IsExpanded())
case 'q':
g.App.Stop()
} }
switch event.Key() { switch event.Key() {
case tcell.KeyCtrlJ: case tcell.KeyCtrlJ:
t.moveNode(moveNext) t.moveParent(moveToNext)
case tcell.KeyCtrlK: case tcell.KeyCtrlK:
t.moveNode(movePre) t.moveParent(moveToPre)
} }
return event return event
@ -189,19 +195,19 @@ func (t *Tree) CollapseValues(node *tview.TreeNode) {
}) })
} }
func (t *Tree) moveNode(movement int) { func (t *Tree) moveParent(movement int) {
current := t.GetCurrentNode() current := t.GetCurrentNode()
t.GetRoot().Walk(func(node, parent *tview.TreeNode) bool { t.GetRoot().Walk(func(node, parent *tview.TreeNode) bool {
if parent != nil { if parent != nil {
children := parent.GetChildren() children := parent.GetChildren()
for i, n := range children { for i, n := range children {
if n.GetReference().(Reference).ID == current.GetReference().(Reference).ID { if n.GetReference().(Reference).ID == current.GetReference().(Reference).ID {
if movement == moveNext { if movement == moveToNext {
if i < len(children)-1 { if i < len(children)-1 {
t.SetCurrentNode(children[i+1]) t.SetCurrentNode(children[i+1])
return false return false
} }
} else if movement == movePre { } else if movement == moveToPre {
if i > 0 { if i > 0 {
t.SetCurrentNode(children[i-1]) t.SetCurrentNode(children[i-1])
return false return false
@ -229,6 +235,7 @@ func parseValueType(text string) ValueType {
return Int return Int
} }
log.Println(String.String())
return String return String
} }

@ -1,28 +0,0 @@
package lib
import (
"encoding/json"
"io/ioutil"
"log"
"github.com/skanehira/tson/gui"
)
// Edit use tson as a library
func Edit(b []byte) ([]byte, error) {
// dont output log
log.SetOutput(ioutil.Discard)
var i interface{}
if err := json.Unmarshal(b, &i); err != nil {
log.Println(err)
return nil, err
}
g := gui.New()
if err := g.Run(i); err != nil {
return nil, err
}
return json.Marshal(g.MakeJSON(g.Tree.GetRoot()))
}

@ -8,7 +8,6 @@ import (
"net/http" "net/http"
"os" "os"
"path/filepath" "path/filepath"
"syscall"
"github.com/mitchellh/go-homedir" "github.com/mitchellh/go-homedir"
"github.com/skanehira/tson/gui" "github.com/skanehira/tson/gui"
@ -44,7 +43,6 @@ func init() {
} else { } else {
log.SetOutput(ioutil.Discard) log.SetOutput(ioutil.Discard)
} }
} }
func run() int { func run() int {
@ -59,17 +57,14 @@ func run() int {
if err != nil { if err != nil {
return printError(err) return printError(err)
} }
} else { }
if !terminal.IsTerminal(0) { if !terminal.IsTerminal(0) {
var err error var err error
i, err = gui.UnMarshalJSON(os.Stdin) i, err = gui.UnMarshalJSON(os.Stdin)
if err != nil { if err != nil {
return printError(err) return printError(err)
} }
// set tview tty to stdin
os.Stdin = os.NewFile(uintptr(syscall.Stderr), "/dev/tty")
}
} }
if i == nil { if i == nil {

Loading…
Cancel
Save