From 6f9017871fc36e334545d3d66fc6950ddf50551cc043d90dd831187ed27eeb46 Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Sun, 13 Apr 2025 15:13:57 +0300 Subject: [PATCH] Move human pretty printer to separate file Just for convenience. --- go/cmd/pp/main.go | 198 -------------------------------------- go/cmd/pp/printer.go | 223 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 223 insertions(+), 198 deletions(-) create mode 100644 go/cmd/pp/printer.go diff --git a/go/cmd/pp/main.go b/go/cmd/pp/main.go index bb77ab6..b26c41c 100644 --- a/go/cmd/pp/main.go +++ b/go/cmd/pp/main.go @@ -17,21 +17,15 @@ package main import ( "bufio" - "encoding/hex" "encoding/json" "flag" "fmt" "io" "log" "os" - "slices" - "strconv" "strings" - "time" "go.cypherpunks.su/keks" - "go.cypherpunks.su/keks/types" - "go.cypherpunks.su/tai64n/v4" ) func usage() { @@ -60,198 +54,6 @@ var ( pth []string ) -func prindent(depth int) { - fmt.Print(strings.Repeat(" ", depth)) -} - -func hexenc(b []byte) string { - return strings.ToUpper(hex.EncodeToString(b)) -} - -func printbin(s []byte) { - sLen := len(s) - var dots string - if sLen > int(*MaxStrLen) { - s = s[:int(*MaxStrLen)] - dots = "..." - } - if *onlyV { - fmt.Println(hexenc(s)) - } else { - fmt.Printf("%s%d:%s%s%s\n", Magenta, sLen, Reset, hexenc(s), dots) - } -} - -func isQuiet(where []string) bool { - if len(pth) == 0 { - return false - } - if len(pth) > len(where) { - return true - } - return !slices.Equal(where[:len(pth)], pth) -} - -func printer(iter *keks.Iterator, where []string, count int, inList, inMap bool) { - var quiet bool - for i := range count { - if !iter.Next() { - panic("unexpected") - } - depth := iter.Depth - var key string - if inMap { - key = iter.Str() - if !iter.Next() { - panic("unexpected") - } - } - if inList { - where[len(where)-1] = strconv.Itoa(i) - } else if inMap { - where[len(where)-1] = key - } - quiet = isQuiet(where) - if !quiet && !*onlyV { - fmt.Print(Blue + strconv.Itoa(depth) + Reset) - fmt.Printf(" %s%03d%s ", Red, iter.Offset(), Reset) - prindent(depth) - if inList { - fmt.Printf("%s%d:%s ", Yellow, i, Reset) - } else if inMap { - fmt.Printf("%s%s:%s ", Green, key, Reset) - } - } - var listOrMap bool - switch iter.T { - case types.List: - listOrMap = true - if !quiet && !*onlyV { - fmt.Printf("[ %s%d%s\n", Cyan, iter.Len(), Reset) - } - printer(iter, append(where, "0"), iter.Len(), true, false) - if !quiet && !*onlyV { - prindent(depth) - fmt.Println(" " + " ]") - } - case types.Map: - listOrMap = true - if !quiet && !*onlyV { - fmt.Printf("{ %s%d%s\n", Cyan, iter.Len(), Reset) - } - printer(iter, append(where, key), iter.Len(), false, true) - if !quiet && !*onlyV { - prindent(depth) - fmt.Println(" " + " }") - } - } - if listOrMap || quiet { - continue - } - switch iter.T { - case types.NIL: - fmt.Println("NIL") - case types.Bool: - if iter.Bool() { - fmt.Println("TRUE") - } else { - fmt.Println("FALSE") - } - case types.Hexlet: - h := iter.Hexlet() - if *onlyV { - fmt.Println(h.UUID()) - } else { - fmt.Println(h.UUID(), h.IP()) - } - case types.UInt: - fmt.Println(iter.UInt()) - case types.Int: - fmt.Println(iter.Int()) - case types.BigInt: - fmt.Println(iter.BigInt()) - case types.Blob: - blob := iter.Blob() - if *onlyV { - v, err := io.ReadAll(blob.Reader()) - if err != nil { - log.Fatal(err) - } - fmt.Println(hex.EncodeToString(v)) - break - } - fmt.Printf("BLOB[ %s%d l=%d%s\n", - Cyan, len(blob.Chunks), blob.ChunkLen, Reset) - off := iter.Offset() + 1 + 8 - for i, chunk := range blob.Chunks { - fmt.Print(Blue + strconv.Itoa(depth+1) + Reset) - fmt.Printf(" %s%03d%s ", Red, off, Reset) - prindent(depth + 1) - fmt.Printf("%s%d:%s ", Yellow, i, Reset) - printbin([]byte(chunk)) - off += int64(len(chunk)) + 1 - } - prindent(depth) - fmt.Println(" " + " ]") - case types.TAI64: - t := iter.TAI64().Time() - utc, isLeap := tai64n.Leapsecs.Sub(t) - if isLeap { - fmt.Printf("TAI64(%s TAI, leap)\n", t.Format(time.DateTime)) - } else { - fmt.Printf("TAI64(%s TAI, %s UTC)\n", - t.Format(time.DateTime), utc.Format(time.DateTime)) - } - case types.TAI64N: - t := iter.TAI64N().Time() - utc, isLeap := tai64n.Leapsecs.Sub(t) - if isLeap { - fmt.Printf("TAI64N(%s TAI, leap)\n", - t.Format(time.DateTime+".000000000")) - } else { - fmt.Printf("TAI64N(%s TAI, %s UTC)\n", - t.Format(time.DateTime+".000000000"), - utc.Format(time.DateTime+".000000000")) - } - case types.TAI64NA: - t := iter.TAI64NA() - fmt.Printf("TAI64NA(%s)\n", hexenc(t[:])) - case types.Magic: - var builder strings.Builder - for _, b := range []byte(iter.Magic()) { - if strconv.IsPrint(rune(b)) { - builder.WriteByte(b) - } else { - builder.WriteString(fmt.Sprintf("\\x%02x", b)) - } - } - fmt.Printf("Magic(%s)\n", builder.String()) - case types.Bin: - printbin(iter.Bin()) - case types.Str: - if !*onlyV { - fmt.Print(`"`) - } - s := iter.Str() - sLen := len(s) - if sLen > int(*MaxStrLen) { - fmt.Print(s[:int(*MaxStrLen)]) - fmt.Print("...") - } else { - fmt.Print(s) - } - if !*onlyV { - fmt.Print(`"`) - } - fmt.Println("") - case types.Raw: - fmt.Printf("(l=%d v=%s)\n", len(iter.Raw()), hexenc(iter.Raw())) - default: - fmt.Println("???") - } - } -} - func main() { flag.Usage = usage flag.Parse() diff --git a/go/cmd/pp/printer.go b/go/cmd/pp/printer.go new file mode 100644 index 0000000..6d91d5c --- /dev/null +++ b/go/cmd/pp/printer.go @@ -0,0 +1,223 @@ +// pp -- KEKS pretty printer +// Copyright (C) 2024-2025 Sergey Matveev +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation, version 3 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this program. If not, see . + +package main + +import ( + "encoding/hex" + "fmt" + "io" + "log" + "slices" + "strconv" + "strings" + "time" + + "go.cypherpunks.su/keks" + "go.cypherpunks.su/keks/types" + "go.cypherpunks.su/tai64n/v4" +) + +func isQuiet(where []string) bool { + if len(pth) == 0 { + return false + } + if len(pth) > len(where) { + return true + } + return !slices.Equal(where[:len(pth)], pth) +} + +func prindent(depth int) { + fmt.Print(strings.Repeat(" ", depth)) +} + +func hexenc(b []byte) string { + return strings.ToUpper(hex.EncodeToString(b)) +} + +func printbin(s []byte) { + sLen := len(s) + var dots string + if sLen > int(*MaxStrLen) { + s = s[:int(*MaxStrLen)] + dots = "..." + } + if *onlyV { + fmt.Println(hexenc(s)) + } else { + fmt.Printf("%s%d:%s%s%s\n", Magenta, sLen, Reset, hexenc(s), dots) + } +} + +func printer(iter *keks.Iterator, where []string, count int, inList, inMap bool) { + var quiet bool + for i := range count { + if !iter.Next() { + panic("unexpected") + } + depth := iter.Depth + var key string + if inMap { + key = iter.Str() + if !iter.Next() { + panic("unexpected") + } + } + if inList { + where[len(where)-1] = strconv.Itoa(i) + } else if inMap { + where[len(where)-1] = key + } + quiet = isQuiet(where) + if !quiet && !*onlyV { + fmt.Print(Blue + strconv.Itoa(depth) + Reset) + fmt.Printf(" %s%03d%s ", Red, iter.Offset(), Reset) + prindent(depth) + if inList { + fmt.Printf("%s%d:%s ", Yellow, i, Reset) + } else if inMap { + fmt.Printf("%s%s:%s ", Green, key, Reset) + } + } + var listOrMap bool + switch iter.T { + case types.List: + listOrMap = true + if !quiet && !*onlyV { + fmt.Printf("[ %s%d%s\n", Cyan, iter.Len(), Reset) + } + printer(iter, append(where, "0"), iter.Len(), true, false) + if !quiet && !*onlyV { + prindent(depth) + fmt.Println(" " + " ]") + } + case types.Map: + listOrMap = true + if !quiet && !*onlyV { + fmt.Printf("{ %s%d%s\n", Cyan, iter.Len(), Reset) + } + printer(iter, append(where, key), iter.Len(), false, true) + if !quiet && !*onlyV { + prindent(depth) + fmt.Println(" " + " }") + } + } + if listOrMap || quiet { + continue + } + switch iter.T { + case types.NIL: + fmt.Println("NIL") + case types.Bool: + if iter.Bool() { + fmt.Println("TRUE") + } else { + fmt.Println("FALSE") + } + case types.Hexlet: + h := iter.Hexlet() + if *onlyV { + fmt.Println(h.UUID()) + } else { + fmt.Println(h.UUID(), h.IP()) + } + case types.UInt: + fmt.Println(iter.UInt()) + case types.Int: + fmt.Println(iter.Int()) + case types.BigInt: + fmt.Println(iter.BigInt()) + case types.Blob: + blob := iter.Blob() + if *onlyV { + v, err := io.ReadAll(blob.Reader()) + if err != nil { + log.Fatal(err) + } + fmt.Println(hex.EncodeToString(v)) + break + } + fmt.Printf("BLOB[ %s%d l=%d%s\n", + Cyan, len(blob.Chunks), blob.ChunkLen, Reset) + off := iter.Offset() + 1 + 8 + for i, chunk := range blob.Chunks { + fmt.Print(Blue + strconv.Itoa(depth+1) + Reset) + fmt.Printf(" %s%03d%s ", Red, off, Reset) + prindent(depth + 1) + fmt.Printf("%s%d:%s ", Yellow, i, Reset) + printbin([]byte(chunk)) + off += int64(len(chunk)) + 1 + } + prindent(depth) + fmt.Println(" " + " ]") + case types.TAI64: + t := iter.TAI64().Time() + utc, isLeap := tai64n.Leapsecs.Sub(t) + if isLeap { + fmt.Printf("TAI64(%s TAI, leap)\n", t.Format(time.DateTime)) + } else { + fmt.Printf("TAI64(%s TAI, %s UTC)\n", + t.Format(time.DateTime), utc.Format(time.DateTime)) + } + case types.TAI64N: + t := iter.TAI64N().Time() + utc, isLeap := tai64n.Leapsecs.Sub(t) + if isLeap { + fmt.Printf("TAI64N(%s TAI, leap)\n", + t.Format(time.DateTime+".000000000")) + } else { + fmt.Printf("TAI64N(%s TAI, %s UTC)\n", + t.Format(time.DateTime+".000000000"), + utc.Format(time.DateTime+".000000000")) + } + case types.TAI64NA: + t := iter.TAI64NA() + fmt.Printf("TAI64NA(%s)\n", hexenc(t[:])) + case types.Magic: + var builder strings.Builder + for _, b := range []byte(iter.Magic()) { + if strconv.IsPrint(rune(b)) { + builder.WriteByte(b) + } else { + builder.WriteString(fmt.Sprintf("\\x%02x", b)) + } + } + fmt.Printf("Magic(%s)\n", builder.String()) + case types.Bin: + printbin(iter.Bin()) + case types.Str: + if !*onlyV { + fmt.Print(`"`) + } + s := iter.Str() + sLen := len(s) + if sLen > int(*MaxStrLen) { + fmt.Print(s[:int(*MaxStrLen)]) + fmt.Print("...") + } else { + fmt.Print(s) + } + if !*onlyV { + fmt.Print(`"`) + } + fmt.Println("") + case types.Raw: + fmt.Printf("(l=%d v=%s)\n", len(iter.Raw()), hexenc(iter.Raw())) + default: + fmt.Println("???") + } + } +} -- 2.48.1