scriptcast 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. scriptcast-0.1.0/PKG-INFO +21 -0
  2. scriptcast-0.1.0/README.md +258 -0
  3. scriptcast-0.1.0/pyproject.toml +71 -0
  4. scriptcast-0.1.0/scriptcast/__init__.py +0 -0
  5. scriptcast-0.1.0/scriptcast/__main__.py +371 -0
  6. scriptcast-0.1.0/scriptcast/assets/__init__.py +0 -0
  7. scriptcast-0.1.0/scriptcast/assets/fonts/DMSans-Regular.ttf +0 -0
  8. scriptcast-0.1.0/scriptcast/assets/fonts/Pacifico.ttf +0 -0
  9. scriptcast-0.1.0/scriptcast/assets/themes/aurora.sh +20 -0
  10. scriptcast-0.1.0/scriptcast/assets/themes/dark.sh +19 -0
  11. scriptcast-0.1.0/scriptcast/assets/themes/light.sh +19 -0
  12. scriptcast-0.1.0/scriptcast/config.py +199 -0
  13. scriptcast-0.1.0/scriptcast/directives.py +444 -0
  14. scriptcast-0.1.0/scriptcast/export.py +595 -0
  15. scriptcast-0.1.0/scriptcast/generator.py +265 -0
  16. scriptcast-0.1.0/scriptcast/recorder.py +212 -0
  17. scriptcast-0.1.0/scriptcast/shell/__init__.py +20 -0
  18. scriptcast-0.1.0/scriptcast/shell/adapter.py +13 -0
  19. scriptcast-0.1.0/scriptcast/shell/bash.py +11 -0
  20. scriptcast-0.1.0/scriptcast/shell/zsh.py +11 -0
  21. scriptcast-0.1.0/scriptcast.egg-info/PKG-INFO +21 -0
  22. scriptcast-0.1.0/scriptcast.egg-info/SOURCES.txt +36 -0
  23. scriptcast-0.1.0/scriptcast.egg-info/dependency_links.txt +1 -0
  24. scriptcast-0.1.0/scriptcast.egg-info/entry_points.txt +2 -0
  25. scriptcast-0.1.0/scriptcast.egg-info/requires.txt +10 -0
  26. scriptcast-0.1.0/scriptcast.egg-info/top_level.txt +5 -0
  27. scriptcast-0.1.0/setup.cfg +4 -0
  28. scriptcast-0.1.0/tests/__init__.py +0 -0
  29. scriptcast-0.1.0/tests/test_cli.py +304 -0
  30. scriptcast-0.1.0/tests/test_config.py +400 -0
  31. scriptcast-0.1.0/tests/test_directives.py +606 -0
  32. scriptcast-0.1.0/tests/test_export.py +986 -0
  33. scriptcast-0.1.0/tests/test_generator.py +434 -0
  34. scriptcast-0.1.0/tests/test_integration.py +97 -0
  35. scriptcast-0.1.0/tests/test_recorder.py +462 -0
  36. scriptcast-0.1.0/tests/test_registry.py +57 -0
  37. scriptcast-0.1.0/tests/test_shell.py +34 -0
  38. scriptcast-0.1.0/tests/test_theme.py +204 -0
