demotape 0.0.2 → 0.0.3

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 (548) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +6 -0
  3. data/CHANGELOG.md +9 -0
  4. data/Makefile +4 -2
  5. data/README.md +101 -10
  6. data/demotape.gemspec +1 -1
  7. data/demotape.y +224 -505
  8. data/demotape_new.y.backup +160 -0
  9. data/demotape_simple_test.y +32 -0
  10. data/editors/sublime-text/DemoTape.sublime-completions +4 -0
  11. data/editors/sublime-text/DemoTape.sublime-syntax +24 -2
  12. data/editors/vim/syntax/demotape.vim +16 -2
  13. data/editors/vscode/demotape.tmLanguage.json +31 -3
  14. data/lib/demo_tape/cli.rb +36 -0
  15. data/lib/demo_tape/command.rb +63 -103
  16. data/lib/demo_tape/exporter.rb +3 -0
  17. data/lib/demo_tape/formatter.rb +142 -0
  18. data/lib/demo_tape/lexer.rb +118 -34
  19. data/lib/demo_tape/parser/helpers.rb +363 -0
  20. data/lib/demo_tape/parser/rules.rb +396 -0
  21. data/lib/demo_tape/parser.rb +381 -592
  22. data/lib/demo_tape/runner.rb +82 -27
  23. data/lib/demo_tape/token.rb +86 -0
  24. data/lib/demo_tape/version.rb +1 -1
  25. data/lib/demo_tape.rb +5 -2
  26. metadata +10 -527
  27. data/examples/alt.mp4 +0 -0
  28. data/examples/alt.png +0 -0
  29. data/examples/alt.tape +0 -9
  30. data/examples/arrow.mp4 +0 -0
  31. data/examples/arrow.png +0 -0
  32. data/examples/arrow.tape +0 -7
  33. data/examples/backspace.mp4 +0 -0
  34. data/examples/backspace.png +0 -0
  35. data/examples/backspace.tape +0 -4
  36. data/examples/bash.mp4 +0 -0
  37. data/examples/bash.png +0 -0
  38. data/examples/bash.tape +0 -4
  39. data/examples/bg.jpg +0 -0
  40. data/examples/clear.mp4 +0 -0
  41. data/examples/clear.png +0 -0
  42. data/examples/clear.tape +0 -6
  43. data/examples/cli_ui_interactive_prompt.mp4 +0 -0
  44. data/examples/cli_ui_interactive_prompt.png +0 -0
  45. data/examples/cli_ui_interactive_prompt.tape +0 -16
  46. data/examples/cli_ui_nested_frames.mp4 +0 -0
  47. data/examples/cli_ui_nested_frames.png +0 -0
  48. data/examples/cli_ui_nested_frames.tape +0 -15
  49. data/examples/cli_ui_progress.mp4 +0 -0
  50. data/examples/cli_ui_progress.png +0 -0
  51. data/examples/cli_ui_progress.tape +0 -6
  52. data/examples/cli_ui_spinner.mp4 +0 -0
  53. data/examples/cli_ui_spinner.png +0 -0
  54. data/examples/cli_ui_spinner.tape +0 -6
  55. data/examples/cli_ui_status_widget.mp4 +0 -0
  56. data/examples/cli_ui_status_widget.png +0 -0
  57. data/examples/cli_ui_status_widget.tape +0 -6
  58. data/examples/cli_ui_symbols.mp4 +0 -0
  59. data/examples/cli_ui_symbols.png +0 -0
  60. data/examples/cli_ui_symbols.tape +0 -6
  61. data/examples/cli_ui_text_prompt.mp4 +0 -0
  62. data/examples/cli_ui_text_prompt.png +0 -0
  63. data/examples/cli_ui_text_prompt.tape +0 -10
  64. data/examples/clipboard.mp4 +0 -0
  65. data/examples/clipboard.png +0 -0
  66. data/examples/clipboard.tape +0 -5
  67. data/examples/ctrl.mp4 +0 -0
  68. data/examples/ctrl.png +0 -0
  69. data/examples/ctrl.tape +0 -5
  70. data/examples/ctrl_arrows.mp4 +0 -0
  71. data/examples/ctrl_arrows.png +0 -0
  72. data/examples/ctrl_arrows.tape +0 -14
  73. data/examples/demotape.mp4 +0 -0
  74. data/examples/demotape.png +0 -0
  75. data/examples/demotape.tape +0 -6
  76. data/examples/demotape.txt +0 -13
  77. data/examples/enter.mp4 +0 -0
  78. data/examples/enter.png +0 -0
  79. data/examples/enter.tape +0 -3
  80. data/examples/errors/include_itself.tape +0 -1
  81. data/examples/fastfetch.gif +0 -0
  82. data/examples/fastfetch.mp4 +0 -0
  83. data/examples/fastfetch.png +0 -0
  84. data/examples/fastfetch.tape +0 -11
  85. data/examples/fish.mp4 +0 -0
  86. data/examples/fish.png +0 -0
  87. data/examples/fish.tape +0 -4
  88. data/examples/format.mp4 +0 -0
  89. data/examples/format.png +0 -0
  90. data/examples/format.tape +0 -15
  91. data/examples/gh-cli.mp4 +0 -0
  92. data/examples/gh-cli.png +0 -0
  93. data/examples/gh-cli.tape +0 -13
  94. data/examples/gif_loop.gif +0 -0
  95. data/examples/gif_loop.png +0 -0
  96. data/examples/gif_loop.tape +0 -5
  97. data/examples/include.mp4 +0 -0
  98. data/examples/include.png +0 -0
  99. data/examples/include.tape +0 -1
  100. data/examples/include_with_set.mp4 +0 -0
  101. data/examples/include_with_set.png +0 -0
  102. data/examples/include_with_set.tape +0 -2
  103. data/examples/meta/cli.tape +0 -10
  104. data/examples/nerdfonts.mp4 +0 -0
  105. data/examples/nerdfonts.png +0 -0
  106. data/examples/nerdfonts.tape +0 -9
  107. data/examples/output.avi +0 -0
  108. data/examples/output.gif +0 -0
  109. data/examples/output.mov +0 -0
  110. data/examples/output.mp4 +0 -0
  111. data/examples/output.png +0 -0
  112. data/examples/output.tape +0 -9
  113. data/examples/output.webm +0 -0
  114. data/examples/products.json +0 -1803
  115. data/examples/screenshot.mp4 +0 -0
  116. data/examples/screenshot.png +0 -0
  117. data/examples/screenshot.tape +0 -9
  118. data/examples/script.rb +0 -3
  119. data/examples/set_cursor_bar.mp4 +0 -0
  120. data/examples/set_cursor_bar.png +0 -0
  121. data/examples/set_cursor_bar.tape +0 -5
  122. data/examples/set_cursor_blink.mp4 +0 -0
  123. data/examples/set_cursor_blink.png +0 -0
  124. data/examples/set_cursor_blink.tape +0 -4
  125. data/examples/set_cursor_underline.mp4 +0 -0
  126. data/examples/set_cursor_underline.png +0 -0
  127. data/examples/set_cursor_underline.tape +0 -5
  128. data/examples/set_dimensions.mp4 +0 -0
  129. data/examples/set_dimensions.png +0 -0
  130. data/examples/set_dimensions.tape +0 -5
  131. data/examples/set_font_family.mp4 +0 -0
  132. data/examples/set_font_family.png +0 -0
  133. data/examples/set_font_family.tape +0 -4
  134. data/examples/set_font_size.mp4 +0 -0
  135. data/examples/set_font_size.png +0 -0
  136. data/examples/set_font_size.tape +0 -4
  137. data/examples/set_line_height.mp4 +0 -0
  138. data/examples/set_line_height.png +0 -0
  139. data/examples/set_line_height.tape +0 -8
  140. data/examples/set_margin.mp4 +0 -0
  141. data/examples/set_margin.png +0 -0
  142. data/examples/set_margin.tape +0 -7
  143. data/examples/set_margin_with_border_radius.mp4 +0 -0
  144. data/examples/set_margin_with_border_radius.png +0 -0
  145. data/examples/set_margin_with_border_radius.tape +0 -8
  146. data/examples/set_margin_with_image.mp4 +0 -0
  147. data/examples/set_margin_with_image.png +0 -0
  148. data/examples/set_margin_with_image.tape +0 -7
  149. data/examples/set_padding.mp4 +0 -0
  150. data/examples/set_padding.png +0 -0
  151. data/examples/set_padding.tape +0 -7
  152. data/examples/set_theme.mp4 +0 -0
  153. data/examples/set_theme.png +0 -0
  154. data/examples/set_theme.tape +0 -9
  155. data/examples/set_theme_property.mp4 +0 -0
  156. data/examples/set_theme_property.png +0 -0
  157. data/examples/set_theme_property.tape +0 -10
  158. data/examples/set_typing_speed.mp4 +0 -0
  159. data/examples/set_typing_speed.png +0 -0
  160. data/examples/set_typing_speed.tape +0 -6
  161. data/examples/slides.mp4 +0 -0
  162. data/examples/slides.png +0 -0
  163. data/examples/slides.tape +0 -14
  164. data/examples/space.mp4 +0 -0
  165. data/examples/space.png +0 -0
  166. data/examples/space.tape +0 -3
  167. data/examples/stdin.mp4 +0 -0
  168. data/examples/stdin.png +0 -0
  169. data/examples/stdin.tape +0 -7
  170. data/examples/tab.mp4 +0 -0
  171. data/examples/tab.png +0 -0
  172. data/examples/tab.tape +0 -5
  173. data/examples/themes/3024_day.png +0 -0
  174. data/examples/themes/3024_night.png +0 -0
  175. data/examples/themes/aardvark_blue.png +0 -0
  176. data/examples/themes/abernathy.png +0 -0
  177. data/examples/themes/adventure.png +0 -0
  178. data/examples/themes/adventure_time.png +0 -0
  179. data/examples/themes/afterglow.png +0 -0
  180. data/examples/themes/alabaster.png +0 -0
  181. data/examples/themes/alien_blood.png +0 -0
  182. data/examples/themes/andromeda.png +0 -0
  183. data/examples/themes/apple_classic.png +0 -0
  184. data/examples/themes/apple_system_colors.png +0 -0
  185. data/examples/themes/arcoiris.png +0 -0
  186. data/examples/themes/argonaut.png +0 -0
  187. data/examples/themes/arthur.png +0 -0
  188. data/examples/themes/atelier_sulphurpool.png +0 -0
  189. data/examples/themes/atom.png +0 -0
  190. data/examples/themes/atom_one_light.png +0 -0
  191. data/examples/themes/aurora.png +0 -0
  192. data/examples/themes/ayu.png +0 -0
  193. data/examples/themes/ayu_light.png +0 -0
  194. data/examples/themes/ayu_mirage.png +0 -0
  195. data/examples/themes/banana_blueberry.png +0 -0
  196. data/examples/themes/batman.png +0 -0
  197. data/examples/themes/belafonte_day.png +0 -0
  198. data/examples/themes/belafonte_night.png +0 -0
  199. data/examples/themes/birds_of_paradise.png +0 -0
  200. data/examples/themes/blazer.png +0 -0
  201. data/examples/themes/blue_berry_pie.png +0 -0
  202. data/examples/themes/blue_dolphin.png +0 -0
  203. data/examples/themes/blue_matrix.png +0 -0
  204. data/examples/themes/bluloco_dark.png +0 -0
  205. data/examples/themes/bluloco_light.png +0 -0
  206. data/examples/themes/borland.png +0 -0
  207. data/examples/themes/breeze.png +0 -0
  208. data/examples/themes/bright_lights.png +0 -0
  209. data/examples/themes/broadcast.png +0 -0
  210. data/examples/themes/brogrammer.png +0 -0
  211. data/examples/themes/bubbles.png +0 -0
  212. data/examples/themes/builtin_dark.png +0 -0
  213. data/examples/themes/builtin_light.png +0 -0
  214. data/examples/themes/builtin_pastel_dark.png +0 -0
  215. data/examples/themes/builtin_solarized_dark.png +0 -0
  216. data/examples/themes/builtin_solarized_light.png +0 -0
  217. data/examples/themes/builtin_tango_dark.png +0 -0
  218. data/examples/themes/builtin_tango_light.png +0 -0
  219. data/examples/themes/c64.png +0 -0
  220. data/examples/themes/calamity.png +0 -0
  221. data/examples/themes/catppuccin_frappe.png +0 -0
  222. data/examples/themes/catppuccin_latte.png +0 -0
  223. data/examples/themes/catppuccin_macchiato.png +0 -0
  224. data/examples/themes/catppuccin_mocha.png +0 -0
  225. data/examples/themes/cga.png +0 -0
  226. data/examples/themes/chalk.png +0 -0
  227. data/examples/themes/chalkboard.png +0 -0
  228. data/examples/themes/challenger_deep.png +0 -0
  229. data/examples/themes/chester.png +0 -0
  230. data/examples/themes/ciapre.png +0 -0
  231. data/examples/themes/clrs.png +0 -0
  232. data/examples/themes/cobalt2.png +0 -0
  233. data/examples/themes/cobalt_neon.png +0 -0
  234. data/examples/themes/coffee_theme.png +0 -0
  235. data/examples/themes/contrast_light.png +0 -0
  236. data/examples/themes/coolnight.png +0 -0
  237. data/examples/themes/crayon_pony_fish.png +0 -0
  238. data/examples/themes/crystal_violet.png +0 -0
  239. data/examples/themes/cutie_pro.png +0 -0
  240. data/examples/themes/cyber_cube.png +0 -0
  241. data/examples/themes/cyber_punk2077.png +0 -0
  242. data/examples/themes/cyberdyne.png +0 -0
  243. data/examples/themes/cyberpunk.png +0 -0
  244. data/examples/themes/dark_pastel.png +0 -0
  245. data/examples/themes/dark_plus.png +0 -0
  246. data/examples/themes/darkermatrix.png +0 -0
  247. data/examples/themes/darkmatrix.png +0 -0
  248. data/examples/themes/darkside.png +0 -0
  249. data/examples/themes/dayfox.png +0 -0
  250. data/examples/themes/deep.png +0 -0
  251. data/examples/themes/desert.png +0 -0
  252. data/examples/themes/dimmed_monokai.png +0 -0
  253. data/examples/themes/django.png +0 -0
  254. data/examples/themes/django_reborn_again.png +0 -0
  255. data/examples/themes/django_smooth.png +0 -0
  256. data/examples/themes/doom_one.png +0 -0
  257. data/examples/themes/doom_peacock.png +0 -0
  258. data/examples/themes/dot_gov.png +0 -0
  259. data/examples/themes/dracula.png +0 -0
  260. data/examples/themes/dracula_plus.png +0 -0
  261. data/examples/themes/duckbones.png +0 -0
  262. data/examples/themes/duotone_dark.png +0 -0
  263. data/examples/themes/earthsong.png +0 -0
  264. data/examples/themes/elemental.png +0 -0
  265. data/examples/themes/elementary.png +0 -0
  266. data/examples/themes/encom.png +0 -0
  267. data/examples/themes/espresso.png +0 -0
  268. data/examples/themes/espresso_libre.png +0 -0
  269. data/examples/themes/everblush.png +0 -0
  270. data/examples/themes/fahrenheit.png +0 -0
  271. data/examples/themes/fairyfloss.png +0 -0
  272. data/examples/themes/farmhouse_dark.png +0 -0
  273. data/examples/themes/farmhouse_light.png +0 -0
  274. data/examples/themes/fideloper.png +0 -0
  275. data/examples/themes/firefly_traditional.png +0 -0
  276. data/examples/themes/firefox_dev.png +0 -0
  277. data/examples/themes/firewatch.png +0 -0
  278. data/examples/themes/fish_tank.png +0 -0
  279. data/examples/themes/flat.png +0 -0
  280. data/examples/themes/flatland.png +0 -0
  281. data/examples/themes/flexoki_dark.png +0 -0
  282. data/examples/themes/flexoki_light.png +0 -0
  283. data/examples/themes/floraverse.png +0 -0
  284. data/examples/themes/forest_blue.png +0 -0
  285. data/examples/themes/framer.png +0 -0
  286. data/examples/themes/front_end_delight.png +0 -0
  287. data/examples/themes/fun_forrest.png +0 -0
  288. data/examples/themes/galaxy.png +0 -0
  289. data/examples/themes/galizur.png +0 -0
  290. data/examples/themes/ganyu.png +0 -0
  291. data/examples/themes/git_hub_dark.png +0 -0
  292. data/examples/themes/github.png +0 -0
  293. data/examples/themes/glacier.png +0 -0
  294. data/examples/themes/glorious.png +0 -0
  295. data/examples/themes/grape.png +0 -0
  296. data/examples/themes/grass.png +0 -0
  297. data/examples/themes/grey_green.png +0 -0
  298. data/examples/themes/gruvbox_dark.png +0 -0
  299. data/examples/themes/gruvbox_dark_hard.png +0 -0
  300. data/examples/themes/gruvbox_light.png +0 -0
  301. data/examples/themes/guezwhoz.png +0 -0
  302. data/examples/themes/h4rithd.png +0 -0
  303. data/examples/themes/h4rithd_com.png +0 -0
  304. data/examples/themes/ha_x0_r_blue.png +0 -0
  305. data/examples/themes/ha_x0_r_gr33_n.png +0 -0
  306. data/examples/themes/ha_x0_r_r3_d.png +0 -0
  307. data/examples/themes/hacktober.png +0 -0
  308. data/examples/themes/hardcore.png +0 -0
  309. data/examples/themes/harper.png +0 -0
  310. data/examples/themes/highway.png +0 -0
  311. data/examples/themes/hipster_green.png +0 -0
  312. data/examples/themes/hivacruz.png +0 -0
  313. data/examples/themes/homebrew.png +0 -0
  314. data/examples/themes/hopscotch.png +0 -0
  315. data/examples/themes/hopscotch_256.png +0 -0
  316. data/examples/themes/horizon.png +0 -0
  317. data/examples/themes/hurtado.png +0 -0
  318. data/examples/themes/hybrid.png +0 -0
  319. data/examples/themes/hyper.png +0 -0
  320. data/examples/themes/ic_green_ppl.png +0 -0
  321. data/examples/themes/ic_orange_ppl.png +0 -0
  322. data/examples/themes/iceberg_dark.png +0 -0
  323. data/examples/themes/iceberg_light.png +0 -0
  324. data/examples/themes/idea.png +0 -0
  325. data/examples/themes/idle_toes.png +0 -0
  326. data/examples/themes/ir_black.png +0 -0
  327. data/examples/themes/iterm2_dark_background.png +0 -0
  328. data/examples/themes/iterm2_default.png +0 -0
  329. data/examples/themes/iterm2_light_background.png +0 -0
  330. data/examples/themes/iterm2_pastel_dark_background.png +0 -0
  331. data/examples/themes/iterm2_smoooooth.png +0 -0
  332. data/examples/themes/iterm2_solarized_dark.png +0 -0
  333. data/examples/themes/iterm2_solarized_light.png +0 -0
  334. data/examples/themes/iterm2_tango_dark.png +0 -0
  335. data/examples/themes/iterm2_tango_light.png +0 -0
  336. data/examples/themes/jackie_brown.png +0 -0
  337. data/examples/themes/japanesque.png +0 -0
  338. data/examples/themes/jellybeans.png +0 -0
  339. data/examples/themes/jet_brains_darcula.png +0 -0
  340. data/examples/themes/jubi.png +0 -0
  341. data/examples/themes/juicy_colors.png +0 -0
  342. data/examples/themes/kanagawa.png +0 -0
  343. data/examples/themes/kanagawabones.png +0 -0
  344. data/examples/themes/kibble.png +0 -0
  345. data/examples/themes/kolorit.png +0 -0
  346. data/examples/themes/konsolas.png +0 -0
  347. data/examples/themes/lab_fox.png +0 -0
  348. data/examples/themes/laser.png +0 -0
  349. data/examples/themes/later_this_evening.png +0 -0
  350. data/examples/themes/lavandula.png +0 -0
  351. data/examples/themes/liquid_carbon.png +0 -0
  352. data/examples/themes/liquid_carbon_transparent.png +0 -0
  353. data/examples/themes/liquid_carbon_transparent_inverse.png +0 -0
  354. data/examples/themes/lovelace.png +0 -0
  355. data/examples/themes/man_page.png +0 -0
  356. data/examples/themes/mariana.png +0 -0
  357. data/examples/themes/material.png +0 -0
  358. data/examples/themes/material_dark.png +0 -0
  359. data/examples/themes/material_darker.png +0 -0
  360. data/examples/themes/material_design_colors.png +0 -0
  361. data/examples/themes/material_ocean.png +0 -0
  362. data/examples/themes/mathias.png +0 -0
  363. data/examples/themes/matrix.png +0 -0
  364. data/examples/themes/medallion.png +0 -0
  365. data/examples/themes/mellifluous.png +0 -0
  366. data/examples/themes/midnight_in_mojave.png +0 -0
  367. data/examples/themes/mirage.png +0 -0
  368. data/examples/themes/misterioso.png +0 -0
  369. data/examples/themes/molokai.png +0 -0
  370. data/examples/themes/mona_lisa.png +0 -0
  371. data/examples/themes/monokai_cmder.png +0 -0
  372. data/examples/themes/monokai_pro.png +0 -0
  373. data/examples/themes/monokai_pro_filter_octagon.png +0 -0
  374. data/examples/themes/monokai_pro_filter_ristretto.png +0 -0
  375. data/examples/themes/monokai_remastered.png +0 -0
  376. data/examples/themes/monokai_soda.png +0 -0
  377. data/examples/themes/monokai_vivid.png +0 -0
  378. data/examples/themes/moonlight_ii.png +0 -0
  379. data/examples/themes/n0tch2k.png +0 -0
  380. data/examples/themes/neobones_dark.png +0 -0
  381. data/examples/themes/neobones_light.png +0 -0
  382. data/examples/themes/neon.png +0 -0
  383. data/examples/themes/neopolitan.png +0 -0
  384. data/examples/themes/neutron.png +0 -0
  385. data/examples/themes/night_city.png +0 -0
  386. data/examples/themes/night_lion_v1.png +0 -0
  387. data/examples/themes/night_lion_v2.png +0 -0
  388. data/examples/themes/night_owlish_light.png +0 -0
  389. data/examples/themes/nightfox.png +0 -0
  390. data/examples/themes/niji.png +0 -0
  391. data/examples/themes/nocturnal_winter.png +0 -0
  392. data/examples/themes/nord.png +0 -0
  393. data/examples/themes/nord_light.png +0 -0
  394. data/examples/themes/novel.png +0 -0
  395. data/examples/themes/nvim_dark.png +0 -0
  396. data/examples/themes/nvim_light.png +0 -0
  397. data/examples/themes/obsidian.png +0 -0
  398. data/examples/themes/ocean.png +0 -0
  399. data/examples/themes/oceanic_material.png +0 -0
  400. data/examples/themes/oceanic_next.png +0 -0
  401. data/examples/themes/ollie.png +0 -0
  402. data/examples/themes/one_dark.png +0 -0
  403. data/examples/themes/one_half_dark.png +0 -0
  404. data/examples/themes/one_half_light.png +0 -0
  405. data/examples/themes/one_star.png +0 -0
  406. data/examples/themes/operator_mono_dark.png +0 -0
  407. data/examples/themes/overnight_slumber.png +0 -0
  408. data/examples/themes/pale_night_hc.png +0 -0
  409. data/examples/themes/pandora.png +0 -0
  410. data/examples/themes/paraiso_dark.png +0 -0
  411. data/examples/themes/paul_millr.png +0 -0
  412. data/examples/themes/pencil_dark.png +0 -0
  413. data/examples/themes/pencil_light.png +0 -0
  414. data/examples/themes/peppermint.png +0 -0
  415. data/examples/themes/piatto_light.png +0 -0
  416. data/examples/themes/pnevma.png +0 -0
  417. data/examples/themes/popping_and_locking.png +0 -0
  418. data/examples/themes/primary.png +0 -0
  419. data/examples/themes/primer.png +0 -0
  420. data/examples/themes/pro.png +0 -0
  421. data/examples/themes/pro_light.png +0 -0
  422. data/examples/themes/purple_rain.png +0 -0
  423. data/examples/themes/purplepeter.png +0 -0
  424. data/examples/themes/qb64_super_dark_blue.png +0 -0
  425. data/examples/themes/rapture.png +0 -0
  426. data/examples/themes/raycast_dark.png +0 -0
  427. data/examples/themes/raycast_light.png +0 -0
  428. data/examples/themes/rebecca.png +0 -0
  429. data/examples/themes/red_alert.png +0 -0
  430. data/examples/themes/red_planet.png +0 -0
  431. data/examples/themes/red_sands.png +0 -0
  432. data/examples/themes/relaxed.png +0 -0
  433. data/examples/themes/retro.png +0 -0
  434. data/examples/themes/retrowave.png +0 -0
  435. data/examples/themes/rippedcasts.png +0 -0
  436. data/examples/themes/rose_pine.png +0 -0
  437. data/examples/themes/rose_pine_dawn.png +0 -0
  438. data/examples/themes/rose_pine_moon.png +0 -0
  439. data/examples/themes/rouge_2.png +0 -0
  440. data/examples/themes/royal.png +0 -0
  441. data/examples/themes/ryuuko.png +0 -0
  442. data/examples/themes/sakura.png +0 -0
  443. data/examples/themes/scarlet_protocol.png +0 -0
  444. data/examples/themes/sea_shells.png +0 -0
  445. data/examples/themes/seafoam_pastel.png +0 -0
  446. data/examples/themes/seoulbones_dark.png +0 -0
  447. data/examples/themes/seoulbones_light.png +0 -0
  448. data/examples/themes/serendipity_midnight.png +0 -0
  449. data/examples/themes/serendipity_morning.png +0 -0
  450. data/examples/themes/serendipity_sunset.png +0 -0
  451. data/examples/themes/seti.png +0 -0
  452. data/examples/themes/shades_of_purple.png +0 -0
  453. data/examples/themes/shaman.png +0 -0
  454. data/examples/themes/slate.png +0 -0
  455. data/examples/themes/sleepy_hollow.png +0 -0
  456. data/examples/themes/smyck.png +0 -0
  457. data/examples/themes/snazzy.png +0 -0
  458. data/examples/themes/soft_server.png +0 -0
  459. data/examples/themes/solarized_darcula.png +0 -0
  460. data/examples/themes/solarized_dark_higher_contrast.png +0 -0
  461. data/examples/themes/solarized_dark_patched.png +0 -0
  462. data/examples/themes/sonoran_gothic.png +0 -0
  463. data/examples/themes/sonoran_sunrise.png +0 -0
  464. data/examples/themes/space_gray.png +0 -0
  465. data/examples/themes/space_gray_eighties.png +0 -0
  466. data/examples/themes/space_gray_eighties_dull.png +0 -0
  467. data/examples/themes/spacedust.png +0 -0
  468. data/examples/themes/spiderman.png +0 -0
  469. data/examples/themes/spring.png +0 -0
  470. data/examples/themes/square.png +0 -0
  471. data/examples/themes/sublette.png +0 -0
  472. data/examples/themes/subliminal.png +0 -0
  473. data/examples/themes/sundried.png +0 -0
  474. data/examples/themes/symfonic.png +0 -0
  475. data/examples/themes/synthwave.png +0 -0
  476. data/examples/themes/synthwave_alpha.png +0 -0
  477. data/examples/themes/synthwave_everything.png +0 -0
  478. data/examples/themes/tango_adapted.png +0 -0
  479. data/examples/themes/tango_half_adapted.png +0 -0
  480. data/examples/themes/teerb.png +0 -0
  481. data/examples/themes/terafox.png +0 -0
  482. data/examples/themes/terminal_basic.png +0 -0
  483. data/examples/themes/thayer_bright.png +0 -0
  484. data/examples/themes/the_hulk.png +0 -0
  485. data/examples/themes/theme.tape +0 -13
  486. data/examples/themes/tinacious_design_dark.png +0 -0
  487. data/examples/themes/tinacious_design_light.png +0 -0
  488. data/examples/themes/tokyo_night.png +0 -0
  489. data/examples/themes/tokyo_night_light.png +0 -0
  490. data/examples/themes/tokyo_night_storm.png +0 -0
  491. data/examples/themes/tokyonight.png +0 -0
  492. data/examples/themes/tokyonight_day.png +0 -0
  493. data/examples/themes/tokyonight_storm.png +0 -0
  494. data/examples/themes/tomorrow.png +0 -0
  495. data/examples/themes/tomorrow_night.png +0 -0
  496. data/examples/themes/tomorrow_night_blue.png +0 -0
  497. data/examples/themes/tomorrow_night_bright.png +0 -0
  498. data/examples/themes/tomorrow_night_burns.png +0 -0
  499. data/examples/themes/tomorrow_night_eighties.png +0 -0
  500. data/examples/themes/toy_chest.png +0 -0
  501. data/examples/themes/treehouse.png +0 -0
  502. data/examples/themes/twilight.png +0 -0
  503. data/examples/themes/ubuntu.png +0 -0
  504. data/examples/themes/ultra_dark.png +0 -0
  505. data/examples/themes/ultra_violent.png +0 -0
  506. data/examples/themes/under_the_sea.png +0 -0
  507. data/examples/themes/unholy.png +0 -0
  508. data/examples/themes/unikitty.png +0 -0
  509. data/examples/themes/urple.png +0 -0
  510. data/examples/themes/vaughn.png +0 -0
  511. data/examples/themes/vesper.png +0 -0
  512. data/examples/themes/vibrant_ink.png +0 -0
  513. data/examples/themes/vimbones.png +0 -0
  514. data/examples/themes/violet_dark.png +0 -0
  515. data/examples/themes/violet_light.png +0 -0
  516. data/examples/themes/warm_neon.png +0 -0
  517. data/examples/themes/wez.png +0 -0
  518. data/examples/themes/whimsy.png +0 -0
  519. data/examples/themes/wild_cherry.png +0 -0
  520. data/examples/themes/wilmersdorf.png +0 -0
  521. data/examples/themes/wombat.png +0 -0
  522. data/examples/themes/wryan.png +0 -0
  523. data/examples/themes/zenbones.png +0 -0
  524. data/examples/themes/zenbones_dark.png +0 -0
  525. data/examples/themes/zenbones_light.png +0 -0
  526. data/examples/themes/zenburn.png +0 -0
  527. data/examples/themes/zenburned.png +0 -0
  528. data/examples/themes/zenwritten_dark.png +0 -0
  529. data/examples/themes/zenwritten_light.png +0 -0
  530. data/examples/themes/zeonica.png +0 -0
  531. data/examples/tmux.mp4 +0 -0
  532. data/examples/tmux.png +0 -0
  533. data/examples/tmux.tape +0 -28
  534. data/examples/type.mp4 +0 -0
  535. data/examples/type.png +0 -0
  536. data/examples/type.tape +0 -11
  537. data/examples/type_file.mp4 +0 -0
  538. data/examples/type_file.png +0 -0
  539. data/examples/type_file.tape +0 -23
  540. data/examples/variable_typing.mp4 +0 -0
  541. data/examples/variable_typing.png +0 -0
  542. data/examples/variable_typing.tape +0 -41
  543. data/examples/wait_until.mp4 +0 -0
  544. data/examples/wait_until.png +0 -0
  545. data/examples/wait_until.tape +0 -8
  546. data/examples/zsh.mp4 +0 -0
  547. data/examples/zsh.png +0 -0
  548. data/examples/zsh.tape +0 -4
