docgen

Reference

Sample page

A page with most marker kinds: its empty markers, the same page after docgen update -module v2, and how that page renders. It is the test fixture of docgen, so the tests compare this output with the result of each change.

v2/machine/machine.go

// Package machine is a small state machine for the docgen tests.
//
// # Rates
//
// A Lamp blinks at these rates:
//   - slow, every [DefaultWait]
//   - fast, every period
//
// # Other
//
// Not copied.
package machine

import (
    "errors"
    "time"

    "github.com/USA-RedDragon/docgen/v2"
)

// DefaultWait is the wait of a Lamp that Config does not set.
const DefaultWait = 250 * time.Millisecond

// MaxTries is the largest Config.Tries.
const MaxTries = 3

var (
    // ErrBusy is returned by Start while the Lamp is on.
    ErrBusy = errors.New("machine: busy")
    // ErrOff is returned by Stop while the Lamp is off.
    ErrOff = errors.New("machine: off")
)

// Config configures NewLamp.
type Config struct {
    // Wait is how long the Lamp stays on. 0 means DefaultWait.
    Wait time.Duration
    // Tries is the number of blinks. 0 means 1, and it is at most MaxTries.
    Tries int
    // Name is a label.
    Name string
}

// LampState is the state of a Lamp.
type LampState uint8

// The LampState values.
const (
    // LampOff gives no light.
    LampOff LampState = iota
    // LampOn gives light.
    LampOn
    // LampBroken never gives light again.
    LampBroken
)

// Lamp turns on and off.
type Lamp struct {
    state LampState
    wait  time.Duration
    tries int
    until time.Duration
}

// NewLamp returns a Lamp. It returns a *docgen.ConfigError for a Tries
// above MaxTries.
func NewLamp(cfg Config) (*Lamp, error) {
    if cfg.Tries > MaxTries {
        return nil, &docgen.ConfigError{Field: "Tries"}
    }
    l := &Lamp{wait: cfg.Wait, tries: cfg.Tries}
    if l.wait == 0 {
        l.wait = DefaultWait
    }
    if cfg.Tries == 0 {
        l.tries = 1
    }
    return l, nil
}

// State returns the state of the Lamp.
func (l *Lamp) State() LampState { return l.state }

// Start turns the Lamp on. It returns ErrBusy while the Lamp is on.
func (l *Lamp) Start(now time.Duration) error {
    if l.state == LampOn {
        return ErrBusy
    }
    if l.state == LampOff {
        l.state, l.until = LampOn, now+l.wait
    }
    return nil
}

// Stop turns the Lamp off. It returns ErrOff while the Lamp is off.
func (l *Lamp) Stop() error {
    if l.state != LampOn {
        return ErrOff
    }
    l.off()
    return nil
}

// Tick turns the Lamp off at the end of its wait.
func (l *Lamp) Tick(now time.Duration) {
    if l.state == LampOn && now >= l.until {
        l.off()
    }
}

// Break breaks the Lamp.
func (l *Lamp) Break() { l.state = LampBroken }

func (l *Lamp) off() { l.state = LampOff }

// Counter counts and has no State method.
type Counter struct{ n int }

// Add adds one.
func (c *Counter) Add() { c.n++ }

// Clear sets the count to 0.
func (c *Counter) Clear() { c.n = 0 }

// Len returns the count.
func (c *Counter) Len() int { return c.n }

const period = 30 * time.Millisecond

var hold = 4 * period

// Side is one side of a Pair.
type Side uint8

// The Side values.
const (
    // SideA is the first side.
    SideA Side = iota + 1
    // SideB is the second side.
    SideB
)

// SideState is the state of one side of a Pair.
type SideState uint8

// The SideState values.
const (
    // SideDown is down.
    SideDown SideState = iota
    // SideUp is up.
    SideUp
)

// Pair has two sides.
type Pair struct{ up [3]bool }

// Raise raises side s.
func (p *Pair) Raise(s Side) {
    if s == SideA || s == SideB {
        p.up[s] = true
    }
}

