Compare commits
No commits in common. "master" and "v0.0.6" have entirely different histories.
22
README.md
22
README.md
|
@ -1,11 +1,27 @@
|
||||||
// Copyright 2025 WIT.COM Inc Licensed GPL 3.0
|
// Copyright 2025 WIT.COM Inc Licensed GPL 3.0
|
||||||
|
|
||||||
|
// you can replace all of COBOL with this amount of GO
|
||||||
|
|
||||||
// ah yes, COBOL. what an ancient throwback. for those that know
|
// ah yes, COBOL. what an ancient throwback. for those that know
|
||||||
// then you know exactly what is in this file. For those that don't, here it is:
|
// then you know exactly what is in this file. For those that don't, here it is:
|
||||||
|
|
||||||
// All this does is output human readable text formatted to be viewable on
|
// All this does is output human readable text formatted to be viewable on
|
||||||
// a console with a fixed with font. AKA: a typerwriter. Which is exactly
|
// a console with a fixed with font. AKA: a typerwriter. Which is exactly
|
||||||
// what COBOL did in the 1970's (60s? notsure). And the 80s.
|
// what COBOL did in the 1970's (60s? notsure) And the 80s.
|
||||||
|
|
||||||
// Perl, before GO, was great for this kinda thing. GO with
|
// So, you want to dump out stuff on the console. Let's see. Something like
|
||||||
// protobuffers is even better
|
|
||||||
|
/*
|
||||||
|
forge --favorites
|
||||||
|
|
||||||
|
go.wit.com/apps/myapp v0.2.0 (installed)
|
||||||
|
go.wit.com/lib/somethingfun v0.0.7 (not downloaded)
|
||||||
|
*/
|
||||||
|
|
||||||
|
// anyway, you get the idea. This is also called COBOL because it does
|
||||||
|
// truncate every line output to the columns you see with stty -a
|
||||||
|
// my monitor is huge, so it's not going to work at 80x24. 160x48 is better
|
||||||
|
// actually, I'd predict some of these will probably end up 240 wide
|
||||||
|
// long live good eyesight and 4K monitors!
|
||||||
|
|
||||||
|
// TODO: fix this to truncate with stty cols width
|
||||||
|
|
|
@ -4,7 +4,6 @@ package cobol
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: make this more generic
|
// TODO: make this more generic
|
||||||
|
@ -14,42 +13,6 @@ import (
|
||||||
// sizes := []int{40, 12, 6, 12, 16, 16, 16, 12, 12, 8}
|
// sizes := []int{40, 12, 6, 12, 16, 16, 16, 12, 12, 8}
|
||||||
// log.Info(standardTableSize10(sizes, args))
|
// log.Info(standardTableSize10(sizes, args))
|
||||||
|
|
||||||
// returns the line and the Sprintf fmt string
|
|
||||||
func StandardTableRow(sizes []int, args []string) (string, string) {
|
|
||||||
var fmts []string
|
|
||||||
var parts []string
|
|
||||||
for i, si := range sizes {
|
|
||||||
var cell string
|
|
||||||
var sfmt string
|
|
||||||
if si < 0 {
|
|
||||||
sfmt = "%-s"
|
|
||||||
} else if si == 0 {
|
|
||||||
sfmt = "%-8.8s"
|
|
||||||
} else {
|
|
||||||
sfmt = "%-" + fmt.Sprintf("%d", si) + "." + fmt.Sprintf("%d", si) + "s "
|
|
||||||
}
|
|
||||||
fmts = append(fmts, sfmt)
|
|
||||||
if len(args) > i {
|
|
||||||
val := args[i]
|
|
||||||
cell = fmt.Sprintf(sfmt, val)
|
|
||||||
parts = append(parts, cell)
|
|
||||||
} else {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// todo: change pad based on total size(?)
|
|
||||||
line := strings.Join(parts, " ")
|
|
||||||
|
|
||||||
var small int
|
|
||||||
if len(line) > WIDTH {
|
|
||||||
small = WIDTH
|
|
||||||
} else {
|
|
||||||
small = len(line) - 3
|
|
||||||
}
|
|
||||||
return line[0:small], strings.Join(fmts, " ")
|
|
||||||
}
|
|
||||||
|
|
||||||
func StandardTableSize5(sizes []int, args []string) string {
|
func StandardTableSize5(sizes []int, args []string) string {
|
||||||
WIDTH, _ := getTerminalWidth()
|
WIDTH, _ := getTerminalWidth()
|
||||||
var s string
|
var s string
|
||||||
|
|
217
tablePB.go
217
tablePB.go
|
@ -3,225 +3,10 @@
|
||||||
package cobol
|
package cobol
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"go.wit.com/lib/gui/shell"
|
|
||||||
"go.wit.com/lib/protobuf/guipb"
|
"go.wit.com/lib/protobuf/guipb"
|
||||||
"go.wit.com/log"
|
"go.wit.com/log"
|
||||||
"google.golang.org/protobuf/types/known/anypb"
|
|
||||||
"google.golang.org/protobuf/types/known/timestamppb"
|
|
||||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func PrintTable(pb *guipb.Table) {
|
func PrintTable(pb *guipb.Table) {
|
||||||
// log.Info("print PB here")
|
log.Info("print PB here")
|
||||||
|
|
||||||
if pb.Grid == nil {
|
|
||||||
// log.Info("grid = nil")
|
|
||||||
} else {
|
|
||||||
// log.Info("grid.Id =", pb.Grid.Id)
|
|
||||||
}
|
|
||||||
|
|
||||||
var h int = 0
|
|
||||||
var w int = 0
|
|
||||||
var HEIGHT int
|
|
||||||
if pb.Height == 0 {
|
|
||||||
HEIGHT = 4
|
|
||||||
}
|
|
||||||
// log.Info("pb.Height", pb.Height, HEIGHT)
|
|
||||||
var args []string
|
|
||||||
var sizes []int
|
|
||||||
for _, name := range pb.Order {
|
|
||||||
arg, attr, tmp := getColAttr(pb, name)
|
|
||||||
if attr == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
HEIGHT = tmp
|
|
||||||
args = append(args, arg)
|
|
||||||
if attr.Width == 0 {
|
|
||||||
sizes = append(sizes, 8)
|
|
||||||
} else {
|
|
||||||
sizes = append(sizes, int(attr.Width))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// sizes = []int{24, 5, 8, 32, 13, 4, 4, 4, 4}
|
|
||||||
header, _ := StandardTableRow(sizes, args)
|
|
||||||
log.Info(header)
|
|
||||||
|
|
||||||
for i := range HEIGHT {
|
|
||||||
var cells []string
|
|
||||||
for _, name := range pb.Order {
|
|
||||||
if val, ok := getAnyCell(pb, name, int(i)); ok {
|
|
||||||
h += 1
|
|
||||||
cells = append(cells, val)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if val, ok := getTableCell(pb, name, int(i)); ok {
|
|
||||||
// log.Info("tree: CELL GOOD", pb.Title, name, w, h, val)
|
|
||||||
h += 1
|
|
||||||
cells = append(cells, val)
|
|
||||||
} else {
|
|
||||||
log.Info("tree: CELL FAIL", pb.Title, name, w, h, val)
|
|
||||||
cells = append(cells, "err")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
line, fmtline := StandardTableRow(sizes, cells)
|
|
||||||
if os.Getenv("TABLEPB_VERBOSE") == "true" {
|
|
||||||
line += "FMT: " + fmtline
|
|
||||||
}
|
|
||||||
log.Info(line)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeGridLabel(pb *guipb.Widget, w int, h int) {
|
|
||||||
log.Info("MAKE GRID LABEL", w, h, pb.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
func extractInt64(anyVal *anypb.Any) (int64, error) {
|
|
||||||
val := &wrapperspb.Int64Value{}
|
|
||||||
if err := anyVal.UnmarshalTo(val); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return val.Value, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getTableCell(t *guipb.Table, name string, row int) (string, bool) {
|
|
||||||
// find the Column that matches the "name"
|
|
||||||
for _, r := range t.StringCols {
|
|
||||||
if name != r.Header.Name {
|
|
||||||
// log.Info("skip string row:", r.Header.Name, "!=", name)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// log.Info("Cell value:", r.Vals[row])
|
|
||||||
return r.Vals[row], true
|
|
||||||
}
|
|
||||||
for _, r := range t.ButtonCols {
|
|
||||||
if name != r.Header.Name {
|
|
||||||
// log.Info("skip string row:", r.Header.Name, "!=", name)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// log.Info("Cell value:", r.Vals[row])
|
|
||||||
return r.Vals[row], true
|
|
||||||
}
|
|
||||||
for _, r := range t.IntCols {
|
|
||||||
if name != r.Header.Name {
|
|
||||||
// log.Info("skip string row:", r.Header.Name, "!=", name)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("%d", r.Vals[row]), true
|
|
||||||
}
|
|
||||||
for _, r := range t.TimeCols {
|
|
||||||
if name != r.Header.Name {
|
|
||||||
// log.Info("skip sint row:", r.Header.Name, "!=", name)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
cellTime := r.Vals[row]
|
|
||||||
s := shell.FormatDuration(time.Since(cellTime.AsTime()))
|
|
||||||
return s, true
|
|
||||||
}
|
|
||||||
for _, r := range t.AnyCols {
|
|
||||||
if name != r.Header.Name {
|
|
||||||
// log.Info("skip sint row:", r.Header.Name, "!=", name)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// cellTime := r.Vals[row]
|
|
||||||
// s := shell.FormatDuration(time.Since(cellTime.AsTime()))
|
|
||||||
return "fixme", true
|
|
||||||
}
|
|
||||||
return "", false
|
|
||||||
}
|
|
||||||
|
|
||||||
func getAnyCell(t *guipb.Table, name string, row int) (string, bool) {
|
|
||||||
for _, col := range t.AnyCols {
|
|
||||||
if name != col.Header.Name {
|
|
||||||
// log.Info("skip sint row:", r.Header.Name, "!=", name)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
anyVal := col.Vals[row]
|
|
||||||
|
|
||||||
switch col.Attr.Type {
|
|
||||||
case guipb.ColAttr_STRING:
|
|
||||||
// return col.Vals[row] true
|
|
||||||
// Assume 'anyVal' is an element from your r.Vals slice
|
|
||||||
var stringValue wrapperspb.StringValue
|
|
||||||
if err := anyVal.UnmarshalTo(&stringValue); err == nil {
|
|
||||||
// It's a string, now convert it back to a native Go string
|
|
||||||
goString := stringValue.GetValue()
|
|
||||||
// fmt.Printf("Successfully unpacked string: %s\n", goString)
|
|
||||||
return goString, true
|
|
||||||
}
|
|
||||||
case guipb.ColAttr_INT:
|
|
||||||
var finalInt int32
|
|
||||||
// 1. Check if the Any contains an Int32Value
|
|
||||||
if anyVal.MessageIs(&wrapperspb.Int32Value{}) {
|
|
||||||
var intValue wrapperspb.Int32Value
|
|
||||||
// 2. Unmarshal into the wrapper
|
|
||||||
if err := anyVal.UnmarshalTo(&intValue); err == nil {
|
|
||||||
// 3. Get the native Go int32 from the wrapper
|
|
||||||
finalInt = intValue.GetValue()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Sprintf("%d", finalInt), true
|
|
||||||
case guipb.ColAttr_DURATION:
|
|
||||||
case guipb.ColAttr_TIME:
|
|
||||||
var sout string
|
|
||||||
var tsProto timestamppb.Timestamp
|
|
||||||
if err := anyVal.UnmarshalTo(&tsProto); err == nil {
|
|
||||||
// It's a timestamp, now convert it back to a Go time.Time
|
|
||||||
goTime := tsProto.AsTime()
|
|
||||||
// fmt.Printf("Successfully unpacked timestamp: %v\n", goTime)
|
|
||||||
sout = shell.FormatDuration(time.Since(goTime))
|
|
||||||
return sout, true
|
|
||||||
}
|
|
||||||
return "", false
|
|
||||||
default:
|
|
||||||
log.Info("cell unhandled type", col.Attr.Type)
|
|
||||||
}
|
|
||||||
// cellTime := r.Vals[row]
|
|
||||||
// s := shell.FormatDuration(time.Since(cellTime.AsTime()))
|
|
||||||
return "fixme", true
|
|
||||||
}
|
|
||||||
return "", false
|
|
||||||
}
|
|
||||||
|
|
||||||
func getColAttr(t *guipb.Table, name string) (string, *guipb.ColAttr, int) {
|
|
||||||
// find the Column that matches the "name"
|
|
||||||
for _, r := range t.StringCols {
|
|
||||||
if name != r.Header.Name {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return r.Header.Name, r.Attr, len(r.Vals)
|
|
||||||
}
|
|
||||||
for _, r := range t.ButtonCols {
|
|
||||||
if name != r.Header.Name {
|
|
||||||
// log.Info("skip string row:", r.Header.Name, "!=", name)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return r.Header.Name, r.Attr, len(r.Vals)
|
|
||||||
}
|
|
||||||
for _, r := range t.IntCols {
|
|
||||||
if name != r.Header.Name {
|
|
||||||
// log.Info("skip string row:", r.Header.Name, "!=", name)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return r.Header.Name, r.Attr, len(r.Vals)
|
|
||||||
}
|
|
||||||
for _, r := range t.TimeCols {
|
|
||||||
if name != r.Header.Name {
|
|
||||||
// log.Info("skip sint row:", r.Header.Name, "!=", name)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return r.Header.Name, r.Attr, len(r.Vals)
|
|
||||||
}
|
|
||||||
for _, r := range t.AnyCols {
|
|
||||||
if name != r.Header.Name {
|
|
||||||
// log.Info("skip sint row:", r.Header.Name, "!=", name)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return r.Header.Name, r.Attr, len(r.Vals)
|
|
||||||
}
|
|
||||||
return "", nil, 0
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue