Some work, I guess
This commit is contained in:
parent
dce6e6c368
commit
22ffda8d13
@ -108,12 +108,12 @@ func (bd *BoltDB) GetPairFromPath(path []string) (*BoltPair, error) {
|
|||||||
return p, err
|
return p, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bd *BoltDB) GetVisibleItemCount(path []string) (int, error) {
|
func (bd *BoltDB) GetVisibleItemCount(path []string, search string) (int, error) {
|
||||||
vis := 0
|
vis := 0
|
||||||
var retErr error
|
var retErr error
|
||||||
if len(path) == 0 {
|
if len(path) == 0 {
|
||||||
for i := range bd.buckets {
|
for i := range bd.buckets {
|
||||||
n, err := bd.GetVisibleItemCount(bd.buckets[i].GetPath())
|
n, err := bd.GetVisibleItemCount(bd.buckets[i].GetPath(), search)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@ -126,13 +126,13 @@ func (bd *BoltDB) GetVisibleItemCount(path []string) (int, error) {
|
|||||||
}
|
}
|
||||||
// 1 for the bucket
|
// 1 for the bucket
|
||||||
vis++
|
vis++
|
||||||
if b.expanded {
|
if b.expanded || search != "" {
|
||||||
// This bucket is expanded, add up it's children
|
// This bucket is expanded (or we're searching), add up it's children
|
||||||
// * 1 for each pair
|
// * 1 for each pair
|
||||||
vis += len(b.pairs)
|
vis += len(b.pairs)
|
||||||
// * recurse for buckets
|
// * recurse for buckets
|
||||||
for i := range b.buckets {
|
for i := range b.buckets {
|
||||||
n, err := bd.GetVisibleItemCount(b.buckets[i].GetPath())
|
n, err := bd.GetVisibleItemCount(b.buckets[i].GetPath(), search)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@ -143,12 +143,12 @@ func (bd *BoltDB) GetVisibleItemCount(path []string) (int, error) {
|
|||||||
return vis, retErr
|
return vis, retErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bd *BoltDB) BuildVisiblePathSlice(filter string) ([][]string, error) {
|
func (bd *BoltDB) BuildVisiblePathSlice(search string) ([][]string, error) {
|
||||||
var retSlice [][]string
|
var retSlice [][]string
|
||||||
var retErr error
|
var retErr error
|
||||||
// The root path, recurse for root buckets
|
// The root path, recurse for root buckets
|
||||||
for i := range bd.buckets {
|
for i := range bd.buckets {
|
||||||
bktS, bktErr := bd.buckets[i].BuildVisiblePathSlice([]string{}, filter)
|
bktS, bktErr := bd.buckets[i].BuildVisiblePathSlice([]string{}, search)
|
||||||
if bktErr == nil {
|
if bktErr == nil {
|
||||||
retSlice = append(retSlice, bktS...)
|
retSlice = append(retSlice, bktS...)
|
||||||
} else {
|
} else {
|
||||||
@ -159,8 +159,8 @@ func (bd *BoltDB) BuildVisiblePathSlice(filter string) ([][]string, error) {
|
|||||||
return retSlice, retErr
|
return retSlice, retErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bd *BoltDB) IsVisiblePath(path []string, filter string) bool {
|
func (bd *BoltDB) IsVisiblePath(path []string, search string) bool {
|
||||||
visPaths, err := bd.BuildVisiblePathSlice(filter)
|
visPaths, err := bd.BuildVisiblePathSlice(search)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -181,8 +181,8 @@ func (bd *BoltDB) IsVisiblePath(path []string, filter string) bool {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
func (bd *BoltDB) GetPrevVisiblePath(path []string, filter string) []string {
|
func (bd *BoltDB) GetPrevVisiblePath(path []string, search string) []string {
|
||||||
visPaths, err := bd.BuildVisiblePathSlice(filter)
|
visPaths, err := bd.BuildVisiblePathSlice(search)
|
||||||
if path == nil {
|
if path == nil {
|
||||||
if len(visPaths) > 0 {
|
if len(visPaths) > 0 {
|
||||||
return visPaths[len(visPaths)-1]
|
return visPaths[len(visPaths)-1]
|
||||||
@ -205,8 +205,8 @@ func (bd *BoltDB) GetPrevVisiblePath(path []string, filter string) []string {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (bd *BoltDB) GetNextVisiblePath(path []string, filter string) []string {
|
func (bd *BoltDB) GetNextVisiblePath(path []string, search string) []string {
|
||||||
visPaths, err := bd.BuildVisiblePathSlice(filter)
|
visPaths, err := bd.BuildVisiblePathSlice(search)
|
||||||
if path == nil {
|
if path == nil {
|
||||||
if len(visPaths) > 0 {
|
if len(visPaths) > 0 {
|
||||||
return visPaths[0]
|
return visPaths[0]
|
||||||
|
@ -38,14 +38,16 @@ func (b *BoltBucket) GetPath() []string {
|
|||||||
buildVisiblePathSlice builds a slice of string slices containing all visible paths in this bucket
|
buildVisiblePathSlice builds a slice of string slices containing all visible paths in this bucket
|
||||||
The passed prefix is the path leading to the current bucket
|
The passed prefix is the path leading to the current bucket
|
||||||
*/
|
*/
|
||||||
func (b *BoltBucket) BuildVisiblePathSlice(prefix []string, filter string) ([][]string, error) {
|
func (b *BoltBucket) BuildVisiblePathSlice(prefix []string, search string) ([][]string, error) {
|
||||||
var retSlice [][]string
|
var retSlice [][]string
|
||||||
var retErr error
|
var retErr error
|
||||||
retSlice = append(retSlice, append(prefix, b.name))
|
if search == "" || strings.Contains(b.name, search) {
|
||||||
if b.expanded {
|
retSlice = append(retSlice, append(prefix, b.name))
|
||||||
|
}
|
||||||
|
if b.expanded || search != "" {
|
||||||
// Add subbuckets
|
// Add subbuckets
|
||||||
for i := range b.buckets {
|
for i := range b.buckets {
|
||||||
bktS, bktErr := b.buckets[i].BuildVisiblePathSlice(append(prefix, b.name), filter)
|
bktS, bktErr := b.buckets[i].BuildVisiblePathSlice(append(prefix, b.name), search)
|
||||||
if bktErr != nil {
|
if bktErr != nil {
|
||||||
return retSlice, bktErr
|
return retSlice, bktErr
|
||||||
}
|
}
|
||||||
@ -53,7 +55,7 @@ func (b *BoltBucket) BuildVisiblePathSlice(prefix []string, filter string) ([][]
|
|||||||
}
|
}
|
||||||
// Add pairs
|
// Add pairs
|
||||||
for i := range b.pairs {
|
for i := range b.pairs {
|
||||||
if filter != "" && !strings.Contains(b.pairs[i].key, filter) {
|
if search != "" && !strings.Contains(b.pairs[i].key, search) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
retSlice = append(retSlice, append(append(prefix, b.name), b.pairs[i].key))
|
retSlice = append(retSlice, append(append(prefix, b.name), b.pairs[i].key))
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"git.bullercodeworks.com/brian/boltbrowser/models"
|
"git.bullercodeworks.com/brian/boltbrowser/models"
|
||||||
"git.bullercodeworks.com/brian/boltbrowser/util"
|
"git.bullercodeworks.com/brian/boltbrowser/util"
|
||||||
"git.bullercodeworks.com/brian/wandle"
|
"git.bullercodeworks.com/brian/wandle"
|
||||||
|
"git.bullercodeworks.com/brian/widdles"
|
||||||
"github.com/nsf/termbox-go"
|
"github.com/nsf/termbox-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -21,8 +22,7 @@ type BoltTreePane struct {
|
|||||||
pathBuffer [][]string
|
pathBuffer [][]string
|
||||||
currentPath []string
|
currentPath []string
|
||||||
currentPathIdx int
|
currentPathIdx int
|
||||||
filter string
|
search *widdles.Field
|
||||||
filterMode bool
|
|
||||||
|
|
||||||
insertPairCmd func(*models.BoltBucket) wandle.Cmd
|
insertPairCmd func(*models.BoltBucket) wandle.Cmd
|
||||||
insertBucketCmd func(*models.BoltBucket) wandle.Cmd
|
insertBucketCmd func(*models.BoltBucket) wandle.Cmd
|
||||||
@ -46,6 +46,7 @@ func NewBoltTreePane(x, y, w, h int) *BoltTreePane {
|
|||||||
return &BoltTreePane{
|
return &BoltTreePane{
|
||||||
x: x, y: y,
|
x: x, y: y,
|
||||||
width: w, height: h,
|
width: w, height: h,
|
||||||
|
search: widdles.NewField("Search", "", x, y+h),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,16 +54,18 @@ func (w *BoltTreePane) Init() wandle.Cmd {
|
|||||||
if w.db != nil {
|
if w.db != nil {
|
||||||
w.refreshDBAndBuffer()
|
w.refreshDBAndBuffer()
|
||||||
}
|
}
|
||||||
|
w.search.SetWidth(w.width)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (w *BoltTreePane) SetDetailPane(pane *BoltDetailPane) { w.detailPane = pane }
|
func (w *BoltTreePane) SetDetailPane(pane *BoltDetailPane) { w.detailPane = pane }
|
||||||
func (w *BoltTreePane) Measure() {}
|
func (w *BoltTreePane) Measure() {
|
||||||
|
}
|
||||||
func (w *BoltTreePane) Update(msg wandle.Msg) wandle.Cmd {
|
func (w *BoltTreePane) Update(msg wandle.Msg) wandle.Cmd {
|
||||||
if w.db == nil {
|
if w.db == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if len(w.currentPath) == 0 {
|
if len(w.currentPath) == 0 {
|
||||||
w.currentPath = w.db.GetNextVisiblePath(nil, w.filter)
|
w.currentPath = w.db.GetNextVisiblePath(nil, w.search.GetValue())
|
||||||
}
|
}
|
||||||
switch msg := msg.(type) {
|
switch msg := msg.(type) {
|
||||||
case BrowseMsg:
|
case BrowseMsg:
|
||||||
@ -88,48 +91,65 @@ func (w *BoltTreePane) Update(msg wandle.Msg) wandle.Cmd {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (w *BoltTreePane) handleTermboxEvent(msg termbox.Event) wandle.Cmd {
|
func (w *BoltTreePane) handleTermboxEvent(msg termbox.Event) wandle.Cmd {
|
||||||
switch msg.Type {
|
if w.search.IsActive() {
|
||||||
case termbox.EventKey:
|
if msg.Type == termbox.EventKey {
|
||||||
if msg.Ch == 'g' {
|
if msg.Key == termbox.KeyEnter {
|
||||||
return w.jumpToStart
|
return func() wandle.Msg {
|
||||||
} else if msg.Ch == 'G' {
|
w.search.SetActive(false)
|
||||||
return w.jumpToEnd
|
return nil
|
||||||
} else if msg.Key == termbox.KeyCtrlF {
|
}
|
||||||
return w.pageDown
|
} else {
|
||||||
} else if msg.Key == termbox.KeyCtrlB {
|
w.setStatus(w.search.Message, time.Second)
|
||||||
return w.pageUp
|
return w.search.Update(msg)
|
||||||
} else if msg.Ch == 'j' || msg.Key == termbox.KeyArrowDown {
|
}
|
||||||
return w.moveCursorDown
|
}
|
||||||
} else if msg.Ch == 'k' || msg.Key == termbox.KeyArrowUp {
|
} else {
|
||||||
return w.moveCursorUp
|
switch msg.Type {
|
||||||
} else if msg.Key == termbox.KeyCtrlR {
|
case termbox.EventKey:
|
||||||
return w.refreshDBAndBuffer
|
if msg.Ch == 'g' {
|
||||||
} else if msg.Ch == 'p' {
|
return w.jumpToStart
|
||||||
return w.insertPairAtCurrent
|
} else if msg.Ch == 'G' {
|
||||||
} else if msg.Ch == 'P' {
|
return w.jumpToEnd
|
||||||
return w.insertPairAtParent
|
} else if msg.Key == termbox.KeyCtrlF {
|
||||||
} else if msg.Ch == 'b' {
|
return w.pageDown
|
||||||
return w.insertBucketAtCurrent
|
} else if msg.Key == termbox.KeyCtrlB {
|
||||||
} else if msg.Ch == 'B' {
|
return w.pageUp
|
||||||
return w.insertBucketAtParent
|
} else if msg.Ch == 'j' || msg.Key == termbox.KeyArrowDown {
|
||||||
} else if msg.Ch == 'e' {
|
return w.moveCursorDown
|
||||||
return w.editPairValue
|
} else if msg.Ch == 'k' || msg.Key == termbox.KeyArrowUp {
|
||||||
} else if msg.Ch == 'r' {
|
return w.moveCursorUp
|
||||||
return w.renameBucketOrPair
|
} else if msg.Key == termbox.KeyCtrlR {
|
||||||
} else if msg.Key == termbox.KeyEnter {
|
return w.refreshDBAndBuffer
|
||||||
return w.handleEnterPressed
|
} else if msg.Ch == 'p' {
|
||||||
} else if msg.Ch == 'l' || msg.Key == termbox.KeyArrowRight {
|
return w.insertPairAtCurrent
|
||||||
return w.handleRightPressed
|
} else if msg.Ch == 'P' {
|
||||||
} else if msg.Ch == 'h' || msg.Key == termbox.KeyArrowLeft {
|
return w.insertPairAtParent
|
||||||
return w.handleLeftPressed
|
} else if msg.Ch == 'b' {
|
||||||
} else if msg.Ch == 'D' {
|
return w.insertBucketAtCurrent
|
||||||
return w.handleDelete
|
} else if msg.Ch == 'B' {
|
||||||
} else if msg.Ch == 'x' {
|
return w.insertBucketAtParent
|
||||||
// TODO: Export Value
|
} else if msg.Ch == 'e' {
|
||||||
} else if msg.Ch == 'X' {
|
return w.editPairValue
|
||||||
// TODO: Export Key/Value (or Bucket) as JSON
|
} else if msg.Ch == 'r' {
|
||||||
} else if msg.Ch == '/' {
|
return w.renameBucketOrPair
|
||||||
// TODO: Start Filtering
|
} else if msg.Key == termbox.KeyEnter {
|
||||||
|
return w.handleEnterPressed
|
||||||
|
} else if msg.Ch == 'l' || msg.Key == termbox.KeyArrowRight {
|
||||||
|
return w.handleRightPressed
|
||||||
|
} else if msg.Ch == 'h' || msg.Key == termbox.KeyArrowLeft {
|
||||||
|
return w.handleLeftPressed
|
||||||
|
} else if msg.Ch == 'D' {
|
||||||
|
return w.handleDelete
|
||||||
|
} else if msg.Ch == 'x' {
|
||||||
|
// TODO: Export Value
|
||||||
|
} else if msg.Ch == 'X' {
|
||||||
|
// TODO: Export Key/Value (or Bucket) as JSON
|
||||||
|
} else if msg.Ch == '/' {
|
||||||
|
return func() wandle.Msg {
|
||||||
|
w.search.SetActive(true)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -145,6 +165,9 @@ func (w *BoltTreePane) View(style wandle.Style) {
|
|||||||
wandle.Print(midX, midY, style, txt)
|
wandle.Print(midX, midY, style, txt)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if w.search.IsActive() || w.search.GetValue() != "" {
|
||||||
|
w.search.View(style)
|
||||||
|
}
|
||||||
// Find the cursor in the pane
|
// Find the cursor in the pane
|
||||||
for k, v := range w.pathBuffer {
|
for k, v := range w.pathBuffer {
|
||||||
if comparePaths(w.currentPath, v) {
|
if comparePaths(w.currentPath, v) {
|
||||||
@ -230,9 +253,9 @@ func (w *BoltTreePane) RefreshBuffer() {
|
|||||||
for i := range buckets {
|
for i := range buckets {
|
||||||
w.buffer = append(w.buffer, buckets[i].Lines()...)
|
w.buffer = append(w.buffer, buckets[i].Lines()...)
|
||||||
}
|
}
|
||||||
w.pathBuffer, _ = w.db.BuildVisiblePathSlice(w.filter)
|
w.pathBuffer, _ = w.db.BuildVisiblePathSlice(w.search.GetValue())
|
||||||
if len(w.currentPath) == 0 {
|
if len(w.currentPath) == 0 {
|
||||||
w.currentPath = w.db.GetNextVisiblePath(nil, w.filter)
|
w.currentPath = w.db.GetNextVisiblePath(nil, w.search.GetValue())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,7 +283,7 @@ func (w *BoltTreePane) jumpCursorDown(distance int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if isCurPath {
|
if isCurPath {
|
||||||
w.currentPath = w.db.GetNextVisiblePath(nil, w.filter)
|
w.currentPath = w.db.GetNextVisiblePath(nil, w.search.GetValue())
|
||||||
}
|
}
|
||||||
w.UpdateDetailPane()
|
w.UpdateDetailPane()
|
||||||
}
|
}
|
||||||
@ -289,17 +312,17 @@ func (w *BoltTreePane) jumpCursorUp(distance int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if isCurPath {
|
if isCurPath {
|
||||||
w.currentPath = w.db.GetNextVisiblePath(nil, w.filter)
|
w.currentPath = w.db.GetNextVisiblePath(nil, w.search.GetValue())
|
||||||
}
|
}
|
||||||
w.UpdateDetailPane()
|
w.UpdateDetailPane()
|
||||||
}
|
}
|
||||||
func (w *BoltTreePane) jumpToStart() wandle.Msg {
|
func (w *BoltTreePane) jumpToStart() wandle.Msg {
|
||||||
w.currentPath = w.db.GetNextVisiblePath(nil, w.filter)
|
w.currentPath = w.db.GetNextVisiblePath(nil, w.search.GetValue())
|
||||||
w.UpdateDetailPane()
|
w.UpdateDetailPane()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (w *BoltTreePane) jumpToEnd() wandle.Msg {
|
func (w *BoltTreePane) jumpToEnd() wandle.Msg {
|
||||||
w.currentPath = w.db.GetPrevVisiblePath(nil, w.filter)
|
w.currentPath = w.db.GetPrevVisiblePath(nil, w.search.GetValue())
|
||||||
w.UpdateDetailPane()
|
w.UpdateDetailPane()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -314,7 +337,7 @@ func (w *BoltTreePane) pageDown() wandle.Msg {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (w *BoltTreePane) moveCursorUp() wandle.Msg {
|
func (w *BoltTreePane) moveCursorUp() wandle.Msg {
|
||||||
p := w.db.GetPrevVisiblePath(w.currentPath, w.filter)
|
p := w.db.GetPrevVisiblePath(w.currentPath, w.search.GetValue())
|
||||||
if p != nil {
|
if p != nil {
|
||||||
w.currentPath = p
|
w.currentPath = p
|
||||||
}
|
}
|
||||||
@ -322,7 +345,7 @@ func (w *BoltTreePane) moveCursorUp() wandle.Msg {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (w *BoltTreePane) moveCursorDown() wandle.Msg {
|
func (w *BoltTreePane) moveCursorDown() wandle.Msg {
|
||||||
p := w.db.GetNextVisiblePath(w.currentPath, w.filter)
|
p := w.db.GetNextVisiblePath(w.currentPath, w.search.GetValue())
|
||||||
if p != nil {
|
if p != nil {
|
||||||
w.currentPath = p
|
w.currentPath = p
|
||||||
}
|
}
|
||||||
|
@ -75,6 +75,7 @@ func (s *browseScreen) Init() wandle.Cmd {
|
|||||||
}
|
}
|
||||||
s.dbPath = dbs[dbidx]
|
s.dbPath = dbs[dbidx]
|
||||||
s.treePane = NewBoltTreePane(0, 3, s.width/2, s.height-6)
|
s.treePane = NewBoltTreePane(0, 3, s.width/2, s.height-6)
|
||||||
|
s.treePane.Init()
|
||||||
s.treePane.SetVisible(true)
|
s.treePane.SetVisible(true)
|
||||||
s.treePane.SetInsertPairCommand(s.insertPair)
|
s.treePane.SetInsertPairCommand(s.insertPair)
|
||||||
s.treePane.SetInsertBucketCommand(s.insertBucket)
|
s.treePane.SetInsertBucketCommand(s.insertBucket)
|
||||||
@ -143,6 +144,9 @@ func (s *browseScreen) handleTermboxEvent(msg termbox.Event) wandle.Cmd {
|
|||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if s.treePane.search.IsActive() {
|
||||||
|
return s.treePane.Update(msg)
|
||||||
|
}
|
||||||
var cmds []wandle.Cmd
|
var cmds []wandle.Cmd
|
||||||
cmds = append(cmds, s.treePane.Update(msg))
|
cmds = append(cmds, s.treePane.Update(msg))
|
||||||
cmds = append(cmds, s.detailPane.Update(msg))
|
cmds = append(cmds, s.detailPane.Update(msg))
|
||||||
|
Loading…
Reference in New Issue
Block a user