Format list as an aligned table
The name is what the eye looks for, but it came last, behind a ragged date column, so nothing lined up. Worse, colorRepoLine rebuilt the line with strings.Fields and single spaces, which destroyed the alignment ls had produced -- the output was aligned only when colour was off. The listing line is now parsed properly instead of being split at the size field: name, date and size come out as fields, the date is re-padded to a fixed twelve columns so "Sep 28 2016" and "Jan 3 14:32" agree, and the name leads in a column sized to the longest entry. Colour decorates that layout without changing it, which a test now checks by stripping the escapes and comparing. `list -a` shows archive sizes, which were parsed and thrown away before. An empty result says so instead of printing nothing, which was indistinguishable from a failure, and the count line matches the rest of mgsh. The pattern now filters on the repository name rather than the whole listing line: matching the owner or the date was never intended and `list 2016` quietly did it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -43,17 +44,47 @@ func padRight(s string, n int) string {
|
||||
return s
|
||||
}
|
||||
|
||||
// colorRepoLine colors a `list` entry: the leading `ls -ltr` date (3 fields) in
|
||||
// yellow and the repository name in green.
|
||||
func colorRepoLine(s string) string {
|
||||
if !useColor {
|
||||
return s
|
||||
// formatRepoList renders the server listing for `list`: the name first, in a
|
||||
// column wide enough for the longest one, then the date, and for archives the
|
||||
// size. Names come first because that is what the eye scans for; putting the
|
||||
// ragged date there instead is what made the old output hard to read.
|
||||
//
|
||||
// The order is left as it arrives: `ls -ltr` sorts by modification time, and
|
||||
// `push` touches the bare repository, so the most recently worked-on project
|
||||
// ends up closest to the prompt.
|
||||
func formatRepoList(entries []lsEntry, withSize bool) string {
|
||||
width := 0
|
||||
for _, e := range entries {
|
||||
if len(e.name) > width {
|
||||
width = len(e.name)
|
||||
}
|
||||
}
|
||||
parts := strings.Fields(s)
|
||||
if len(parts) >= 4 {
|
||||
date := strings.Join(parts[:3], " ")
|
||||
name := strings.Join(parts[3:], " ")
|
||||
return col(cYellow, date) + " " + col(cGreen, name)
|
||||
var b strings.Builder
|
||||
for _, e := range entries {
|
||||
fmt.Fprintf(&b, " %s %s", col(cGreen, padRight(e.name, width)), col(cYellow, e.date))
|
||||
if withSize {
|
||||
fmt.Fprintf(&b, " %s", col(cGray, fmt.Sprintf("%7s", humanSize(e.size))))
|
||||
}
|
||||
b.WriteByte('\n')
|
||||
}
|
||||
return col(cGreen, s)
|
||||
return b.String()
|
||||
}
|
||||
|
||||
// humanSize renders a byte count compactly, the way `ls -h` does: a decimal
|
||||
// only while it still carries information, so "3.2M" but "512K".
|
||||
func humanSize(n int64) string {
|
||||
const unit = 1024
|
||||
if n < unit {
|
||||
return strconv.FormatInt(n, 10) + "B"
|
||||
}
|
||||
div, exp := int64(unit), 0
|
||||
for v := n / unit; v >= unit && exp < 4; v /= unit {
|
||||
div *= unit
|
||||
exp++
|
||||
}
|
||||
v := float64(n) / float64(div)
|
||||
if v < 10 {
|
||||
return fmt.Sprintf("%.1f%c", v, "KMGTP"[exp])
|
||||
}
|
||||
return fmt.Sprintf("%.0f%c", v, "KMGTP"[exp])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user