{"id":13903088,"url":"https://github.com/saschagrunert/demo","last_synced_at":"2025-04-05T11:13:07.696Z","repository":{"id":36700458,"uuid":"229565174","full_name":"saschagrunert/demo","owner":"saschagrunert","description":"A framework for performing live pre-recorded command line demos in the wild 📼","archived":false,"fork":false,"pushed_at":"2024-08-29T14:35:32.000Z","size":3471,"stargazers_count":311,"open_issues_count":1,"forks_count":19,"subscribers_count":6,"default_branch":"main","last_synced_at":"2024-10-11T23:43:20.337Z","etag":null,"topics":["cli","command-line","demo","demonstration","demonstration-tool"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/saschagrunert.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-12-22T12:36:10.000Z","updated_at":"2024-08-29T14:35:35.000Z","dependencies_parsed_at":"2024-02-22T10:36:00.353Z","dependency_job_id":"6d26b41a-1dd7-409f-b0a9-62e58ab0ffe7","html_url":"https://github.com/saschagrunert/demo","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saschagrunert%2Fdemo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saschagrunert%2Fdemo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saschagrunert%2Fdemo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saschagrunert%2Fdemo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/saschagrunert","download_url":"https://codeload.github.com/saschagrunert/demo/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247325696,"owners_count":20920714,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","command-line","demo","demonstration","demonstration-tool"],"created_at":"2024-08-06T22:01:36.752Z","updated_at":"2025-04-05T11:13:07.679Z","avatar_url":"https://github.com/saschagrunert.png","language":"Go","funding_links":[],"categories":["cli","🛠️ Developer Tools"],"sub_categories":[],"readme":"# demo\n\n[![ci](https://github.com/saschagrunert/demo/actions/workflows/test.yml/badge.svg)](https://github.com/saschagrunert/demo/actions/workflows/test.yml)\n[![codecov](https://codecov.io/gh/saschagrunert/demo/branch/main/graph/badge.svg)](https://codecov.io/gh/saschagrunert/demo)\n[![docs](https://img.shields.io/badge/godoc-demo-blue)](https://godoc.org/github.com/saschagrunert/demo)\n\n![demo](.github/demo.svg)\n\n### A framework for performing live pre-recorded command line demos in the wild 📼\n\nRecording command line demos can be a difficult topic these days. Doing a video\nrecord has the drawback of lacking flexibility and reduced interactivity during\nthe demo. Typing everything by our own is error prone and distracts the audience\nfrom the actual topic we want to show them. So we need something in between,\nwhich is easy to use…\n\nThis framework should solve the issue by provided interactive demos from your\ncommand line!\n\n# Usage\n\nEvery _demo_ is a stand-alone command line application which consist of\nmultiple _runs_. For example, if we create a demo like this:\n\n```go\npackage main\n\nimport (\n\tdemo \"github.com/saschagrunert/demo\"\n)\n\nfunc main() {\n\tdemo.New().Run()\n}\n```\n\nThen this demo already contains features like _auto-play_. We can verify this\nchecking the help output of the executable:\n\n```\nNAME:\n   main - A new cli application\n\nUSAGE:\n   main [global options] command [command options] [arguments...]\n\nVERSION:\n   0.0.0\n\nCOMMANDS:\n   help, h  Shows a list of commands or help for one command\n\nGLOBAL OPTIONS:\n   --all, -l                     run all demos (default: false)\n   --auto, -a                    run the demo in automatic mode, where every step gets executed automatically (default: false)\n   --dry-run                     run the demo and only prints the commands (default: false)\n   --no-color                    run the demo and output to be without colors (default: false)\n   --auto-timeout auto, -t auto  the timeout to be waited when auto is enabled (default: 1s)\n   --with-breakpoints            breakpoint (default: false)\n   --continue-on-error           continue if there a step fails (default: false)\n   --continuously, -c            run the demos continuously without any end (default: false)\n   --hide-descriptions, -d       hide descriptions between the steps (default: false)\n   --immediate, -i               immediately output without the typewriter animation (default: false)\n   --skip-steps value, -s value  skip the amount of initial steps within the demo (default: 0)\n   --shell value                 define the shell that is used to execute the command(s) (default: bash)\n   --help, -h                    show help (default: false)\n   --version, -v                 print the version (default: false)\n```\n\nThe application is based on the [urfave/cli](https://github.com/urfave/cli)\nframework, which means that we have every possibility to change the app before\nactually running it.\n\n```go\n// Create a new demo CLI application\nd := demo.New()\n\n// A demo is an usual urfave/cli application, which means\n// that we can set its properties as expected:\nd.Name = \"A demo of something\"\nd.Usage = \"Learn how this framework is being used\"\nd.HideVersion = true\n```\n\n## Creating runs inside demos\n\nTo have something to show, we need to create a run and add it to the demo. This\ncan be done by using the `demo.Add()` method:\n\n```go\nfunc main() {\n\t// Create a new demo CLI application\n\td := demo.New()\n\n\t// Register the demo run\n\td.Add(example(), \"demo-0\", \"just an example demo run\")\n\n\t// Run the application, which registers all signal handlers and waits for\n\t// the app to exit\n\td.Run()\n}\n\n// example is the single demo run for this application\nfunc example() *Run {\n\t// A new run contains a title and an optional description\n\tr := NewRun(\n\t\t\"Demo Title\",\n\t\t\"Some additional\",\n\t\t\"multi-line description\",\n\t\t\"is possible as well!\",\n\t)\n\n\t// A single step can consist of a description and a command to be executed\n\tr.Step(S(\n\t\t\"This is a possible\",\n\t\t\"description of the following command\",\n\t\t\"to be executed\",\n\t), S(\n\t\t\"echo hello world\",\n\t))\n\n\t// Commands do not need to have a description, so we could set it to `nil`\n\tr.Step(nil, S(\n\t\t\"echo without description\",\n\t\t\"but this can be executed in\",\n\t\t\"multiple lines as well\",\n\t))\n\n\t// It is also not needed at all to provide a command\n\tr.Step(S(\n\t\t\"Just a description without a command\",\n\t), nil)\n\n\treturn r\n}\n```\n\nThe `example()` function creates a new demo run, which itself contains of\nmultiple steps. These steps are executed in order, can contain a description and\na command to be executed. Wrapping commands in multiple lines will automatically\ncreate a line break in the command line.\n\n## Setup and Cleanup functions\n\nIt is also possible to do something before or after each run. For this the setup\nand cleanup functions can be set to the demo:\n\n```go\nfunc main() {\n\t// Create a new demo CLI application\n\td := demo.New()\n\n\t// Be able to run a Setup/Cleanup function before/after each run\n\td.Setup(setup)\n\td.Cleanup(cleanup)\n}\n\n// setup will run before every demo\nfunc setup(ctx *cli.Context) error {\n\t// Ensure can be used for easy sequential command execution\n\treturn Ensure(\n\t\t\"echo 'Doing first setup…'\",\n\t\t\"echo 'Doing second setup…'\",\n\t\t\"echo 'Doing third setup…'\",\n\t)\n}\n\n// setup will run after every demo\nfunc cleanup(ctx *cli.Context) error {\n\treturn Ensure(\"echo 'Doing cleanup…'\")\n}\n```\n\n# Contributing\n\nYou want to contribute to this project? Wow, thanks! So please just fork it and\nsend me a pull request.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsaschagrunert%2Fdemo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsaschagrunert%2Fdemo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsaschagrunert%2Fdemo/lists"}