@@ -0,0 +1,160 @@
1
+ class DemoTape::Parser
2
+ rule
3
+ # Top level: document is a flat list of tokens and contexts
4
+ document: items { result = val[0].flatten.compact }
5
+ | /* empty */ { result = [] }
6
+
7
+ items: item { result = [val[0]] }
8
+ | items item { result = val[0] << val[1] }
9
+
10
+ # An item can be a token or a context
11
+ item: COMMENT { result = make_token(:comment, val[0], @token_index - 1) }
12
+ | NEWLINE { result = make_token(:newline, val[0], @token_index - 1) }
13
+ | LEADING_SPACE { result = make_token(:leading_space, val[0], @token_index - 1) }
14
+ | TRAILING_SPACE { result = make_token(:trailing_space, val[0], @token_index - 1) }
15
+ | command_line { result = val[0] }
16
+ | group_context { result = val[0] }
17
+
18
+ # A command line: tokens terminated by newline
19
+ command_line: command_tokens NEWLINE {
20
+ result = [{
21
+ type: :command,
22
+ tokens: val[0],
23
+ line: line_for_token_at(@command_start_index),
24
+ column: column_for_token_at(@command_start_index)
25
+ }, make_token(:newline, val[1], @token_index - 1)]
26
+ }
27
+
28
+ leading_space: LEADING_SPACE { result = make_token(:leading_space, val[0], @token_index - 1) }
29
+
30
+ trailing_space: TRAILING_SPACE { result = make_token(:trailing_space, val[0], @token_index - 1) }
31
+
32
+ # Group context: Group name do ... end
33
+ group_context: IDENTIFIER SPACE IDENTIFIER SPACE DO NEWLINE group_body END {
34
+ @command_start_index = @token_index - 8
35
+ result = {
36
+ type: :group,
37
+ name: val[2],
38
+ tokens: [
39
+ make_token(:identifier, val[0], @token_index - 8),
40
+ make_token(:space, val[1], @token_index - 7),
41
+ make_token(:identifier, val[2], @token_index - 6),
42
+ make_token(:space, val[3], @token_index - 5),
43
+ make_token(:keyword, "do", @token_index - 4)
44
+ ],
45
+ body: val[6],
46
+ line: line_for_token_at(@token_index - 8),
47
+ column: column_for_token_at(@token_index - 8)
48
+ }
49
+ }
50
+
51
+ group_body: /* empty */ { result = [] }
52
+ | group_body item { result = val[0] << val[1] }
53
+
54
+ # Command tokens: any sequence of tokens until newline
55
+ command_tokens: command_token { @command_start_index = @token_index - 1; result = [val[0]] }
56
+ | command_tokens SPACE command_token { result = val[0] << make_token(:space, val[1], @token_index - 2) << val[2] }
57
+ | command_tokens optional_space COMMA optional_space command_token {
58
+ result = val[0]
59
+ result << make_token(:space, val[1], @token_index - 4) if val[1]
60
+ result << make_token(:operator, ",", @token_index - 3)
61
+ result << make_token(:space, val[3], @token_index - 2) if val[3]
62
+ result << val[4]
63
+ }
64
+ | command_tokens PLUS command_token {
65
+ result = val[0] << make_token(:operator, "+", @token_index - 2) << val[2]
66
+ }
67
+ | command_tokens AT duration {
68
+ result = val[0] << make_token(:operator, "@", @token_index - 2) << val[2]
69
+ }
70
+
71
+ optional_space: SPACE { result = val[0] }
72
+ | /* empty */ { result = nil }
73
+
74
+ command_token: IDENTIFIER { result = make_token(:identifier, val[0], @token_index - 1) }
75
+ | STRING { result = make_token(:string, val[0], @token_index - 1) }
76
+ | NUMBER { result = make_token(:number, val[0], @token_index - 1) }
77
+ | REGEX { result = make_token(:regex, val[0], @token_index - 1) }
78
+
79
+ duration: NUMBER TIME_UNIT {
80
+ result = make_token(:duration, "#{val[0]}#{val[1]}", @token_index - 2)
81
+ }
82
+
83
+ ---- header
84
+ require_relative "token"
85
+ require_relative "lexer"
86
+ require_relative "ast"
87
+
88
+ ---- inner
89
+ def parse(str, file: "<unknown>")
90
+ @file = file
91
+ @lexer = DemoTape::Lexer.new
92
+ @tokens = @lexer.tokenize(str)
93
+ @token_index = 0
94
+ do_parse
95
+ end
96
+
97
+ def next_token
98
+ token = @tokens.shift
99
+ @current_token_index = @token_index
100
+ @token_index += 1
101
+ token
102
+ end
103
+
104
+ def make_token(type, value, index)
105
+ line_info = @lexer.line_map[index] || {}
106
+ token_class = case type
107
+ when :identifier then DemoTape::Token::Identifier
108
+ when :string then DemoTape::Token::String
109
+ when :number then DemoTape::Token::Number
110
+ when :duration then DemoTape::Token::Duration
111
+ when :regex then DemoTape::Token::Regex
112
+ when :time_unit then DemoTape::Token::TimeUnit
113
+ when :operator then DemoTape::Token::Operator
114
+ when :space then DemoTape::Token::Space
115
+ when :leading_space then DemoTape::Token::LeadingSpace
116
+ when :trailing_space then DemoTape::Token::TrailingSpace
117
+ when :keyword then DemoTape::Token::Keyword
118
+ when :comment then DemoTape::Token::Comment
119
+ when :newline then DemoTape::Token::Newline
120
+ else DemoTape::Token::Base
121
+ end
122
+
123
+ token_class.new(
124
+ value,
125
+ line: line_info[:line],
126
+ column: line_info[:column],
127
+ raw: line_info[:raw]
128
+ )
129
+ end
130
+
131
+ def line_for_token_at(index)
132
+ line_info = @lexer.line_map[index] || {}
133
+ line_info[:line]
134
+ end
135
+
136
+ def column_for_token_at(index)
137
+ line_info = @lexer.line_map[index] || {}
138
+ line_info[:column]
139
+ end
140
+
141
+ def collect_tokens(*values)
142
+ values.flatten.compact.select { |v| v.is_a?(DemoTape::Token::Base) }
143
+ end
144
+
145
+ def on_error(token_id, token_value, value_stack)
146
+ line_info = @lexer.line_map[@current_token_index] || {}
147
+ line_num = line_info[:line] || "?"
148
+ col_num = line_info[:column] || 1
149
+ line_content = line_info[:content] || ""
150
+
151
+ token_name = token_to_str(token_id) || token_id.to_s
152
+
153
+ error_msg = "Unexpected token #{token_name.inspect} at #{@file}:#{line_num}:#{col_num}:\n"
154
+ error_msg += " #{line_content.strip}\n"
155
+ error_msg += " #{' ' * (col_num - line_content.length + line_content.strip.length - 1)}^"
156
+
157
+ raise DemoTape::ParseError, error_msg
158
+ end
159
+
160
+ ---- footer
@@ -0,0 +1,32 @@
1
+ class DemoTape::SimpleParser
2
+ rule
3
+ # Match lines - each line is either comment+newline or command tokens+newline
4
+ document: lines { result = val[0].flatten }
5
+ | /* empty */ { result = [] }
6
+
7
+ lines: line { result = [val[0]] }
8
+ | lines line { result = val[0] + val[1] }
9
+
10
+ # A line ends with NEWLINE
11
+ line: COMMENT NEWLINE { result = [[:comment, val[0]], [:newline, val[1]]] }
12
+ | NEWLINE { result = [[:newline, val[0]]] }
13
+ | line_tokens NEWLINE { result = [{ type: :command, tokens: val[0] }, [:newline, val[1]]] }
14
+
15
+ # Line tokens: anything that's not a newline
16
+ line_tokens: line_token { result = [val[0]] }
17
+ | line_tokens line_token { result = val[0] << val[1] }
18
+
19
+ line_token: IDENTIFIER { result = [:id, val[0]] }
20
+ | STRING { result = [:str, val[0]] }
21
+ | SPACE { result = [:sp, val[0]] }
22
+ | LEADING_SPACE { result = [:lsp, val[0]] }
23
+
24
+ ---- inner
25
+ def parse(tokens)
26
+ @tokens = tokens
27
+ do_parse
28
+ end
29
+
30
+ def next_token
31
+ @tokens.shift
32
+ end
@@ -6,6 +6,8 @@
6
6
  { "trigger": "Type@", "contents": "Type@${1:50ms} \"${2:text}\"" },
