Some work, I guess

This commit is contained in:
Brian Buller 2022-11-18 13:43:52 -06:00
parent dce6e6c368
commit 22ffda8d13
4 changed files with 101 additions and 72 deletions

View File

@ -108,12 +108,12 @@ func (bd *BoltDB) GetPairFromPath(path []string) (*BoltPair, error) {
return p, err
}
func (bd *BoltDB) GetVisibleItemCount(path []string) (int, error) {
func (bd *BoltDB) GetVisibleItemCount(path []string, search string) (int, error) {
vis := 0
var retErr error
if len(path) == 0 {
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 {
return 0, err
}
@ -126,13 +126,13 @@ func (bd *BoltDB) GetVisibleItemCount(path []string) (int, error) {
}
// 1 for the bucket
vis++
if b.expanded {
// This bucket is expanded, add up it's children
if b.expanded || search != "" {
// This bucket is expanded (or we're searching), add up it's children
// * 1 for each pair
vis += len(b.pairs)
// * recurse for 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 {
return 0, err
}
@ -143,12 +143,12 @@ func (bd *BoltDB) GetVisibleItemCount(path []string) (int, error) {
return vis, retErr
}
func (bd *BoltDB) BuildVisiblePathSlice(filter string) ([][]string, error) {
func (bd *BoltDB) BuildVisiblePathSlice(search string) ([][]string, error) {
var retSlice [][]string
var retErr error
// The root path, recurse for root 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 {
retSlice = append(retSlice, bktS...)
} else {
@ -159,8 +159,8 @@ func (bd *BoltDB) BuildVisiblePathSlice(filter string) ([][]string, error) {
return retSlice, retErr
}
func (bd *BoltDB) IsVisiblePath(path []string, filter string) bool {
visPaths, err := bd.BuildVisiblePathSlice(filter)
func (bd *BoltDB) IsVisiblePath(path []string, search string) bool {
visPaths, err := bd.BuildVisiblePathSlice(search)
if err != nil {
return false
}
@ -181,8 +181,8 @@ func (bd *BoltDB) IsVisiblePath(path []string, filter string) bool {
}
return false
}
func (bd *BoltDB) GetPrevVisiblePath(path []string, filter string) []string {
visPaths, err := bd.BuildVisiblePathSlice(filter)
func (bd *BoltDB) GetPrevVisiblePath(path []string, search string) []string {
visPaths, err := bd.BuildVisiblePathSlice(search)
if path == nil {
if len(visPaths) > 0 {
return visPaths[len(visPaths)-1]
@ -205,8 +205,8 @@ func (bd *BoltDB) GetPrevVisiblePath(path []string, filter string) []string {
}
return nil
}
func (bd *BoltDB) GetNextVisiblePath(path []string, filter string) []string {
visPaths, err := bd.BuildVisiblePathSlice(filter)
func (bd *BoltDB) GetNextVisiblePath(path []string, search string) []string {
visPaths, err := bd.BuildVisiblePathSlice(search)
if path == nil {
if len(visPaths) > 0 {
return visPaths[0]

View File

@ -38,14 +38,16 @@ func (b *BoltBucket) GetPath() []string {
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
*/
func (b *BoltBucket) BuildVisiblePathSlice(prefix []string, filter string) ([][]string, error) {
func (b *BoltBucket) BuildVisiblePathSlice(prefix []string, search string) ([][]string, error) {
var retSlice [][]string
var retErr error
retSlice = append(retSlice, append(prefix, b.name))
if b.expanded {
if search == "" || strings.Contains(b.name, search) {
retSlice = append(retSlice, append(prefix, b.name))
}
if b.expanded || search != "" {
// Add subbuckets
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 {
return retSlice, bktErr
}
@ -53,7 +55,7 @@ func (b *BoltBucket) BuildVisiblePathSlice(prefix []string, filter string) ([][]
}
// Add 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
}
retSlice = append(retSlice, append(append(prefix, b.name), b.pairs[i].key))

View File

@ -6,6 +6,7 @@ import (
"git.bullercodeworks.com/brian/boltbrowser/models"
"git.bullercodeworks.com/brian/boltbrowser/util"
"git.bullercodeworks.com/brian/wandle"
"git.bullercodeworks.com/brian/widdles"
"github.com/nsf/termbox-go"
)
@ -21,8 +22,7 @@ type BoltTreePane struct {
pathBuffer [][]string
currentPath []string
currentPathIdx int
filter string
filterMode bool
search *widdles.Field
insertPairCmd 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{
x: x, y: y,
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 {
w.refreshDBAndBuffer()
}
w.search.SetWidth(w.width)
return nil
}
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 {
if w.db == nil {
return nil
}
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) {
case BrowseMsg:
@ -88,48 +91,65 @@ func (w *BoltTreePane) Update(msg wandle.Msg) wandle.Cmd {
return nil
}
func (w *BoltTreePane) handleTermboxEvent(msg termbox.Event) wandle.Cmd {
switch msg.Type {
case termbox.EventKey:
if msg.Ch == 'g' {
return w.jumpToStart
} else if msg.Ch == 'G' {
return w.jumpToEnd
} else if msg.Key == termbox.KeyCtrlF {
return w.pageDown
} else if msg.Key == termbox.KeyCtrlB {
return w.pageUp
} else if msg.Ch == 'j' || msg.Key == termbox.KeyArrowDown {
return w.moveCursorDown
} else if msg.Ch == 'k' || msg.Key == termbox.KeyArrowUp {
return w.moveCursorUp
} else if msg.Key == termbox.KeyCtrlR {
return w.refreshDBAndBuffer
} else if msg.Ch == 'p' {
return w.insertPairAtCurrent
} else if msg.Ch == 'P' {
return w.insertPairAtParent
} else if msg.Ch == 'b' {
return w.insertBucketAtCurrent
} else if msg.Ch == 'B' {
return w.insertBucketAtParent
} else if msg.Ch == 'e' {
return w.editPairValue
} else if msg.Ch == 'r' {
return w.renameBucketOrPair
} 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 == '/' {
// TODO: Start Filtering
if w.search.IsActive() {
if msg.Type == termbox.EventKey {
if msg.Key == termbox.KeyEnter {
return func() wandle.Msg {
w.search.SetActive(false)
return nil
}
} else {
w.setStatus(w.search.Message, time.Second)
return w.search.Update(msg)
}
}
} else {
switch msg.Type {
case termbox.EventKey:
if msg.Ch == 'g' {
return w.jumpToStart
} else if msg.Ch == 'G' {
return w.jumpToEnd
} else if msg.Key == termbox.KeyCtrlF {
return w.pageDown
} else if msg.Key == termbox.KeyCtrlB {
return w.pageUp
} else if msg.Ch == 'j' || msg.Key == termbox.KeyArrowDown {
return w.moveCursorDown
} else if msg.Ch == 'k' || msg.Key == termbox.KeyArrowUp {
return w.moveCursorUp
} else if msg.Key == termbox.KeyCtrlR {
return w.refreshDBAndBuffer
} else if msg.Ch == 'p' {
return w.insertPairAtCurrent
} else if msg.Ch == 'P' {
return w.insertPairAtParent
} else if msg.Ch == 'b' {
return w.insertBucketAtCurrent
} else if msg.Ch == 'B' {
return w.insertBucketAtParent
} else if msg.Ch == 'e' {
return w.editPairValue
} else if msg.Ch == 'r' {
return w.renameBucketOrPair
} 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
@ -145,6 +165,9 @@ func (w *BoltTreePane) View(style wandle.Style) {
wandle.Print(midX, midY, style, txt)
return
}
if w.search.IsActive() || w.search.GetValue() != "" {
w.search.View(style)
}
// Find the cursor in the pane
for k, v := range w.pathBuffer {
if comparePaths(w.currentPath, v) {
@ -230,9 +253,9 @@ func (w *BoltTreePane) RefreshBuffer() {
for i := range buckets {
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 {
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 {
w.currentPath = w.db.GetNextVisiblePath(nil, w.filter)
w.currentPath = w.db.GetNextVisiblePath(nil, w.search.GetValue())
}
w.UpdateDetailPane()
}
@ -289,17 +312,17 @@ func (w *BoltTreePane) jumpCursorUp(distance int) {
}
}
if isCurPath {
w.currentPath = w.db.GetNextVisiblePath(nil, w.filter)
w.currentPath = w.db.GetNextVisiblePath(nil, w.search.GetValue())
}
w.UpdateDetailPane()
}
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()
return nil
}
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()
return nil
}
@ -314,7 +337,7 @@ func (w *BoltTreePane) pageDown() wandle.Msg {
return nil
}
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 {
w.currentPath = p
}
@ -322,7 +345,7 @@ func (w *BoltTreePane) moveCursorUp() wandle.Msg {
return nil
}
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 {
w.currentPath = p
}

View File

@ -75,6 +75,7 @@ func (s *browseScreen) Init() wandle.Cmd {
}
s.dbPath = dbs[dbidx]
s.treePane = NewBoltTreePane(0, 3, s.width/2, s.height-6)
s.treePane.Init()
s.treePane.SetVisible(true)
s.treePane.SetInsertPairCommand(s.insertPair)
s.treePane.SetInsertBucketCommand(s.insertBucket)
@ -143,6 +144,9 @@ func (s *browseScreen) handleTermboxEvent(msg termbox.Event) wandle.Cmd {
return cmd
}
if s.treePane.search.IsActive() {
return s.treePane.Update(msg)
}
var cmds []wandle.Cmd
cmds = append(cmds, s.treePane.Update(msg))
cmds = append(cmds, s.detailPane.Update(msg))