go-vise

Constrained Size Output Virtual Machine
Info | Log | Files | Refs | README | LICENSE

commit 789f38411f8a83c69ea0968b25cbafc26bd6e84f
parent e5a158b4e5c669ce65c013de4464955055b39af3
Author: lash <dev@holbrook.no>
Date:   Sat, 31 Aug 2024 22:16:30 +0100

WIP complete inline documentation, remove logger exports

Diffstat:
Masm/asm.go | 9++++++++-
Masm/flag.go | 4++--
Masm/log.go | 2+-
Masm/menu.go | 24++++++++++++------------
Mcache/cache.go | 74+++++++++++++++++++++++++++++---------------------------------------------
Mcache/log.go | 2+-
Mcache/memory.go | 38+++++++++++++++++++++++++++++++++++++-
Mdb/error.go | 2+-
Mengine/config.go | 8+++++++-
Mengine/debug.go | 10+++++++++-
Mengine/default.go | 4++--
Mengine/engine.go | 37++++++++++++++++++++-----------------
Mengine/log.go | 2+-
Mengine/loop.go | 2+-
Mengine/persist.go | 2+-
Mexamples/db/main.go | 6++++--
Mexamples/languages/main.go | 12+++++++-----
Mexamples/pincheck/main.go | 4+++-
Mexamples/session/main.go | 4+++-
Mexamples/state/main.go | 6++++--
Mexamples/state_passive/main.go | 9+++++++--
Mlang/lang.go | 8++++++++
Mlogging/logging.go | 28+++++++++++++++++++++-------
Mlogging/vanilla.go | 24+++++++++++++++---------
Dpersist/gdbm.go | 92-------------------------------------------------------------------------------
Mpersist/log.go | 2+-
Mpersist/persist.go | 2+-
Mrender/log.go | 2+-
Mrender/menu.go | 38+++++++++++++++++++++++++++++++++-----
Mrender/page.go | 26+++++++++++++-------------
Mrender/size.go | 11+++++++----
Mrender/split.go | 8+++-----
Mresource/fs.go | 1+
Mresource/gdbm.go | 1+
Mvm/input.go | 2+-
Mvm/runner.go | 2+-
36 files changed, 267 insertions(+), 241 deletions(-)

