annotate

package module
v0.4.1 Latest Latest
Warning

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

Go to latest
Published: Mar 23, 2026 License: MIT Imports: 6 Imported by: 2

README

annotate-go

A Go library for rendering annotated source code with line numbers and labeled markers.

Installation

go get github.com/koki-develop/annotate-go

Usage

src := []byte(`name = "Alice"
age = 30
`)
labels := []annotate.Label{
	{Span: annotate.Span{Start: 0, End: 4}, Marker: annotate.MarkerDash, Text: "string field"},
	{Span: annotate.Span{Start: 15, End: 18}, Marker: annotate.MarkerTilde, Text: "integer field"},
}
r := annotate.New()
output, _ := r.Render(src, labels)
fmt.Print(output)
1 | name = "Alice"
  | ---- string field
2 | age = 30
  | ~~~ integer field

See pkg.go.dev for full API documentation.

License

MIT

Documentation

Overview

Package annotate renders annotated source code with line numbers and labeled markers.

It is designed for displaying diagnostic messages (errors, warnings, hints) that point to specific byte ranges within source code, similar to the output of compilers like rustc or Go's go vet.

Basic usage:

src := []byte(`name = "Alice"
age = 30
`)
labels := []annotate.Label{
	{Span: annotate.Span{Start: 0, End: 14}, Marker: annotate.MarkerDash, Text: "string field"},
	{Span: annotate.Span{Start: 15, End: 23}, Marker: annotate.MarkerTilde, Text: "integer field"},
}
r := annotate.New()
output, _ := r.Render(src, labels)
fmt.Print(output)

Output:

1 | name = "Alice"
  | -------------- string field
2 | age = 30
  | ~~~~~~~~ integer field
Example
src := []byte(`name = "Alice"
age = 30
`)

labels := []annotate.Label{
	{Span: annotate.Span{Start: 0, End: 14}, Marker: annotate.MarkerDash, Text: "string field"},
	{Span: annotate.Span{Start: 15, End: 23}, Marker: annotate.MarkerTilde, Text: "integer field"},
}

r := annotate.New()
output, err := r.Render(src, labels)
if err != nil {
	panic(err)
}
fmt.Print(output)
Output:
1 | name = "Alice"
  | -------------- string field
2 | age = 30
  | ~~~~~~~~ integer field

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// Bold applies ANSI bold styling.
	Bold = ansiStyle("1")
	// Dim applies ANSI dim (faint) styling.
	Dim = ansiStyle("2")
	// Italic applies ANSI italic styling.
	Italic = ansiStyle("3")
	// Underline applies ANSI underline styling.
	Underline = ansiStyle("4")
)
View Source
var (
	// FgRed applies ANSI red foreground color.
	FgRed = ansiStyle("31")
	// FgGreen applies ANSI green foreground color.
	FgGreen = ansiStyle("32")
	// FgYellow applies ANSI yellow foreground color.
	FgYellow = ansiStyle("33")
	// FgBlue applies ANSI blue foreground color.
	FgBlue = ansiStyle("34")
	// FgMagenta applies ANSI magenta foreground color.
	FgMagenta = ansiStyle("35")
	// FgCyan applies ANSI cyan foreground color.
	FgCyan = ansiStyle("36")
	// FgWhite applies ANSI white foreground color.
	FgWhite = ansiStyle("37")
)
View Source
var (
	// BgRed applies ANSI red background color.
	BgRed = ansiStyle("41")
	// BgGreen applies ANSI green background color.
	BgGreen = ansiStyle("42")
	// BgYellow applies ANSI yellow background color.
	BgYellow = ansiStyle("43")
	// BgBlue applies ANSI blue background color.
	BgBlue = ansiStyle("44")
	// BgMagenta applies ANSI magenta background color.
	BgMagenta = ansiStyle("45")
	// BgCyan applies ANSI cyan background color.
	BgCyan = ansiStyle("46")
	// BgWhite applies ANSI white background color.
	BgWhite = ansiStyle("47")
)
View Source
var DefaultStyle = Style{
	LineNumber: Dim,
	Separator:  Dim,
	Ellipsis:   Dim,
}

DefaultStyle is a Style preset that dims line numbers and separators.

View Source
var LabelStyleError = LabelStyle{
	Marker:    FgRed,
	LabelText: ComposeStyles(FgRed, Bold),
}

LabelStyleError is a LabelStyle preset for error diagnostics. Markers are red; label text is red and bold.

View Source
var LabelStyleHint = LabelStyle{
	Marker:    Dim,
	LabelText: Dim,
}

LabelStyleHint is a LabelStyle preset for hint diagnostics. Markers and label text are dimmed.

View Source
var LabelStyleInfo = LabelStyle{
	Marker:    FgBlue,
	LabelText: FgBlue,
}

LabelStyleInfo is a LabelStyle preset for informational diagnostics. Markers and label text are blue.

View Source
var LabelStyleWarning = LabelStyle{
	Marker:    FgYellow,
	LabelText: FgYellow,
}

LabelStyleWarning is a LabelStyle preset for warning diagnostics. Markers and label text are yellow.

Functions

This section is empty.

Types

type Label

type Label struct {
	Span   Span
	Marker LabelMarker
	Text   string
	Style  LabelStyle
	// Before overrides [Renderer.Before] for this label. Nil falls back to the Renderer default.
	Before *int
	// After overrides [Renderer.After] for this label. Nil falls back to the Renderer default.
	After *int
}

Label defines an annotation for a byte range within the source code. Each label points to a Span, uses a LabelMarker to optionally underline that span, and optionally displays descriptive text after the markers.

If Marker is zero, MarkerDash is used by default. If Style is set, its non-nil fields override the global Style for this label. Labels may span multiple lines; the text is displayed on the last line of the span.

