0
0
forked from toolshed/abra

chore: go mod vendor / tidy

This commit is contained in:
2025-01-03 20:21:06 +01:00
parent a379b31a19
commit b9f2d1f568
182 changed files with 184390 additions and 209 deletions

View File

@ -0,0 +1,101 @@
// Package prnt provides common functionality for code generators.
package prnt
import (
"bytes"
"fmt"
"go/build/constraint"
"io"
"strings"
)
// Generator provides convenience methods for code generators. In particular it
// provides fmt-like methods which print to an internal buffer. It also allows
// any errors to be stored so they can be checked at the end, rather than having
// error checks obscuring the code generation.
type Generator struct {
buf bytes.Buffer
level int // current indentation level
indent string // indentation string
pending bool // if there's a pending indentation
err error // saved error from printing
}
// Raw provides direct access to the underlying output stream.
func (g *Generator) Raw() io.Writer {
return &g.buf
}
// SetIndentString sets the string used for one level of indentation. Use
// Indent() and Dedent() to control indent level.
func (g *Generator) SetIndentString(indent string) {
g.indent = indent
}
// Indent increments the indent level.
func (g *Generator) Indent() {
g.level++
}
// Dedent decrements the indent level.
func (g *Generator) Dedent() {
g.level--
}
// Linef prints formatted output terminated with a new line.
func (g *Generator) Linef(format string, args ...any) {
g.Printf(format, args...)
g.NL()
}
// Printf prints to the internal buffer.
func (g *Generator) Printf(format string, args ...any) {
if g.err != nil {
return
}
if g.pending {
indent := strings.Repeat(g.indent, g.level)
format = indent + format
g.pending = false
}
_, err := fmt.Fprintf(&g.buf, format, args...)
g.AddError(err)
}
// NL prints a new line.
func (g *Generator) NL() {
g.Printf("\n")
g.pending = true
}
// Comment writes comment lines prefixed with "// ".
func (g *Generator) Comment(lines ...string) {
for _, line := range lines {
line = strings.TrimSpace("// " + line)
g.Printf("%s\n", line)
}
}
// BuildConstraint outputs a build constraint.
func (g *Generator) BuildConstraint(expr string) {
line := fmt.Sprintf("//go:build %s", expr)
if _, err := constraint.Parse(line); err != nil {
g.AddError(err)
}
g.Linef(line)
}
// AddError records an error in code generation. The first non-nil error will
// prevent printing operations from writing anything else, and the error will be
// returned from Result().
func (g *Generator) AddError(err error) {
if err != nil && g.err == nil {
g.err = err
}
}
// Result returns the printed bytes. If any error was recorded with AddError
// during code generation, the first such error will be returned here.
func (g *Generator) Result() ([]byte, error) {
return g.buf.Bytes(), g.err
}

View File

@ -0,0 +1,73 @@
// Package stack provides helpers for querying the callstack.
package stack
import (
"path"
"runtime"
"strings"
)
// Frames returns at most max callstack Frames, starting with its caller and
// skipping skip Frames.
func Frames(skip, max int) []runtime.Frame {
pc := make([]uintptr, max)
n := runtime.Callers(skip+2, pc)
if n == 0 {
return nil
}
pc = pc[:n]
frames := runtime.CallersFrames(pc)
var fs []runtime.Frame
for {
f, more := frames.Next()
fs = append(fs, f)
if !more {
break
}
}
return fs
}
// Match returns the first stack frame for which the predicate function returns
// true. Returns nil if no match is found. Starts matching after skip frames,
// starting with its caller.
func Match(skip int, predicate func(runtime.Frame) bool) *runtime.Frame {
i, n := skip+1, 16
for {
fs := Frames(i, n)
for j, f := range fs {
if predicate(f) {
return &fs[j]
}
}
if len(fs) < n {
break
}
i += n
}
return nil
}
// Main returns the main() function Frame.
func Main() *runtime.Frame {
return Match(1, func(f runtime.Frame) bool {
return f.Function == "main.main"
})
}
// ExternalCaller returns the first frame outside the callers package.
func ExternalCaller() *runtime.Frame {
var first *runtime.Frame
return Match(1, func(f runtime.Frame) bool {
if first == nil {
first = &f
}
return pkg(first.Function) != pkg(f.Function)
})
}
func pkg(ident string) string {
dir, name := path.Split(ident)
parts := strings.Split(name, ".")
return dir + parts[0]
}