diff --git a/asm/asm.go b/asm/asm.go @@ -18,11 +18,15 @@ import ( // Asm assembles bytecode from the vise assembly mini-language. +// +// TODO: Conceal from outside use type Asm struct { Instructions []*Instruction `@@*` } // Arg holds all parsed argument elements of a single line of assembly code. +// +// TODO: Conceal from outside use type Arg struct { Sym *string `(@Sym Whitespace?)?` Size *uint32 `(@Size Whitespace?)?` @@ -32,6 +36,7 @@ type Arg struct { //Desc *string `(Quote ((@Sym | @Size) @Whitespace?)+ Quote Whitespace?)?` } +// writes the parsed instruction bytes to output. func flush(b *bytes.Buffer, w io.Writer) (int, error) { if w != nil { return w.Write(b.Bytes()) @@ -309,13 +314,15 @@ func (a Arg) String() string { } // Instruction represents one full line of assembly code. +// +// TODO: Conceal from outside use type Instruction struct { OpCode string `@Ident` OpArg Arg `(Whitespace @@)?` Comment string `Comment? EOL` } -// String implement the String interface. +// String implements the String interface. func (i Instruction) String() string { return fmt.Sprintf("%s %s", i.OpCode, i.OpArg) } diff --git a/asm/flag.go b/asm/flag.go @@ -113,9 +113,9 @@ func(pp *FlagParser) Load(fp string) (int, error) { if (len(v) > 3) { pp.flagDescription[uint32(fl)] = v[3] - Logg.Debugf("added flag translation", "from", v[1], "to", v[2], "description", v[3]) + logg.Debugf("added flag translation", "from", v[1], "to", v[2], "description", v[3]) } else { - Logg.Debugf("added flag translation", "from", v[1], "to", v[2]) + logg.Debugf("added flag translation", "from", v[1], "to", v[2]) } } } diff --git a/asm/log.go b/asm/log.go @@ -5,5 +5,5 @@ import ( ) var ( - Logg logging.Logger = logging.NewVanilla().WithDomain("asm") + logg logging.Logger = logging.NewVanilla().WithDomain("asm") ) diff --git a/asm/menu.go b/asm/menu.go @@ -11,18 +11,18 @@ type BatchCode uint16 const ( _MENU_OFFSET = 256 - MENU_DOWN = _MENU_OFFSET - MENU_UP = _MENU_OFFSET + 1 - MENU_NEXT = _MENU_OFFSET + 2 - MENU_PREVIOUS = _MENU_OFFSET + 3 + _MENU_DOWN = _MENU_OFFSET + _MENU_UP = _MENU_OFFSET + 1 + _MENU_NEXT = _MENU_OFFSET + 2 + _MENU_PREVIOUS = _MENU_OFFSET + 3 ) var ( batchCode = map[string]BatchCode{ - "DOWN": MENU_DOWN, - "UP": MENU_UP, - "NEXT": MENU_NEXT, - "PREVIOUS": MENU_PREVIOUS, + "DOWN": _MENU_DOWN, + "UP": _MENU_UP, + "NEXT": _MENU_NEXT, + "PREVIOUS": _MENU_PREVIOUS, } ) @@ -54,7 +54,7 @@ func(mp *MenuProcessor) Add(bop string, choice string, display string, target st if bopCode == 0 { return fmt.Errorf("unknown menu instruction: %v", bop) } - if len(target) > 0 && bopCode != MENU_DOWN { + if len(target) > 0 && bopCode != _MENU_DOWN { return fmt.Errorf("target is only valid for DOWN") } m := menuItem{ @@ -74,13 +74,13 @@ func (mp *MenuProcessor) ToLines() []byte { for _, v := range mp.items { switch v.code { - case MENU_UP: + case _MENU_UP: preLines = vm.NewLine(preLines, vm.MOUT, []string{v.display, v.choice}, nil, nil) postLines = vm.NewLine(postLines, vm.INCMP, []string{"_", v.choice}, nil, nil) - case MENU_NEXT: + case _MENU_NEXT: preLines = vm.NewLine(preLines, vm.MNEXT, []string{v.display, v.choice}, nil, nil) postLines = vm.NewLine(postLines, vm.INCMP, []string{">", v.choice}, nil, nil) - case MENU_PREVIOUS: + case _MENU_PREVIOUS: preLines = vm.NewLine(preLines, vm.MPREV, []string{v.display, v.choice}, nil, nil) postLines = vm.NewLine(postLines, vm.INCMP, []string{"<", v.choice}, nil, nil) default: diff --git a/cache/cache.go b/cache/cache.go @@ -5,17 +5,23 @@ import ( ) // Cache stores loaded content, enforcing size limits and keeping track of size usage. +// // TODO: hide values from client, while allowing cbor serialization type Cache struct { - CacheSize uint32 // Total allowed cumulative size of values (not code) in cache - CacheUseSize uint32 // Currently used bytes by all values (not code) in cache - Cache []map[string]string // All loaded cache items - Sizes map[string]uint16 // Size limits for all loaded symbols. - LastValue string // last inserted value + // Total allowed cumulative size of values (not code) in cache + CacheSize uint32 + // Currently used bytes by all values (not code) in cache + CacheUseSize uint32 + // All loaded cache items + Cache []map[string]string + // Size limits for all loaded symbols. + Sizes map[string]uint16 + // Last inserted value (regardless of scope) + LastValue string invalid bool } -// NewCache creates a new ready-to-use cache object +// NewCache creates a new ready-to-use Cache object func NewCache() *Cache { ca := &Cache{ Cache: []map[string]string{make(map[string]string)}, @@ -24,34 +30,23 @@ func NewCache() *Cache { return ca } -// Invalidate marks a cache as invalid. -// -// An invalid cache should not be persisted or propagated +// Invalidate implements the Memory interface. func(ca *Cache) Invalidate() { ca.invalid = true } -// Invalid returns true if cache is invalid. -// -// An invalid cache should not be persisted or propagated +// Invalid implements the Memory interface. func(ca *Cache) Invalid() bool { return ca.invalid } -// WithCacheSize applies a cumulative cache size limitation for all cached items. +// WithCacheSize is a chainable method that applies a cumulative cache size limitation for all cached items. func(ca *Cache) WithCacheSize(cacheSize uint32) *Cache { ca.CacheSize = cacheSize return ca } -// Add adds a cache value under a cache symbol key. -// -// Also stores the size limitation of for key for later updates. -// -// Fails if: -// - key already defined -// - value is longer than size limit -// - adding value exceeds cumulative cache capacity +// Add implements the Memory interface. func(ca *Cache) Add(key string, value string, sizeLimit uint16) error { if sizeLimit > 0 { l := uint16(len(value)) @@ -63,7 +58,7 @@ func(ca *Cache) Add(key string, value string, sizeLimit uint16) error { if checkFrame > -1 { thisFrame := len(ca.Cache) - 1 if checkFrame == thisFrame { - Logg.Debugf("Ignoring load request on frame that has symbol already loaded") + logg.Debugf("Ignoring load request on frame that has symbol already loaded") return nil } return fmt.Errorf("key %v already defined in frame %v, this is frame %v", key, checkFrame, thisFrame) @@ -75,8 +70,8 @@ func(ca *Cache) Add(key string, value string, sizeLimit uint16) error { return fmt.Errorf("Cache capacity exceeded %v of %v", ca.CacheUseSize + sz, ca.CacheSize) } } - Logg.Infof("Cache add", "key", key, "size", sz, "limit", sizeLimit) - Logg.Tracef("", "Cache add data", value) + logg.Infof("Cache add", "key", key, "size", sz, "limit", sizeLimit) + logg.Tracef("", "Cache add data", value) ca.Cache[len(ca.Cache)-1][key] = value ca.CacheUseSize += sz ca.Sizes[key] = sizeLimit @@ -84,7 +79,7 @@ func(ca *Cache) Add(key string, value string, sizeLimit uint16) error { return nil } -// ReservedSize returns the maximum byte size available for the given symbol. +// ReservedSize implements the Memory interface. func(ca *Cache) ReservedSize(key string) (uint16, error) { v, ok := ca.Sizes[key] if !ok { @@ -93,14 +88,7 @@ func(ca *Cache) ReservedSize(key string) (uint16, error) { return v, nil } -// Update sets a new value for an existing key. -// -// Uses the size limitation from when the key was added. -// -// Fails if: -// - key not defined -// - value is longer than size limit -// - replacing value exceeds cumulative cache capacity +// Update implements the Memory interface. func(ca *Cache) Update(key string, value string) error { sizeLimit := ca.Sizes[key] if ca.Sizes[key] > 0 { @@ -129,9 +117,7 @@ func(ca *Cache) Update(key string, value string) error { return nil } -// Get the content currently loaded for a single key, loaded at any level. -// -// Fails if key has not been loaded. +// Get implements the Memory interface. func(ca *Cache) Get(key string) (string, error) { i := ca.frameOf(key) if i == -1 { @@ -144,7 +130,7 @@ func(ca *Cache) Get(key string) (string, error) { return r, nil } -// Reset flushes all state contents below the top level. +// Reset implements the Memory interface. func(ca *Cache) Reset() { if len(ca.Cache) == 0 { return @@ -153,17 +139,14 @@ func(ca *Cache) Reset() { ca.CacheUseSize = 0 return } - -// Push adds a new level to the cache. +// Push implements the Memory interface. func (ca *Cache) Push() error { m := make(map[string]string) ca.Cache = append(ca.Cache, m) return nil } -// Pop frees the cache of the current level and makes the previous level the current level. -// -// Fails if already on top level. +// Pop implements the Memory interface. func (ca *Cache) Pop() error { l := len(ca.Cache) if l == 0 { @@ -174,7 +157,7 @@ func (ca *Cache) Pop() error { for k, v := range m { sz := len(v) ca.CacheUseSize -= uint32(sz) - Logg.Debugf("Cache free", "frame", l, "key", k, "size", sz) + logg.Debugf("Cache free", "frame", l, "key", k, "size", sz) } ca.Cache = ca.Cache[:l] //ca.resetCurrent() @@ -186,9 +169,8 @@ func(ca *Cache) Check(key string) bool { return ca.frameOf(key) == -1 } -// Last returns the last inserted value +// Last implements the Memory interface. // -// The stored last inserter value will be reset to an empty string // TODO: needs to be invalidated when out of scope func(ca *Cache) Last() string { s := ca.LastValue @@ -221,10 +203,12 @@ func(ca *Cache) frameOf(key string) int { return -1 } +// Levels implements the Memory interface. func(ca *Cache) Levels() uint32 { return uint32(len(ca.Cache)) } +// Keys implements the Memory interface. func(ca *Cache) Keys(level uint32) []string { var r []string for k := range ca.Cache[level] { diff --git a/cache/log.go b/cache/log.go @@ -5,5 +5,5 @@ import ( ) var ( - Logg logging.Logger = logging.NewVanilla().WithDomain("cache") + logg logging.Logger = logging.NewVanilla().WithDomain("cache") ) diff --git a/cache/memory.go b/cache/memory.go @@ -1,17 +1,53 @@ package cache -// Memory defines the interface for store of a symbol mapped content store. +// Memory defines the interface for store of a symbol mapped content cache. type Memory interface { + // Add adds a cache value under a cache symbol key. + // + // Also stores the size limitation of for key for later updates. + // + // Must fail if: + // * key already defined + // * value is longer than size limit + // * adding value exceeds cumulative cache capacity Add(key string, val string, sizeLimit uint16) error + // Update sets a new value for an existing key. + // + // Uses the size limitation from when the key was added. + // + // Must fail if: + // - key not defined + // - value is longer than size limit + // - replacing value exceeds cumulative cache capacity Update(key string, val string) error + // ReservedSize returns the maximum byte size available for the given symbol. ReservedSize(key string) (uint16, error) + // Get the content currently loaded for a single key, loaded at any level. + // + // Must fail if key has not been loaded. Get(key string) (string, error) + // Push adds a new level to the cache. Push() error + // Pop frees the cache of the current level and makes the previous level the current level. + // + // Fails if already on top level. Pop() error + // Reset flushes all state contents below the top level. Reset() + // Levels returns the current number of levels. Levels() uint32 + // Keys returns all storage keys for the given level. Keys(level uint32) []string + // Last returns the last inserted value + // + // The stored last inserter value must be reset to an empty string Last() string + // Invalidate marks a cache as invalid. + // + // An invalid cache should not be persisted or propagated Invalidate() + // Invalid returns true if cache is invalid. + // + // An invalid cache should not be persisted or propagated Invalid() bool } diff --git a/db/error.go b/db/error.go @@ -14,7 +14,7 @@ func NewErrNotFound(k []byte) error { return ErrNotFound{k} } -// Error implements error. +// Error implements Error. func(e ErrNotFound) Error() string { return fmt.Sprintf("key not found: %x", e.k) } diff --git a/engine/config.go b/engine/config.go @@ -2,10 +2,16 @@ package engine // Config globally defines behavior of all components driven by the engine. type Config struct { - OutputSize uint32 // Maximum size of output from a single rendered page + // OutputSize sets the maximum size of output from a single rendered page. If set to 0, no size limit is imposed. + OutputSize uint32 + // SessionId is used to segment the context of state and application data retrieval and storage. SessionId string + // Root is the node name of the bytecode entry point. Root string + // FlagCount is used to set the number of user-defined signal flags used in the execution state. FlagCount uint32 + // CacheSize determines the total allowed cumulative cache size for a single SessionId storage segment. If set to 0, no size limit is imposed. CacheSize uint32 + // Language determines the ISO-639-3 code of the default translation language. If not set, no language translations will be looked up. Language string } diff --git a/engine/debug.go b/engine/debug.go @@ -9,15 +9,19 @@ import ( "git.defalsify.org/vise.git/state" ) +// Debug implementations output details about the execution state on each execution halt. type Debug interface { + // Break receives the state and cache in order to generate its output. Break(*state.State, cache.Memory) } +// SimpleDebug is a vanilla implementation of the Debug interface. type SimpleDebug struct { pfx string w io.Writer } +// NewSimpleDebug instantiates a new SimpleDebug object. func NewSimpleDebug(w io.Writer) Debug { if w == nil { w = os.Stderr @@ -28,10 +32,14 @@ func NewSimpleDebug(w io.Writer) Debug { } } +// Break implements the Debug interface. func (dbg* SimpleDebug) Break(st *state.State, ca cache.Memory) { fmt.Fprintf(dbg.w, "%s State:\n", dbg.pfx) + node, lvl := st.Where() + fmt.Fprintf(dbg.w, "%s\tPath: %s (%d)\n", dbg.pfx, node, lvl) + fmt.Fprintf(dbg.w, "%s\tFlags:\n", dbg.pfx) for _, s := range state.FlagDebugger.AsList(st.Flags, st.BitSize - 8) { - fmt.Fprintf(dbg.w, "%s\t%s\n", dbg.pfx, s) + fmt.Fprintf(dbg.w, "%s\t\t%s\n", dbg.pfx, s) } for i := uint32(0); i < ca.Levels(); i++ { fmt.Fprintf(dbg.w, "%s Cache[%d]:\n", dbg.pfx, i) diff --git a/engine/default.go b/engine/default.go @@ -31,7 +31,7 @@ func NewDefaultEngine(dir string, persistDb db.Db, session *string) (EngineIsh, pr := persist.NewPersister(persistDb) en, err = NewPersistedEngine(ctx, cfg, pr, rs) if err != nil { - Logg.Infof("persisted engine create error. trying again with persisting empty state first...") + logg.Infof("persisted engine create error. trying again with persisting empty state first...") pr = pr.WithContent(&st, ca) err = pr.Save(cfg.SessionId) if err != nil { @@ -67,7 +67,7 @@ func NewSizedEngine(dir string, size uint32, persistDb db.Db, session *string) ( pr := persist.NewPersister(persistDb) en, err = NewPersistedEngine(ctx, cfg, pr, rs) if err != nil { - Logg.Infof("persisted engine create error. trying again with persisting empty state first...") + logg.Infof("persisted engine create error. trying again with persisting empty state first...") pr = pr.WithContent(&st, ca) err = pr.Save(cfg.SessionId) if err != nil { diff --git a/engine/engine.go b/engine/engine.go @@ -57,7 +57,7 @@ func NewEngine(ctx context.Context, cfg Config, st *state.State, rs resource.Res if err != nil { panic(err) } - Logg.InfoCtxf(ctx, "set language from config", "language", cfg.Language) + logg.InfoCtxf(ctx, "set language from config", "language", cfg.Language) } } @@ -67,6 +67,9 @@ func NewEngine(ctx context.Context, cfg Config, st *state.State, rs resource.Res return engine } +// SetDebugger sets a debugger to use. +// +// No debugger is set by default. func (en *Engine) SetDebugger(debugger Debug) { en.dbg = debugger } @@ -78,7 +81,7 @@ func(en *Engine) SetFirst(fn resource.EntryFunc) { // Finish implements EngineIsh interface func(en *Engine) Finish() error { - Logg.Tracef("that's a wrap", "engine", en) + logg.Tracef("that's a wrap", "engine", en) return nil } @@ -90,7 +93,7 @@ func(en *Engine) restore() { return } if en.root != location { - Logg.Infof("restoring state", "sym", location) + logg.Infof("restoring state", "sym", location) en.root = "." } } @@ -102,7 +105,7 @@ func(en *Engine) runFirst(ctx context.Context) (bool, error) { if en.first == nil { return true, nil } - Logg.DebugCtxf(ctx, "start pre-VM check") + logg.DebugCtxf(ctx, "start pre-VM check") rs := resource.NewMenuResource() rs.AddLocalFunc("_first", en.first) en.st.Down("_first") @@ -119,7 +122,7 @@ func(en *Engine) runFirst(ctx context.Context) (bool, error) { } else { if en.st.MatchFlag(state.FLAG_TERMINATE, true) { en.exit = en.ca.Last() - Logg.InfoCtxf(ctx, "Pre-VM check says not to continue execution", "state", en.st) + logg.InfoCtxf(ctx, "Pre-VM check says not to continue execution", "state", en.st) } else { r = true } @@ -130,7 +133,7 @@ func(en *Engine) runFirst(ctx context.Context) (bool, error) { } en.st.ResetFlag(state.FLAG_TERMINATE) en.st.ResetFlag(state.FLAG_DIRTY) - Logg.DebugCtxf(ctx, "end pre-VM check") + logg.DebugCtxf(ctx, "end pre-VM check") return r, err } @@ -140,7 +143,7 @@ func(en *Engine) runFirst(ctx context.Context) (bool, error) { func(en *Engine) Init(ctx context.Context) (bool, error) { en.restore() if en.initd { - Logg.DebugCtxf(ctx, "already initialized") + logg.DebugCtxf(ctx, "already initialized") return true, nil } @@ -164,13 +167,13 @@ func(en *Engine) Init(ctx context.Context) (bool, error) { } b := vm.NewLine(nil, vm.MOVE, []string{sym}, nil, nil) - Logg.DebugCtxf(ctx, "start new init VM run", "code", b) + logg.DebugCtxf(ctx, "start new init VM run", "code", b) b, err = en.vm.Run(ctx, b) if err != nil { return false, err } - Logg.DebugCtxf(ctx, "end new init VM run", "code", b) + logg.DebugCtxf(ctx, "end new init VM run", "code", b) en.st.SetCode(b) err = en.st.SetInput(inSave) if err != nil { @@ -214,7 +217,7 @@ func (en *Engine) Exec(ctx context.Context, input []byte) (bool, error) { // backend for Exec, after the input validity check func(en *Engine) exec(ctx context.Context, input []byte) (bool, error) { - Logg.InfoCtxf(ctx, "new VM execution with input", "input", string(input)) + logg.InfoCtxf(ctx, "new VM execution with input", "input", string(input)) code, err := en.st.GetCode() if err != nil { return false, err @@ -223,26 +226,26 @@ func(en *Engine) exec(ctx context.Context, input []byte) (bool, error) { return false, fmt.Errorf("no code to execute") } - Logg.Debugf("start new VM run", "code", code) + logg.Debugf("start new VM run", "code", code) code, err = en.vm.Run(ctx, code) if err != nil { return false, err } - Logg.Debugf("end new VM run", "code", code) + logg.Debugf("end new VM run", "code", code) v := en.st.MatchFlag(state.FLAG_TERMINATE, true) if v { if len(code) > 0 { - Logg.Debugf("terminated with code remaining", "code", code) + logg.Debugf("terminated with code remaining", "code", code) } return false, err } en.st.SetCode(code) if len(code) == 0 { - Logg.Infof("runner finished with no remaining code", "state", en.st) + logg.Infof("runner finished with no remaining code", "state", en.st) if en.st.MatchFlag(state.FLAG_DIRTY, true) { - Logg.Debugf("have output for quitting") + logg.Debugf("have output for quitting") en.exit = en.ca.Last() } _, err = en.reset(ctx) @@ -266,7 +269,7 @@ func(en *Engine) WriteResult(ctx context.Context, w io.Writer) (int, error) { if en.st.Language != nil { ctx = context.WithValue(ctx, "Language", *en.st.Language) } - Logg.TraceCtxf(ctx, "render with state", "state", en.st) + logg.TraceCtxf(ctx, "render with state", "state", en.st) r, err := en.vm.Render(ctx) if err != nil { return 0, err @@ -278,7 +281,7 @@ func(en *Engine) WriteResult(ctx context.Context, w io.Writer) (int, error) { } } if len(en.exit) > 0 { - Logg.TraceCtxf(ctx, "have exit", "exit", en.exit) + logg.TraceCtxf(ctx, "have exit", "exit", en.exit) n, err := io.WriteString(w, en.exit) if err != nil { return l, err diff --git a/engine/log.go b/engine/log.go @@ -5,5 +5,5 @@ import ( ) var ( - Logg logging.Logger = logging.NewVanilla().WithDomain("engine") + logg logging.Logger = logging.NewVanilla().WithDomain("engine") ) diff --git a/engine/loop.go b/engine/loop.go @@ -32,7 +32,7 @@ func Loop(ctx context.Context, en EngineIsh, reader io.Reader, writer io.Writer) for running { in, err := bufReader.ReadString('\n') if err == io.EOF { - Logg.DebugCtxf(ctx, "EOF found, that's all folks") + logg.DebugCtxf(ctx, "EOF found, that's all folks") return nil } if err != nil { diff --git a/engine/persist.go b/engine/persist.go @@ -44,7 +44,7 @@ func(pe PersistedEngine) Exec(ctx context.Context, input []byte) (bool, error) { // Finish implements EngineIsh interface func(pe PersistedEngine) Finish() error { - Logg.Tracef("that's a wrap", "engine", pe) + logg.Tracef("that's a wrap", "engine", pe) return pe.pr.Save(pe.Engine.session) } diff --git a/examples/db/main.go b/examples/db/main.go @@ -17,9 +17,11 @@ import ( "git.defalsify.org/vise.git/resource" "git.defalsify.org/vise.git/state" "git.defalsify.org/vise.git/db" + "git.defalsify.org/vise.git/logging" ) var ( + logg = logging.NewVanilla() baseDir = testdataloader.GetBasePath() scriptDir = path.Join(baseDir, "examples", "db") store = db.NewFsDb() @@ -141,11 +143,11 @@ func main() { st := state.NewState(1) en, err := engine.NewPersistedEngine(ctx, cfg, pr, rs) if err != nil { - engine.Logg.Infof("persisted engine create error. trying again with persisting empty state first...") + logg.Infof("persisted engine create error. trying again with persisting empty state first...") pr = pr.WithContent(&st, ca) err = pr.Save(cfg.SessionId) if err != nil { - engine.Logg.ErrorCtxf(ctx, "fail state save", "err", err) + logg.ErrorCtxf(ctx, "fail state save", "err", err) os.Exit(1) } en, err = engine.NewPersistedEngine(ctx, cfg, pr, rs) diff --git a/examples/languages/main.go b/examples/languages/main.go @@ -17,6 +17,7 @@ import ( "git.defalsify.org/vise.git/resource" "git.defalsify.org/vise.git/state" "git.defalsify.org/vise.git/db" + "git.defalsify.org/vise.git/logging" ) const ( @@ -24,6 +25,7 @@ const ( ) var ( + logg = logging.NewVanilla() baseDir = testdataloader.GetBasePath() scriptDir = path.Join(baseDir, "examples", "languages") translationDir = path.Join(scriptDir, "locale") @@ -31,7 +33,7 @@ var ( func codeFromCtx(ctx context.Context) string { var code string - engine.Logg.DebugCtxf(ctx, "in msg", "ctx", ctx, "val", code) + logg.DebugCtxf(ctx, "in msg", "ctx", ctx, "val", code) if ctx.Value("Language") != nil { lang := ctx.Value("Language").(lang.Language) code = lang.Code @@ -75,7 +77,7 @@ func(l *langController) moMsg(ctx context.Context, sym string, input []byte) (re o := gotext.NewLocale(translationDir, code) o.AddDomain("default") r.Content = o.Get("This message is translated using gettext") - engine.Logg.DebugCtxf(ctx, "lang", "code", code, "translateor", o) + logg.DebugCtxf(ctx, "lang", "code", code, "translateor", o) return r, nil } @@ -101,17 +103,17 @@ func main() { store := db.NewFsDb() err := store.Connect(ctx, dp) if err != nil { - engine.Logg.ErrorCtxf(ctx, "db connect fail", "err", err) + logg.ErrorCtxf(ctx, "db connect fail", "err", err) os.Exit(1) } pr := persist.NewPersister(store) en, err := engine.NewPersistedEngine(ctx, cfg, pr, rs) if err != nil { - engine.Logg.Infof("persisted engine create error. trying again with persisting empty state first...") + logg.Infof("persisted engine create error. trying again with persisting empty state first...") pr = pr.WithContent(&st, ca) err = pr.Save(cfg.SessionId) if err != nil { - engine.Logg.ErrorCtxf(ctx, "fail state save", "err", err) + logg.ErrorCtxf(ctx, "fail state save", "err", err) os.Exit(1) } en, err = engine.NewPersistedEngine(ctx, cfg, pr, rs) diff --git a/examples/pincheck/main.go b/examples/pincheck/main.go @@ -15,6 +15,7 @@ import ( "git.defalsify.org/vise.git/engine" "git.defalsify.org/vise.git/resource" "git.defalsify.org/vise.git/state" + "git.defalsify.org/vise.git/logging" ) const ( @@ -23,6 +24,7 @@ const ( ) var ( + logg = logging.NewVanilla() baseDir = testdataloader.GetBasePath() scriptDir = path.Join(baseDir, "examples", "pincheck") pin = []byte("1234") @@ -51,7 +53,7 @@ func(rs *pinResource) pinCheck(ctx context.Context, sym string, input []byte) (r } if bytes.Equal(input, pin) { r.FlagSet = []uint32{USERFLAG_VALIDPIN} - engine.Logg.DebugCtxf(ctx, "pin match", "state", rs.st, "rs", r.FlagSet, "rr", r.FlagReset) + logg.DebugCtxf(ctx, "pin match", "state", rs.st, "rs", r.FlagSet, "rr", r.FlagReset) } else { r.Content = "Wrong PIN please try again" } diff --git a/examples/session/main.go b/examples/session/main.go @@ -15,9 +15,11 @@ import ( "git.defalsify.org/vise.git/engine" "git.defalsify.org/vise.git/resource" "git.defalsify.org/vise.git/state" + "git.defalsify.org/vise.git/logging" ) var ( + logg = logging.NewVanilla() baseDir = testdataloader.GetBasePath() scriptDir = path.Join(baseDir, "examples", "session") emptyResult = resource.Result{} @@ -32,7 +34,7 @@ func save(ctx context.Context, sym string, input []byte) (resource.Result, error } fp := path.Join(sessionDir, "data.txt") if len(input) > 0 { - engine.Logg.Debugf("write data %s session %s", input, sessionId) + logg.Debugf("write data %s session %s", input, sessionId) err = ioutil.WriteFile(fp, input, 0600) if err != nil { return emptyResult, err diff --git a/examples/state/main.go b/examples/state/main.go @@ -1,4 +1,4 @@ -// Example: Toggling states with external functions. +// Example: Toggling states with external functions, with engine debugger. package main import ( @@ -13,6 +13,7 @@ import ( "git.defalsify.org/vise.git/engine" "git.defalsify.org/vise.git/resource" "git.defalsify.org/vise.git/state" + "git.defalsify.org/vise.git/logging" ) const ( @@ -22,6 +23,7 @@ const ( ) var ( + logg = logging.NewVanilla() baseDir = testdataloader.GetBasePath() scriptDir = path.Join(baseDir, "examples", "state") ) @@ -40,7 +42,7 @@ func(f *flagResource) get(ctx context.Context, sym string, input []byte) (resour func(f *flagResource) do(ctx context.Context, sym string, input []byte) (resource.Result, error) { var r resource.Result - engine.Logg.DebugCtxf(ctx, "in do", "sym", sym) + logg.DebugCtxf(ctx, "in do", "sym", sym) switch(sym) { case "do_foo": diff --git a/examples/state_passive/main.go b/examples/state_passive/main.go @@ -15,6 +15,7 @@ import ( "git.defalsify.org/vise.git/cache" "git.defalsify.org/vise.git/persist" "git.defalsify.org/vise.git/db" + "git.defalsify.org/vise.git/logging" ) const ( @@ -24,6 +25,10 @@ const ( USERFLAG_DONE ) +var ( + logg = logging.NewVanilla() +) + type fsData struct { path string persister *persist.Persister @@ -57,9 +62,9 @@ func (fsd *fsData) poke(ctx context.Context, sym string, input []byte) (resource st := fsd.persister.GetState() for i := 8; i < 12; i++ { v := uint32(i) - engine.Logg.DebugCtxf(ctx, "checking flag", "flag", v) + logg.DebugCtxf(ctx, "checking flag", "flag", v) if st.MatchFlag(v, true) { - engine.Logg.DebugCtxf(ctx, "match on flag", "flag", v) + logg.DebugCtxf(ctx, "match on flag", "flag", v) res.FlagReset = append(res.FlagReset, v) res.FlagSet = append(res.FlagSet, v + 1) break diff --git a/lang/lang.go b/lang/lang.go @@ -7,14 +7,19 @@ import ( ) var ( + // Default language (hard to get around) Default = "eng" // ISO639-3 ) +// Language is used to set and get language translation to be used for rendering output. type Language struct { Code string Name string } +// LanguageFromCode returns a Language object from the given ISO-639-3 (three-letter) code. +// +// Will fail if an unknown code is provided. func LanguageFromCode(code string) (Language, error) { r := iso639_3.FromAnyCode(code) if r == nil { @@ -26,6 +31,9 @@ func LanguageFromCode(code string) (Language, error) { }, nil } +// String implements the String interface. +// +// Returns a representation of the Language fit for debugging. func(l Language) String() string { return fmt.Sprintf("%s (%s)", l.Code, l.Name) } diff --git a/logging/logging.go b/logging/logging.go @@ -3,15 +3,20 @@ package logging import ( "context" "io" - "os" ) const ( + // No logging LVL_NONE = iota + // Error log level - unexpected states that need immediate developer attention. LVL_ERROR + // Warning log level - unexpected states that may need developer attention. LVL_WARN + // Info log level - expected states that are of general interest to the end-user. LVL_INFO + // Debug log level - expected states that are of general interest to the developer. LVL_DEBUG + // Trace log level - everything else. LVL_TRACE ) @@ -25,30 +30,39 @@ var ( } ) -var ( - LogWriter = os.Stderr -) - - +// AsString returns the string representation used in logging output for the given log level. func AsString(level int) string { return levelStr[level] } - type Logger interface { + // Writef logs a line to the given writer with the given loglevel. Writef(w io.Writer, level int, msg string, args ...any) + // WriteCtxf logs a line with context to the given writer with the given loglevel. WriteCtxf(ctx context.Context, w io.Writer, level int, msg string, args ...any) + // Printf logs a line to the default writer with the given loglevel. Printf(level int, msg string, args ...any) + // Printf logs a line with context to the default writer with the given loglevel. PrintCtxf(ctx context.Context, level int, msg string, args ...any) + // Tracef logs a line to the default writer the TRACE loglevel. Tracef(msg string, args ...any) + // TraceCtxf logs a line with context to the default writer the TRACE loglevel. TraceCtxf(ctx context.Context, msg string, args ...any) + // Debugf logs a line to the default writer the DEBUG loglevel. Debugf(msg string, args ...any) + // DebugCtxf logs a line with context to the default writer the DEBUG loglevel. DebugCtxf(ctx context.Context, msg string, args ...any) + // Infof logs a line to the default writer the INFO loglevel. Infof(msg string, args ...any) + // InfoCtxf logs a line with context to the default writer the INFO loglevel. InfoCtxf(ctx context.Context, msg string, args ...any) + // Warnf logs a line to the default writer the WARN loglevel. Warnf(msg string, args ...any) + // WarnCtxf logs a line with context to the default writer the WARN loglevel. WarnCtxf(ctx context.Context, msg string, args ...any) + // Errorf logs a line to the default writer the ERROR loglevel. Errorf(msg string, args ...any) + // ErrorCtxf logs a line with context to the default writer the ERROR loglevel. ErrorCtxf(ctx context.Context, msg string, args ...any) } diff --git a/logging/vanilla.go b/logging/vanilla.go @@ -4,10 +4,16 @@ import ( "context" "fmt" "io" + "os" "path" "runtime" ) +var ( + // LogWriter is used as io.Writer the Vanilla Logger implementation. + LogWriter = os.Stderr +) + // Vanilla is a basic single-line structured output logger for terminal output. type Vanilla struct { domain string @@ -86,47 +92,47 @@ func(v Vanilla) Tracef(msg string, args ...any) { v.printf(LVL_TRACE, msg, args...) } -// Tracef logs a line with level DEBUG to the global writer. +// Debugf logs a line with level DEBUG to the global writer. func(v Vanilla) Debugf(msg string, args ...any) { v.printf(LVL_DEBUG, msg, args...) } -// Tracef logs a line with level INFO to the global writer. +// Infof logs a line with level INFO to the global writer. func(v Vanilla) Infof(msg string, args ...any) { v.printf(LVL_INFO, msg, args...) } -// Tracef logs a line with level WARN to the global writer. +// Warnf logs a line with level WARN to the global writer. func(v Vanilla) Warnf(msg string, args ...any) { v.printf(LVL_WARN, msg, args...) } -// Tracef logs a line with level ERROR to the global writer. +// Errorf logs a line with level ERROR to the global writer. func(v Vanilla) Errorf(msg string, args ...any) { v.printf(LVL_ERROR, msg, args...) } -// Tracef logs a line with context with level TRACE to the global writer. +// TraceCtxf logs a line with context with level TRACE to the global writer. func(v Vanilla) TraceCtxf(ctx context.Context, msg string, args ...any) { v.printCtxf(ctx, LVL_TRACE, msg, args...) } -// Tracef logs a line with context with level DEBUG to the global writer. +// DebugCtxf logs a line with context with level DEBUG to the global writer. func(v Vanilla) DebugCtxf(ctx context.Context, msg string, args ...any) { v.printCtxf(ctx, LVL_DEBUG, msg, args...) } -// Tracef logs a line with context with level INFO to the global writer. +// InfoCtxf logs a line with context with level INFO to the global writer. func(v Vanilla) InfoCtxf(ctx context.Context, msg string, args ...any) { v.printCtxf(ctx, LVL_INFO, msg, args...) } -// Tracef logs a line with context with level WARN to the global writer. +// WarnCtxf logs a line with context with level WARN to the global writer. func(v Vanilla) WarnCtxf(ctx context.Context, msg string, args ...any) { v.printCtxf(ctx, LVL_WARN, msg, args...) } -// Tracef logs a line with context with level ERROR to the global writer. +// ErrorCtxf logs a line with context with level ERROR to the global writer. func(v Vanilla) ErrorCtxf(ctx context.Context, msg string, args ...any) { v.printCtxf(ctx, LVL_ERROR, msg, args...) } diff --git a/persist/gdbm.go b/persist/gdbm.go @@ -1,92 +0,0 @@ -package persist - -import ( - "github.com/fxamacker/cbor/v2" - gdbm "github.com/graygnuorg/go-gdbm" - - "git.defalsify.org/vise.git/cache" - "git.defalsify.org/vise.git/state" - "git.defalsify.org/vise.git/db" -) - -// gdbmPersister is an implementation of Persister that saves state to the file system. -type gdbmPersister struct { - State *state.State - Memory *cache.Cache - db *gdbm.Database -} - -func NewGdbmPersiser(fp string) *gdbmPersister { - gdb, err := gdbm.Open(fp, gdbm.ModeReader) - if err != nil { - panic(err) - } - return NewGdbmPersisterFromDatabase(gdb) -} - -func NewGdbmPersisterFromDatabase(gdb *gdbm.Database) *gdbmPersister { - return &gdbmPersister{ - db: gdb, - } -} - -// WithContent sets a current State and Cache object. -// -// This method is normally called before Serialize / Save. -func(p *gdbmPersister) WithContent(st *state.State, ca *cache.Cache) *gdbmPersister { - p.State = st - p.Memory = ca - return p -} - -// TODO: DRY -// GetState implements the Persister interface. -func(p *gdbmPersister) GetState() *state.State { - return p.State -} - -// GetMemory implements the Persister interface. -func(p *gdbmPersister) GetMemory() cache.Memory { - return p.Memory -} - -// Serialize implements the Persister interface. -func(p *gdbmPersister) Serialize() ([]byte, error) { - return cbor.Marshal(p) -} - -// Deserialize implements the Persister interface. -func(p *gdbmPersister) Deserialize(b []byte) error { - err := cbor.Unmarshal(b, p) - return err -} - -// Save implements the Persister interface. -func(p *gdbmPersister) Save(key string) error { - b, err := p.Serialize() - if err != nil { - return err - } - k := db.ToDbKey(db.DATATYPE_STATE, []byte(key), nil) - err = p.db.Store(k, b, true) - if err != nil { - return err - } - Logg.Debugf("saved state and cache", "key", key, "bytecode", p.State.Code, "flags", p.State.Flags) - return nil -} - -// Load implements the Persister interface. -func(p *gdbmPersister) Load(key string) error { - k := db.ToDbKey(db.DATATYPE_STATE, []byte(key), nil) - b, err := p.db.Fetch(k) - if err != nil { - return err - } - err = p.Deserialize(b) - if err != nil { - return err - } - Logg.Debugf("loaded state and cache", "key", key, "bytecode", p.State.Code) - return nil -} diff --git a/persist/log.go b/persist/log.go @@ -5,5 +5,5 @@ import ( ) var ( - Logg logging.Logger = logging.NewVanilla().WithDomain("persist") + logg logging.Logger = logging.NewVanilla().WithDomain("persist") ) diff --git a/persist/persist.go b/persist/persist.go @@ -100,6 +100,6 @@ func(p *Persister) Load(key string) error { if err != nil { return err } - Logg.Debugf("loaded state and cache", "key", key, "bytecode", p.State.Code) + logg.Debugf("loaded state and cache", "key", key, "bytecode", p.State.Code) return nil } diff --git a/render/log.go b/render/log.go @@ -5,5 +5,5 @@ import ( ) var ( - Logg logging.Logger = logging.NewVanilla().WithDomain("render") + logg logging.Logger = logging.NewVanilla().WithDomain("render") ) diff --git a/render/menu.go b/render/menu.go @@ -9,7 +9,9 @@ import ( // BrowseError is raised when browsing outside the page range of a rendered node. type BrowseError struct { + // The lateral page index where the error occurred. Idx uint16 + // The total number of lateral page indicies. PageCount uint16 } @@ -20,15 +22,21 @@ func(err *BrowseError) Error() string { // BrowseConfig defines the availability and display parameters for page browsing. type BrowseConfig struct { + // Set if a consecutive page is available for lateral navigation. NextAvailable bool + // Menu selector used to navigate to next page. NextSelector string + // Menu title used to label selector for next page. NextTitle string + // Set if a previous page is available for lateral navigation. PreviousAvailable bool + // Menu selector used to navigate to previous page. PreviousSelector string + // Menu title used to label selector for previous page. PreviousTitle string } -// Default browse settings for convenience. +// Create a BrowseConfig with default values. func DefaultBrowseConfig() BrowseConfig { return BrowseConfig{ NextAvailable: true, @@ -40,7 +48,9 @@ func DefaultBrowseConfig() BrowseConfig { } } -// Menu renders menus. May be included in a Page object to render menus for pages. +// Menu renders menus. +// +// May be included in a Page object to render menus for pages. type Menu struct { rs resource.Resource menu [][2]string // selector and title for menu items. @@ -53,6 +63,9 @@ type Menu struct { keep bool } +// String implements the String interface. +// +// It returns debug representation of menu. func(m Menu) String() string { return fmt.Sprintf("pagecount: %v menusink: %v next: %v prev: %v", m.pageCount, m.sink, m.canNext, m.canPrevious) } @@ -64,12 +77,15 @@ func NewMenu() *Menu { } } -// WithBrowseConfig defines the criteria for page browsing. +// WithPageCount is a chainable function that defines the number of allowed pages for browsing. func(m *Menu) WithPageCount(pageCount uint16) *Menu { m.pageCount = pageCount return m } +// WithPages is a chainable function which activates pagination in the menu. +// +// It is equivalent to WithPageCount(1) func(m *Menu) WithPages() *Menu { if m.pageCount == 0 { m.pageCount = 1 @@ -77,11 +93,17 @@ func(m *Menu) WithPages() *Menu { return m } +// WithSink is a chainable function that informs the menu that a content sink exists in the render. +// +// A content sink receives priority to consume all remaining space after all non-sink items have been rendered. func(m *Menu) WithSink() *Menu { m.sink = true return m } +// WithDispose is a chainable function that preserves the menu after render is complete. +// +// It is used for multi-page content. func(m *Menu) WithDispose() *Menu { m.keep = false return m @@ -129,7 +151,11 @@ func(m *Menu) Put(selector string, title string) error { // return m.outputSize //} - // mainSize, prevsize, nextsize, nextsize+prevsize +// Sizes returns the size limitations for each part of the render, as a four-element array: +// 1. mainSize +// 2. prevsize +// 3. nextsize +// 4. nextsize + prevsize func(m *Menu) Sizes(ctx context.Context) ([4]uint32, error) { var menuSizes [4]uint32 cfg := m.GetBrowseConfig() @@ -154,6 +180,7 @@ func(m *Menu) Sizes(ctx context.Context) ([4]uint32, error) { return menuSizes, nil } +// title corresponding to the menu symbol. func(m *Menu) titleFor(ctx context.Context, title string) (string, error) { if m.rs == nil { return title, nil @@ -223,7 +250,7 @@ func(m *Menu) applyPage(idx uint16) error { if idx == 0 { m.canPrevious = false } - Logg.Debugf("applypage", "m", m, "idx", idx) + logg.Debugf("applypage", "m", m, "idx", idx) if m.canNext { err := m.Put(m.browse.NextSelector, m.browse.NextTitle) @@ -261,6 +288,7 @@ func(m *Menu) reset() { } } +// Reset clears all current state from the menu object, making it ready for re-use in a new render. func(m *Menu) Reset() { m.menu = [][2]string{} m.sink = false diff --git a/render/page.go b/render/page.go @@ -11,7 +11,7 @@ import ( "git.defalsify.org/vise.git/resource" ) -// Page exectues output rendering into pages constrained by size. +// Page executes output rendering into pages constrained by size. type Page struct { cacheMap map[string]string // Mapped content symbols cache cache.Memory // Content store. @@ -56,7 +56,7 @@ func(pg *Page) WithError(err error) *Page { return pg } -// Error implements error interface. +// Error implements the Error interface. func(pg *Page) Error() string { if pg.err != nil { return pg.err.Error() @@ -111,7 +111,7 @@ func(pg *Page) Map(key string) error { return err } } - Logg.Tracef("mapped", "key", key) + logg.Tracef("mapped", "key", key) return nil } @@ -154,7 +154,7 @@ func(pg *Page) RenderTemplate(ctx context.Context, sym string, values map[string tpl += pg.extra if pg.err != nil { derr := pg.Error() - Logg.DebugCtxf(ctx, "prepending error", "err", pg.err, "display", derr) + logg.DebugCtxf(ctx, "prepending error", "err", pg.err, "display", derr) if len(tpl) == 0 { tpl = derr } else { @@ -169,7 +169,7 @@ func(pg *Page) RenderTemplate(ctx context.Context, sym string, values map[string } else if idx > 0 { return "", fmt.Errorf("sizer needed for indexed render") } - Logg.Debugf("render for", "index", idx) + logg.Debugf("render for", "index", idx) tp, err := template.New("tester").Option("missingkey=error").Parse(tpl) if err != nil { @@ -228,13 +228,13 @@ func(pg *Page) split(sym string, values map[string]string) (map[string]string, s sink = k sinkValues = strings.Split(v, "\n") v = "" - Logg.Infof("found sink", "sym", sym, "sink", k) + logg.Infof("found sink", "sym", sym, "sink", k) } noSinkValues[k] = v } if sink == "" { - Logg.Tracef("no sink found", "sym", sym) + logg.Tracef("no sink found", "sym", sym) return values, "", nil, nil } return noSinkValues, sink, sinkValues, nil @@ -261,7 +261,7 @@ func(pg *Page) joinSink(sinkValues []string, remaining uint32, menuSizes [4]uint for i, v := range sinkValues { l += len(v) - Logg.Tracef("processing sink", "idx", i, "value", v, "netremaining", netRemaining, "l", l) + logg.Tracef("processing sink", "idx", i, "value", v, "netremaining", netRemaining, "l", l) if uint32(l) > netRemaining - 1 { if tb.Len() == 0 { return "", 0, fmt.Errorf("capacity insufficient for sink field %v", i) @@ -329,7 +329,7 @@ func(pg *Page) prepare(ctx context.Context, sym string, values map[string]string pg.extra = "\n{{._menu}}" pg.sizer.sink = sink noSinkValues[sink] = "" - Logg.DebugCtxf(ctx, "menu is sink", "items", len(sinkValues)) + logg.DebugCtxf(ctx, "menu is sink", "items", len(sinkValues)) } } @@ -355,7 +355,7 @@ func(pg *Page) prepare(ctx context.Context, sym string, values map[string]string return nil, err } } - Logg.Debugf("calculated pre-navigation allocation", "bytes", remaining, "menusizes", menuSizes) + logg.Debugf("calculated pre-navigation allocation", "bytes", remaining, "menusizes", menuSizes) // process sink values array into newline-separated string sinkString, count, err := pg.joinSink(sinkValues, remaining, menuSizes) @@ -371,7 +371,7 @@ func(pg *Page) prepare(ctx context.Context, sym string, values map[string]string // write all sink values to log. for i, v := range strings.Split(sinkString, "\n") { - Logg.Tracef("nosinkvalue", "idx", i, "value", v) + logg.Tracef("nosinkvalue", "idx", i, "value", v) } return noSinkValues, nil @@ -385,7 +385,7 @@ func(pg *Page) render(ctx context.Context, sym string, values map[string]string, if err != nil { return "", err } - Logg.Debugf("rendered template", "bytes", len(s)) + logg.Debugf("rendered template", "bytes", len(s)) r += s if pg.menu != nil { @@ -394,7 +394,7 @@ func(pg *Page) render(ctx context.Context, sym string, values map[string]string, return "", err } l := len(s) - Logg.Debugf("rendered menu", "bytes", l) + logg.Debugf("rendered menu", "bytes", l) if l > 0 { r += "\n" + s } diff --git a/render/size.go b/render/size.go @@ -45,8 +45,8 @@ func(szr *Sizer) Check(s string) (uint32, bool) { l := uint32(len(s)) if szr.outputSize > 0 { if l > szr.outputSize { - Logg.Infof("sized check fails", "length", l, "sizer", szr) - Logg.Tracef("", "sizer contents", s) + logg.Infof("sized check fails", "length", l, "sizer", szr) + logg.Tracef("", "sizer contents", s) return 0, false } l = szr.outputSize - l @@ -55,6 +55,8 @@ func(szr *Sizer) Check(s string) (uint32, bool) { } // String implements the String interface. +// +// It outputs a representation of the Sizer fit for debug output. func(szr *Sizer) String() string { // var diff uint32 // if szr.outputSize > 0 { @@ -82,7 +84,7 @@ func(szr *Sizer) Size(s string) (uint16, error) { // AddCursor adds a pagination cursor for the paged sink content. func(szr *Sizer) AddCursor(c uint32) { - Logg.Debugf("Added cursor", "offset", c) + logg.Debugf("Added cursor", "offset", c) szr.crsrs = append(szr.crsrs, c) } @@ -95,7 +97,7 @@ func(szr *Sizer) GetAt(values map[string]string, idx uint16) (map[string]string, } outValues := make(map[string]string) for k, v := range values { - Logg.Tracef("check values", "k", k, "v", v, "idx", idx, "cursors", szr.crsrs) + logg.Tracef("check values", "k", k, "v", v, "idx", idx, "cursors", szr.crsrs) if szr.sink == k { if idx >= uint16(len(szr.crsrs)) { return nil, fmt.Errorf("no more values in index") @@ -114,6 +116,7 @@ func(szr *Sizer) GetAt(values map[string]string, idx uint16) (map[string]string, return outValues, nil } +// Reset flushes all size measurements, making the sizer available for reuse. func(szr *Sizer) Reset() { szr.crsrs = []uint32{} } diff --git a/render/split.go b/render/split.go @@ -2,11 +2,9 @@ package render import ( "fmt" - "log" "strings" ) - func bookmark(values []string) []uint32 { var c int var bookmarks []uint32 = []uint32{0} @@ -95,7 +93,7 @@ func paginate(bookmarks []uint32, capacity uint32, nextSize uint32, prevSize uin var z int currentPage := len(pages) - 1 for i < lastIndex { - log.Printf("have item %v:%v (%v) index %v prevsize %v nextsize %v remain %v cap %v", bookmarks[i], lookAhead[i], lookAhead[i] - bookmarks[i], i, prevSize, nextSize, remaining, capacity) + logg.Tracef("have render", "bookmark", bookmarks[i], "lookahead", lookAhead[i], "diff", lookAhead[i] - bookmarks[i], "index", i, "prevsize", prevSize, "nextsize", nextSize, "remain", remaining, "capacity", capacity) v := lookAhead[i] delta := int((v - c) + 1) @@ -112,7 +110,7 @@ func paginate(bookmarks []uint32, capacity uint32, nextSize uint32, prevSize uin c = v i += 1 } - log.Printf("more %v remaining %v c %v last %v pages %v", haveMore, remaining, c, last, pages) + logg.Tracef("render more", "have", haveMore, "remain", remaining, "c", c, "last", last, "pages", pages) if haveMore { pages = append(pages, []uint32{}) @@ -146,7 +144,7 @@ func explode(values []string, pages [][]uint32) string { } end = c - z v := s[start:end] - log.Printf("page %v part %v %v %s", i, start, end, v) + logg.Tracef("explode", "page", i, "part start", start, "part end", end, "part str", v) v = s[start:end] sb.WriteString(v) start = end diff --git a/resource/fs.go b/resource/fs.go @@ -107,6 +107,7 @@ func(fsr FsResource) FuncFor(sym string) (EntryFunc, error) { return fsr.getFunc, nil } +// String implements the String interface. func(fsr FsResource) String() string { return fmt.Sprintf("fs resource at path: %s", fsr.Path) } diff --git a/resource/gdbm.go b/resource/gdbm.go @@ -87,6 +87,7 @@ func(dbr *gdbmResource) AddLocalFunc(sym string, fn EntryFunc) { dbr.fns[sym] = fn } +// String implements the String interface. func(dbr *gdbmResource) String() string { return fmt.Sprintf("gdbm: %v", dbr.db) } diff --git a/vm/input.go b/vm/input.go @@ -30,7 +30,7 @@ func NewInvalidInputError(input string) error { return InvalidInputError{input} } -// Error implements error interface. +// Error implements the Error interface. func(e InvalidInputError) Error() string { return fmt.Sprintf("invalid input: '%s'", e.input) } diff --git a/vm/runner.go b/vm/runner.go @@ -30,7 +30,7 @@ func(e *ExternalCodeError) WithCode(code int) *ExternalCodeError { return e } -// Error implements error interface +// Error implements the Error interface. func(e ExternalCodeError) Error() string { Logg.Errorf("external code error: %v", e.err) return fmt.Sprintf("error %v:%v", e.sym, e.code)