runzmd

package module
v1.0.43 Latest Latest
Warning

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

Go to latest
Published: Apr 9, 2024 License: Apache-2.0 Imports: 15 Imported by: 2

README

runzmd

A Go library for making runnable markdown tutorials, demos and setup scripts. It takes inspiration from the Literate Programming paradigm.

The library is used by the OpenZiti project for tutorials and examples.

Overview

runzmd exists to help consolidate scripts and documentation. If you can make a markdown tutorial runnable, then you get the following benefits:

  1. Testable documentation
  2. No duplication between the tutorial and the script
  3. Well documented, easy to read script
  4. Documentation can be run or viewed in browzer. Browzer view isn't degraded by runnable code portions.

Where It Makes Sense

While this library could be used for generalized scripts, it excels when wrapping a specific tool. The OpenZiti examples mostly use the ziti CLI. The actions used can be found in the actionz directory.

While this library could be used for generalized scripting it hasn't been optimized for that, and best suited for targeted use cases, like the above.

In Action

Here's an example of a markdown file being run. This is the creating your first service tutorial for OpenZiti, which is the most involved example I have. Below you can see the original markdown is on the left. On the right is the markdown being executed. The markdown viewed in the browser should still be usable on its own.

example of runzmd running

How It Works

runzmd starts with embedded markdown and finds any blockquote sections and comments marked as being executable. Markdown sections between executable blocks are outputted it using the go-term-markdown library. The executable sections are handed off to registered handlers, to executable in whatever manner is appropriate.

There is a small example in the example directory which just runs the ls command.

It looks like this:

# Example

This is an example

```action:exec
ls
```

The go code to run this example markdown, looks like this:

package main

import (
	_ "embed"
	"fmt"
	"github.com/openziti/runzmd"
	"time"
)

//go:embed example.md
var scriptSource []byte

func main() {
	t := runzmd.NewRunner()
	t.NewLinePause = time.Millisecond * 20
	t.AssumeDefault = false

	t.RegisterActionHandler("exec", &runzmd.ExecActionHandler{})

	if err := t.Run(scriptSource); err != nil {
		fmt.Printf("failure running example: [%v]\n", err)
	}
}
What's in the Box?

The library comes with a few actions.

  • ExecActionHandler - supports executing a list of commands
  • ShowActionHandler - supports showing some text, usually an embedded file

The library also has a few useful utility functions, which can be used in building custom actions.

  • Continue - Used for waiting in interactive scripts
  • Exec - Used to execute a command
  • AskYesNo - Asks a yes/no question
  • AskYesNoWithDefault - Asks a yes/no question with a default answer
  • Ask - Asks for string response

Documentation

Index

Constants

This section is empty.

Variables

View Source
var CodeAction = CodeActionBlock{}
View Source
var CommentAction = CommentActionBlock{}

Functions

func Ask

func Ask(prompt string, f func(string) bool) (string, error)

func AskYesNo

func AskYesNo(prompt string) (bool, error)

func AskYesNoWithDefault

func AskYesNoWithDefault(prompt string, defaultVal bool) (bool, error)

func Continue

func Continue(prompt string, defaultValue bool)

func Exec

func Exec(program string, colorStdout bool, args ...string) error

func NewSlowWriter

func NewSlowWriter(newlinePause time.Duration) io.Writer

func ParseArgumentsWithStrings

func ParseArgumentsWithStrings(val string) []string

Types

type ActionContext

type ActionContext struct {
	Action  string
	Headers map[string]string
	Body    string
	Runner  *Runner
}

type ActionHandler

type ActionHandler interface {
	Execute(ctx *ActionContext) error
}

type ActionHandlerF

type ActionHandlerF func(ctx *ActionContext) error

func (ActionHandlerF) Execute

func (self ActionHandlerF) Execute(ctx *ActionContext) error

type CodeActionBlock

type CodeActionBlock struct{}

func (CodeActionBlock) GetEndToken

func (self CodeActionBlock) GetEndToken() string

func (CodeActionBlock) GetStartToken

func (self CodeActionBlock) GetStartToken() string

func (CodeActionBlock) IsStarting

func (self CodeActionBlock) IsStarting(source []byte) bool

type CommentActionBlock

type CommentActionBlock struct{}

func (CommentActionBlock) GetEndToken

func (self CommentActionBlock) GetEndToken() string

func (CommentActionBlock) GetStartToken

func (self CommentActionBlock) GetStartToken() string

func (CommentActionBlock) IsStarting

func (self CommentActionBlock) IsStarting(source []byte) bool

type ExecActionHandler

type ExecActionHandler struct{}

func (*ExecActionHandler) Execute

func (self *ExecActionHandler) Execute(ctx *ActionContext) error

type Runner

type Runner struct {
	LineWidth     int
	LeftPad       int
	NewLinePause  time.Duration
	AssumeDefault bool
	// contains filtered or unexported fields
}

func NewRunner

func NewRunner() *Runner

func (*Runner) AddVariable

func (self *Runner) AddVariable(name string, val interface{})

func (*Runner) ClearVariable

func (self *Runner) ClearVariable(name string)

func (*Runner) EmitTemplatized

func (self *Runner) EmitTemplatized(s string, out io.Writer) error

func (*Runner) HandlePause

func (self *Runner) HandlePause(*ActionContext) error

func (*Runner) HandlePromptForInput

func (self *Runner) HandlePromptForInput(ctx *ActionContext) error

func (*Runner) LeftPadBuilder

func (self *Runner) LeftPadBuilder(b *strings.Builder)

func (*Runner) RegisterActionHandler

func (self *Runner) RegisterActionHandler(action string, handler ActionHandler)

func (*Runner) RegisterActionHandlerF

func (self *Runner) RegisterActionHandlerF(action string, handler func(ctx *ActionContext) error)

func (*Runner) Run

func (self *Runner) Run(source []byte) error

func (*Runner) Template

func (self *Runner) Template(s string) (string, error)

type ShowActionHandler

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

func NewShowActionHandler

func NewShowActionHandler() *ShowActionHandler

func (*ShowActionHandler) Add

func (self *ShowActionHandler) Add(name, contents string)

func (*ShowActionHandler) Execute

func (self *ShowActionHandler) Execute(ctx *ActionContext) error

type WriterWrapper

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

func (*WriterWrapper) Write

func (self *WriterWrapper) Write(p []byte) (n int, err error)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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