// SideState returns the state of side s.
func (p *Pair) SideState(s Side) SideState {
    if s != SideA && s != SideB || !p.up[s] {
        return SideDown
    }
    return SideUp
}

docs/machines/machine-lamp.md

Before
# Lamp

This page covers every marker kind.

<!-- docgen:config pkg=machine type=Config -->
<!-- /docgen:config -->

The default wait is <!-- docgen:const pkg=machine name=DefaultWait --><!-- /docgen:const --> and at most <!-- docgen:const pkg=machine name=MaxTries --><!-- /docgen:const --> tries.

<!-- docgen:states pkg=machine type=Lamp -->
<!-- /docgen:states -->

<!-- docgen:states pkg=machine type=Counter -->
<!-- /docgen:states -->

<!-- docgen:errors pkg=machine type=Lamp -->
<!-- /docgen:errors -->

<!-- docgen:states pkg=machine type=SideState -->
<!-- /docgen:states -->

The period is <!-- docgen:const pkg=machine name=period --><!-- /docgen:const --> and the hold <!-- docgen:const pkg=machine name=hold --><!-- /docgen:const -->.

<!-- docgen:doc pkg=machine section=Rates -->
<!-- /docgen:doc -->

<!-- docgen:doc pkg=machine name=Lamp.Start -->
<!-- /docgen:doc -->

<!-- docgen:code file=v2/machine/machine.go lines=96-102 -->
<!-- /docgen:code -->

<!-- docgen:output test=machine.ExampleLamp -->
<!-- /docgen:output -->

<!-- docgen:output cmd=v2/examples/hello -->
<!-- /docgen:output -->

<!-- docgen:code file=v2/machine/example_test.go symbol=ExampleLamp -->
<!-- /docgen:code -->

<!-- docgen:code file=v2/machine/machine.go symbol=Lamp.Tick -->
<!-- /docgen:code -->

<!-- docgen:code file=v2/machine/machine.go symbol=SideState -->
<!-- /docgen:code -->

<!-- docgen:code file=v2/machine/machine.go symbol=SideB -->
<!-- /docgen:code -->

It needs Go <!-- docgen:gomod field=go --><!-- /docgen:gomod --> or later.

<!-- docgen:usage cmd=cmd/tool -->
<!-- /docgen:usage -->

<!-- docgen:doc pkg=cmd/tool section=Flags -->
<!-- /docgen:doc -->

<!-- docgen:code file=v2/examples/hello/main.go -->
<!-- /docgen:code -->
After
# Lamp

This page covers every marker kind.

<!-- docgen:config pkg=machine type=Config -->
| Field | Type | Default | Description |
|---|---|---|---|
| `Wait` | `time.Duration` | `DefaultWait` (250ms) | Wait is how long the Lamp stays on. 0 means DefaultWait. |
| `Tries` | `int` | `1` | Tries is the number of blinks. 0 means 1, and it is at most MaxTries. |
| `Name` | `string` | zero value | Name is a label. |
<!-- /docgen:config -->

The default wait is <!-- docgen:const pkg=machine name=DefaultWait -->`250ms`<!-- /docgen:const --> and at most <!-- docgen:const pkg=machine name=MaxTries -->`3`<!-- /docgen:const --> tries.