@@ -0,0 +1,21 @@
1
+ Metadata-Version: 2.4
2
+ Name: scriptcast
3
+ Version: 0.1.0
4
+ Summary: Generate terminal demos (asciinema casts & GIFs) from simple shell-like scripts.
5
+ Author-email: Nasser Alansari <dacrystal@users.noreply.github.com>
6
+ License: MIT
7
+ Classifier: License :: OSI Approved :: MIT License
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.10
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Requires-Python: >=3.10
13
+ Requires-Dist: click>=8.0
14
+ Requires-Dist: pillow>=9.0
15
+ Provides-Extra: dev
16
+ Requires-Dist: asciinema>=2.4.0; extra == "dev"
17
+ Requires-Dist: pytest>=8.0; extra == "dev"
18
+ Requires-Dist: pytest-cov; extra == "dev"
19
+ Requires-Dist: ruff>=0.4; extra == "dev"
20
+ Requires-Dist: mypy>=1.10; extra == "dev"
21
+ Requires-Dist: git-cliff>=2.0; extra == "dev"
@@ -0,0 +1,258 @@
1
+ # scriptcast
2
+
3
+ ![scriptcast demo](assets/demo.png)
4
+
5
+ [![Standard Readme](https://img.shields.io/badge/readme%20style-standard-brightgreen.svg)](https://github.com/RichardLitt/standard-readme)
6
+ [![PyPI version](https://img.shields.io/pypi/v/scriptcast.svg)](https://pypi.org/project/scriptcast/)
7
+ [![Tests](https://github.com/dacrystal/scriptcast/actions/workflows/tests.yml/badge.svg)](https://github.com/dacrystal/scriptcast/actions)
8
+
9
+ Generate terminal demos (asciinema casts & GIFs) from annotated shell scripts.
10
+
11
+ scriptcast turns a shell script into a reproducible, polished terminal demo — with
12
+ typing animations, multiple scenes, mocked commands, interactive sessions, output
13
+ filtering, and more.
14
+
15
+ ## Table of Contents
16
+
17
+ - [Background](#background)
18
+ - [Install](#install)
19
+ - [Usage](#usage)
20
+ - [Examples](#examples)
21
+ - [Script Syntax](#script-syntax)
22
+ - [Similar Projects](#similar-projects)
23
+ - [Contributing](#contributing)
24
+ - [License](#license)
25
+
26
+ ## Background
27
+
28
+ Terminal demos are hard to reproduce. Screen recordings drift, manual re-runs produce
29
+ different output, and polishing timing or hiding sensitive paths requires video editing.
30
+
31
+ scriptcast treats demos as code. You write a shell script annotated with `SC`
32
+ directives — controlling scenes, typing speed, mocked commands, interactive expect
33
+ sessions, and output filters — then run a two-stage pipeline:
34
+
35
+ 1. **Record** — the script executes with shell tracing enabled; raw output is captured
36
+ and written to a JSONL `.sc` file containing timestamped `cmd`, `output`, `input`,
37
+ and `directive` events.
38
+ 2. **Generate** — the `.sc` file is read by a streaming renderer that synthesises a
39
+ polished asciinema `.cast` file with typing animations and timing.
40
+
41
+ The `.sc` file is plain text, version-controllable, and diffable. Re-generating a cast
42
+ from an existing `.sc` is instant.
43
+
44
+ ## Install
45
+
46
+ ```bash
47
+ pip install scriptcast
48
+ ```
49
+
50
+ Requires Python 3.10+. For GIF output, install [agg](https://github.com/asciinema/agg).
51
+
52
+ ### From source
53
+
54
+ ```bash
55
+ git clone https://github.com/dacrystal/scriptcast.git
56
+ cd scriptcast
57
+ pip install -e .
58
+ ```
59
+
60
+ ## Usage
61
+
62
+ ```bash
63
+ scriptcast demo.sh # record → generate → export (PNG by default)
64
+ scriptcast demo.sc # generate → export (skip record)
65
+ scriptcast demo.cast # export only
66
+
67
+ scriptcast --no-export demo.sh # record + generate only, no image
68
+ scriptcast --format gif demo.sh # export as GIF (requires agg)
69
+ scriptcast install # install agg binary and fonts
70
+ ```
71
+
72
+ Key flags:
73
+
74
+ | Flag | Default | Description |
75
+ |------|---------|-------------|
76
+ | `--output-dir PATH` | same dir as input | Where to write output files |
77
+ | `--no-export` | off | Stop after generating `.cast`; skip image export |
78
+ | `--format [gif\|png]` | `png` | Export format |
79
+ | `--theme TEXT` | `dark` | Built-in theme name or path to `.sh` theme file |
80
+ | `--directive-prefix PREFIX` | `SC` | Directive prefix used in scripts |
81
+ | `--trace-prefix CHAR` | `+` | PS4/xtrace prefix |
82
+ | `--shell PATH` | `$SHELL` | Shell used for recording |
83
+ | `--split-scenes` | off | Write one `.cast` file per scene |
84
+ | `--xtrace-log` | off | Save raw xtrace capture to `<stem>.xtrace` |
85
+
86
+ ## Examples
87
+
88
+ **`examples/showcase.sh`** — a realistic three-scene demo: interactive login, mocked deploy, status check with filter.
89
+
90
+ ![showcase](assets/showcase-aurora.png)
91
+
92
+ **`examples/tutorial.sh`** — one scene per directive: mock, expect, filter, comment, sleep, word\_speed, record pause/resume.
93
+
94
+ ![tutorial](assets/tutorial.png)
95
+
96
+ ### Themes
97
+
98
+ Built-in themes: `dark` (default), `aurora`, `light`. Pass `--theme <name>` or a path to a custom `.sh` theme file.
99
+
100
+ | `--theme dark` | `--theme aurora` | `--theme light` |
101
+ |:---:|:---:|:---:|
102
+ | ![dark](assets/showcase-dark.png) | ![aurora](assets/showcase-aurora.png) | ![light](assets/showcase-light.png) |
103
+
104
+ ## Script Syntax
105
+
106
+ Scripts are valid shell scripts. `SC` directives are embedded as shell no-ops
107
+ (`: SC ...`) so they execute harmlessly but appear in the xtrace output for the
108
+ recorder to process.
109
+
110
+ ```sh
111
+ #!/usr/bin/env scriptcast
112
+
113
+ # Global config — applied before any scene
114
+ : SC set type_speed 40
115
+ : SC set width 80
116
+ : SC set height 24
117
+
118
+ # ── Scene: intro ──────────────────────────────
119
+ : SC scene intro
120
+
121
+ echo "Hello from scriptcast"
122
+
123
+ # ── Scene: mock ───────────────────────────────
124
+ : SC scene mock
125
+
126
+ : SC mock deploy <<'EOF'
127
+ Deploying to production...
128
+ Build: OK
129
+ Tests: OK
130
+ Deploy: OK
131
+ EOF
132
+
133
+ deploy
134
+
135
+ # ── Scene: expect ─────────────────────────────
136
+ : SC scene expect
137
+
138
+ : SC expect ./my-app <<'EOF'
139
+ expect "Password:"
140
+ send "secret\r"
141
+ expect "prompt>"
142
+ send "quit\r"
143
+ expect eof
144
+ EOF
145
+
146
+ # ── Scene: filter ─────────────────────────────
147
+ : SC scene filter
148
+
149
+ : SC filter sed 's#/home/user/projects#<project>#g'
150
+
151
+ pwd
152
+
153
+ # ── Scene: comment ────────────────────────────
154
+ : SC scene comment
155
+
156
+ : SC '\' This is a visual comment
157
+ echo "comments appear as prompt lines in the cast"
158
+
159
+ # ── Scene: setup (not recorded) ───────────────
160
+ : SC scene setup
161
+
162
+ : SC record pause
163
+ DB_URL="postgres://localhost/mydb"
164
+ : SC record resume
165
+
166
+ echo "Connecting to $DB_URL"
167
+ ```
168
+
169
+ ### Recorder directives
170
+
171
+ These are consumed during recording and never appear in the `.sc` file.
172
+
173
+ | Directive | Description |
174
+ |-----------|-------------|
175
+ | `SC mock <cmd> <<'EOF'` ... `EOF` | Mock `<cmd>` so it prints fixed output during recording |
176
+ | `SC expect <cmd> <<'EOF'` ... `EOF` | Run an interactive session via [expect(1)](https://core.tcl-lang.org/expect/index) |
177
+ | `SC record pause` | Stop capturing output (commands still execute) |
178
+ | `SC record resume` | Resume capturing |
179
+ | `SC filter <cmd> [args...]` | Replace the current output filter with a shell command (stdin→stdout) |
180
+ | `SC filter-add <cmd> [args...]` | Append a command to the current filter chain |
181
+ | `SC '\' <text>` | Emit a `# text` comment line in the cast (visual annotation) |
182
+ | `SC helpers` | Inject ANSI color variables (`RED`, `YELLOW`, `GREEN`, `CYAN`, `BOLD`, `RESET`) silently into the script |
183
+
184
+ #### `SC expect` syntax
185
+
186
+ The heredoc body is a standard expect script. scriptcast preprocesses it to capture
187
+ typed input and clean up spawn noise. Inputs sent with `send` are recorded as `input`
188
+ events; silent inputs (e.g. passwords read with `read -rs`) produce silent animations.
189
+
190
+ ```sh
191
+ : SC expect ./fake-db <<'EOF'
192
+ expect "Password:"
193
+ send "secret\r"
194
+ expect "mysql>"
195
+ send "show databases;\r"
196
+ expect eof
197
+ EOF
198
+ ```
199
+
200
+ ### Generator directives
201
+
202
+ These are stored in the `.sc` file and interpreted during cast generation.
203
+
204
+ | Directive | Description |
205
+ |-----------|-------------|
206
+ | `SC scene <name>` | Start a new scene |
207
+ | `SC set <key> <value>` | Set a timing or display config key |
208
+ | `SC sleep <ms>` | Pause for N milliseconds |
209
+
210
+ ### Config keys (`SC set`)
211
+
212
+ | Key | Default | Description |
213
+ |-----|---------|-------------|
214
+ | `type_speed` | `40` | ms per character when typing commands |
215
+ | `cmd_wait` | `80` | ms after a command is typed, before output |
216
+ | `input_wait` | `80` | ms to pause before typing interactive input |
217
+ | `enter_wait` | `80` | ms at the start of each scene, after clearing |
218
+ | `exit_wait` | `120` | ms after the last output line of a scene |
219
+ | `width` | `100` | Terminal width (columns) |
220
+ | `height` | `28` | Terminal height (rows) |
221
+ | `prompt` | `$ ` | Prompt string shown before commands |
222
+ | `word_speed` | same as `type_speed` | Extra ms pause after each space when typing |
223
+ | `cr_delay` | `0` | ms between `\r`-split segments (for progress-bar animations) |
224
+
225
+ When using ANSI escape sequences in `prompt`, use ANSI-C quoting so the shell
226
+ interprets the escapes before scriptcast sees them:
227
+
228
+ ```sh
229
+ : SC set prompt $'\033[92m> \033[0m'
230
+ ```
231
+
232
+ ## Similar Projects
233
+
234
+ - [VHS](https://github.com/charmbracelet/vhs) — declarative `.tape` DSL for scripted terminal recordings; outputs GIF, MP4, WebM
235
+ - [Terminalizer](https://github.com/faressoft/terminalizer) — record a live terminal session and render it as a GIF or HTML player
236
+ - [asciinema_automation](https://github.com/PierreMarchand20/asciinema_automation) — automate asciinema recordings using pexpect and comment directives
237
+ - [demo-magic](https://github.com/paxtonhare/demo-magic) — bash function library for simulated typing in live terminal presentations
238
+
239
+ **What makes scriptcast different:**
240
+
241
+ - **Shell-script-native** — the demo source is a real, runnable `.sh` file, not a DSL or config format. Directives are no-op shell comments that execute harmlessly.
242
+ - **Two-stage pipeline** — `record` and `generate` are separate. Re-rendering with different timing or themes is instant, no re-recording needed.
243
+ - **Version-controllable** — the `.sc` file is plain JSONL, diffable and reviewable in git.
244
+ - **Mocking and expect** — `SC mock` and `SC expect` let you script slow, side-effectful, or interactive commands without running the real thing.
245
+ - **Output filters** — `SC filter` pipes captured output through any shell command to scrub paths, tokens, or hostnames before they reach the cast.
246
+
247
+ ## Contributing
248
+
249
+ Issues and pull requests are welcome at
250
+ [github.com/dacrystal/scriptcast](https://github.com/dacrystal/scriptcast/issues).
251
+
252
+ Before opening a PR, ensure:
253
+ - All tests pass: `uv run pytest`
254
+ - New behaviour is covered by tests
255
+
256
+ ## License
257
+
258
+ MIT © dacrystal
@@ -0,0 +1,71 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "scriptcast"
7
+ version = "0.1.0"
8
+ description = "Generate terminal demos (asciinema casts & GIFs) from simple shell-like scripts."
9
+ requires-python = ">=3.10"
10
+ authors = [
11
+ {name = "Nasser Alansari", email = "dacrystal@users.noreply.github.com"},
12
+ ]
13
+ license = {text = "MIT"}
14
+ classifiers = [
15
+ "License :: OSI Approved :: MIT License",
16
+ "Programming Language :: Python :: 3",
17
+ "Programming Language :: Python :: 3.10",
18
+ "Programming Language :: Python :: 3.11",
19
+ "Programming Language :: Python :: 3.12",
20
+ ]
21
+ dependencies = [
22
+ "click>=8.0",
23
+ "pillow>=9.0",
24
+ ]
25
+
26
+ [project.scripts]
27
+ scriptcast = "scriptcast.__main__:cli"
28
+
29
+ [project.optional-dependencies]
30
+ dev = [
31
+ "asciinema>=2.4.0",
32
+ "pytest>=8.0",
33
+ "pytest-cov",
34
+ "ruff>=0.4",
35
+ "mypy>=1.10",
36
+ "git-cliff>=2.0",
37
+ ]
38
+
39
+ [tool.setuptools.packages.find]
40
+ where = ["."]
41
+
42
+ [tool.setuptools.package-data]
43
+ scriptcast = ["assets/**/*"]
44
+
45
+ [tool.pytest.ini_options]
46
+ testpaths = ["tests"]
47
+
48
+ [tool.ruff]
49
+ target-version = "py310"
50
+ line-length = 100
51
+
52
+ [tool.ruff.lint]
53
+ select = ["E", "F", "I", "UP"]
54
+
55
+ [tool.mypy]
56
+ python_version = "3.10"
57
+ strict = false
58
+ warn_unused_ignores = true
59
+ warn_return_any = true
60
+ disallow_untyped_defs = true
61
+
62
+ [[tool.mypy.overrides]]
63
+ module = ["PIL", "PIL.*"]
64
+ ignore_missing_imports = true
65
+
66
+ [[tool.mypy.overrides]]
67
+ module = ["tests.*"]
68
+ disallow_untyped_defs = false
69
+
70
+ # Entry-point group for third-party directives. See DIRECTIVES.md.
71
+ [project.entry-points."scriptcast.directives"]
File without changes