Skip to content

Commit ad31658

Browse files
authored
Merge pull request #352 from krissetto/order-cli-list-output
Sort output of `docker model list` to make it more human readable
2 parents ecda085 + 1f3dc48 commit ad31658

File tree

2 files changed

+383
-8
lines changed

2 files changed

+383
-8
lines changed

cmd/cli/commands/list.go

Lines changed: 65 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"bytes"
55
"fmt"
66
"os"
7+
"sort"
78
"strconv"
89
"strings"
910
"time"
@@ -114,6 +115,68 @@ func listModels(openai bool, desktopClient *desktop.Client, quiet bool, jsonForm
114115
}
115116

116117
func prettyPrintModels(models []dmrm.Model) string {
118+
type displayRow struct {
119+
displayName string
120+
tag string
121+
model dmrm.Model
122+
}
123+
124+
var rows []displayRow
125+
126+
for _, m := range models {
127+
if len(m.Tags) == 0 {
128+
rows = append(rows, displayRow{
129+
displayName: "<none>",
130+
tag: "<none>",
131+
model: m,
132+
})
133+
continue
134+
}
135+
136+
for _, tag := range m.Tags {
137+
displayName := stripDefaultsFromModelName(tag)
138+
rows = append(rows, displayRow{
139+
displayName: displayName,
140+
tag: tag,
141+
model: m,
142+
})
143+
}
144+
}
145+
146+
// Helper function to split display name into base and variant
147+
splitDisplayName := func(displayName string) (base, variant string) {
148+
if idx := strings.LastIndex(displayName, ":"); idx != -1 {
149+
return displayName[:idx], displayName[idx+1:]
150+
}
151+
return displayName, ""
152+
}
153+
154+
// Sort all rows by display name
155+
sort.Slice(rows, func(i, j int) bool {
156+
displayI := rows[i].displayName
157+
displayJ := rows[j].displayName
158+
159+
// Split on last ':' to get base name and variant
160+
baseI, variantI := splitDisplayName(displayI)
161+
baseJ, variantJ := splitDisplayName(displayJ)
162+
163+
baseILower := strings.ToLower(baseI)
164+
baseJLower := strings.ToLower(baseJ)
165+
if baseILower != baseJLower {
166+
return baseILower < baseJLower
167+
}
168+
169+
// If base names are equal, compare variants
170+
// Empty variants (no ':' in name) come first
171+
if variantI == "" && variantJ != "" {
172+
return true
173+
}
174+
if variantI != "" && variantJ == "" {
175+
return false
176+
}
177+
return strings.ToLower(variantI) < strings.ToLower(variantJ)
178+
})
179+
117180
var buf bytes.Buffer
118181
table := tablewriter.NewWriter(&buf)
119182

@@ -137,14 +200,8 @@ func prettyPrintModels(models []dmrm.Model) string {
137200
})
138201
table.SetHeaderAlignment(tablewriter.ALIGN_LEFT)
139202

140-
for _, m := range models {
141-
if len(m.Tags) == 0 {
142-
appendRow(table, "<none>", m)
143-
continue
144-
}
145-
for _, tag := range m.Tags {
146-
appendRow(table, tag, m)
147-
}
203+
for _, row := range rows {
204+
appendRow(table, row.tag, row.model)
148205
}
149206

150207
table.Render()

0 commit comments

Comments
 (0)