Skip to content

Commit cc4dabe

Browse files
feat(slides): add native slide structure commands
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
1 parent c78e609 commit cc4dabe

12 files changed

Lines changed: 972 additions & 1 deletion

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
- Slides: add structured element geometry, styled text runs, table-cell content, image source URLs, native presentation metadata, and read-only text location with exact UTF-16 ranges. (#822) — thanks @sebsnyk.
99
- Slides: add range-scoped styling, links, bullets, and object-scoped replacement; `replace-text` now requires explicit `--object`, `--page`, or `--all` scope instead of silently changing the whole deck. (#823, #835) — thanks @sebsnyk.
1010
- Slides: add native table creation and zero-based table-cell targeting for `insert-text`, including atomic cell replacement. (#824, #834) — thanks @sebsnyk.
11+
- Slides: add native themed slide creation, duplication, and reordering with predefined or exact custom layouts and explicit zero-based positions. (#826, #833) — thanks @sebsnyk.
1112

1213
### Fixed
1314

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,7 @@ Docs: [Slides from Markdown](docs/slides-markdown.md),
384384
[introspection](docs/slides-introspection.md),
385385
[text editing](docs/slides-text-editing.md),
386386
[tables](docs/slides-tables.md),
387+
[slide structure](docs/slides-structure.md),
387388
[`gog slides`](docs/commands/gog-slides.md),
388389
[`gog forms`](docs/commands/gog-forms.md).
389390

@@ -396,6 +397,9 @@ gog slides style-text <presentationId> <objectId> --range 0:12 --bold --size 24
396397
gog slides replace-text <presentationId> old new --object <objectId>
397398
gog slides table create <presentationId> <slideId> --rows 2 --cols 3
398399
gog slides insert-text <presentationId> <tableId> "Revenue" --row 0 --col 0 --replace
400+
gog slides new-slide <presentationId> --layout TITLE_AND_BODY --index 1
401+
gog slides duplicate-slide <presentationId> <slideId> --to-index 2
402+
gog slides move-slide <presentationId> <slideId> --to-index 0
399403
gog slides insert-image <presentationId> <slideId> chart.png --x 24 --y 24 --width 240
400404
gog slides insert-text <presentationId> <objectId> "New text"
401405
gog forms update <formId> --quiz=true

docs/commands.generated.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,13 +592,16 @@ Generated from `gog schema --json`.
592592
- [`gog slides (slide) create-from-markdown <title> [flags]`](commands/gog-slides-create-from-markdown.md) - Create a Google Slides presentation from markdown
593593
- [`gog slides (slide) create-from-template <templateId> <title> [flags]`](commands/gog-slides-create-from-template.md) - Create a presentation from template with text replacements
594594
- [`gog slides (slide) delete-slide <presentationId> <slideId>`](commands/gog-slides-delete-slide.md) - Delete a slide by object ID
595+
- [`gog slides (slide) duplicate-slide <presentationId> <slideId> [flags]`](commands/gog-slides-duplicate-slide.md) - Duplicate a slide by object ID
595596
- [`gog slides (slide) export (download,dl) <presentationId> [flags]`](commands/gog-slides-export.md) - Export a Google Slides deck (pdf|pptx)
596597
- [`gog slides (slide) info (get,show) <presentationId>`](commands/gog-slides-info.md) - Get Google Slides presentation metadata
597598
- [`gog slides (slide) insert-image --width=FLOAT-64 <presentationId> <slideId> [<image>] [flags]`](commands/gog-slides-insert-image.md) - Insert a local or public image at a position and size
598599
- [`gog slides (slide) insert-text <presentationId> <objectId> <text> [flags]`](commands/gog-slides-insert-text.md) - Insert text into an existing page element (shape or table) by objectId
599600
- [`gog slides (slide) link --range=STRING <presentationId> <objectId> [flags]`](commands/gog-slides-link.md) - Apply a hyperlink to a text range in one page element
600601
- [`gog slides (slide) list-slides <presentationId>`](commands/gog-slides-list-slides.md) - List all slides with their object IDs
601602
- [`gog slides (slide) locate (find-element) <presentationId> <text> [flags]`](commands/gog-slides-locate.md) - Locate text in shapes and table cells with object IDs and UTF-16 ranges
603+
- [`gog slides (slide) move-slide --to-index=TO-INDEX <presentationId> <slideId>`](commands/gog-slides-move-slide.md) - Move a slide to a zero-based insertion index
604+
- [`gog slides (slide) new-slide <presentationId> [flags]`](commands/gog-slides-new-slide.md) - Create a native themed slide
602605
- [`gog slides (slide) raw <presentationId> [flags]`](commands/gog-slides-raw.md) - Dump raw Google Slides API response as JSON (Presentations.Get; lossless; for scripting and LLM consumption)
603606
- [`gog slides (slide) read-slide <presentationId> <slideId> [flags]`](commands/gog-slides-read-slide.md) - Read slide content: speaker notes, text elements, and images
604607
- [`gog slides (slide) replace-slide <presentationId> <slideId> [<image>] [flags]`](commands/gog-slides-replace-slide.md) - Replace an existing slide image from a local file or public URL

docs/commands/README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
Every `gog` command has a generated docs page. The source of truth is the live CLI schema; run `make docs-commands` after changing command names, flags, help text, aliases, or arguments.
44

5-
Generated pages: 652.
5+
Generated pages: 655.
66

77
## Top-level Commands
88

@@ -643,13 +643,16 @@ Generated pages: 652.
643643
- [gog slides create-from-markdown](gog-slides-create-from-markdown.md) - Create a Google Slides presentation from markdown
644644
- [gog slides create-from-template](gog-slides-create-from-template.md) - Create a presentation from template with text replacements
645645
- [gog slides delete-slide](gog-slides-delete-slide.md) - Delete a slide by object ID
646+
- [gog slides duplicate-slide](gog-slides-duplicate-slide.md) - Duplicate a slide by object ID
646647
- [gog slides export](gog-slides-export.md) - Export a Google Slides deck (pdf|pptx)
647648
- [gog slides info](gog-slides-info.md) - Get Google Slides presentation metadata
648649
- [gog slides insert-image](gog-slides-insert-image.md) - Insert a local or public image at a position and size
649650
- [gog slides insert-text](gog-slides-insert-text.md) - Insert text into an existing page element (shape or table) by objectId
650651
- [gog slides link](gog-slides-link.md) - Apply a hyperlink to a text range in one page element
651652
- [gog slides list-slides](gog-slides-list-slides.md) - List all slides with their object IDs
652653
- [gog slides locate](gog-slides-locate.md) - Locate text in shapes and table cells with object IDs and UTF-16 ranges
654+
- [gog slides move-slide](gog-slides-move-slide.md) - Move a slide to a zero-based insertion index
655+
- [gog slides new-slide](gog-slides-new-slide.md) - Create a native themed slide
653656
- [gog slides raw](gog-slides-raw.md) - Dump raw Google Slides API response as JSON (Presentations.Get; lossless; for scripting and LLM consumption)
654657
- [gog slides read-slide](gog-slides-read-slide.md) - Read slide content: speaker notes, text elements, and images
655658
- [gog slides replace-slide](gog-slides-replace-slide.md) - Replace an existing slide image from a local file or public URL
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# `gog slides duplicate-slide`
2+
3+
> Generated from `gog schema --json`. Do not edit this page by hand; run `make docs-commands`.
4+
5+
Duplicate a slide by object ID
6+
7+
## Usage
8+
9+
```bash
10+
gog slides (slide) duplicate-slide <presentationId> <slideId> [flags]
11+
```
12+
13+
## Parent
14+
15+
- [gog slides](gog-slides.md)
16+
17+
## Flags
18+
19+
| Flag | Type | Default | Help |
20+
| --- | --- | --- | --- |
21+
| `--access-token` | `string` | | Use provided access token directly (bypasses stored refresh tokens; token expires in ~1h) |
22+
| `-a`<br>`--account`<br>`--acct` | `string` | | Account email, alias, or auto for authenticated Google API commands |
23+
| `--client` | `string` | | OAuth client name (selects stored credentials + token bucket) |
24+
| `--color` | `string` | auto | Color output: auto\|always\|never |
25+
| `--disable-commands` | `string` | | Comma-separated list of disabled commands; dot paths allowed |
26+
| `-n`<br>`--dry-run`<br>`--dryrun`<br>`--noop`<br>`--preview` | `bool` | | Do not make changes; print intended actions and exit successfully |
27+
| `--enable-commands` | `string` | | Comma-separated list of enabled command prefixes; dot paths allowed (restricts CLI) |
28+
| `--enable-commands-exact` | `string` | | Comma-separated list of exact enabled commands; dot paths allowed and parent commands do not enable children |
29+
| `-y`<br>`--force`<br>`--assume-yes`<br>`--yes` | `bool` | | Skip confirmations for destructive commands |
30+
| `--gmail-no-send` | `bool` | false | Block Gmail send operations (agent safety) |
31+
| `-h`<br>`--help` | `kong.helpFlag` | | Show context-sensitive help. |
32+
| `--home` | `string` | | Override gogcli config/data/state/cache root (equivalent to GOG_HOME) |
33+
| `-j`<br>`--json`<br>`--machine` | `bool` | false | Output JSON to stdout (best for scripting) |
34+
| `--no-input`<br>`--non-interactive`<br>`--noninteractive` | `bool` | | Never prompt; fail instead (useful for CI) |
35+
| `-p`<br>`--plain`<br>`--tsv` | `bool` | false | Output stable, parseable text to stdout (TSV; no colors) |
36+
| `--results-only` | `bool` | | In JSON mode, emit only the primary result (drops envelope fields like nextPageToken) |
37+
| `--select`<br>`--pick`<br>`--project` | `string` | | In JSON mode, select comma-separated fields (best-effort; supports dot paths). Desire path: use --fields for most commands. |
38+
| `--to-index` | `*int64` | | Zero-based insertion index for the duplicated slide |
39+
| `-v`<br>`--verbose` | `bool` | | Enable verbose logging |
40+
| `--version` | `kong.VersionFlag` | | Print version and exit |
41+
| `--wrap-untrusted` | `bool` | false | In JSON/raw output, wrap fetched text fields in external untrusted-content markers |
42+
43+
## See Also
44+
45+
- [gog slides](gog-slides.md)
46+
- [Command index](README.md)
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# `gog slides move-slide`
2+
3+
> Generated from `gog schema --json`. Do not edit this page by hand; run `make docs-commands`.
4+
5+
Move a slide to a zero-based insertion index
6+
7+
## Usage
8+
9+
```bash
10+
gog slides (slide) move-slide --to-index=TO-INDEX <presentationId> <slideId>
11+
```
12+
13+
## Parent
14+
15+
- [gog slides](gog-slides.md)
16+
17+
## Flags
18+
19+
| Flag | Type | Default | Help |
20+
| --- | --- | --- | --- |
21+
| `--access-token` | `string` | | Use provided access token directly (bypasses stored refresh tokens; token expires in ~1h) |
22+
| `-a`<br>`--account`<br>`--acct` | `string` | | Account email, alias, or auto for authenticated Google API commands |
23+
| `--client` | `string` | | OAuth client name (selects stored credentials + token bucket) |
24+
| `--color` | `string` | auto | Color output: auto\|always\|never |
25+
| `--disable-commands` | `string` | | Comma-separated list of disabled commands; dot paths allowed |
26+
| `-n`<br>`--dry-run`<br>`--dryrun`<br>`--noop`<br>`--preview` | `bool` | | Do not make changes; print intended actions and exit successfully |
27+
| `--enable-commands` | `string` | | Comma-separated list of enabled command prefixes; dot paths allowed (restricts CLI) |
28+
| `--enable-commands-exact` | `string` | | Comma-separated list of exact enabled commands; dot paths allowed and parent commands do not enable children |
29+
| `-y`<br>`--force`<br>`--assume-yes`<br>`--yes` | `bool` | | Skip confirmations for destructive commands |
30+
| `--gmail-no-send` | `bool` | false | Block Gmail send operations (agent safety) |
31+
| `-h`<br>`--help` | `kong.helpFlag` | | Show context-sensitive help. |
32+
| `--home` | `string` | | Override gogcli config/data/state/cache root (equivalent to GOG_HOME) |
33+
| `-j`<br>`--json`<br>`--machine` | `bool` | false | Output JSON to stdout (best for scripting) |
34+
| `--no-input`<br>`--non-interactive`<br>`--noninteractive` | `bool` | | Never prompt; fail instead (useful for CI) |
35+
| `-p`<br>`--plain`<br>`--tsv` | `bool` | false | Output stable, parseable text to stdout (TSV; no colors) |
36+
| `--results-only` | `bool` | | In JSON mode, emit only the primary result (drops envelope fields like nextPageToken) |
37+
| `--select`<br>`--pick`<br>`--project` | `string` | | In JSON mode, select comma-separated fields (best-effort; supports dot paths). Desire path: use --fields for most commands. |
38+
| `--to-index` | `*int64` | | Zero-based insertion index where the slide should be moved |
39+
| `-v`<br>`--verbose` | `bool` | | Enable verbose logging |
40+
| `--version` | `kong.VersionFlag` | | Print version and exit |
41+
| `--wrap-untrusted` | `bool` | false | In JSON/raw output, wrap fetched text fields in external untrusted-content markers |
42+
43+
## See Also
44+
45+
- [gog slides](gog-slides.md)
46+
- [Command index](README.md)
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# `gog slides new-slide`
2+
3+
> Generated from `gog schema --json`. Do not edit this page by hand; run `make docs-commands`.
4+
5+
Create a native themed slide
6+
7+
## Usage
8+
9+
```bash
10+
gog slides (slide) new-slide <presentationId> [flags]
11+
```
12+
13+
## Parent
14+
15+
- [gog slides](gog-slides.md)
16+
17+
## Flags
18+
19+
| Flag | Type | Default | Help |
20+
| --- | --- | --- | --- |
21+
| `--access-token` | `string` | | Use provided access token directly (bypasses stored refresh tokens; token expires in ~1h) |
22+
| `-a`<br>`--account`<br>`--acct` | `string` | | Account email, alias, or auto for authenticated Google API commands |
23+
| `--client` | `string` | | OAuth client name (selects stored credentials + token bucket) |
24+
| `--color` | `string` | auto | Color output: auto\|always\|never |
25+
| `--disable-commands` | `string` | | Comma-separated list of disabled commands; dot paths allowed |
26+
| `-n`<br>`--dry-run`<br>`--dryrun`<br>`--noop`<br>`--preview` | `bool` | | Do not make changes; print intended actions and exit successfully |
27+
| `--enable-commands` | `string` | | Comma-separated list of enabled command prefixes; dot paths allowed (restricts CLI) |
28+
| `--enable-commands-exact` | `string` | | Comma-separated list of exact enabled commands; dot paths allowed and parent commands do not enable children |
29+
| `-y`<br>`--force`<br>`--assume-yes`<br>`--yes` | `bool` | | Skip confirmations for destructive commands |
30+
| `--gmail-no-send` | `bool` | false | Block Gmail send operations (agent safety) |
31+
| `-h`<br>`--help` | `kong.helpFlag` | | Show context-sensitive help. |
32+
| `--home` | `string` | | Override gogcli config/data/state/cache root (equivalent to GOG_HOME) |
33+
| `--index` | `*int64` | | Zero-based insertion index for the new slide |
34+
| `-j`<br>`--json`<br>`--machine` | `bool` | false | Output JSON to stdout (best for scripting) |
35+
| `--layout` | `*string` | | Predefined slide layout; defaults to BLANK |
36+
| `--layout-id` | `string` | | Exact presentation layout object ID from 'slides info --json'; mutually exclusive with --layout |
37+
| `--no-input`<br>`--non-interactive`<br>`--noninteractive` | `bool` | | Never prompt; fail instead (useful for CI) |
38+
| `-p`<br>`--plain`<br>`--tsv` | `bool` | false | Output stable, parseable text to stdout (TSV; no colors) |
39+
| `--results-only` | `bool` | | In JSON mode, emit only the primary result (drops envelope fields like nextPageToken) |
40+
| `--select`<br>`--pick`<br>`--project` | `string` | | In JSON mode, select comma-separated fields (best-effort; supports dot paths). Desire path: use --fields for most commands. |
41+
| `-v`<br>`--verbose` | `bool` | | Enable verbose logging |
42+
| `--version` | `kong.VersionFlag` | | Print version and exit |
43+
| `--wrap-untrusted` | `bool` | false | In JSON/raw output, wrap fetched text fields in external untrusted-content markers |
44+
45+
## See Also
46+
47+
- [gog slides](gog-slides.md)
48+
- [Command index](README.md)

docs/commands/gog-slides.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,16 @@ gog slides (slide) <command> [flags]
2323
- [gog slides create-from-markdown](gog-slides-create-from-markdown.md) - Create a Google Slides presentation from markdown
2424
- [gog slides create-from-template](gog-slides-create-from-template.md) - Create a presentation from template with text replacements
2525
- [gog slides delete-slide](gog-slides-delete-slide.md) - Delete a slide by object ID
26+
- [gog slides duplicate-slide](gog-slides-duplicate-slide.md) - Duplicate a slide by object ID
2627
- [gog slides export](gog-slides-export.md) - Export a Google Slides deck (pdf|pptx)
2728
- [gog slides info](gog-slides-info.md) - Get Google Slides presentation metadata
2829
- [gog slides insert-image](gog-slides-insert-image.md) - Insert a local or public image at a position and size
2930
- [gog slides insert-text](gog-slides-insert-text.md) - Insert text into an existing page element (shape or table) by objectId
3031
- [gog slides link](gog-slides-link.md) - Apply a hyperlink to a text range in one page element
3132
- [gog slides list-slides](gog-slides-list-slides.md) - List all slides with their object IDs
3233
- [gog slides locate](gog-slides-locate.md) - Locate text in shapes and table cells with object IDs and UTF-16 ranges
34+
- [gog slides move-slide](gog-slides-move-slide.md) - Move a slide to a zero-based insertion index
35+
- [gog slides new-slide](gog-slides-new-slide.md) - Create a native themed slide
3336
- [gog slides raw](gog-slides-raw.md) - Dump raw Google Slides API response as JSON (Presentations.Get; lossless; for scripting and LLM consumption)
3437
- [gog slides read-slide](gog-slides-read-slide.md) - Read slide content: speaker notes, text elements, and images
3538
- [gog slides replace-slide](gog-slides-replace-slide.md) - Replace an existing slide image from a local file or public URL

docs/slides-structure.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Slides structure
2+
3+
Create native, editable slides without rendering an image first:
4+
5+
```bash
6+
gog slides new-slide <presentationId>
7+
gog slides new-slide <presentationId> --layout TITLE_AND_BODY --index 1
8+
```
9+
10+
Without a layout flag, Google creates a blank slide. `--layout` accepts the
11+
Slides predefined layouts. A presentation theme can remove or modify a
12+
predefined layout; Google returns an error when the selected layout is not
13+
available in the active master.
14+
15+
For an exact theme layout, read its object ID from `slides info --json` and use
16+
`--layout-id`:
17+
18+
```bash
19+
gog slides info <presentationId> --json
20+
gog slides new-slide <presentationId> --layout-id <layoutId>
21+
```
22+
23+
`--layout` and `--layout-id` are mutually exclusive. `--index` is zero-based;
24+
omitting it appends the slide.
25+
26+
## Duplicate and move
27+
28+
Find stable slide IDs, then duplicate or reorder them:
29+
30+
```bash
31+
gog slides list-slides <presentationId> --json
32+
gog slides duplicate-slide <presentationId> <slideId>
33+
gog slides duplicate-slide <presentationId> <slideId> --to-index 2
34+
gog slides move-slide <presentationId> <slideId> --to-index 0
35+
```
36+
37+
Without `--to-index`, Google places a duplicate immediately after its source.
38+
With `--to-index`, duplication and positioning happen in one batch update.
39+
Move indexes are zero-based and refer to the presentation order before the move,
40+
matching the Slides API. An index can range from zero through the slide count.
41+
42+
Use `--dry-run --json` to inspect the exact batch request without contacting
43+
Google, and `slides list-slides --json` to verify the resulting order.

internal/cmd/slides.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ type SlidesCmd struct {
2222
CreateFromTemplate SlidesCreateFromTemplateCmd `cmd:"" name:"create-from-template" help:"Create a presentation from template with text replacements"`
2323
Copy SlidesCopyCmd `cmd:"" name:"copy" aliases:"cp,duplicate" help:"Copy a Google Slides presentation"`
2424
AddSlide SlidesAddSlideCmd `cmd:"" name:"add-slide" help:"Add a slide with a full-bleed image and optional speaker notes"`
25+
NewSlide SlidesNewSlideCmd `cmd:"" name:"new-slide" help:"Create a native themed slide"`
26+
DuplicateSlide SlidesDuplicateSlideCmd `cmd:"" name:"duplicate-slide" help:"Duplicate a slide by object ID"`
27+
MoveSlide SlidesMoveSlideCmd `cmd:"" name:"move-slide" help:"Move a slide to a zero-based insertion index"`
2528
ListSlides SlidesListSlidesCmd `cmd:"" name:"list-slides" help:"List all slides with their object IDs"`
2629
DeleteSlide SlidesDeleteSlideCmd `cmd:"" name:"delete-slide" help:"Delete a slide by object ID"`
2730
ReadSlide SlidesReadSlideCmd `cmd:"" name:"read-slide" help:"Read slide content: speaker notes, text elements, and images"`

0 commit comments

Comments
 (0)