7
7
  { "trigger": "TypeFile", "contents": "TypeFile \"${1:path/to/file}\"" },
8
8
  { "trigger": "TypeFile@", "contents": "TypeFile@${1:50ms} \"${2:path/to/file}\"" },
9
+ { "trigger": "Run", "contents": "Run \"${1:command}\"" },
10
+ { "trigger": "Run@", "contents": "Run@${1:1s} \"${2:command}\"" },
9
11
  { "trigger": "Copy", "contents": "Copy \"${1:text}\"" },
10
12
  { "trigger": "Paste", "contents": "Paste \"${1:text}\"" },
11
13
  { "trigger": "Send", "contents": "Send \"${1:text}\"" },
@@ -56,6 +58,8 @@
56
58
  { "trigger": "Set variable_typing", "contents": "Set variable_typing ${1:true}" },
57
59
  { "trigger": "Set loop", "contents": "Set loop ${1:true}" },
58
60
  { "trigger": "Set loop_delay", "contents": "Set loop_delay ${1:2s}" },
61
+ { "trigger": "Set run_enter_delay", "contents": "Set run_enter_delay ${1:300ms}" },
62
+ { "trigger": "Set run_sleep", "contents": "Set run_sleep ${1:1s}" },
59
63
 
60
64
  // Theme color overrides
