From 9777794492d8c462d4c84f7a5688a8e191fe6920 Mon Sep 17 00:00:00 2001 From: Chris Hall Date: Sat, 30 May 2026 00:41:28 -0400 Subject: [PATCH 1/2] feat(sheets): add --inherit-from-before to sheets insert MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `gog sheets insert` always derived InsertDimensionRequest.inheritFromBefore from --after, so there was no way to insert columns/rows with plain formatting next to a formatted neighbour (the reported case: plain 0–100 score columns inserted beside a currency column first rendered as currency). Add a tri-state `--inherit-from-before` flag (*bool): omitted keeps the prior default (inherit only with --after), `--inherit-from-before=false` forces plain formatting, and `--inherit-from-before` forces inheritance on a before-insert. Regenerate the command reference (make docs-commands) so the flag is documented. Co-Authored-By: Claude Opus 4.8 --- docs/commands/gog-sheets-insert.md | 1 + internal/cmd/sheets_insert.go | 8 +++++++ internal/cmd/sheets_insert_test.go | 34 ++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/docs/commands/gog-sheets-insert.md b/docs/commands/gog-sheets-insert.md index abbd48033..778377e1c 100644 --- a/docs/commands/gog-sheets-insert.md +++ b/docs/commands/gog-sheets-insert.md @@ -31,6 +31,7 @@ gog sheets (sheet) insert [flags] | `--gmail-no-send` | `bool` | false | Block Gmail send operations (agent safety) | | `-h`
`--help` | `kong.helpFlag` | | Show context-sensitive help. | | `--home` | `string` | | Override gogcli config/data/state/cache root (equivalent to GOG_HOME) | +| `--inherit-from-before` | `*bool` | | Inherit number format / styling from the adjacent row/column. Defaults to true with --after, false otherwise; set to false to insert with plain formatting. | | `-j`
`--json`
`--machine` | `bool` | false | Output JSON to stdout (best for scripting) | | `--no-input`
`--non-interactive`
`--noninteractive` | `bool` | | Never prompt; fail instead (useful for CI) | | `-p`
`--plain`
`--tsv` | `bool` | false | Output stable, parseable text to stdout (TSV; no colors) | diff --git a/internal/cmd/sheets_insert.go b/internal/cmd/sheets_insert.go index 335900365..aa6351257 100644 --- a/internal/cmd/sheets_insert.go +++ b/internal/cmd/sheets_insert.go @@ -18,6 +18,9 @@ type SheetsInsertCmd struct { Start int64 `arg:"" name:"start" help:"Position before which to insert (1-based; for cols 1=A, 2=B)"` Count int64 `name:"count" help:"Number of rows/columns to insert" default:"1"` After bool `name:"after" help:"Insert after the position instead of before"` + // *bool so an unset flag keeps the historical default (inherit only when + // --after); passing --inherit-from-before[=false] overrides it explicitly. + InheritFromBefore *bool `name:"inherit-from-before" help:"Inherit number format / styling from the adjacent row/column. Defaults to true with --after, false otherwise; set to false to insert with plain formatting."` } func (c *SheetsInsertCmd) Run(ctx context.Context, flags *RootFlags) error { @@ -58,7 +61,12 @@ func (c *SheetsInsertCmd) Run(ctx context.Context, flags *RootFlags) error { startIndex = c.Start } endIndex := startIndex + c.Count + // Default: inherit formatting only when inserting after an existing line. + // An explicit --inherit-from-before[=false] overrides that default. inheritFromBefore := c.After + if c.InheritFromBefore != nil { + inheritFromBefore = *c.InheritFromBefore + } if dryRunErr := dryRunExit(ctx, flags, "sheets.insert", map[string]any{ "spreadsheet_id": spreadsheetID, diff --git a/internal/cmd/sheets_insert_test.go b/internal/cmd/sheets_insert_test.go index a6db69715..53058d030 100644 --- a/internal/cmd/sheets_insert_test.go +++ b/internal/cmd/sheets_insert_test.go @@ -124,6 +124,40 @@ func TestSheetsInsertCmd(t *testing.T) { } }) + t.Run("insert after without inheriting formatting", func(t *testing.T) { + gotInsert = nil + cmd := &SheetsInsertCmd{} + if err := runKong(t, cmd, []string{ + "s1", "Data", "rows", "2", "--count", "1", "--after", "--inherit-from-before=false", + }, ctx, flags); err != nil { + t.Fatalf("insert rows: %v", err) + } + if gotInsert == nil { + t.Fatal("expected insertDimension request") + } + // --after would default inheritFromBefore=true; the explicit flag overrides it. + if gotInsert.InheritFromBefore { + t.Fatal("expected inheritFromBefore=false when --inherit-from-before=false overrides --after") + } + }) + + t.Run("insert before with explicit inherit", func(t *testing.T) { + gotInsert = nil + cmd := &SheetsInsertCmd{} + if err := runKong(t, cmd, []string{ + "s1", "Data", "rows", "2", "--count", "1", "--inherit-from-before", + }, ctx, flags); err != nil { + t.Fatalf("insert rows: %v", err) + } + if gotInsert == nil { + t.Fatal("expected insertDimension request") + } + // before-insert defaults inheritFromBefore=false; the explicit flag overrides it. + if !gotInsert.InheritFromBefore { + t.Fatal("expected inheritFromBefore=true when --inherit-from-before is set") + } + }) + t.Run("insert cols before", func(t *testing.T) { gotInsert = nil cmd := &SheetsInsertCmd{} From d1da0e673c34caf9354aefe26b81169439650ee0 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 30 May 2026 18:51:29 +0100 Subject: [PATCH 2/2] fix(sheets): validate insert formatting inheritance --- CHANGELOG.md | 1 + docs/commands/gog-sheets-insert.md | 2 +- internal/cmd/sheets_insert.go | 5 ++++- internal/cmd/sheets_insert_test.go | 22 ++++++++++++++++++++-- 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f05a4d315..1ffa692ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Gmail: keep label IDs case-sensitive during label resolution and duplicate-name checks while still matching label names case-insensitively. - Gmail: clarify that `gmail drafts delete` permanently deletes drafts and cannot be recovered. (#656, #659) — thanks @chrischall. +- Sheets: add `--inherit-from-before` to `sheets insert` so callers can choose whether inserted rows/columns inherit formatting from the preceding or following neighbor. (#655, #658) — thanks @chrischall. - Docs: update the bundled `gog` agent skill to preserve broad user OAuth scopes during reauth and rely on command guards for scoped execution. ## 0.19.0 - 2026-05-22 diff --git a/docs/commands/gog-sheets-insert.md b/docs/commands/gog-sheets-insert.md index 778377e1c..6aeb302df 100644 --- a/docs/commands/gog-sheets-insert.md +++ b/docs/commands/gog-sheets-insert.md @@ -31,7 +31,7 @@ gog sheets (sheet) insert [flags] | `--gmail-no-send` | `bool` | false | Block Gmail send operations (agent safety) | | `-h`
`--help` | `kong.helpFlag` | | Show context-sensitive help. | | `--home` | `string` | | Override gogcli config/data/state/cache root (equivalent to GOG_HOME) | -| `--inherit-from-before` | `*bool` | | Inherit number format / styling from the adjacent row/column. Defaults to true with --after, false otherwise; set to false to insert with plain formatting. | +| `--inherit-from-before` | `*bool` | | Inherit number format / styling from the row/column before the insertion. Defaults to true with --after, false otherwise; false inherits from the row/column after the insertion. | | `-j`
`--json`
`--machine` | `bool` | false | Output JSON to stdout (best for scripting) | | `--no-input`
`--non-interactive`
`--noninteractive` | `bool` | | Never prompt; fail instead (useful for CI) | | `-p`
`--plain`
`--tsv` | `bool` | false | Output stable, parseable text to stdout (TSV; no colors) | diff --git a/internal/cmd/sheets_insert.go b/internal/cmd/sheets_insert.go index aa6351257..3149b5b33 100644 --- a/internal/cmd/sheets_insert.go +++ b/internal/cmd/sheets_insert.go @@ -20,7 +20,7 @@ type SheetsInsertCmd struct { After bool `name:"after" help:"Insert after the position instead of before"` // *bool so an unset flag keeps the historical default (inherit only when // --after); passing --inherit-from-before[=false] overrides it explicitly. - InheritFromBefore *bool `name:"inherit-from-before" help:"Inherit number format / styling from the adjacent row/column. Defaults to true with --after, false otherwise; set to false to insert with plain formatting."` + InheritFromBefore *bool `name:"inherit-from-before" help:"Inherit number format / styling from the row/column before the insertion. Defaults to true with --after, false otherwise; false inherits from the row/column after the insertion."` } func (c *SheetsInsertCmd) Run(ctx context.Context, flags *RootFlags) error { @@ -67,6 +67,9 @@ func (c *SheetsInsertCmd) Run(ctx context.Context, flags *RootFlags) error { if c.InheritFromBefore != nil { inheritFromBefore = *c.InheritFromBefore } + if inheritFromBefore && startIndex == 0 { + return usagef("cannot inherit from the previous %s when inserting at position 1", dimLabel) + } if dryRunErr := dryRunExit(ctx, flags, "sheets.insert", map[string]any{ "spreadsheet_id": spreadsheetID, diff --git a/internal/cmd/sheets_insert_test.go b/internal/cmd/sheets_insert_test.go index 53058d030..f17588161 100644 --- a/internal/cmd/sheets_insert_test.go +++ b/internal/cmd/sheets_insert_test.go @@ -124,7 +124,7 @@ func TestSheetsInsertCmd(t *testing.T) { } }) - t.Run("insert after without inheriting formatting", func(t *testing.T) { + t.Run("insert after inheriting from following dimension", func(t *testing.T) { gotInsert = nil cmd := &SheetsInsertCmd{} if err := runKong(t, cmd, []string{ @@ -135,7 +135,8 @@ func TestSheetsInsertCmd(t *testing.T) { if gotInsert == nil { t.Fatal("expected insertDimension request") } - // --after would default inheritFromBefore=true; the explicit flag overrides it. + // --after would default inheritFromBefore=true; the explicit flag overrides it + // so the API inherits from the following adjacent row/column instead. if gotInsert.InheritFromBefore { t.Fatal("expected inheritFromBefore=false when --inherit-from-before=false overrides --after") } @@ -158,6 +159,23 @@ func TestSheetsInsertCmd(t *testing.T) { } }) + t.Run("reject inherit from before at first row", func(t *testing.T) { + gotInsert = nil + cmd := &SheetsInsertCmd{} + err := runKong(t, cmd, []string{ + "s1", "Data", "rows", "1", "--inherit-from-before", + }, ctx, flags) + if err == nil { + t.Fatal("expected error") + } + if !strings.Contains(err.Error(), "cannot inherit from the previous row") { + t.Fatalf("unexpected error: %v", err) + } + if gotInsert != nil { + t.Fatal("did not expect API request") + } + }) + t.Run("insert cols before", func(t *testing.T) { gotInsert = nil cmd := &SheetsInsertCmd{}