Commit dbc19527c5

dbc19527c5a13487c003bd3aecf6d2561bfd4e09

parent: fa2d1b2316

Verified · cmc

cmc <hello@cleberg.net> · 2026-09-12 05:58 UTC

cli: align list rows into columns at a terminal

Piped output keeps the server's tabs.

Ref #183
cmd/gitbay/ssh.go +41
@@ -1,8 +1,11 @@
11package main
22
33import (
4 "text/tabwriter"
5
46 "encoding/json"
57 "fmt"
8 "golang.org/x/term"
69 "io"
710 "os"
811 "os/exec"
@@ -120,7 +123,15 @@ func runSSH(t target, serverArgv []string, stdin io.Reader) int {
120123 cmd.Stdin = stdin
121124 cmd.Stdout = os.Stdout
122125 cmd.Stderr = os.Stderr
126 var tw *tabwriter.Writer
127 if alignColumns(serverArgv) {
128 tw = tabwriter.NewWriter(os.Stdout, 0, 8, 2, ' ', 0)
129 cmd.Stdout = tw
130 }
123131 err := cmd.Run()
132 if tw != nil {
133 tw.Flush()
134 }
124135 if err == nil {
125136 return 0
126137 }
@@ -193,3 +204,33 @@ func withRepo(t target, args []string) ([]string, error) {
193204 }
194205 return append([]string{t.repo}, args...), nil
195206}
207
208// listVerbs are the server commands whose plain output is one row per
209// item with tab-separated columns.
210var listVerbs = map[string]bool{
211 "list": true, "runners": true, "deliveries": true, "refs": true,
212 "revisions": true, "threads": true, "bookmarks": true, "jobs": true,
213}
214
215// alignColumns reports whether a command's rows should be padded into
216// columns: a list command, printed for a person at a terminal. Piped
217// output keeps the server's tabs so cut and awk see the same bytes stock
218// ssh prints, and --json is never touched.
219func alignColumns(serverArgv []string) bool {
220 verb := ""
221 for _, a := range serverArgv {
222 if strings.HasPrefix(a, "-") {
223 break
224 }
225 if a == "--json" {
226 return false
227 }
228 verb = a
229 }
230 for _, a := range serverArgv {
231 if a == "--json" {
232 return false
233 }
234 }
235 return listVerbs[verb] && term.IsTerminal(int(os.Stdout.Fd()))
236}