61
65
  { "trigger": "Set theme.background", "contents": "Set theme.background \"${1:#222222}\"" },
@@ -11,6 +11,23 @@ variables:
11
11
  contexts:
12
12
  main:
13
13
  - include: comments
14
+ - include: blocks
15
+ - include: commands
16
+
17
+ blocks:
18
+ # Group blocks
19
+ - match: '\b(Group)\s+([a-z_][a-z0-9_]*)\s+(do)\b'
20
+ captures:
21
+ 1: keyword.control.demotape
22
+ 2: entity.name.function.demotape
23
+ 3: keyword.control.demotape
24
+ push: group_body
25
+
26
+ group_body:
27
+ - match: '\b(end)\b'
28
+ scope: keyword.control.demotape
29
+ pop: true
30
+ - include: comments
14
31
  - include: commands
15
32
 
16
33
  comments:
@@ -18,8 +35,13 @@ contexts:
18
35
  scope: comment.line.number-sign.demotape
19
36
 
20
37
  commands:
38
+ # Group invocations (lowercase identifiers)
39
+ - match: '^(\s*)([a-z_][a-z0-9_]*)(\s*)$'
40
+ captures:
41
+ 2: entity.name.function.demotape
42
+
21
43
  # Commands with @ duration/speed
22
- - match: '\b(Type|TypeFile|WaitUntil)\b'
44
+ - match: '\b(Type|TypeFile|WaitUntil|Run)\b'
23
45
  scope: keyword.control.demotape
