Skip to content

Commit 277e5b7

Browse files
committed
use lipgloss
Signed-off-by: Pulak Kanti Bhowmick <[email protected]>
1 parent ef8a25d commit 277e5b7

File tree

1 file changed

+59
-15
lines changed

1 file changed

+59
-15
lines changed

pkg/list/list_components.go

Lines changed: 59 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,11 @@ package list
22

33
import (
44
"fmt"
5-
"os"
65
"regexp"
76
"sort"
87
"strings"
9-
"text/tabwriter"
108

9+
"github.com/charmbracelet/lipgloss"
1110
"github.com/samber/lo"
1211

1312
"github.com/cloudposse/atmos/pkg/schema"
@@ -37,7 +36,7 @@ func getStackComponents(stackData any, listFields []string) ([]string, error) {
3736
data := terraformComponents[dataKey]
3837
dataMap, ok := data.(map[string]any)
3938
if !ok {
40-
return nil, fmt.Errorf("unexpected data type for component '%s'", dataKey)
39+
return nil, fmt.Errorf("unexpected data type for component '%s'", dataKey)
4140
}
4241
rowData := make([]string, 0)
4342
for _, key := range listFields {
@@ -84,14 +83,18 @@ func resolveKey(data map[string]any, key string) (any, bool) {
8483

8584
// FilterAndListComponents filters and lists components based on the given stack
8685
func FilterAndListComponents(stackFlag string, stacksMap map[string]any, listConfig schema.ListConfig) (string, error) {
87-
components := []string{}
86+
components := [][]string{}
87+
88+
// Define lipgloss styles for headers and rows
89+
headerStyle := lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("#00BFFF"))
90+
rowStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("#FFFFFF"))
8891

89-
writer := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', tabwriter.AlignRight)
9092
header := make([]string, 0)
9193
listFields := make([]string, 0)
9294

9395
re := regexp.MustCompile(`\{\{\s*(.*?)\s*\}\}`)
9496

97+
// Extract and format headers
9598
for _, v := range listConfig.Columns {
9699
header = append(header, v.Name)
97100
match := re.FindStringSubmatch(v.Value)
@@ -102,16 +105,18 @@ func FilterAndListComponents(stackFlag string, stacksMap map[string]any, listCon
102105
return "", fmt.Errorf("invalid value format for column name %s", v.Name)
103106
}
104107
}
105-
fmt.Fprintln(writer, strings.Join(header, "\t\t"))
106108

109+
// Collect components for the table
107110
if stackFlag != "" {
108111
// Filter components for the specified stack
109112
if stackData, ok := stacksMap[stackFlag]; ok {
110113
stackComponents, err := getStackComponents(stackData, listFields)
111114
if err != nil {
112115
return "", fmt.Errorf("error processing stack '%s': %w", stackFlag, err)
113116
}
114-
components = append(components, stackComponents...)
117+
for _, c := range stackComponents {
118+
components = append(components, strings.Fields(c))
119+
}
115120
} else {
116121
return "", fmt.Errorf("stack '%s' not found", stackFlag)
117122
}
@@ -122,21 +127,60 @@ func FilterAndListComponents(stackFlag string, stacksMap map[string]any, listCon
122127
if err != nil {
123128
continue // Skip invalid stacks
124129
}
125-
components = append(components, stackComponents...)
130+
for _, c := range stackComponents {
131+
components = append(components, strings.Fields(c))
132+
}
126133
}
127134
}
128135

129-
// Remove duplicates and sort components
130-
components = lo.Uniq(components)
131-
sort.Strings(components)
136+
// Remove duplicates, sort, and prepare rows
137+
componentsMap := lo.UniqBy(components, func(item []string) string {
138+
return strings.Join(item, "\t")
139+
})
140+
sort.Slice(componentsMap, func(i, j int) bool {
141+
return strings.Join(componentsMap[i], "\t") < strings.Join(componentsMap[j], "\t")
142+
})
132143

133-
if len(components) == 0 {
144+
if len(componentsMap) == 0 {
134145
return "No components found", nil
135146
}
136147

137-
for _, com := range components {
138-
fmt.Fprintln(writer, com)
148+
// Determine column widths
149+
colWidths := make([]int, len(header))
150+
for i, h := range header {
151+
colWidths[i] = len(h)
152+
}
153+
for _, row := range componentsMap {
154+
for i, field := range row {
155+
if len(field) > colWidths[i] {
156+
colWidths[i] = len(field)
157+
}
158+
}
159+
}
160+
161+
// Format the headers
162+
headerRow := make([]string, len(header))
163+
for i, h := range header {
164+
headerRow[i] = headerStyle.Render(padToWidth(h, colWidths[i]))
139165
}
140-
writer.Flush()
166+
fmt.Println(strings.Join(headerRow, " "))
167+
168+
// Format the rows
169+
for _, row := range componentsMap {
170+
formattedRow := make([]string, len(row))
171+
for i, field := range row {
172+
formattedRow[i] = rowStyle.Render(padToWidth(field, colWidths[i]))
173+
}
174+
fmt.Println(strings.Join(formattedRow, " "))
175+
}
176+
141177
return "", nil
142178
}
179+
180+
// padToWidth ensures a string is padded to the given width
181+
func padToWidth(str string, width int) string {
182+
for len(str) < width {
183+
str += " "
184+
}
185+
return str
186+
}

0 commit comments

Comments
 (0)