<!-- docgen:states pkg=machine type=Lamp -->
States of [`Lamp`](https://pkg.go.dev/github.com/USA-RedDragon/docgen/v2/machine#Lamp), from [`Lamp.State`](https://pkg.go.dev/github.com/USA-RedDragon/docgen/v2/machine#Lamp.State):

| State | Meaning | Seen in tests |
|---|---|---|
| [`LampOff`](https://pkg.go.dev/github.com/USA-RedDragon/docgen/v2/machine#LampOff) | LampOff gives no light. | yes, first state |
| [`LampOn`](https://pkg.go.dev/github.com/USA-RedDragon/docgen/v2/machine#LampOn) | LampOn gives light. | yes |
| [`LampBroken`](https://pkg.go.dev/github.com/USA-RedDragon/docgen/v2/machine#LampBroken) | LampBroken never gives light again. | yes |

Transitions seen in tests:

| From | Method call | To |
|---|---|---|
| LampOff | `Start` | LampOn |
| LampOff | `Break` | LampBroken |
| LampOn | `Stop`, `Tick` | LampOff |

![Transitions of Lamp](states/machine-lamp.svg)
<!-- /docgen:states -->

<!-- docgen:states pkg=machine type=Counter -->
[`Counter`](https://pkg.go.dev/github.com/USA-RedDragon/docgen/v2/machine#Counter) has no State method. The state in this table is the result of `Len()`. States seen in tests:

| State | Seen in tests |
|---|---|
| Len() 0 | yes, first state |
| Len() > 0 | yes |

Transitions seen in tests:

| From | Method call | To |
|---|---|---|
| Len() 0 | `Add` | Len() > 0 |
| Len() > 0 | `Clear` | Len() 0 |

![Transitions of Counter](states/machine-counter.svg)
<!-- /docgen:states -->

<!-- docgen:errors pkg=machine type=Lamp -->
| Error | Returned by | Meaning |
|---|---|---|
| [`docgen.ConfigError`](https://pkg.go.dev/github.com/USA-RedDragon/docgen/v2#ConfigError) | `NewLamp` | ConfigError is the error of a constructor for a field with a value out of range. |
| [`machine.ErrBusy`](https://pkg.go.dev/github.com/USA-RedDragon/docgen/v2/machine#ErrBusy) | `Lamp.Start` | ErrBusy is returned by Start while the Lamp is on. |
| [`machine.ErrOff`](https://pkg.go.dev/github.com/USA-RedDragon/docgen/v2/machine#ErrOff) | `Lamp.Stop` | ErrOff is returned by Stop while the Lamp is off. |
<!-- /docgen:errors -->

<!-- docgen:states pkg=machine type=SideState -->
States of [`Pair`](https://pkg.go.dev/github.com/USA-RedDragon/docgen/v2/machine#Pair), from [`Pair.SideState`](https://pkg.go.dev/github.com/USA-RedDragon/docgen/v2/machine#Pair.SideState) for each `Side`:

| State | Meaning | Seen in tests |
|---|---|---|
| [`SideDown`](https://pkg.go.dev/github.com/USA-RedDragon/docgen/v2/machine#SideDown) | SideDown is down. | yes, first state |
| [`SideUp`](https://pkg.go.dev/github.com/USA-RedDragon/docgen/v2/machine#SideUp) | SideUp is up. | yes |

Transitions seen in tests:

| From | Method call | To |
|---|---|---|
| SideDown | `Raise` | SideUp |

![Transitions of Pair](states/machine-pair-sidestate.svg)
<!-- /docgen:states -->

The period is <!-- docgen:const pkg=machine name=period -->`30ms`<!-- /docgen:const --> and the hold <!-- docgen:const pkg=machine name=hold -->`120ms`<!-- /docgen:const -->.

<!-- docgen:doc pkg=machine section=Rates -->
A Lamp blinks at these rates:

  - slow, every [DefaultWait](https://pkg.go.dev/github.com/USA-RedDragon/docgen/v2/machine#DefaultWait)
  - fast, every period
<!-- /docgen:doc -->

<!-- docgen:doc pkg=machine name=Lamp.Start -->
Start turns the Lamp on. It returns ErrBusy while the Lamp is on.
<!-- /docgen:doc -->

<!-- docgen:code file=v2/machine/machine.go lines=96-102 -->
```go
func (l *Lamp) Stop() error {
    if l.state != LampOn {
        return ErrOff
    }
    l.off()
    return nil
}
```
<!-- /docgen:code -->

<!-- docgen:output test=machine.ExampleLamp -->
```text
true
```
<!-- /docgen:output -->

<!-- docgen:output cmd=v2/examples/hello -->
```text
hello from the fixture
```
<!-- /docgen:output -->

<!-- docgen:code file=v2/machine/example_test.go symbol=ExampleLamp -->
```go
func ExampleLamp() {
    l, _ := machine.NewLamp(machine.Config{})
    _ = l.Start(0)
    fmt.Println(l.State() == machine.LampOn)
}
```
<!-- /docgen:code -->

<!-- docgen:code file=v2/machine/machine.go symbol=Lamp.Tick -->
```go
func (l *Lamp) Tick(now time.Duration) {
    if l.state == LampOn && now >= l.until {
        l.off()
    }
}
```
<!-- /docgen:code -->

<!-- docgen:code file=v2/machine/machine.go symbol=SideState -->
```go
type SideState uint8
```
<!-- /docgen:code -->

<!-- docgen:code file=v2/machine/machine.go symbol=SideB -->
```go
const (
    // SideA is the first side.
    SideA Side = iota + 1
    // SideB is the second side.
    SideB
)
```
<!-- /docgen:code -->

It needs Go <!-- docgen:gomod field=go -->`1.24.0`<!-- /docgen:gomod --> or later.

<!-- docgen:usage cmd=cmd/tool -->
```text
Usage of tool:
  -n int
        how many lines to print (default 3)
```
<!-- /docgen:usage -->

<!-- docgen:doc pkg=cmd/tool section=Flags -->
It takes one flag.
<!-- /docgen:doc -->

<!-- docgen:code file=v2/examples/hello/main.go -->
```go
// Command hello prints a greeting.
package main

import "fmt"

func main() {
    fmt.Println("hello from the fixture")
}
```
<!-- /docgen:code -->
Preview

Lamp

This page covers every marker kind.

Field Type Default Description
Wait time.Duration DefaultWait (250ms) Wait is how long the Lamp stays on. 0 means DefaultWait.
Tries int 1 Tries is the number of blinks. 0 means 1, and it is at most MaxTries.
Name string zero value Name is a label.

The default wait is 250ms and at most 3 tries.

States of Lamp, from Lamp.State:

State Meaning Seen in tests
LampOff LampOff gives no light. yes, first state
LampOn LampOn gives light. yes
LampBroken LampBroken never gives light again. yes

Transitions seen in tests:

From Method call To
LampOff Start LampOn
LampOff Break LampBroken
LampOn Stop, Tick LampOff
Transitions of Lamp

Counter has no State method. The state in this table is the result of Len(). States seen in tests:

State Seen in tests
Len() 0 yes, first state
Len() > 0 yes

Transitions seen in tests:

From Method call To
Len() 0 Add Len() > 0
Len() > 0 Clear Len() 0
Transitions of Counter
Error Returned by Meaning
docgen.ConfigError NewLamp ConfigError is the error of a constructor for a field with a value out of range.
machine.ErrBusy Lamp.Start ErrBusy is returned by Start while the Lamp is on.
machine.ErrOff Lamp.Stop ErrOff is returned by Stop while the Lamp is off.

States of Pair, from Pair.SideState for each Side:

State Meaning Seen in tests
SideDown SideDown is down. yes, first state
SideUp SideUp is up. yes

Transitions seen in tests:

From Method call To
SideDown Raise SideUp
Transitions of Pair

The period is 30ms and the hold 120ms.

A Lamp blinks at these rates:

Start turns the Lamp on. It returns ErrBusy while the Lamp is on.

func (l *Lamp) Stop() error {
    if l.state != LampOn {
        return ErrOff
    }
    l.off()
    return nil
}
true
hello from the fixture
func ExampleLamp() {
    l, _ := machine.NewLamp(machine.Config{})
    _ = l.Start(0)
    fmt.Println(l.State() == machine.LampOn)
}
func (l *Lamp) Tick(now time.Duration) {
    if l.state == LampOn && now >= l.until {
        l.off()
    }
}
type SideState uint8
const (
    // SideA is the first side.
    SideA Side = iota + 1
    // SideB is the second side.
    SideB
)

It needs Go 1.24.0 or later.

Usage of tool:
  -n int
        how many lines to print (default 3)

It takes one flag.

// Command hello prints a greeting.
package main

import "fmt"

func main() {
    fmt.Println("hello from the fixture")
}

Source: docs/reference/sample-page.md