24
46
  push: command_with_speed_or_timeout
25
47
 
@@ -132,7 +154,7 @@ contexts:
132
154
  pop: true
133
155
 
134
156
  set_command:
135
- - match: '\b(border_radius|shell|theme|width|height|font_size|font_family|line_height|cursor_blink|cursor_width|cursor_style|letter_spacing|padding|margin|margin_fill|fps|typing_speed|loop|loop_delay|variable_typing)(\.[a-z_]+)?\b'
157
+ - match: '\b(border_radius|shell|theme|width|height|font_size|font_family|line_height|cursor_blink|cursor_width|cursor_style|letter_spacing|padding|margin|margin_fill|fps|typing_speed|loop|loop_delay|variable_typing|run_enter_delay|run_sleep)(\.[a-z_]+)?\b'
136
158
  captures:
137
159
  1: variable.parameter.demotape
138
160
  2: variable.other.member.demotape
@@ -11,9 +11,18 @@ endif
11
11
  syn match demotapeComment "#.*$"
12
12
 
13
13
  " Commands
14
- syn keyword demotapeCommand Type TypeFile WaitUntil Set Output Copy Paste Send Include Screenshot
14
+ syn keyword demotapeCommand Type TypeFile WaitUntil Run Set Output Copy Paste Send Include Screenshot
15
15
  syn keyword demotapeCommand Wait Sleep Require Pause Resume Clear nextgroup=demotapeString,demotapeDuration,demotapeNumber skipwhite
