displaySnapshotsFields is a copy of displayJailsFields to pretty display jails snapshots

This commit is contained in:
yo 2022-04-04 19:47:15 +02:00
parent 1c40e29eff
commit 7b34495cf6
3 changed files with 215 additions and 5 deletions

View File

@ -139,7 +139,7 @@ func ListJails(args []string, display bool) {
/ Finally, display jails
/**************************************************************/
if display {
displayStructFields(jails, fields)
displayJailsFields(jails, fields)
}
}

View File

@ -80,7 +80,8 @@ func listJailSnapshots(jail Jail) {
SnapshotsOrderedBy(ss.CreationInc).Sort(snapshots)
// TODO : Pretty display. Make an interface of displayStructFields?
for _, s := range snapshots {
displaySnapshotsFields(snapshots, []string{"Name","Creation","Referenced","Used"})
/*for _, s := range snapshots {
fmt.Printf("| %s | %s | %s | %s |\n", s.Name, s.Creation.String(), s.Referenced, s.Used)
}
}*/
}

View File

@ -288,9 +288,9 @@ func getStructField(parentStruct interface{}, fieldName string) (reflect.Value,
/********************************************************************************
* Pretty display of jails field
* Fields to show are given in a string array parameter
* Ex. : displayJails(["Name", "JID", "RootPath"])
* Ex. : displayJailsFields(["Name", "JID", "RootPath"])
*******************************************************************************/
func displayStructFields(jails []Jail, valsToDisplay []string) {
func displayJailsFields(jails []Jail, valsToDisplay []string) {
/* A line is defined by :
* Nr of fields
* For each field :
@ -495,6 +495,215 @@ func displayStructFields(jails []Jail, valsToDisplay []string) {
fmt.Printf("\n")
}
/********************************************************************************
* Pretty display of snapshots field
* Fields to show are given in a string array parameter
* Ex. : displaySnapshotsFields(["Name", "Dsname", "Used"])
*******************************************************************************/
func displaySnapshotsFields(snaps []Snapshot, 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 _, s := range snaps {
// Have to use a pointer, else reflect.Value.Elem() will panic : https://pkg.go.dev/reflect#Value.Elem
tj := &s
line := make([]Field, len(valsToDisplay))
for i, f := range valsToDisplay {
a, f := getStructField(tj, f)
field := Field {
Name: f,
}
if a.FieldByName(f).IsValid() {
// For now this just contains this item length, will adjust later
// We need to divide length by number of items in string fields (because we can have more than 1 ip4_addr)
if reflect.TypeOf(a.FieldByName(f).Interface()).Kind() == reflect.String {
itnr := len(strings.Split(string(a.FieldByName(f).Interface().(string)), ","))
field.MaxLen = len(fmt.Sprintf("%v", a.FieldByName(f).Interface())) / itnr
} else {
field.MaxLen = len(fmt.Sprintf("%v", a.FieldByName(f).Interface()))
}
field.Value = fmt.Sprintf("%v", a.FieldByName(f).Interface())
} else {
fmt.Printf("Invalid field name: %s\n", f)
}
line[i] = field
}
out = append(out, line)
}
if len(out) == 0 {
fmt.Printf("Nothing to see here!\n")
return
}
// Get real maximum length
maxlen := make([]int, len(valsToDisplay))
for i := 0; i< len(valsToDisplay); i++ {
maxlen[i] = len(valsToDisplay[i])
}
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
// For each field, 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: 1st separator line
for i, f := range out[0] {
if i == 0 { fmt.Printf("+") }
for i := 0 ; i < f.MaxLen+2 ; i++ { fmt.Printf("=") }
fmt.Printf("+")
}
fmt.Printf("\n")
// Column names
for i, f := range out[0] {
if i == 0 {
fmt.Printf("|")
}
/* Use vlsToDisplay to get real name (with "Config.")
* fmt.Printf(" %s", f.Name)
* for i := len(f.Name)+1 ; i < f.MaxLen+1 ; i++ { */
fmt.Printf(" %s", valsToDisplay[i])
for i := len(valsToDisplay[i])+1 ; i < f.MaxLen+1 ; i++ {
fmt.Printf(" ")
}
fmt.Printf(" |")
}
// Finally separator line
fmt.Printf("\n")
for i, f := range out[0] {
if i == 0 { fmt.Printf("+") }
for i := 0 ; i < f.MaxLen+2 ; i++ { fmt.Printf("=") }
fmt.Printf("+")
}
fmt.Printf("\n")
// Then display data
// Loop through lines
for _, l := range out {
// Loop through fields
// In case we need to add a line for a 2nd IP, or whatever object
var supplines = make(map[string]string)
for i, f := range l {
if i == 0 {
fmt.Printf("|")
}
// Special cases of value displaying
/* if f.Name == "JID" && f.Value == "0" {
fmt.Printf(" ")
} else if f.Name == "Ip4_addr" {
ia := strings.Split(f.Value, ",")
// If we have more than 1 value we need to finish this line, and store value for writing at the end of line loop
for i, inter := range ia {
if i > 0 {
supplines[f.Name] = inter
} else {
fmt.Printf(" %s", inter)
}
}
//fmt.Printf(" %s", strings.Split(strings.Split(f.Value, "|")[1], "/")[0])
} else {*/
fmt.Printf(" %s", f.Value)
/*}*/
// Complete with spaces to the max length
for i := len(f.Value)+1 ; i < f.MaxLen+1 ; i++ {
fmt.Printf(" ")
}
fmt.Printf(" |")
}
// Draw supplementary lines
if len(supplines) > 0 {
for i, f := range l {
if i == 0 {
fmt.Printf("\n|")
}
// Overwrite value in this scope
v, exists := supplines[f.Name]
if exists {
fmt.Printf(" %s", v)
} else {
// 1st option : Do not redisplay precedent line values
fmt.Printf(" ")
// 2nd option : Redisplay precedenet line values
//fmt.Printf(" %s", f.Value)
}
// Complete with spaces to the max length
for i := len(v)+1 ; i < f.MaxLen+1 ; i++ {
fmt.Printf(" ")
}
fmt.Printf(" |")
}
}
// Draw line separator between jails
if !gNoLineSep {
fmt.Printf("\n")
for i, f := range out[0] {
if i == 0 { fmt.Printf("+") }
for i := 0 ; i < f.MaxLen+2 ; i++ { fmt.Printf("-") }
fmt.Printf("+")
}
}
fmt.Printf("\n")
}
if gNoLineSep {
for i, f := range out[0] {
if i == 0 { fmt.Printf("+") }
for i := 0 ; i < f.MaxLen+2 ; i++ { fmt.Printf("-") }
fmt.Printf("+")
}
}
fmt.Printf("\n")
}
/*****************************************************************************