type LabelMarker

type LabelMarker rune

LabelMarker is the character used to underline the annotated span. Any rune can be used as a marker, but the package provides common presets. Use MarkerNone to suppress marker characters entirely.

const (
	// MarkerNone suppresses marker characters. Only the label text is displayed,
	// aligned to where the span begins on the last covered line.
	// If text is empty, no marker line is emitted.
	// For multi-line spans, no marker lines are emitted on non-last lines.
	MarkerNone LabelMarker = -1
	// MarkerDash uses '-' as the marker character.
	MarkerDash LabelMarker = '-'
	// MarkerTilde uses '~' as the marker character.
	MarkerTilde LabelMarker = '~'
	// MarkerCaret uses '^' as the marker character.
	MarkerCaret LabelMarker = '^'
)

type LabelStyle

type LabelStyle struct {
	// LineNumber overrides [Style.LineNumber] for lines containing this label.
	LineNumber StyleFunc
	// Separator overrides [Style.Separator] for lines containing this label.
	Separator StyleFunc
	// SpanCode overrides [Style.SpanCode] for the span covered by this label.
	SpanCode StyleFunc
	// Marker overrides [Style.Marker] for this label's marker characters.
	Marker StyleFunc
	// LabelText overrides [Style.LabelText] for this label's descriptive text.
	LabelText StyleFunc
}

LabelStyle provides per-label style overrides. Non-nil fields take precedence over the corresponding fields in the global Style for this label only.

Unlike Style, LabelStyle does not have a NonSpanCode field because non-span code is not associated with any particular label.

type Option

type Option func(*Renderer)

Option is a functional option for configuring a Renderer.

func WithAfter added in v0.1.0

func WithAfter(n int) Option

WithAfter returns an Option that sets the default number of lines to display after each labeled line. Negative values are clamped to 0.

func WithBefore added in v0.1.0

func WithBefore(n int) Option

WithBefore returns an Option that sets the default number of lines to display before each labeled line. Negative values are clamped to 0.

func WithSourceStyle added in v0.3.0

func WithSourceStyle(fn SourceStyleFunc) Option

WithSourceStyle returns an Option that sets a function to apply syntax highlighting or other styling to the source code. When set, [Style.SpanCode], [Style.NonSpanCode], and [LabelStyle.SpanCode] are ignored for source code lines.

func WithStyle

func WithStyle(s Style) Option

WithStyle returns an Option that sets the Renderer's global Style.

type Renderer

type Renderer struct {
	// Style controls the visual styling applied to each element of the output.
	// If zero, no styling is applied.
	Style Style

	// Before is the default number of lines to display before each labeled line.
	Before int
	// After is the default number of lines to display after each labeled line.
	After int

	// SourceStyle applies syntax highlighting or other styling to the source code.
	// When set, [Style.SpanCode], [Style.NonSpanCode], and [LabelStyle.SpanCode]
	// are ignored for source code lines.
	SourceStyle SourceStyleFunc
}

Renderer renders annotated source code. Use New to create a Renderer.

func New

func New(opts ...Option) *Renderer

New creates a new Renderer with the given options.

func (*Renderer) Render

func (r *Renderer) Render(src []byte, labels []Label) (string, error)

Render renders the annotated source code and returns it as a string.

Each label's Span must satisfy: 0 <= Start < End <= len(src). An error is returned if any label has an invalid span.

func (*Renderer) Write

func (r *Renderer) Write(w io.Writer, src []byte, labels []Label) error

Write renders the annotated source code and writes the output to w.

Each label's Span must satisfy: 0 <= Start < End <= len(src). An error is returned if any label has an invalid span or if writing to w fails. Only lines covered by labels (plus surrounding Before/After context lines) are output. If labels is empty, nothing is written.

type SourceStyleFunc added in v0.3.0

type SourceStyleFunc func(src string) string

SourceStyleFunc is a function that takes tab-expanded source code and returns a styled version. The returned string may contain ANSI escape sequences. The number of newlines in the output must match the input.

type Span

type Span struct {
	Start int
	End   int
}

Span represents a half-open byte range [Start, End) within the source code. Both Start and End are zero-based byte offsets. Start must be less than End.

type Style

type Style struct {
	// LineNumber styles the line number column (e.g., "1", "2", "10").
	LineNumber StyleFunc
	// Separator styles the "|" separator between the line number and code.
	Separator StyleFunc
	// SpanCode styles the portion of source code covered by a label's span.
	SpanCode StyleFunc
	// NonSpanCode styles the portion of source code not covered by any label's span.
	NonSpanCode StyleFunc
	// Marker styles the marker characters (e.g., "---", "~~~") on annotation lines.
	Marker StyleFunc
	// LabelText styles the descriptive text on annotation lines.
	LabelText StyleFunc
	// Ellipsis styles the "..." ellipsis indicator shown between non-contiguous line groups.
	Ellipsis StyleFunc
}

Style controls the visual styling applied to each element of the rendered output. Each field is a StyleFunc applied to the corresponding element. Nil fields leave the element unstyled.

type StyleFunc

type StyleFunc func(string) string

StyleFunc is a function that transforms a string for visual styling. It is typically used to wrap text with ANSI escape codes or other formatting. A nil StyleFunc applies no styling.

func ComposeStyles

func ComposeStyles(fns ...StyleFunc) StyleFunc

ComposeStyles combines multiple StyleFunc functions into one. The functions are applied in the order given (left to right), so the first function becomes the outermost wrapper.

redBold := ComposeStyles(FgRed, Bold)
redBold("text") // equivalent to FgRed(Bold("text"))

Jump to

Keyboard shortcuts

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