16
16
 
17
+ " Group blocks
18
+ syn keyword demotapeCommand Group nextgroup=demotapeGroupName skipwhite
19
+ syn match demotapeGroupName "\<[a-z_][a-z0-9_]*\>" contained nextgroup=demotapeGroupDo skipwhite
20
+ syn keyword demotapeGroupDo do contained
21
+ syn keyword demotapeGroupEnd end
22
+
23
+ " Group invocations (lowercase identifiers on their own line)
24
+ syn match demotapeGroupInvocation "^\s*\zs[a-z_][a-z0-9_]*\ze\s*$"
25
+
17
26
  " Special keys
18
27
  syn keyword demotapeKey Enter Return Tab Backspace Delete Escape Esc Space
19
28
  syn keyword demotapeKey Up Down Left Right Home End PageUp PageDown Insert
@@ -33,7 +42,8 @@ syn match demotapeOperator "@"
33
42
  syn keyword demotapeOption border_radius shell theme width height font_size font_family
34
43
  syn keyword demotapeOption line_height cursor_blink cursor_width cursor_style letter_spacing
35
44
  syn keyword demotapeOption padding margin margin_fill fps typing_speed loop loop_delay variable_typing
36
- syn match demotapeOption "\<\(border_radius\|shell\|theme\|width\|height\|font_size\|font_family\|line_height\|cursor_blink\|cursor_width\|cursor_style\|letter_spacing\|padding\|margin\|margin_fill\|fps\|typing_speed\|loop_delay\|loop\|variable_typing\)\.\w\+\>"
45
+ syn keyword demotapeOption run_enter_delay run_sleep
46
+ syn match demotapeOption "\<\(border_radius\|shell\|theme\|width\|height\|font_size\|font_family\|line_height\|cursor_blink\|cursor_width\|cursor_style\|letter_spacing\|padding\|margin\|margin_fill\|fps\|typing_speed\|loop_delay\|loop\|variable_typing\|run_enter_delay\|run_sleep\)\.\w\+\>"
37
47
 
