go get github.com/nuvrel/diagBuild each diagnostic separately, then hand them all to the printer at once. Print accepts any number of diagnostics and renders them in order, with spacing between each one.
src := []byte(`func add(a, b int) int {
return a + c
}`)
d := diag.NewError("undefined: c").
Code("E001").
Detail(
"Variables must be declared before use. The identifier `c` was not found in any enclosing scope.",
"If you meant to use `b`, note that it was declared in the same function signature.",
).
Snippet(diag.NewSnippet(src).
File("math.go").
From(2, 13).
To(2, 14).
Message("c is not defined")).
Help("did you mean to use b?")
p := diag.NewPrinter(os.Stdout, diag.DefaultConfig())
if err := p.Print(d); err != nil {
return fmt.Errorf("printing diagnostics: %w", err)
}The Config struct controls every aspect of the output. Use the Default* helpers for the parts you want to keep as-is and override only what you need.
cfg := diag.Config{
Profile: colorprofile.Detect(os.Stdout, os.Environ()),
Theme: diag.DefaultTheme(),
Characters: diag.DefaultCharacters(),
Prefixes: diag.DefaultPrefixes(),
SeverityLabels: diag.DefaultSeverityLabels(),
DetailPad: 2,
}Profile
Controls color output. Detected automatically from the terminal by default. Set to colorprofile.Ascii or colorprofile.NoTTY to disable colors:
cfg := diag.Config{
Profile: colorprofile.Ascii,
// ...
}Theme
Controls the style of every visual element. All fields accept a lipgloss.Style:
cfg := diag.Config{
// ...
Theme: diag.Theme{
Error: lipgloss.NewStyle().Foreground(lipgloss.Color("#EB4268")).Bold(true),
Warning: lipgloss.NewStyle().Foreground(lipgloss.Color("#E8FE96")).Bold(true),
Message: lipgloss.NewStyle().Bold(true),
Detail: lipgloss.NewStyle().Foreground(lipgloss.Color("#CCCCCC")),
Help: lipgloss.NewStyle().Foreground(lipgloss.Color("#00D7FF")),
Note: lipgloss.NewStyle().Foreground(lipgloss.Color("#858392")),
Muted: lipgloss.NewStyle().Foreground(lipgloss.Color("#858392")),
},
}Characters
Controls every character used in the output. Defaults use Unicode box-drawing characters and symbols. Swap to ASCII alternatives for environments that cannot render Unicode:
cfg := diag.Config{
// ...
Characters: diag.Characters{
Top: ",",
Mid: "|",
Bot: "'",
Dash: "-",
Dot: ".",
HintHelp: ">",
HintNote: "~",
},
}HintHelp and HintNote are prepended to help and note lines. Set either to "" to remove the prefix character entirely.
Prefixes
Controls the label text for help and note lines:
cfg := diag.Config{
// ...
Prefixes: diag.Prefixes{
Help: "ajuda",
Note: "observação",
},
}SeverityLabels
Controls the label text for each severity level:
cfg := diag.Config{
// ...
SeverityLabels: diag.SeverityLabels{
Error: "erro",
Warning: "aviso",
},
}DetailPad
Controls the number of spaces used to indent .Detail() text (default 2):
cfg := diag.Config{
// ...
DetailPad: 4,
}Diagnostics
NewError(msg)/NewWarning(msg)creates a new diagnostic.Code(code)attaches an error code shown in the header.Detail(paragraphs...)sets the detail body rendered as indented prose below the header.Snippet(s)attaches a source code snippet.Help(text)appends a help note.Note(text)appends an informational note
Regardless of the order methods are chained, the output always renders in a fixed sequence: header, detail, snippets, then hints (help and note).
Snippets
NewSnippet(src)creates a snippet from a byte slice.File(name)sets the file name shown above the snippet.From(line, col)/.To(line, col)sets the highlighted range.Message(text)sets the label shown under the highlight.Pad(n)sets how many context lines to show around the highlight (default 2).TabWidth(n)sets the tab width used for alignment (default 4)
diag is pre-1.0. The API is functional and tested, but minor versions may introduce breaking changes as the library grows. If you depend on it, pin to a specific version and review the changelog before upgrading.
These are the features planned before a stable 1.0 release:
- Syntax highlighting for snippet blocks, likely powered by chroma, with configurable language detection and theme support
- Text wrapping for detail and hint content, using terminal width detection with a configurable fallback column limit
- List blocks for attaching structured bullet-point content to a diagnostic
- Table blocks for displaying tabular data inline in the output
Have a feature in mind that isn't listed here? Open a feature request.
MIT
