Documentation
¶
Overview ¶
Package niceyaml provides utilities for working with YAML documents. It is built using yaml and lipgloss.
By directly styling YAML tokens a single time, niceyaml is much more consistent, flexible, and performant, when compared to using multiple distinct styling systems.
It also provides an alternative implementation of go-yaml's source annotations for errors, as well as adapters for use with JSON schema validation.
Usage ¶
Parse YAML into a Source, then use a Printer to render it with syntax highlighting:
source := niceyaml.NewSourceFromString(yamlContent) printer := niceyaml.NewPrinter() fmt.Println(printer.Print(source))
When errors occur, wrap them with source context to show users exactly where the problem is:
file, err := source.File()
if err != nil {
// Error displays the YAML with the problematic location highlighted.
fmt.Println(source.WrapError(err))
}
Architecture ¶
The package centers on Source, which organizes YAML tokens from go-yaml into line.Lines.
Each line tracks its tokens plus optional metadata: annotations (error messages, diff headers), flags (inserted/deleted), and overlays (style spans for highlighting).
This line-oriented structure enables efficient rendering and precise position tracking.
Printer renders any LineIterator (including *Source) with syntax highlighting via lipgloss.
It supports customizable gutters (line numbers, diff markers), word wrapping, and annotation rendering.
Themes from jacobcolvin.com/niceyaml/style/theme provide color palettes; use theme.Charm as a sensible default.
Error wraps errors with YAML source context.
When you know the error location (via token or path), Error.Error renders surrounding lines with the error position highlighted.
Multiple nested errors appear as annotations below their respective lines, with distant errors displayed in separate hunks.
Validation Pipeline ¶
For structured validation, Decoder iterates over documents in an *ast.File and DocumentDecoder provides the validation pipeline:
source := niceyaml.NewSourceFromString(yamlContent)
file, _ := source.File()
decoder := niceyaml.NewDecoder(file)
for _, doc := range decoder.Documents() {
var config Config
if err := doc.Unmarshal(&config); err != nil {
return source.WrapError(err)
}
}
DocumentDecoder.Unmarshal supports two validation hooks: types implementing SchemaValidator are validated against an external schema before decoding, and types implementing Validator are self-validated after decoding.
Both produce Error values with path information that Source.WrapError can annotate with source context.
Diffs ¶
Revision chains document versions in a doubly-linked list.
Differ computes line differences using the diff package. The default diff.Hirschberg algorithm is space-efficient for large files:
revs := niceyaml.NewRevision(original).Append(modified) result := niceyaml.Diff(revs.Origin(), revs.Tip()) printer := niceyaml.NewPrinter() fmt.Println(printer.Print(result.Unified())) source, spans := result.Hunks(3) fmt.Println(printer.Print(source, spans...))
Custom algorithms implement diff.Algorithm. For reusable differ instances:
differ := niceyaml.NewDiffer(niceyaml.WithAlgorithm(myAlgo)) result := differ.Diff(revA, revB)
The diff output uses line.Flag to mark inserted/deleted lines and line.Annotation for unified diff hunk headers.
Text Search ¶
Finder locates strings within tokens, returning position.Range values suitable for Source.AddOverlay.
Use StandardNormalizer with WithNormalizer for case-insensitive, diacritic-insensitive matching:
finder := niceyaml.NewFinder(niceyaml.WithNormalizer(niceyaml.NewStandardNormalizer()))
finder.Load(source)
for _, rng := range finder.Find("search term") {
source.AddOverlay(style.GenericInserted, rng)
}
Index ¶
- Variables
- type AnnotationContext
- type AnnotationFunc
- type Decoder
- type DiffResult
- func (r *DiffResult) After() LineIterator
- func (r *DiffResult) Before() LineIterator
- func (r *DiffResult) Hunks(context int) (*Source, position.Spans)
- func (r *DiffResult) IsEmpty() bool
- func (r *DiffResult) Name() string
- func (r *DiffResult) Stats() (int, int)
- func (r *DiffResult) Unified() *Source
- type Differ
- type DifferOption
- type DocumentDecoder
- func (dd *DocumentDecoder) Decode(v any) error
- func (dd *DocumentDecoder) DecodeContext(ctx context.Context, v any) error
- func (dd *DocumentDecoder) GetValue(path *paths.YAMLPath) (string, bool)
- func (dd *DocumentDecoder) Unmarshal(v any) error
- func (dd *DocumentDecoder) UnmarshalContext(ctx context.Context, v any) error
- func (dd *DocumentDecoder) ValidateSchema(sv SchemaValidator) error
- func (dd *DocumentDecoder) ValidateSchemaContext(ctx context.Context, sv SchemaValidator) error
- type Encoder
- type Error
- type ErrorOption
- func WithErrorToken(tk *token.Token) ErrorOption
- func WithErrors(errs ...*Error) ErrorOption
- func WithPath(p *paths.Path) ErrorOption
- func WithPrinter(p WrappingPrinter) ErrorOption
- func WithSource(src *Source) ErrorOption
- func WithSourceLines(lines int) ErrorOption
- func WithWidthFunc(fn func() int) ErrorOption
- type Finder
- type FinderOption
- type GutterContext
- type GutterFunc
- type LineGetter
- type LineIterator
- type Normalizer
- type Printer
- type PrinterOption
- type Revision
- func (t *Revision) Append(s *Source) *Revision
- func (t *Revision) At(index int) *Revision
- func (t *Revision) AtOrigin() bool
- func (t *Revision) AtTip() bool
- func (t *Revision) Index() int
- func (t *Revision) Len() int
- func (t *Revision) Name() string
- func (t *Revision) Names() []string
- func (t *Revision) Origin() *Revision
- func (t *Revision) Prepend(s *Source) *Revision
- func (t *Revision) Seek(n int) *Revision
- func (t *Revision) Source() *Source
- func (t *Revision) Tip() *Revision
- type SchemaValidator
- type Source
- func (s *Source) AddOverlay(kind style.Style, ranges ...position.Range)
- func (s *Source) AllLines(spans ...position.Span) iter.Seq2[position.Position, line.Line]
- func (s *Source) AllRunes(ranges ...position.Range) iter.Seq2[position.Position, rune]
- func (s *Source) ClearOverlays()
- func (s *Source) Content() string
- func (s *Source) ContentPositionRanges(positions ...position.Position) []position.Range
- func (s *Source) ContentPositionRangesFromToken(tk *token.Token) []position.Range
- func (s *Source) File() (*ast.File, error)
- func (s *Source) IsEmpty() bool
- func (s *Source) Len() int
- func (s *Source) Line(idx int) *line.Line
- func (s *Source) Lines() line.Lines
- func (s *Source) Name() string
- func (s *Source) String() string
- func (s *Source) TokenAt(pos position.Position) *token.Token
- func (s *Source) TokenPositionRanges(positions ...position.Position) []position.Range
- func (s *Source) TokenPositionRangesFromToken(tk *token.Token) []position.Range
- func (s *Source) Tokens() token.Tokens
- func (s *Source) Validate() error
- func (s *Source) Width() int
- func (s *Source) WrapError(err error) error
- type SourceGetter
- type SourceOption
- type StandardNormalizer
- type StyleGetter
- type Validator
- type WrappingPrinter
Constants ¶
This section is empty.
Variables ¶
var ( // ErrNoSource indicates no source was provided to resolve an error path. ErrNoSource = errors.New("no source provided") // ErrNoPathOrToken indicates neither a path nor token was provided. ErrNoPathOrToken = errors.New("no path or token provided") // ErrTokenNotFound indicates the token was not found in the source. ErrTokenNotFound = errors.New("token not found in source") )
var PrettyEncoderOptions = []yaml.EncodeOption{ yaml.Indent(2), yaml.IndentSequence(true), }
PrettyEncoderOptions are default encoding options which can be used by NewEncoder to produce prettier-friendly YAML output.
Functions ¶
This section is empty.
Types ¶
type AnnotationContext ¶
type AnnotationContext struct {
Styles StyleGetter
Annotations line.Annotations
Position line.RelativePosition
}
AnnotationContext provides context for annotation rendering.
It is passed to AnnotationFunc to determine the appropriate annotation content.
type AnnotationFunc ¶
type AnnotationFunc func(AnnotationContext) string
AnnotationFunc returns the rendered annotation content based on AnnotationContext.
func DefaultAnnotation ¶
func DefaultAnnotation() AnnotationFunc
DefaultAnnotation creates an AnnotationFunc that renders annotations with position-based prefixes: "^ " for line.Below, none for line.Above.
type Decoder ¶
type Decoder struct {
// contains filtered or unexported fields
}
Decoder iterates over YAML documents in a parsed *ast.File.
A single YAML file can contain multiple documents separated by "---". These documents often have different schemas and/or validation requirements. Decoder provides lazy iteration over these documents, providing a DocumentDecoder for each.
dec := niceyaml.NewDecoder(file)
for _, dd := range dec.Documents() {
// Each dd is a DocumentDecoder instance.
}
Create instances with NewDecoder.
func NewDecoder ¶
func (*Decoder) Documents ¶
func (d *Decoder) Documents() iter.Seq2[int, *DocumentDecoder]
Documents returns an iterator over all documents in the YAML file.
Each iteration yields the document index and a *DocumentDecoder for that document.
type DiffResult ¶
type DiffResult struct {
// contains filtered or unexported fields
}
DiffResult holds computed diff operations for rendering.
Rendering methods:
- DiffResult.Unified returns all lines in unified diff format.
- DiffResult.Hunks returns only changed lines with context.
- DiffResult.Before and DiffResult.After return aligned iterators for side-by-side rendering.
Create instances with Differ.Diff or Diff.
func Diff ¶
func Diff(a, b SourceGetter) *DiffResult
Diff computes the difference between two sources using the default algorithm.
This is a convenience function equivalent to NewDiffer().Diff(a, b).
func (*DiffResult) After ¶
func (r *DiffResult) After() LineIterator
After returns a LineIterator for the right (after) pane of a side-by-side diff.
Lines are aligned with DiffResult.Before so both iterators have equal line counts. Consecutive delete/insert sequences are paired row-by-row. When there are more deletions than insertions, empty placeholder lines (zero value) fill the remaining rows on this side.
Line flags: line.FlagInserted for inserted lines, line.FlagDefault for equal lines and empty placeholders.
func (*DiffResult) Before ¶
func (r *DiffResult) Before() LineIterator
Before returns a LineIterator for the left (before) pane of a side-by-side diff.
Lines are aligned with DiffResult.After so both iterators have equal line counts. Consecutive delete/insert sequences are paired row-by-row. When there are more insertions than deletions, empty placeholder lines (zero value) fill the remaining rows on this side.
Line flags: line.FlagDeleted for deleted lines, line.FlagDefault for equal lines and empty placeholders.
func (*DiffResult) Hunks ¶
func (r *DiffResult) Hunks(context int) (*Source, position.Spans)
Hunks returns a *Source and line spans for rendering a summarized diff. The context parameter specifies the number of unchanged lines to show around each change. A context of 0 shows only the changed lines. Negative values are treated as 0.
The source contains all diff lines with flags for deleted/inserted lines. Hunk headers are stored in line.Annotation.Content for each hunk's first line.
Pass both to Printer.Print to render the hunks:
printer.Print(source, spans...)
func (*DiffResult) IsEmpty ¶
func (r *DiffResult) IsEmpty() bool
IsEmpty reports whether the diff contains no lines.
func (*DiffResult) Name ¶
func (r *DiffResult) Name() string
Name returns the diff name in "a..b" format.
func (*DiffResult) Stats ¶
func (r *DiffResult) Stats() (int, int)
Stats returns the number of added and removed lines in the diff.
func (*DiffResult) Unified ¶
func (r *DiffResult) Unified() *Source
Unified returns a *Source representing the complete diff.
The returned Source contains merged tokens from both revisions: unchanged lines use tokens from the second source, while changed lines include deleted tokens from the first source followed by inserted tokens from the second.
Source contains flags for deleted/inserted lines.
type Differ ¶
type Differ struct {
// contains filtered or unexported fields
}
Differ computes line differences using a configurable algorithm.
Differ is not safe for concurrent use because the underlying algorithm maintains reusable buffers. Create separate instances for concurrent operations. The returned *DiffResult is safe for concurrent use.
Create instances with NewDiffer.
func NewDiffer ¶
func NewDiffer(opts ...DifferOption) *Differ
NewDiffer creates a new *Differ with the given options.
If no algorithm is specified, uses diff.Hirschberg.
func (*Differ) Diff ¶
func (d *Differ) Diff(a, b SourceGetter) *DiffResult
Diff computes the difference between two sources.
The result can be rendered multiple times with DiffResult.Unified or DiffResult.Hunks.
type DifferOption ¶
type DifferOption func(*Differ)
DifferOption configures a Differ.
Available options:
func WithAlgorithm ¶
func WithAlgorithm(algo diff.Algorithm) DifferOption
WithAlgorithm sets the diff algorithm.
Default is diff.Hirschberg.
type DocumentDecoder ¶
type DocumentDecoder struct {
// contains filtered or unexported fields
}
DocumentDecoder decodes and validates a single YAML document.
It separates decoding from document iteration, allowing validation hooks to run at the right time during unmarshaling. Types implementing SchemaValidator are validated before decoding, and types implementing Validator are validated after. Types may implement both interfaces.
Use DocumentDecoder.GetValue to inspect values without unmarshaling, which is helpful for routing documents based on a discriminator field.
For most use cases, call DocumentDecoder.Unmarshal to get the full validation pipeline:
for _, doc := range decoder.Documents() {
var config Config
if err := doc.Unmarshal(&config); err != nil {
return err
}
}
Use DocumentDecoder.Decode directly when you need decoding without validation hooks. All decoding methods convert YAML errors to Error with source annotations.
Create instances with NewDocumentDecoder.
func NewDocumentDecoder ¶
func NewDocumentDecoder(doc *ast.DocumentNode) *DocumentDecoder
NewDocumentDecoder creates a new *DocumentDecoder for the given *ast.DocumentNode.
func (*DocumentDecoder) Decode ¶
func (dd *DocumentDecoder) Decode(v any) error
Decode decodes the document into v.
This is a convenience wrapper around DocumentDecoder.DecodeContext with context.Background.
YAML decoding errors are converted to Error with source annotations.
func (*DocumentDecoder) DecodeContext ¶
func (dd *DocumentDecoder) DecodeContext(ctx context.Context, v any) error
DecodeContext decodes the document into v with context.Context. YAML decoding errors are converted to Error with source annotations.
func (*DocumentDecoder) GetValue ¶
func (dd *DocumentDecoder) GetValue(path *paths.YAMLPath) (string, bool)
GetValue extracts a raw YAML value without unmarshaling.
This is useful when you need to inspect document content before deciding how to process it. For example, multi-document files often use a discriminator field like "kind" or "version" to determine which schema applies:
kindPath := paths.Root().Child("kind").Path()
for _, doc := range decoder.Documents() {
kind, _ := doc.GetValue(kindPath)
switch kind {
case "Pod":
// Unmarshal to Pod struct.
case "Service":
// Unmarshal to Service struct.
}
}
Returns the string representation of the value at path, or an empty string and false if path is nil, the document is a directive, or no value exists.
func (*DocumentDecoder) Unmarshal ¶
func (dd *DocumentDecoder) Unmarshal(v any) error
Unmarshal validates and decodes the document into v.
This is a convenience wrapper around DocumentDecoder.UnmarshalContext with context.Background.
If v implements SchemaValidator, ValidateSchema is called before decoding. If v implements Validator, Validate is called after successful decoding.
func (*DocumentDecoder) UnmarshalContext ¶
func (dd *DocumentDecoder) UnmarshalContext(ctx context.Context, v any) error
UnmarshalContext validates and decodes the document into v with context.Context.
If v implements SchemaValidator, ValidateSchema is called before decoding. If v implements Validator, Validate is called after successful decoding.
func (*DocumentDecoder) ValidateSchema ¶
func (dd *DocumentDecoder) ValidateSchema(sv SchemaValidator) error
ValidateSchema decodes the document to [any] and validates it using sv.
This is a convenience wrapper around DocumentDecoder.ValidateSchemaContext with context.Background.
func (*DocumentDecoder) ValidateSchemaContext ¶
func (dd *DocumentDecoder) ValidateSchemaContext(ctx context.Context, sv SchemaValidator) error
ValidateSchemaContext decodes the document to [any] and validates it using sv with context.Context.
Returns decoding errors or errors from the SchemaValidator ValidateSchema method.
type Encoder ¶
type Encoder struct {
// contains filtered or unexported fields
}
Encoder wraps *yaml.Encoder for convenience.
Create instances with NewEncoder.
func NewEncoder ¶
func NewEncoder(w io.Writer, opts ...yaml.EncodeOption) *Encoder
NewEncoder creates a new *Encoder that writes to w. Any provided [yaml.EncodeOption]s are passed to the underlying *yaml.Encoder.
type Error ¶
type Error struct {
// contains filtered or unexported fields
}
Error represents a YAML error with optional source annotation.
To enable annotated error output that shows the relevant YAML location, provide:
- WithErrorToken directly specifies the error location, OR
- WithPath combined with WithSource to resolve the path
Since these conditions must only be satisfied before calling Error.Error, you may use Error.SetOption to supply them at any time and in any context before then.
This means that callers may optionally attach any additional context that original Error producers might lack, thus avoiding the need for producers to take on any more responsibility than they need to.
For example, a SchemaValidator that produces Error values will be path-aware, and thus should use WithPath, but it will likely not have access to the Source.
For convenience, Source.WrapError can be used if you only need to add the Source without any other ErrorOption values.
Error implements the error interface. Use Error.Unwrap with errors.Is and errors.As to inspect wrapped errors.
Create instances with NewError or NewErrorFrom.
func NewError ¶
func NewError(msg string, opts ...ErrorOption) *Error
NewError creates a new *Error with the given message. Use NewErrorFrom instead if wrapping an existing error.
func NewErrorFrom ¶
func NewErrorFrom(err error, opts ...ErrorOption) *Error
NewErrorFrom creates a new *Error wrapping an existing error. Use NewError instead if creating an error from a message string.
func (*Error) Path ¶
Path returns the *paths.Path path where the error occurred as a string.
func (*Error) SetOption ¶
func (e *Error) SetOption(opts ...ErrorOption)
SetOption applies the provided ErrorOption values to the Error.
type ErrorOption ¶
type ErrorOption func(e *Error)
ErrorOption configures an Error.
Available options:
func WithErrorToken ¶
func WithErrorToken(tk *token.Token) ErrorOption
WithErrorToken is an ErrorOption that sets the token where the error occurred.
func WithErrors ¶
func WithErrors(errs ...*Error) ErrorOption
WithErrors is an ErrorOption that adds nested errors to the Error.
Each nested error has its own YAML path or token and is rendered as an annotation below its resolved line.
func WithPath ¶
func WithPath(p *paths.Path) ErrorOption
WithPath is an ErrorOption that sets the YAML path where the error occurred.
The *paths.Path provides both the path and whether to highlight the key or value.
func WithPrinter ¶
func WithPrinter(p WrappingPrinter) ErrorOption
WithPrinter is an ErrorOption that sets the WrappingPrinter used for formatting the error source.
func WithSource ¶
func WithSource(src *Source) ErrorOption
WithSource is an ErrorOption that sets the *Source for resolving the error path.
func WithSourceLines ¶
func WithSourceLines(lines int) ErrorOption
WithSourceLines is an ErrorOption that sets the number of context lines to show around the error.
func WithWidthFunc ¶
func WithWidthFunc(fn func() int) ErrorOption
WithWidthFunc is an ErrorOption that sets a function to determine the width for word wrapping. This takes precedence over Error.SetWidth when both are configured.
type Finder ¶
type Finder struct {
// contains filtered or unexported fields
}
Finder finds strings within YAML tokens, returning position.Ranges that can be used to highlight matches in rendered output.
The typical use case is search-as-you-type highlighting: the user views YAML content and types a search term, and matching text is highlighted in place.
Finder solves the challenge of mapping string matches back to their original line and column positions, even when normalization (case folding, diacritic removal) changes the character count.
Finder uses a load-once, search-many design. Call Finder.Load once with your source data; this builds an internal index that maps character positions in the searchable text back to position.Position values in the original. Subsequent calls to Finder.Find use this index for efficient lookups without re-parsing.
Finder is safe for concurrent use. Multiple goroutines may call Finder.Find simultaneously, and Finder.Load uses locking to safely update internal state.
Example:
// Create finder with case-insensitive matching.
finder := niceyaml.NewFinder(
niceyaml.WithNormalizer(niceyaml.NewStandardNormalizer()),
)
finder.Load(source)
// Find matches and highlight them.
for _, rng := range finder.Find("search term") {
source.AddOverlay(highlightStyle, rng)
}
fmt.Println(printer.Print(source))
By default, searches are exact (case-sensitive, no normalization).
Use WithNormalizer with StandardNormalizer for case-insensitive matching that also ignores diacritics (e.g., "cafe" matches "Café").
Create instances with NewFinder.
func NewFinder ¶
func NewFinder(opts ...FinderOption) *Finder
NewFinder creates a new *Finder. Call Finder.Load to provide a LineIterator before searching.
By default, no normalization is applied. Use WithNormalizer to enable case-insensitive or diacritic-insensitive matching.
func (*Finder) Find ¶
Find finds all occurrences of the search string in the preprocessed source.
It returns a slice of position.Range indicating the start and end positions of each match. The slice is provided in the order the matches appear in the source.
Returns nil if the search string is empty or the finder has no source data.
func (*Finder) Load ¶
func (f *Finder) Load(lines LineIterator)
Load preprocesses the given LineIterator, building the internal source string and position map for searching.
This method must be called before using Finder.Find.
type FinderOption ¶
type FinderOption func(*Finder)
FinderOption configures a Finder.
Available options:
func WithNormalizer ¶
func WithNormalizer(normalizer Normalizer) FinderOption
WithNormalizer is a FinderOption that sets a Normalizer applied to both the search string and source text before matching.
See StandardNormalizer for an implementation.
type GutterContext ¶
type GutterContext struct {
Styles StyleGetter
Index int
Number int
TotalLines int
Flag line.Flag
Soft bool
}
GutterContext provides context about the current line for gutter rendering. It is passed to GutterFunc to determine the appropriate gutter content.
type GutterFunc ¶
type GutterFunc func(GutterContext) string
GutterFunc returns the gutter content for a line based on GutterContext. The returned string is rendered as the leftmost content before the line content.
Available gutters:
func DefaultGutter ¶
func DefaultGutter() GutterFunc
DefaultGutter creates a GutterFunc that renders both line numbers and diff markers.
This is the default gutter used by NewPrinter.
func DiffGutter ¶
func DiffGutter() GutterFunc
DiffGutter creates a GutterFunc that renders diff-style markers only (" ", "+", "-").
No line numbers are rendered.
Uses style.GenericInserted and style.GenericDeleted for styling.
func LineNumberGutter ¶
func LineNumberGutter() GutterFunc
LineNumberGutter creates a GutterFunc that renders styled line numbers only.
For soft-wrapped continuation lines, renders " - " as a continuation marker.
No diff markers are rendered.
Uses style.Comment foreground for styling.
func NoGutter ¶
func NoGutter() GutterFunc
NoGutter returns a GutterFunc that returns an empty string for all lines.
type LineGetter ¶
LineGetter provides direct access to lines as a slice. See Source for an implementation.
type LineIterator ¶
type LineIterator interface {
AllLines(spans ...position.Span) iter.Seq2[position.Position, line.Line]
AllRunes(ranges ...position.Range) iter.Seq2[position.Position, rune]
Len() int
IsEmpty() bool
}
LineIterator provides line-by-line access to YAML tokens. See Source for an implementation.
type Normalizer ¶
Normalizer transforms strings for comparison (e.g., removing diacritics).
See StandardNormalizer for an implementation.
type Printer ¶
type Printer struct {
// contains filtered or unexported fields
}
Printer prints YAML with syntax highlighting for terminal output.
It accepts a LineIterator, normally Source, and produces styled terminal output using [lipgloss.Style]s. It applies syntax highlighting to YAML tokens, with support for customizable gutters, annotations, styled overlays, and word wrapping.
Create instances with NewPrinter.
Rendering ¶
Use Printer.Print to render lines. When called without spans, it renders all lines. Pass position.Span arguments to render specific line spans, which is useful for showing error context or diff hunks:
printer.Print(source) // All lines. printer.Print(source, span1, span2) // Specific spans.
Gutters ¶
Gutters appear at the left edge of each line and typically show line numbers or diff markers. The printer uses DefaultGutter by default, which combines line numbers with diff markers (+/-). Other built-in options include DiffGutter (markers only), LineNumberGutter (numbers only), and NoGutter.
Overlays ¶
Overlays apply visual highlighting to specific column spans within lines. Add overlays to a Source via Source.AddOverlay, then print normally. The printer blends overlay styles with the underlying token styles. This is how error positions and search results are highlighted.
Annotations ¶
Annotations are extra text lines rendered above or below a line, outside the token stream. They display error messages, diff hunk headers, or other contextual notes. The printer renders them via AnnotationFunc, defaulting to DefaultAnnotation which prefixes below-line annotations with "^ ".
Word Wrapping ¶
Call Printer.SetWidth to enable word wrapping at a given width. The printer accounts for gutter width when calculating available content width. Wrapped continuation lines show a "-" marker in the gutter.
func NewPrinter ¶
func NewPrinter(opts ...PrinterOption) *Printer
NewPrinter creates a new *Printer. By default it uses theme.Charm, DefaultGutter, and DefaultAnnotation.
func (*Printer) Print ¶
func (p *Printer) Print(lines LineIterator, spans ...position.Span) string
Print prints any LineIterator. It prints lines within the given [position.Span]s, in the supplied order. If no [position.Span]s are provided, all lines are printed.
func (*Printer) SetAnnotationsEnabled ¶
SetAnnotationsEnabled sets whether annotations are rendered. Defaults to true.
func (*Printer) SetWidth ¶
SetWidth sets the width for word wrapping. A width of 0 disables wrapping.
func (*Printer) SetWordWrap ¶
SetWordWrap sets whether word wrapping is enabled. Defaults to true. Word wrapping requires a width to be set via Printer.SetWidth.
func (*Printer) Style ¶
Style retrieves the underlying *lipgloss.Style for the given style.Style, or an empty style if not found.
type PrinterOption ¶
type PrinterOption func(*Printer)
PrinterOption configures a Printer.
Available options:
func WithAnnotationFunc ¶
func WithAnnotationFunc(fn AnnotationFunc) PrinterOption
WithAnnotationFunc is a PrinterOption that sets the AnnotationFunc for rendering annotations.
By default, DefaultAnnotation is used which adds "^ " prefix for line.Below annotations.
func WithGutter ¶
func WithGutter(fn GutterFunc) PrinterOption
WithGutter is a PrinterOption that sets the GutterFunc for rendering. By default, DefaultGutter is used which renders line numbers and diff markers.
func WithStyle ¶
func WithStyle(s lipgloss.Style) PrinterOption
WithStyle is a PrinterOption that configures the printer with the given container style.
func WithStyles ¶
func WithStyles(s StyleGetter) PrinterOption
WithStyles is a PrinterOption that configures the printer with the given StyleGetter.
type Revision ¶
type Revision struct {
// contains filtered or unexported fields
}
Revision represents a *Source at one or more revisions. It may form a linked or doubly-linked list to track changes across revisions. A single revision is valid; multiple revisions are not required.
Create instances with NewRevision.
func NewRevision ¶
NewRevision creates a new *Revision with the given *Source at the head. Use Revision.Append or Revision.Prepend to add more revisions. A builder pattern is supported for values that are known at compile time.
func (*Revision) Append ¶
Append adds a new revision after the *Source at the head. Returns the newly added revision.
func (*Revision) At ¶
At returns the revision at the given zero-based index. If index exceeds the available revisions, it stops at the last one. This is equivalent to Origin().Seek(index).
func (*Revision) Prepend ¶
Prepend adds a new revision before the *Source at the head. Returns the newly added revision.
func (*Revision) Seek ¶
Seek moves n revisions forward (n > 0) or backward (n < 0) in the sequence. If n exceeds the available revisions, it stops at the end.
type SchemaValidator ¶
SchemaValidator is implemented by types that validate arbitrary data against a schema.
If a type implements this interface, DocumentDecoder.Unmarshal automatically decodes the document to [any] and calls ValidateSchema before decoding to the typed struct.
See jacobcolvin.com/niceyaml/schema/validator.Validator for an implementation.
type Source ¶
type Source struct {
// contains filtered or unexported fields
}
Source is the central type for parsing, displaying, and annotating YAML. It organizes YAML tokens into lines, enabling precise position tracking and styled rendering through Printer.
Typical use involves creating a Source, then passing it to utilities like Printer for rendering or Finder for searching:
source := NewSourceFromString(yamlContent) printer := NewPrinter(WithStyles(theme.Charm())) fmt.Println(printer.Print(source))
The token-based line structure enables features that would be difficult with string-based approaches: partial rendering of specific line ranges, accurate diff computation between YAML revisions, and search highlighting that respects token boundaries.
For structured access to the YAML content, use the Source.File method, which lazily parses the AST. Any parsing errors can be wrapped with source context using Source.WrapError for user-friendly error messages.
Overlay operations (for highlighting search results or diagnostics) are thread-safe; a Source can be highlighted from multiple goroutines while being rendered.
Create instances with NewSourceFromString, NewSourceFromToken, or NewSourceFromTokens.
func NewSourceFromString ¶
func NewSourceFromString(src string, opts ...SourceOption) *Source
NewSourceFromString creates a new *Source from a YAML string using lexer.Tokenize.
func NewSourceFromToken ¶
func NewSourceFromToken(tk *token.Token, opts ...SourceOption) *Source
NewSourceFromToken creates a new *Source from a seed *token.Token. It collects all token.Tokens by walking the token chain from start to end.
func NewSourceFromTokens ¶
func NewSourceFromTokens(tks token.Tokens, opts ...SourceOption) *Source
NewSourceFromTokens creates a new *Source from token.Tokens. See line.NewLines for details on token splitting behavior.
func (*Source) AddOverlay ¶
AddOverlay adds an overlay of the given kind to the specified ranges. Multi-line ranges are split into per-line overlays automatically.
func (*Source) AllLines ¶
AllLines returns an iterator over lines within the given spans.
If no spans are provided, all lines are iterated. Each iteration yields a position.Position and the line.Line at that position.
func (*Source) AllRunes ¶
AllRunes returns an iterator over runes within the given ranges. If no ranges are provided, all runes are iterated. Each iteration yields a position.Position and the rune at that position.
func (*Source) ClearOverlays ¶
func (s *Source) ClearOverlays()
ClearOverlays removes all overlays from all lines.
func (*Source) Content ¶
Content returns the combined content of all [line.Line]s as a string. Lines are joined with newlines.
func (*Source) ContentPositionRanges ¶
ContentPositionRanges returns all position ranges for content at the given positions, excluding leading and trailing whitespace.
Duplicate ranges are removed.
Returns nil if no content exists at any of the given positions.
func (*Source) ContentPositionRangesFromToken ¶
ContentPositionRangesFromToken returns all position ranges for content of the given token, excluding leading and trailing whitespace.
Returns nil if the token is nil or not found in the Source.
func (*Source) File ¶
File returns an *ast.File for the Source tokens.
The file is lazily parsed on first call using parser.Parse with options provided via WithParserOptions. Subsequent calls return the cached result.
Any YAML parsing errors are converted to Error with source annotations.
func (*Source) Line ¶
Line returns the *line.Line at the given index. Panics if idx is out of range.
func (*Source) Lines ¶
Lines returns all line.Lines in the Source. This returns the internal slice for efficiency; callers should not modify it.
func (*Source) String ¶
String reconstructs all [line.Line]s as a string, including any annotations. This should generally only be used for debugging.
func (*Source) TokenAt ¶
TokenAt returns the *token.Token at the given position. Returns nil if the position is out of bounds or no token exists there.
func (*Source) TokenPositionRanges ¶
TokenPositionRanges returns all token position ranges that are part of the same joined token group as the tokens at the given [position.Position]s.
For non-joined lines, returns the range of the token at each given column. Duplicate ranges are removed.
Returns nil if no tokens exist at any of the given positions.
func (*Source) TokenPositionRangesFromToken ¶
TokenPositionRangesFromToken returns all position ranges for a given token. Returns nil if the token is nil or not found in the Source.
func (*Source) Tokens ¶
Tokens reconstructs the full token.Tokens stream from all [line.Line]s. See line.Lines.Tokens for details on token recombination behavior.
func (*Source) Validate ¶
Validate checks the integrity of the Source. See line.Lines.Validate for details on validation checks.
type SourceGetter ¶
type SourceGetter interface {
Source() *Source
}
SourceGetter retrieves a *Source.
See Revision for an implementation.
type SourceOption ¶
type SourceOption func(*Source)
SourceOption configures Source creation.
Available options:
func WithErrorOptions ¶
func WithErrorOptions(opts ...ErrorOption) SourceOption
WithErrorOptions is a SourceOption that sets the ErrorOption values used when wrapping errors with Source.WrapError.
func WithName ¶
func WithName(name string) SourceOption
WithName is a SourceOption that sets the name for the Source.
func WithParserOptions ¶
func WithParserOptions(opts ...parser.Option) SourceOption
WithParserOptions is a SourceOption that sets the parser options used when parsing the Source into an *ast.File.
These options are passed to parser.Parse in addition to parser.ParseComments, which is always included.
type StandardNormalizer ¶
type StandardNormalizer struct {
// contains filtered or unexported fields
}
StandardNormalizer removes diacritics and lowercases strings for case-insensitive matching. For example, "Ö" becomes "o". Note that unicode.Mn is the unicode key for nonspacing marks. Create instances with NewStandardNormalizer.
func NewStandardNormalizer ¶
func NewStandardNormalizer() *StandardNormalizer
NewStandardNormalizer creates a new *StandardNormalizer.
func (*StandardNormalizer) Normalize ¶
func (n *StandardNormalizer) Normalize(in string) string
Normalize implements Normalizer.
type StyleGetter ¶
StyleGetter retrieves styles by category.
See style.Styles for an implementation.
type Validator ¶
type Validator interface {
Validate() error
}
Validator is implemented by types that validate themselves.
If a type implements this interface, DocumentDecoder.Unmarshal automatically calls Validate after successful decoding.
type WrappingPrinter ¶
type WrappingPrinter interface {
SetWidth(width int)
Print(lines LineIterator, spans ...position.Span) string
}
WrappingPrinter prints with width-aware word wrapping.
See Printer for an implementation.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
bubbles
|
|
|
yamlviewport
Package yamlviewport provides a Bubble Tea component for viewing YAML with syntax highlighting, revision history, and diff visualization.
|
Package yamlviewport provides a Bubble Tea component for viewing YAML with syntax highlighting, revision history, and diff visualization. |
|
cmd
|
|
|
nyaml
command
Package main provides the nyaml CLI for viewing and validating YAML files.
|
Package main provides the nyaml CLI for viewing and validating YAML files. |
|
Package diff computes minimal edit sequences between string slices.
|
Package diff computes minimal edit sequences between string slices. |
|
examples
|
|
|
diffs
command
|
|
|
finder
command
|
|
|
printer
command
|
|
|
schemas/cafe
Package cafe is an example.
|
Package cafe is an example. |
|
schemas/cafe/schemagen
command
Package main generates a JSON schema for the cafe example.
|
Package main generates a JSON schema for the cafe example. |
|
schemas/cafe/spec
Package spec defines the cafe specification schema.
|
Package spec defines the cafe specification schema. |
|
Package fangs provides CLI utilities for applications built with fang, a Cobra companion library.
|
Package fangs provides CLI utilities for applications built with fang, a Cobra companion library. |
|
internal
|
|
|
ansi
Package ansi provides utilities for handling ANSI.
|
Package ansi provides utilities for handling ANSI. |
|
colors
Package colors provides style combination utilities for layered styling.
|
Package colors provides style combination utilities for layered styling. |
|
yamltest
Package yamltest provides test utilities for code that works with go-yaml tokens and niceyaml styled output.
|
Package yamltest provides test utilities for code that works with go-yaml tokens and niceyaml styled output. |
|
Package lexers provides document-aware YAML tokenization.
|
Package lexers provides document-aware YAML tokenization. |
|
Package line provides abstractions for line-by-line go-yaml Token processing.
|
Package line provides abstractions for line-by-line go-yaml Token processing. |
|
Package paths builds YAML paths that distinguish between keys and values.
|
Package paths builds YAML paths that distinguish between keys and values. |
|
Package position provides 0-indexed coordinates for locating and spanning regions within text documents.
|
Package position provides 0-indexed coordinates for locating and spanning regions within text documents. |
|
Package schema provides common types for JSON Schema operations.
|
Package schema provides common types for JSON Schema operations. |
|
generator
Package generator creates JSON schemas from Go types, bridging Go struct definitions to JSON Schema for YAML validation workflows.
|
Package generator creates JSON schemas from Go types, bridging Go struct definitions to JSON Schema for YAML validation workflows. |
|
validator
Package validator validates YAML data against JSON Schema and returns errors with precise source locations for rich error display.
|
Package validator validates YAML data against JSON Schema and returns errors with precise source locations for rich error display. |
|
Package style provides a hierarchical styling system for YAML syntax highlighting.
|
Package style provides a hierarchical styling system for YAML syntax highlighting. |
|
theme
Package theme provides a catalog of pre-built color themes for YAML syntax highlighting.
|
Package theme provides a catalog of pre-built color themes for YAML syntax highlighting. |
|
Package tokens provides segmentation for multiline YAML tokens and utilities for syntax highlighting.
|
Package tokens provides segmentation for multiline YAML tokens and utilities for syntax highlighting. |