38
48
  " Strings
39
49
  syn region demotapeString start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=demotapeEscape
@@ -64,6 +74,10 @@ syn match demotapeSeparator ","
64
74
  " Highlight groups
65
75
  hi def link demotapeComment Comment
66
76
  hi def link demotapeCommand Keyword
77
+ hi def link demotapeGroupName Function
78
+ hi def link demotapeGroupDo Keyword
79
+ hi def link demotapeGroupEnd Keyword
80
+ hi def link demotapeGroupInvocation Function
67
81
  hi def link demotapeKey Function
68
82
  hi def link demotapeModifier Special
69
83
  hi def link demotapeOperator Operator
@@ -3,8 +3,29 @@
3
3
  "name": "DemoTape",
4
4
  "scopeName": "source.demotape",
5
5
  "fileTypes": ["tape"],
6
- "patterns": [{ "include": "#comments" }, { "include": "#commands" }],
6
+ "patterns": [{ "include": "#comments" }, { "include": "#blocks" }, { "include": "#commands" }],
7
7
  "repository": {
8
+ "blocks": {
9
+ "patterns": [
10
+ {
11
+ "comment": "Group blocks",
12
+ "begin": "\\b(Group)\\s+([a-z_][a-z0-9_]*)\\s+(do)\\b",
13
+ "end": "\\b(end)\\b",
14
+ "beginCaptures": {
15
+ "1": { "name": "keyword.control.demotape" },
16
+ "2": { "name": "entity.name.function.demotape" },
17
+ "3": { "name": "keyword.control.demotape" }
18
+ },
19
+ "endCaptures": {
20
+ "1": { "name": "keyword.control.demotape" }
21
+ },
22
+ "patterns": [
23
+ { "include": "#comments" },
24
+ { "include": "#commands" }
25
+ ]
26
+ }
27
+ ]
28
+ },
8
29
  "comments": {
9
30
  "patterns": [
10
31
  {
@@ -15,9 +36,16 @@
15
36
  },
16
37
  "commands": {
17
38
  "patterns": [
39
+ {
40
+ "comment": "Group invocations (lowercase identifiers)",
41
+ "match": "^\\s*([a-z_][a-z0-9_]*)\\s*$",
42
+ "captures": {
43
+ "1": { "name": "entity.name.function.demotape" }
44
+ }
45
+ },
18
46
  {
19
47
  "comment": "Commands with @ duration/speed",
20
- "match": "\\b(Type|TypeFile|WaitUntil)\\b",
48
+ "match": "\\b(Type|TypeFile|WaitUntil|Run)\\b",
21
49
  "name": "keyword.control.demotape",
22
50
  "captures": {
23
51
  "1": { "name": "keyword.control.demotape" }
@@ -83,7 +111,7 @@
83
111
  },
84
112
  {
85
113
  "comment": "Set command options",
86
- "match": "\\b(border_radius|shell|theme|width|height|font_size|font_family|line_height|cursor_blink|cursor_width|cursor_style|letter_spacing|padding|margin|margin_fill|fps|typing_speed|loop|loop_delay|variable_typing)(\\.[a-z_]+)?\\b",
114
+ "match": "\\b(border_radius|shell|theme|width|height|font_size|font_family|line_height|cursor_blink|cursor_width|cursor_style|letter_spacing|padding|margin|margin_fill|fps|typing_speed|loop|loop_delay|variable_typing|run_enter_delay|run_sleep)(\\.[a-z_]+)?\\b",
87
115
  "captures": {
88
116
  "1": { "name": "variable.parameter.demotape" },
89
117
  "2": { "name": "variable.other.member.demotape" }
data/lib/demo_tape/cli.rb CHANGED
@@ -127,6 +127,14 @@ module DemoTape
127
127
  type: :boolean,
128
128
  default: false,
129
129
  desc: "Take a single screenshot at the end of the session"
130
+ option :run_enter_delay,
131
+ type: :numeric,
132
+ default: 1,
133
+ desc: "Delay (in seconds) before pressing Enter"
134
+ option :run_sleep,
135
+ type: :numeric,
136
+ default: 3,
137
+ desc: "Delay (in seconds) after running each command"
130
138
  def _run(file_path = "")
131
139
  options = self.options.dup
132
140
  options[:padding] =
@@ -172,6 +180,34 @@ module DemoTape
172
180
  )
173
181
  end
174
182
 
183
+ desc "format", "Formats a demo tape script"
184
+ option :write,
185
+ type: :boolean,
186
+ default: false,
187
+ desc: "Overwrite the original files with the formatted content"
188
+ def format(*paths)
189
+ paths = paths.flat_map {|path| Dir.glob(path) }
190
+
191
+ if paths.size > 1 && !options.write
192
+ shell.say(
193
+ "Error: --write must be specified when formatting multiple files.",
194
+ :red
195
+ )
196
+
197
+ exit 1
198
+ end
199
+
200
+ paths.each do |path|
201
+ formatted = Formatter.new(File.read(path)).call
202
+
203
+ if options.write
204
+ File.write(path, formatted)
205
+ else
206
+ puts formatted
207
+ end
208
+ end
209
+ end
210
+
175
211
  no_commands do
176
212
  # Add helper methods here
177
213
  end