Skip to content

sheets get --plain outputs spaces instead of tabs #209

@tomdeboer

Description

@tomdeboer

Problem

The sheets get command with --plain flag is documented to output TSV (tab-separated values), but it currently outputs space-separated values instead. This breaks piping to tools that expect actual tab delimiters.

The --plain flag help text states: "stable TSV on stdout (tabs preserved; best for piping to tools that expect \t)". However, the actual output uses spaces for column alignment.

Steps to Reproduce

gog sheets get "SPREADSHEET_ID" "Sheet1!A1:C1" --plain | od -c

Expected: Tab characters (09 in hex) between columns
Actual: Space characters (20 in hex) between columns

Example Output

# Current (incorrect):
Total requirements   Implemented  Blocked

# Expected (correct):
Total requirements	Implemented	Blocked

Root Cause

The implementation uses tabwriter.NewWriter to format output, which converts tab characters to spaces for visual column alignment. This formatting is applied even when --plain flag is set, contradicting the documented behavior.

Relevant code in internal/cmd/sheets.go:121:

tw := tabwriter.NewWriter(os.Stdout, 0, 4, 2, ' ', 0)
for _, row := range resp.Values {
    cells := make([]string, len(row))
    for i, cell := range row {
        cells[i] = fmt.Sprintf("%v", cell)
    }
    fmt.Fprintln(tw, strings.Join(cells, "\t"))
}
_ = tw.Flush()  // Converts \t to spaces here

Proposed Solution

Add a check for outfmt.IsPlain(ctx) to bypass tabwriter and output raw tab characters when --plain flag is used.

Implementation

var w io.Writer
if outfmt.IsPlain(ctx) {
	w = os.Stdout
} else {
	tw := tabwriter.NewWriter(os.Stdout, 0, 4, 2, ' ', 0)
	defer tw.Flush()
	w = tw
}

for _, row := range resp.Values {
	cells := make([]string, len(row))
	for i, cell := range row {
		cells[i] = fmt.Sprintf("%v", cell)
	}
	fmt.Fprintln(w, strings.Join(cells, "\t"))
}

Use Case

Scripts and tools that process Google Sheets data via --plain output expect standard TSV format with tab delimiters. Current behavior breaks:

  • cut -f commands (field splitting by tabs)
  • awk -F'\t' processing
  • Import into spreadsheet tools expecting TSV
  • Any tool documented to work with tab-separated data

Priority

Medium - breaks documented behavior and scripting workflows

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions