Add pretty display for struct array

This commit is contained in:
yo 2021-12-18 15:22:55 +01:00
parent 541222e2d0
commit 26166489fd

View File

@ -4,6 +4,7 @@ import (
"os" "os"
"fmt" "fmt"
"log" "log"
"reflect"
"io/ioutil" "io/ioutil"
"gocage/jail" "gocage/jail"
"encoding/json" "encoding/json"
@ -13,19 +14,147 @@ import (
var gJails []Jail var gJails []Jail
/* Pretty display of jails field
Fields to show are given in a string array parameter
Ex. : displayJails(["Name", "JID", "RootPath"])
*/
func displayStructFields(jails []Jail, valsToDisplay []string) {
/* A line is defined by :
Nr of fields
For each field :
Its name
Its max length
Its value
*/
type Field struct {
Name string
MaxLen int
Value string
}
type Line []Field
type Output []Line
var out Output
//fmt.Printf("%d fields in a %d items structure\n", len(valsToDisplay), len(jails))
// Browse structure to get max length and values
for _, j := range jails {
// Have to use a pointer, else reflect.Value.Elem() will panic : https://pkg.go.dev/reflect#Value.Elem
tj := &j
line := make([]Field, len(valsToDisplay))
for i, f := range valsToDisplay {
a := reflect.ValueOf(&tj).Elem()
//fmt.Printf("Struct : %s, Champ : %s\n", a.String(), f)
//fmt.Printf("%v", a.Elem().FieldByName(f).Interface())
field := Field {
Name: f,
// For now this just contains this item length, will adjust later
MaxLen: len(fmt.Sprintf("%v", a.Elem().FieldByName(f).Interface())),
Value: fmt.Sprintf("%v", a.Elem().FieldByName(f).Interface()),
}
line[i] = field
}
out = append(out, line)
}
// Get real maximum length
maxlen := make([]int, len(valsToDisplay))
for i := 0; i< len(valsToDisplay); i++ {
maxlen[i] = 0
}
for _, l := range out {
for i, f := range l {
if f.MaxLen > maxlen[i] {
maxlen[i] = f.MaxLen
}
}
}
// Align maxlen to the real maximum length
for io, l := range out {
for ii, _ := range l {
// We need to access slice by index if we want to modify content
out[io][ii].MaxLen = maxlen[ii]
}
}
totalLen := 0
// Add separator and 2 blank spaces
for _, f := range out[0] {
totalLen += f.MaxLen + 3
}
// Then add starting delimiter
totalLen += 1
Debug := false
if Debug == true {
for _, f := range out[0] {
fmt.Printf("%s max length : %d\n", f.Name, f.MaxLen)
}
}
// Lets draw things on the screen!
// First, headers
for i := 0; i < totalLen ; i++ {
fmt.Printf("-")
}
fmt.Printf("\n")
for i, f := range out[0] {
if i == 0 {
fmt.Printf("|")
}
fmt.Printf(" %s", f.Name)
for i := len(f.Name)+1 ; i < f.MaxLen+1 ; i++ {
fmt.Printf(" ")
}
fmt.Printf(" |")
}
fmt.Printf("\n")
for i := 0; i < totalLen ; i++ {
fmt.Printf("-")
}
fmt.Printf("\n")
// Then display data
for _, l := range out {
for i, f := range l {
if i == 0 {
fmt.Printf("|")
}
fmt.Printf(" %s", f.Value)
for i := len(f.Value)+1 ; i < f.MaxLen+1 ; i++ {
fmt.Printf(" ")
}
fmt.Printf(" |")
}
fmt.Printf("\n")
}
for i := 0; i < totalLen ; i++ {
fmt.Printf("-")
}
fmt.Printf("\n")
}
func listJails(args []string) { func listJails(args []string) {
for _, d := range viper.GetStringSlice("datastore") { for _, d := range viper.GetStringSlice("datastore") {
listJailsFromDatastore(d) listJailsFromDatastore(d)
} }
for _, j := range (gJails) { displayStructFields(gJails, []string{"JID", "Name", "RootPath"})
/* for _, j := range (gJails) {
if j.Running { if j.Running {
fmt.Printf("%d ; %s ; %s ; %s\n", j.JID, j.Name, j.Config.Ip4_addr, j.Config.Release) fmt.Printf("%d ; %s ; %s ; %s\n", j.JID, j.Name, j.Config.Ip4_addr, j.Config.Release)
} else { } else {
fmt.Printf(" ; %s ; %s ; %s\n", j.Name, j.Config.Ip4_addr, j.Config.Release) fmt.Printf(" ; %s ; %s ; %s\n", j.Name, j.Config.Ip4_addr, j.Config.Release)
} }
} }
*/
} }