demo

package module
v0.0.0-...-b1fcb3b Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 1, 2024 License: MIT Imports: 14 Imported by: 27

README ¶

demo

ci codecov docs

demo

A framework for performing live pre-recorded command line demos in the wild 📼

Recording command line demos can be a difficult topic these days. Doing a video record has the drawback of lacking flexibility and reduced interactivity during the demo. Typing everything by our own is error prone and distracts the audience from the actual topic we want to show them. So we need something in between, which is easy to use…

This framework should solve the issue by provided interactive demos from your command line!

Usage

Every demo is a stand-alone command line application which consist of multiple runs. For example, if we create a demo like this:

package main

import (
	demo "github.com/saschagrunert/demo"
)

func main() {
	demo.New().Run()
}

Then this demo already contains features like auto-play. We can verify this checking the help output of the executable:

NAME:
   main - A new cli application

USAGE:
   main [global options] command [command options] [arguments...]

VERSION:
   0.0.0

COMMANDS:
   help, h  Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --all, -l                     run all demos (default: false)
   --auto, -a                    run the demo in automatic mode, where every step gets executed automatically (default: false)
   --dry-run                     run the demo and only prints the commands (default: false)
   --no-color                    run the demo and output to be without colors (default: false)
   --auto-timeout auto, -t auto  the timeout to be waited when auto is enabled (default: 1s)
   --with-breakpoints            breakpoint (default: false)
   --continue-on-error           continue if there a step fails (default: false)
   --continuously, -c            run the demos continuously without any end (default: false)
   --hide-descriptions, -d       hide descriptions between the steps (default: false)
   --immediate, -i               immediately output without the typewriter animation (default: false)
   --skip-steps value, -s value  skip the amount of initial steps within the demo (default: 0)
   --shell value                 define the shell that is used to execute the command(s) (default: bash)
   --help, -h                    show help (default: false)
   --version, -v                 print the version (default: false)

The application is based on the urfave/cli framework, which means that we have every possibility to change the app before actually running it.

// Create a new demo CLI application
d := demo.New()

// A demo is an usual urfave/cli application, which means
// that we can set its properties as expected:
d.Name = "A demo of something"
d.Usage = "Learn how this framework is being used"
d.HideVersion = true

Creating runs inside demos

To have something to show, we need to create a run and add it to the demo. This can be done by using the demo.Add() method:

func main() {
	// Create a new demo CLI application
	d := demo.New()

	// Register the demo run
	d.Add(example(), "demo-0", "just an example demo run")

	// Run the application, which registers all signal handlers and waits for
	// the app to exit
	d.Run()
}

// example is the single demo run for this application
func example() *Run {
	// A new run contains a title and an optional description
	r := NewRun(
		"Demo Title",
		"Some additional",
		"multi-line description",
		"is possible as well!",
	)

	// A single step can consist of a description and a command to be executed
	r.Step(S(
		"This is a possible",
		"description of the following command",
		"to be executed",
	), S(
		"echo hello world",
	))

	// Commands do not need to have a description, so we could set it to `nil`
	r.Step(nil, S(
		"echo without description",
		"but this can be executed in",
		"multiple lines as well",
	))

	// It is also not needed at all to provide a command
	r.Step(S(
		"Just a description without a command",
	), nil)

	return r
}

The example() function creates a new demo run, which itself contains of multiple steps. These steps are executed in order, can contain a description and a command to be executed. Wrapping commands in multiple lines will automatically create a line break in the command line.

Setup and Cleanup functions

It is also possible to do something before or after each run. For this the setup and cleanup functions can be set to the demo:

func main() {
	// Create a new demo CLI application
	d := demo.New()

	// Be able to run a Setup/Cleanup function before/after each run
	d.Setup(setup)
	d.Cleanup(cleanup)
}

// setup will run before every demo
func setup(ctx *cli.Context) error {
	// Ensure can be used for easy sequential command execution
	return Ensure(
		"echo 'Doing first setup…'",
		"echo 'Doing second setup…'",
		"echo 'Doing third setup…'",
	)
}

// setup will run after every demo
func cleanup(ctx *cli.Context) error {
	return Ensure("echo 'Doing cleanup…'")
}

Contributing

