From a3f17e0d7472cefa47a139923e86ef0235570732 Mon Sep 17 00:00:00 2001 From: WitheringAway <124115470+notwithering@users.noreply.github.com> Date: Wed, 10 Jun 2026 09:47:18 -0400 Subject: [PATCH] add sequence support --- internal/boltbrowser/bolt_model.go | 31 +++++++++++++++++++++ internal/boltbrowser/screen_about.go | 2 +- internal/boltbrowser/screen_browser.go | 38 +++++++++++++++++++++++++- 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/internal/boltbrowser/bolt_model.go b/internal/boltbrowser/bolt_model.go index 85775b6..ae74e69 100644 --- a/internal/boltbrowser/bolt_model.go +++ b/internal/boltbrowser/bolt_model.go @@ -27,6 +27,7 @@ type BoltBucket struct { expanded bool errorFlag bool isRoot bool + sequence uint64 } /* @@ -273,6 +274,7 @@ func (bd *BoltDB) refreshDatabase() *BoltDB { bb, err := readBucket(b) if err == nil { bb.name = string(nm) + bb.sequence = b.Sequence() bb.expanded = false memBolt.buckets = append(memBolt.buckets, *bb) return nil @@ -453,6 +455,7 @@ func readBucket(b *bbolt.Bucket) (*BoltBucket, error) { tb.parent = bb if err == nil { tb.name = string(k) + tb.sequence = b.Bucket(k).Sequence() bb.buckets = append(bb.buckets, *tb) } } else { @@ -587,6 +590,34 @@ func updatePairValue(path []string, v string) error { return err } +func updateBucketSequence(path []string, seq uint64) error { + if AppArgs.ReadOnly { + return errors.New("DB is in Read-Only Mode") + } + err := db.Update(func(tx *bbolt.Tx) error { + b := tx.Bucket([]byte(path[0])) + if b == nil { + // Invalid path, try for the root bucket + b = tx.Cursor().Bucket() + } + if b != nil { + if len(path) > 0 { + for i := range path[1:] { + b = b.Bucket([]byte(path[i+1])) + if b == nil { + return errors.New("updateBucketSequence: Invalid Path") + } + } + } + // Now update the sequence + err := b.SetSequence(seq) + return err + } + return errors.New("updateBucketSequence: Invalid Path") + }) + return err +} + func insertBucket(path []string, n string) error { if AppArgs.ReadOnly { return errors.New("DB is in Read-Only Mode") diff --git a/internal/boltbrowser/screen_about.go b/internal/boltbrowser/screen_about.go index 00dc24a..7d7c292 100644 --- a/internal/boltbrowser/screen_about.go +++ b/internal/boltbrowser/screen_about.go @@ -108,7 +108,7 @@ func (screen *AboutScreen) drawScreen(style Style) { commands2 := []Command{ {"p,P", "create pair/at parent"}, {"b,B", "create bucket/at parent"}, - {"e", "edit value of pair"}, + {"e", "edit pair value/bucket sequence"}, {"r", "rename pair/bucket"}, {"", ""}, {"D", "delete item"}, diff --git a/internal/boltbrowser/screen_browser.go b/internal/boltbrowser/screen_browser.go index 0f5dd25..4d002fd 100644 --- a/internal/boltbrowser/screen_browser.go +++ b/internal/boltbrowser/screen_browser.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "path/filepath" + "strconv" "strings" "time" @@ -54,6 +55,7 @@ const ( modeChangeKey = 33 // 0000 0010 0001 modeChangeVal = 34 // 0000 0010 0010 modeFilter = 35 // 0100 0010 0011 + modeChangeSeq = 36 // 0100 0010 0100 modeInsert = 64 // 0000 0100 0000 modeInsertBucket = 65 // 0000 0100 0001 modeInsertPair = 68 // 0000 0100 0100 @@ -155,7 +157,7 @@ func (screen *BrowserScreen) handleBrowseKeyEvent(event termbox.Event) int { } else if event.Ch == 'e' { b, p, _ := screen.db.getGenericFromPath(screen.currentPath) if b != nil { - screen.setMessage("Cannot edit a bucket, did you mean to (r)ename?") + screen.startEditBucketSequence() } else if p != nil { screen.startEditItem() } @@ -242,6 +244,21 @@ func (screen *BrowserScreen) handleInputKeyEvent(event termbox.Event) int { screen.setMessage("Bucket Renamed!") screen.refreshDatabase() } + } else if screen.mode == modeChangeSeq { + newSeqStr := screen.inputModal.GetValue() + + newSeq, err := strconv.ParseUint(newSeqStr, 10, 64) + if err != nil { + screen.setMessage("Invalid sequence value.") + } else { + if err := updateBucketSequence(screen.currentPath, newSeq); err != nil { + screen.setMessage("Error occurred updating Sequence.") + } else { + b.sequence = newSeq + screen.setMessage("Sequence updated!") + screen.refreshDatabase() + } + } } } else if p != nil { if screen.mode == modeChangeKey { @@ -624,6 +641,8 @@ func (screen *BrowserScreen) buildRightPane(style Style) { Line{fmt.Sprintf("Buckets: %d", len(b.buckets)), style.defaultFg, style.defaultBg}) screen.rightPaneBuffer = append(screen.rightPaneBuffer, Line{fmt.Sprintf("Pairs: %d", len(b.pairs)), style.defaultFg, style.defaultBg}) + screen.rightPaneBuffer = append(screen.rightPaneBuffer, + Line{fmt.Sprintf("Sequence: %d", b.sequence), style.defaultFg, style.defaultBg}) } else if p != nil { screen.rightPaneBuffer = append(screen.rightPaneBuffer, Line{fmt.Sprintf("Path: %s", strings.Join(stringifyPath(p.GetPath()), " → ")), style.defaultFg, style.defaultBg}) @@ -775,6 +794,23 @@ func (screen *BrowserScreen) startFilter() bool { return false } +func (screen *BrowserScreen) startEditBucketSequence() bool { + b, _, e := screen.db.getGenericFromPath(screen.currentPath) + if e == nil { + w, h := termbox.Size() + inpW, inpH := (w / 2), 6 + inpX, inpY := ((w / 2) - (inpW / 2)), ((h / 2) - inpH) + mod := termboxUtil.CreateInputModal("", inpX, inpY, inpW, inpH, termbox.ColorWhite, termbox.ColorBlack) + mod.SetTitle(termboxUtil.AlignText(fmt.Sprintf("Set sequence for '%s'", b.name), inpW, termboxUtil.AlignCenter)) + mod.SetValue(strconv.Itoa(int(b.sequence))) + mod.Show() + screen.inputModal = mod + screen.mode = modeChangeSeq + return true + } + return false +} + func (screen *BrowserScreen) startEditItem() bool { _, p, e := screen.db.getGenericFromPath(screen.currentPath) if e == nil {