Reputation: 27
Kind of stuck with this. My idea is having a function that prints a two-columns table. The first one is for keys, and it has a fixed width. The second one is for values, which may be very long strings, and its width depends on the current width of the terminal.
An example of what I'd like to have:
Key1 Value1Value1Value1Value1
Key2 Value2Value2Value2Value2Value2Value2Value2Value2Value2Value2Value2
Value2Value2Value2Value2Value2Value2Value2Value2Value2Value2Value2
Value2Value2Value2Value2Value2Value2
So far, the best I achieved is to have a fixed width for the first columns, using lipgloss.
func PrintMetadata(metadata map[string]string, color string) {
style := lipgloss.NewStyle().Width(32).Foreground(lipgloss.Color(color))
for k, v := range metadata {
fmt.Println(style.Render(k) + v)
}
}
The result of which is something like:
Key1 Value1Value1Value1Value1
Key2 Value2Value2Value2Value2Value2Value2Value2Value2Value2Value2Value2
Value2Value2Value2Value2Value2Value2Value2Value2Value2Value2Value2Value2Value2Value2Value2Value2Value2
So, how can I format a string in the way I want? I can use both standard and external libraries, so any suggestions are welcome.
Upvotes: 1
Views: 985
Reputation:
I made a function for this. This function has two parameters first for the map variable for columning, second is for how many characters do you want to fill to per line. It simply change key's value contents with spacing into new variable then prints that key, value. But if you have works with unmodified value you can use unmodified variable.
package main
import (
"fmt"
"strings"
"sort"
)
func main() {
a := map[string]string{
"Key1": strings.Repeat("Value1", 50),
"Key2": strings.Repeat("Value2", 50),
"Key3": strings.Repeat("Value3", 50),
}
columner(a, 30)
}
func columner(m map[string]string, charAmount int) {
var keys []string
var keyLens []int
// to avoid index panics and gathering keys for later usage
for key, value := range m {
if charAmount > len(value) || charAmount < 1{
value += strings.Repeat(" ", charAmount-len(value))
m[key] = value
}
keys = append(keys, key)
keyLens = append(keyLens, len(key))
}
sort.Ints(keyLens)
for i := 0; i < len(keys); i++ {
// for storing updated value of key
var value2 string
value := m[keys[i]]
// will used while extracting substring of key's value as first index
firstI := 0
// last index for extract substring from key's value. the len of substring will be same as charAmount
charAmount2 := charAmount
// will be used to advance next substring of key's value
advance := charAmount2
// spaces between between key and value
// key value
spacing := strings.Repeat(" ", 20 + (keyLens[0] - len(keys[i])))
// var for adjusting spaces of gap between key and value of next line
// key value
// value
// to
// key value
// value
spacingU := spacing + strings.Repeat(" ", len(keys[i]) + 1)
// this loop will be run as long as there is no substring left which exceed next line
for j := 0; j < len(value); j += advance {
// adjusting spaces of gap between key and value of next line
if j > 0 {
spacing = spacingU
}
// add space between key and value, then extract substring, then add spaces to the next line of the
// next substring of key's value
value2 += spacing + value[firstI:charAmount2] + "\n"
// finish loop when there is no substring that can be exceed to next line
if ((len(value) - charAmount2) < advance) || ((len(value) - charAmount2) == advance) {
break
}
// changing first index to start index of next substring of key's value
firstI = charAmount2
// advancing to next substring of key's value
charAmount2 += advance
}
// add last remaining substring of key's value to variable which will be show as formatted.
value2 += spacing + value[charAmount2:]
// show formatted key and value
fmt.Println(keys[i], value2, "\n")
}
}
This is a example output:
Key1 Value1Value1Value1Value1Value1
Value1Value1Value1Value1Value1
Value1Value1Value1Value1Value1
Value1Value1Value1Value1Value1
Value1Value1Value1Value1Value1
Value1Value1Value1Value1Value1
Value1Value1Value1Value1Value1
Value1Value1Value1Value1Value1
Value1Value1Value1Value1Value1
Value1Value1Value1Value1Value1
Key2 Value2Value2Value2Value2Value2
Value2Value2Value2Value2Value2
Value2Value2Value2Value2Value2
Value2Value2Value2Value2Value2
Value2Value2Value2Value2Value2
Value2Value2Value2Value2Value2
Value2Value2Value2Value2Value2
Value2Value2Value2Value2Value2
Value2Value2Value2Value2Value2
Value2Value2Value2Value2Value2
Key3 Value3Value3Value3Value3Value3
Value3Value3Value3Value3Value3
Value3Value3Value3Value3Value3
Value3Value3Value3Value3Value3
Value3Value3Value3Value3Value3
Value3Value3Value3Value3Value3
Value3Value3Value3Value3Value3
Value3Value3Value3Value3Value3
Value3Value3Value3Value3Value3
Value3Value3Value3Value3Value3
But please notice this, order of key and values may be different on each execution because map type is unordered when printed in for loop with key, value pair.
Upvotes: 1