You want to contribute to this project? Wow, thanks! So please just fork it and send me a pull request.

Documentation ¶

Index ¶

Constants ¶

View Source
const (
	// FlagAll is the flag for running all demos.
	FlagAll = "all"

	// FlagAuto is the flag for running in automatic mode.
	FlagAuto = "auto"

	// FlagAutoTimeout is the flag for the timeout to be waited when `auto` is
	// enabled.
	FlagAutoTimeout = "auto-timeout"

	// FlagBreakPoint is the flag for doing`auto` but with breakpoint.
	FlagBreakPoint = "with-breakpoints"

	// FlagContinueOnError is the flag for steps continue running if
	// there is an error.
	FlagContinueOnError = "continue-on-error"

	// FlagContinuously is the flag for running the demos continuously without
	// any end.
	FlagContinuously = "continuously"

	// DryRun only prints the command in the stdout.
	FlagDryRun = "dry-run"

	// FlagHideDescriptions is the flag for hiding the descriptions.
	FlagHideDescriptions = "hide-descriptions"

	// FlagImmediate is the flag for disabling the text animations.
	FlagImmediate = "immediate"

	// NoColor true to print without colors, special characters for writing into file.
	FlagNoColor = "no-color"

	// FlagSkipSteps is the flag for skipping n amount of steps.
	FlagSkipSteps = "skip-steps"

	// FlagShell is the flag for defining the shell that is used to execute the command(s).
	FlagShell = "shell"
)

Variables ¶

This section is empty.

Functions ¶

func Ensure ¶

func Ensure(commands ...string) error

Ensure executes the provided commands in order. This utility function can be used during setup or cleanup.

func MustEnsure ¶

func MustEnsure(commands ...string)

MustEnsure executes the provided commands in order and panics on failure.

func S ¶

func S(s ...string) []string

S is a short-hand for converting string slice syntaxes.

Types ¶

type Demo ¶

type Demo struct {
	*cli.App
	// contains filtered or unexported fields
}

func New ¶

func New() *Demo

New creates a new Demo instance.

func (*Demo) Add ¶

func (d *Demo) Add(run *Run, name, description string)

func (*Demo) Cleanup ¶

func (d *Demo) Cleanup(cleanupFn func(*cli.Context) error)

Cleanup sets the cleanup function called after each run.

func (*Demo) Run ¶

func (d *Demo) Run()

Run starts the demo.

func (*Demo) Setup ¶

func (d *Demo) Setup(setupFn func(*cli.Context) error)

Setup sets the cleanup function called before each run.

type Options ¶

type Options struct {
	AutoTimeout      time.Duration
	Auto             bool
	BreakPoint       bool
	ContinueOnError  bool
	HideDescriptions bool
	DryRun           bool
	NoColor          bool
	Immediate        bool
	SkipSteps        int
	Shell            string
}

Options specify the run options.

type Run ¶

type Run struct {
	// contains filtered or unexported fields
}

Run is an abstraction for one part of the Demo. A demo can contain multiple runs.

func NewRun ¶

func NewRun(title string, description ...string) *Run

NewRun creates a new run for the provided description string.

func (*Run) BreakPoint ¶

func (r *Run) BreakPoint()

BreakPoint creates a new step which can fail on execution.

func (*Run) Cleanup ¶

func (r *Run) Cleanup(cleanupFn func() error)

Cleanup sets the cleanup function called after this run.

func (*Run) Run ¶

func (r *Run) Run(ctx *cli.Context) error

Run executes the run in the provided CLI context.

func (*Run) RunWithOptions ¶

func (r *Run) RunWithOptions(opts Options) error

RunWithOptions executes the run with the provided Options.

func (*Run) SetOutput ¶

func (r *Run) SetOutput(output io.Writer) error

SetOutput can be used to replace the default output for the Run.

func (*Run) Setup ¶

func (r *Run) Setup(setupFn func() error)

Setup sets the cleanup function called before this run.

func (*Run) Step ¶

func (r *Run) Step(text, command []string)

Step creates a new step on the provided run.

func (*Run) StepCanFail ¶

func (r *Run) StepCanFail(text, command []string)

StepCanFail creates a new step which can fail on execution.

Directories ¶

Path Synopsis
test

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL