vuka

package module
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Oct 10, 2026 License: MIT Imports: 10 Imported by: 0

README

Vuka

Vuka

Docs: vuka-lang.github.io/vuka

Vuka is Go with Result and Option, ? error propagation, pattern matching, function and method overloading, typed attributes, decorators, and JSX components rendered by templ, with Elixir-style multi-clause functions on the way. It transpiles to plain Go and builds with the go command you already have.

func area(c Circle) float64 { return math.Pi * c.R * c.R }

@export("RectArea")
func area(r Rect) float64 { return r.W * r.H }

func (c *Counter) Add(by int)    { c.n += by }
func (c *Counter) Add(by string) { c.n += len(by) }

@cache.Memo{TTL: 5 * time.Minute}
func lookup(id int) User { … }
func lookup(arg string) Result[User] {
	id := strconv.Atoi(arg)?          // Go's (T, error) works directly
	u := find(id)?
	return Ok(u)
}

match lookup(arg) {
case Ok(u):
	fmt.Println(u.Name)
case Err(&NotFound{ID: id}):
	fmt.Println("missing user", id)
case Err(e) if errors.Is(e, strconv.ErrSyntax):
	fmt.Println("not a number:", arg)
case Err(e):
	fmt.Println("error:", e)
}
go install github.com/vuka-lang/vuka/cmd/vuka@latest
vuka new hello && cd hello && vuka run .

A Vuka project is a Go module: .vuka and .go files sit side by side in the same packages and call each other, the way Kotlin and Java share a project. Dependencies are Go's: go get a module and import it from any .vuka file.

Editors

vuka lsp is a language server for .vuka files: gopls behind a proxy that keeps the generated Go open in gopls as unsaved buffers (nothing is written to your tree) and maps every position both ways. Completion, hover, signature help, go to definition, references, rename, outline, code actions, inlay hints and formatting (vuka fmt) all work; Vuka's own errors and Go's type errors show on the .vuka lines. Overloads show under the name you wrote (area, not area__Circle).

  • VS Code: the extension in editors/vscode (npm install && npx vsce package, then install the .vsix). It offers to serve your Go files too: run as gopls (a link the extension makes, set as the Go extension's go.alternateTools.gopls), vuka is a drop-in gopls, so .go files in a package with .vuka files see their code instead of "undefined" errors. Both servers use one shared gopls daemon (gopls -remote=auto), so the work is done once.
  • Any other editor: run vuka lsp over stdio for the vuka file type (needs gopls: go install golang.org/x/tools/gopls@latest).

Built to track Go

Vuka owns only its additions. Each one is found by go/scanner and lowered to Go in place; everything else passes through untouched, to be parsed and type-checked by the standard library's go/parser and go/types. When Go adds syntax, Vuka already accepts it.

  • Install Vuka with your own toolchain (go install, or go get -tool and go tool vuka). Its parser is the stdlib of the Go that built it, so it matches yours.
  • TestStdlibPassesThrough feeds every file of $GOROOT/src through Vuka and requires byte-identical output. Run it on a new Go release to find out what, if anything, has to change.
  • The generated code is plain Go; its only runtime is the small Result/Option package. //line directives point compile errors and panics at the .vuka source, down to the column.

What works

Result and Option live in the runtime package github.com/vuka-lang/vuka (its root; nothing else in it). Vuka code writes Result[User], Ok(u), Err(e), Some(x) and None unqualified, and the transpiler adds the import wherever the package doesn't declare those names itself. Err and None take their type from where the value goes (return Err(e) in a function returning Result[User]). Result's error is Go's error, so it meets Go code halfway: vuka.Of(os.ReadFile(p)) wraps a Go call, r.Get() hands back (T, error). Your module needs the dependency: go get github.com/vuka-lang/vuka.

? ends a statement: x := f()?, x = f()?, var x = f()?, return f()? or f()?. The operand is Go's (T…, error), an error, a Result, or an Option (in a function returning an Option). On failure the function returns: zero values plus the error, Err(e), or None, whichever its results call for. The operand stays where it is, so nothing is reordered.

match is a statement of cases, tried in order:

pattern matches
_, default anything
x anything, binding it to x (a constant's name compares instead)
0, "a", Max, pkg.Const, true an equal value
^x the value of the variable x (Elixir's pin)
Ok(p), Err(p), Some(p), None a Result or Option, then p inside
T{F: p, …}, &T{…} a struct's fields; against an interface, a type test too
1, 2, 3 any of them

case p if cond: adds a guard. A match must be exhaustive (Ok and Err, Some and None, true and false, or a case that takes anything), and a case after one that matches everything is an error; both are reported before Go sees the code.

Overloading. Functions and methods may share a name when their parameter types differ. Each declaration is renamed (area__Circle, Add__int_int), and each call goes to the overload that best fits its arguments' static types: identical types beat an untyped constant's default type, which beats any other assignable value. A tie is a compile error that lists the candidates. Calls whose argument types come from other overloaded calls resolve too.

Attributes come before a top-level declaration:

@doc("…") becomes the declaration's doc comment
@deprecated("…") adds a Deprecated: paragraph
@export("Name") generates Name, a wrapper with the declaration's signature: how Go code reaches one overload
@T / @pkg.T{…} any Go type, bare or as a composite literal; the generated code type-checks it

Decorators wrap a declaration, Python-style. The simplest kind works on any function, whatever its signature:

decorator logged(c) {
	fmt.Println("calling", c.Name, c.Args)
	c.Next()                                   // run the function (or the next decorator)
	fmt.Println("returned", c.Results)
}

decorator retry(times int)(c) {             // with parameters
	for i := 0; i < times; i++ {
		if c.Next(); c.Err() == nil {
			return
		}
	}
}

@retry(3)
@logged
func charge(ctx context.Context, id int) (Receipt, error) { … }

@logged
func (s *Store) Save(u User) error { … }   // methods too

decorator name(c) { … } is shorthand for func name(c *vuka.Call), a vuka.Decorator; plain Go functions of that type work the same, in .vuka or .go files. A decorator with parameters (retry(3)) is built once per decorated function, so state it keeps (a cache, a counter) isn't shared.

*vuka.Call
c.Name, c.Receiver "main.charge"; the receiver of a method
c.Args, c.Results arguments (change them before Next) and results
c.Next() run the rest; call it again to retry, or not at all
c.Return(v…) answer without running the function (caches, mocks)
c.Err(), c.SetErr(err) the trailing error result
c.Context() the context.Context argument
vuka.Arg[T](c, i) argument i as a T
c.Attr(&x), vuka.AttrOf[T](c) a typed attribute on the same declaration
@Perm("orders.write")
@guard                                      // reads it: var p Perm; c.Attr(&p)
func save(ctx context.Context, o Order) error { … }

A type decorator receives the type: func Model(t *vuka.Type) gets t.Name, t.Reflect and t.Attr, at init. Packing a call into a *vuka.Call costs a small allocation; for hot paths, a typed decorator func(F) F (or for a type, a generic func[T]) has none and checks every type. Vuka picks the form from the decorator's type, so both mix freely, and a decorator that fits neither is a compile error on its @ line. Functions keep their name for a wrapper that builds the decorated function once; recursion goes through it; init, overloads, generic functions and type ( … ) groups can be decorated.

Static fields and methods belong to a type, as in Kotlin or Java:

type User struct {
	Name string

	static Table   = "users"
	static created int            // private: lowercase, as in Go
	static const Max = 100
}

func User.New(name string) *User {
	User.created++
	return &User{Name: name}
}

u := User.New("ada")
fmt.Println(User.Table, User.Max)

They lower to plain package-level Go: User_Table, _User_created, func User_New, which is also how Go code reaches them. A static can't share a name with a field or method (in Go, User.Save already means a method).

A static on a generic type has one value per instantiation, and statics are reached through embedding. With a base type whose type parameter is named Self, Vuka fills in the embedding type, and methods taking self *Self get the whole outer value. That's enough for a Django-style model API:

// package orm
type Model[Self any] struct {
	static Objects = Manager[Self]{}
}

func (m *Model[Self]) Save(self *Self, ctx context.Context) error { … }

// your models
type User struct {
	orm.Model               // = orm.Model[User]
	Name string
}

users := User.Objects.All(ctx)   // the User manager, from orm.Model
err := u.Save(ctx)               // Save gets u itself as self

orm.Model[User] written out works the same. Self is filled in only for a type parameter of that name, so other generics never get a type argument you didn't write. A type embedding User reaches User's statics, as Go promotes fields; self there is the embedded User. Calls that pass self must not have side effects in the receiver expression (Vuka uses it twice).

Dependency injection comes from a type decorator, with no annotations on fields: a struct's fields are its dependencies.

@di.Component
type OrderService struct {
	db    *DB
	users *UserService
	mu    sync.Mutex `inject:"-"`   // not a dependency
}

A type decorator func(t *vuka.Type) on a struct gets t.New, a constructor taking each injected field as a parameter, func(db *DB, users *UserService) *OrderService: the shape nexus.Provide, fx.Provide and dig.Provide take, so a container wires it from parameter types, with no reflection on fields (and unexported fields work). Every field is injected except _, those tagged inject:"-", and embedded values (embedded pointers and interfaces are). A struct that declares its own static New is built with that instead; otherwise the generated constructor is its static New, handy in tests: OrderService.New(fakeDB, fakeUsers). t.Fields lists the fields with their tags and whether they're injected.

The whole nexus integration is a few lines (examples/nexus-di):

var providers []any

func Component(t *vuka.Type) { providers = append(providers, t.New) }
func Module() nexus.Option  { return nexus.Provide(providers...) }

CLI

vuka new <dir> [module path]
vuka mod tidy|why|vendor|… [args]
vuka explain [-full] file.vuka
vuka fix [-n] [fixer…]
vuka fmt [-l] [-w] [-d] [paths…]
vuka build|run|test|vet|install [go flags] [packages]
vuka gen [-check] [-o build]
vuka gen -inplace [-check] [dir | dir/...]
vuka lsp

build, run and the rest transpile the module into a temporary overlay (go build -overlay), so no generated file lands among your sources.

vuka explain file.vuka shows each line Vuka rewrites beside the Go it becomes, then the code it adds after the source (decorator wrappers, statics), each labelled with the line it comes from; -full prints the whole generated file.

vuka fmt formats .vuka files the way gofmt formats Go (-w writes them back, -l lists those that differ, -d shows the diff): the Go exactly as gofmt prints it, Vuka's syntax spaced to match, and JSX laid out Prettier-style, without changing what a page renders.

vuka fix repairs what tooling can: runtime upgrades the module's Vuka runtime when generated code needs a newer one, static-names rewrites statics spelt by their Go names (User_Table) to User.Table in .vuka files, and orphans removes files vuka gen -inplace wrote for .vuka files that are gone, and attr-of renames vuka.Attr[T](c) to vuka.AttrOf[T](c) (v0.5.0). -n reports without changing anything; name fixers to run only those. It is also where future syntax changes will get their codemods.

Components and JSX. Markup is an expression, and a component is a function returning a vuka.Node, which is templ.Component:

func PetRow(pet Pet) vuka.Node {
	return <tr><td>{pet.Name}</td><td>{pet.Age}</td></tr>
}

func Page(pets []Pet) vuka.Node {
	return <Shell title="Pets">                      // a templ component
		<table>{for _, p := range pets { <PetRow pet={p} /> }}</table>
	</Shell>
}

Attributes bind to parameters by name (or to a props struct's fields), children to a children parameter; {for}, {if} and {match} blocks hold markup. .templ files compile with the package, no templ generate, and call Vuka components back. vuka.Handler/Write/String render HTML; vuka/term renders the same tree as terminal text. See Components and JSX.

The build module

Like Kotlin's build/, vuka build and vuka gen keep a build/ directory: a complete Go module with the same module path, where every .vuka file is replaced by its generated Go and everything else is copied (.go files, embedded assets, testdata; relative replace paths in go.mod adjusted). Inside it, plain Go tools need no Vuka at all:

vuka gen
cd build && go build ./... && go test ./... && go vet ./...

The sync is incremental (only changed files are written, deleted sources are removed), compile errors in build/ point at the .vuka lines, and a .vuka-build marker means vuka never syncs over a directory it didn't make. vuka new adds /build/ to .gitignore. vuka gen -check fails when build/ is out of date, for CI.

Roadmap

  1. Enums (sum types) with exhaustive match; lambdas, ?., ??, tuples, functional helpers (the rest of Dingo's set)
  2. Multi-clause functions with patterns and guards; arity overloading for default arguments; Elixir-style module attributes (@max 3, read as @max)
  3. @derive and generator attributes; lowering to native Go when a Go release adds an equivalent feature

Libraries

Other modules go get your repository root, not build/. To publish a Vuka library for Go users, write the generated files beside the sources and commit them (vuka gen -inplace, and vuka gen -inplace -check in CI).

Known limits

  • Overloads are resolved within a package; calling another package's overloads goes through its @export names.
  • Generic functions can't be overloaded yet.
  • Go's own error messages show mangled names (area__int).
  • An overloaded method can't satisfy an interface method of the plain name.
  • ? ends a statement; it can't sit inside a larger expression, or in an if, for or switch header.
  • Struct patterns of generic types aren't supported yet.

Documentation

Overview

Package vuka is the runtime of Vuka programs: Result and Option.

Vuka code writes Result[User], Ok(u), Err(e), Some(x) and None unqualified; the transpiler points them here. Go code uses the package like any other.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Arg added in v0.2.0

func Arg[T any](c *Call, i int) T

Arg is argument i as a T.

func As added in v0.2.0

func As[T any](v any) T

As converts a value held in an any back to T; nil is T's zero value. It panics, naming both types, when a decorator put something else there.

func AttrOf added in v0.5.0

func AttrOf[T any](c *Call) (T, bool)

AttrOf is the declaration's typed attribute of type T.

func Handler added in v0.5.0

func Handler(f func(r *http.Request) (Node, error)) http.Handler

Handler serves the Node f builds for each request through templ.Handler: rendered in full with the request's context, then sent as text/html. An error from f or from rendering answers 500 with only the status text.

func Instance

func Instance[F any](s *Instances, build func() F) F

Instance returns the instantiation of a generic decorated function whose type is F, building it the first time.

func String added in v0.5.0

func String(ctx context.Context, n Node) (string, error)

String renders n as HTML into a string.

func Void added in v0.5.0

func Void(tag string) bool

Void reports whether tag is a void element: no children, no closing tag.

func Walk added in v0.5.0

func Walk(ctx context.Context, n Node, r Renderer) error

Walk sends n's tree to r. Groups, Builders and Child conversions are flattened (r never sees them); a TryNode with an error stops the walk with it; a Boundary walks its children into a recording first, and replays it into r — or, when they fail, walks Fallback(err) instead, so r never sees the failed part. Inside a Boundary an opaque Node is rendered while recording and replayed as Opaque of its HTML (a RawHTML). Children on a void element are an error. The first error from r stops the walk.

func Write added in v0.5.0

func Write(w http.ResponseWriter, r *http.Request, n Node) error

Write renders n with r's context and sends it as text/html (unless a Content-Type is set already). The page is rendered in full first, so a render error is returned with nothing written.

Types

type Attr added in v0.2.0

type Attr struct {
	Name  string
	Value any
}

Attr is one attribute of an element. In HTML it renders the way templ renders the same attribute written as an expression:

  • nil and false omit it, true writes it bare;
  • class takes a string or anything templ.Classes does ([]string, map[string]bool, templ.KV, …);
  • style takes a Style or anything templ's style attributes do, sanitized by templ (an unsafe property or value becomes templ's placeholder);
  • href on a and link, action on form and data on object are URLs: templ.URL keeps relative URLs and http, https, mailto, tel, ftp and ftps, and turns anything else into about:invalid#TemplFailedSanitizationURL; a templ.SafeURL passes as is. Like templ, other attributes (img src, …) aren't URL-checked;
  • a templ.ComponentScript writes its Call; a Node is rendered and escaped; anything else goes through fmt.Sprint and is escaped (templ.ResolveAttributeValue).

className and htmlFor name class and for. Names must be letters, digits, - _ : and . (templ only ever sees literal names; here a dynamic one could smuggle in another attribute), else Render fails.

type Boundary added in v0.5.0

type Boundary struct {
	Fallback func(err error) Node
	Children []Node
}

Boundary renders Children or, when one of them fails, Fallback(err) in place of everything they produced.

func (Boundary) Render added in v0.5.0

func (n Boundary) Render(ctx context.Context, w io.Writer) error

type Builder added in v0.5.0

type Builder func(add func(Node))

Builder produces children as it runs: a loop, if or match block. It runs once per Render or Walk, each added child rendered as it is added.

func (Builder) Render added in v0.5.0

func (n Builder) Render(ctx context.Context, w io.Writer) error

type Call added in v0.2.0

type Call struct {
	Name     string
	Receiver any   // the receiver, for a method
	Args     []any // the arguments; a variadic parameter is one slice
	Results  []any // the results, once Next has run (or Return was called)
	// contains filtered or unexported fields
}

Call is one call of a decorated function, passed down its decorators.

func NewCall added in v0.2.0

func NewCall(fn *Func, chain []Decorator, recv any, args []any, invoke func(c *Call) []any) *Call

NewCall starts a call through chain, ending in invoke. Generated code calls it.

func (*Call) Attr added in v0.2.0

func (c *Call) Attr(ptr any) bool

Attr fills ptr with the declaration's typed attribute of ptr's element type, reporting whether there is one: var r Route; c.Attr(&r).

func (*Call) Context added in v0.2.0

func (c *Call) Context() context.Context

Context is the call's context.Context argument, or context.Background().

func (*Call) Err added in v0.2.0

func (c *Call) Err() error

Err is the function's error result, or nil.

func (*Call) Next added in v0.2.0

func (c *Call) Next()

Next runs the rest of the chain: the next decorator, or the function itself. It can be called more than once.

func (*Call) Return added in v0.2.0

func (c *Call) Return(results ...any)

Return sets the results without running the function; the rest of the chain is skipped unless Next is called.

func (*Call) Run added in v0.2.0

func (c *Call) Run()

Run runs the chain and checks what it left in Results. Generated code calls it.

func (*Call) SetErr added in v0.2.0

func (c *Call) SetErr(err error)

SetErr replaces the error result. Before Next, it makes the call fail with zero values and err.

type Decorated

type Decorated[F any] struct {
	// contains filtered or unexported fields
}

Decorated holds a decorated function, built from its decorators on first use. Vuka generates one per decorated function or method.

func (*Decorated[F]) Get

func (d *Decorated[F]) Get(build func() F) F

Get returns the decorated function, building it the first time.

type Decorator added in v0.2.0

type Decorator func(c *Call)

Decorator wraps a call of any function: it runs code around c.Next(), may change c.Args before it, read or replace c.Results after it, call it again (retries) or not at all (caches). Written once, it decorates any function or method:

func logged(c *vuka.Call) {
	fmt.Println("calling", c.Name, c.Args)
	c.Next()
}

A decorator with parameters is a function returning one; it runs once per decorated function, so state it keeps isn't shared between functions.

type Element added in v0.5.0

type Element struct {
	Tag      string
	Attrs    []Attr
	Children []Node
}

Element is an element: <Tag Attrs>Children</Tag>. A void element (br, img, input, …; see Void) has no closing tag, and children on one are an error; in HTML, html is preceded by the doctype.

Text inside script follows templ's Go expressions in a script: it is JSON-encoded (templ's runtime.ScriptContentOutsideStringLiteral), so it arrives as a quoted JS string with < > & escaped. templ has no expressions inside style; here text in a style element is written as is with "</" written "<\/", so it can't end the element.

func (*Element) Render added in v0.5.0

func (n *Element) Render(ctx context.Context, w io.Writer) error

type Field added in v0.3.0

type Field struct {
	Name     string
	Type     reflect.Type
	Tag      reflect.StructTag
	Injected bool // a parameter of New: not blank, not tagged inject:"-"
}

Field is a field of a decorated struct.

type Func added in v0.2.0

type Func struct {
	Name     string // "main.charge", "Store.Save"
	Attrs    []any  // the declaration's typed attributes
	ErrIndex int    // the trailing error result's index, or -1
	CtxIndex int    // the context.Context argument's index, or -1
	Zero     func() []any
}

Func describes a decorated function. Vuka generates one per function.

type Group added in v0.5.0

type Group []Node

Group is children with no element around them.

func (Group) Render added in v0.5.0

func (n Group) Render(ctx context.Context, w io.Writer) error

type HTMLRenderer added in v0.5.0

type HTMLRenderer struct {
	// contains filtered or unexported fields
}

HTMLRenderer is the Renderer writing HTML: what Render does. Escaping and sanitizing are templ's (see Attr and Element).

func NewHTMLRenderer added in v0.5.0

func NewHTMLRenderer(ctx context.Context, w io.Writer) *HTMLRenderer

NewHTMLRenderer is an HTMLRenderer writing to w, unbuffered; ctx renders Node attribute values.

func (*HTMLRenderer) Close added in v0.5.0

func (h *HTMLRenderer) Close(e *Element) error

func (*HTMLRenderer) Opaque added in v0.5.0

func (h *HTMLRenderer) Opaque(ctx context.Context, n Node) error

func (*HTMLRenderer) Open added in v0.5.0

func (h *HTMLRenderer) Open(e *Element) error

func (*HTMLRenderer) Raw added in v0.5.0

func (h *HTMLRenderer) Raw(html string) error

func (*HTMLRenderer) Text added in v0.5.0

func (h *HTMLRenderer) Text(s string) error

type Instances

type Instances struct {
	// contains filtered or unexported fields
}

Instances holds a generic decorated function's instantiations, each built from its decorators on first use.

type Node added in v0.5.0

type Node = templ.Component

Node is anything that renders HTML: what a JSX expression evaluates to. It is templ.Component itself, so Vuka components are templ components and templ components are Vuka children, with nothing in between.

The Nodes built here (*Element, TextNode, RawHTML, Group, Builder, TryNode, Boundary) are also a tree any Renderer can Walk; any other Node — a templ component, a NodeFunc — is opaque: it can only render HTML. Nodes are immutable values; rendering one concurrently is safe.

func Child added in v0.5.0

func Child(v any) Node

Child is a {expr} child: a Node as is, nil as nothing, an error as its message, a []Node or []any as each element in turn, anything else as Text.

func El added in v0.5.0

func El(tag string, attrs []Attr, children ...Node) Node

El is an element.

func ErrorBoundary added in v0.5.0

func ErrorBoundary(fallback func(err error) Node, children ...Node) Node

ErrorBoundary renders children, or — when one of them fails — fallback(err) in place of everything they wrote.

func Fragment added in v0.5.0

func Fragment(children ...Node) Node

Fragment renders children in order, with no element around them.

func Nodes added in v0.5.0

func Nodes(build func(add func(Node))) Node

Nodes is the children a loop, if or match block produces.

func Safe added in v0.5.0

func Safe(html string) Node

Safe is trusted HTML, written as is. Never pass it user input.

func Text added in v0.5.0

func Text(v any) Node

Text is text: v formatted like fmt.Sprint, nil as nothing.

func Try added in v0.5.0

func Try(n Node, err error) Node

Try is a (Node, error) component's result as a child.

type NodeFunc added in v0.5.0

type NodeFunc = templ.ComponentFunc

NodeFunc is a function rendering HTML: templ.ComponentFunc.

type Option

type Option[T any] struct {
	// contains filtered or unexported fields
}

Option is a value that may be absent. The zero Option is None.

func FromPtr

func FromPtr[T any](p *T) Option[T]

FromPtr is None for a nil pointer and Some(*p) otherwise.

func MapOption

func MapOption[T, U any](o Option[T], f func(T) U) Option[U]

MapOption applies f to a present value.

func None

func None[T any]() Option[T]

None is an absent value. Vuka code writes plain None; the transpiler fills in T from where the value goes.

func Some

func Some[T any](v T) Option[T]

Some is a present value.

func (Option[T]) Get

func (o Option[T]) Get() (T, bool)

Get is Go's comma-ok form: v, ok := o.Get().

func (Option[T]) IsNone

func (o Option[T]) IsNone() bool

func (Option[T]) IsSome

func (o Option[T]) IsSome() bool

func (Option[T]) String

func (o Option[T]) String() string

func (Option[T]) Unwrap

func (o Option[T]) Unwrap() T

Unwrap is the value; it panics when o is None.

func (Option[T]) UnwrapOr

func (o Option[T]) UnwrapOr(def T) T

UnwrapOr is the value, or def when o is None.

func (Option[T]) Value

func (o Option[T]) Value() T

Value is the value, or T's zero value when o is None.

type RawHTML added in v0.5.0

type RawHTML string

RawHTML is trusted HTML, written as is.

func (RawHTML) Render added in v0.5.0

func (n RawHTML) Render(ctx context.Context, w io.Writer) error

type Renderer added in v0.5.0

type Renderer interface {
	Open(e *Element) error  // before children
	Close(e *Element) error // after children (not called for void elements)
	Text(s string) error
	Raw(html string) error                    // Safe content
	Opaque(ctx context.Context, n Node) error // a component that only renders HTML (templ, NodeFunc)
}

Renderer receives a node tree in document order; Walk drives it. The HTML renderer behind every Node's Render is one; package term is another.

type Result

type Result[T any] struct {
	// contains filtered or unexported fields
}

Result is a value or an error. It is Ok when it holds no error; the zero Result is Ok with T's zero value.

func AndThen

func AndThen[T, U any](r Result[T], f func(T) Result[U]) Result[U]

AndThen chains a step that can fail.

func Err

func Err[T any](err error) Result[T]

Err is a failed Result. err must not be nil.

func Map

func Map[T, U any](r Result[T], f func(T) U) Result[U]

Map applies f to an Ok value.

func Of

func Of[T any](v T, err error) Result[T]

Of turns Go's (T, error) into a Result: vuka.Of(os.ReadFile(name)).

func Ok

func Ok[T any](v T) Result[T]

Ok is a successful Result.

func (Result[T]) Err

func (r Result[T]) Err() error

Err is the error, or nil when r succeeded.

func (Result[T]) Get

func (r Result[T]) Get() (T, error)

Get turns r back into Go's (T, error).

func (Result[T]) IsErr

func (r Result[T]) IsErr() bool

func (Result[T]) IsOk

func (r Result[T]) IsOk() bool

func (Result[T]) String

func (r Result[T]) String() string

func (Result[T]) Unwrap

func (r Result[T]) Unwrap() T

Unwrap is the value; it panics when r failed.

func (Result[T]) UnwrapOr

func (r Result[T]) UnwrapOr(def T) T

UnwrapOr is the value, or def when r failed.

func (Result[T]) Value

func (r Result[T]) Value() T

Value is the value, or T's zero value when r failed.

type Static added in v0.2.0

type Static[V any] struct {
	V V
}

Static is the storage of a static field of a generic type: one per instantiation, so Model[User] and Model[Order] each have their own.

func StaticOf added in v0.2.0

func StaticOf[K, V any](s *Statics, init func() V) *Static[V]

StaticOf returns the static field of the instantiated type K, built by init on first use. Generated code calls it.

type Statics added in v0.2.0

type Statics struct {
	// contains filtered or unexported fields
}

Statics holds one generic static field's instantiations.

type Style added in v0.5.0

type Style map[string]string

Style is an inline style: style={vuka.Style{"color": "red"}}, rendered by templ as "color:red;" sorted by property, each property and value sanitized.

type TextNode added in v0.5.0

type TextNode string

TextNode is text, escaped when rendered.

func (TextNode) Render added in v0.5.0

func (n TextNode) Render(ctx context.Context, w io.Writer) error

type TryNode added in v0.5.0

type TryNode struct {
	Node Node
	Err  error
}

TryNode is a (Node, error) component's result as a child: Err fails the render, else Node renders.

func (TryNode) Render added in v0.5.0

func (n TryNode) Render(ctx context.Context, w io.Writer) error

type Type added in v0.2.0

type Type struct {
	Name    string // "main.User"
	Reflect reflect.Type
	Attrs   []any   // the declaration's typed attributes
	New     any     // the constructor, for a struct; nil otherwise
	Fields  []Field // the struct's fields
}

Type describes a decorated type, for a type decorator:

func Model(t *vuka.Type) { registry[t.Name] = t.Reflect }

For a struct, New is a constructor taking each dependency field as a parameter (or the type's own static New, when it declares one), which is the shape dependency-injection containers take:

func Component(t *vuka.Type) { providers = append(providers, t.New) }

func TypeOf added in v0.2.0

func TypeOf[T any](name string, attrs ...any) *Type

TypeOf describes T for its decorators. Generated code calls it.

func TypeWith added in v0.3.0

func TypeWith[T any](name string, ctor any, attrs ...any) *Type

TypeWith describes a struct T with its constructor. Generated code calls it.

func (*Type) Attr added in v0.2.0

func (t *Type) Attr(ptr any) bool

Attr fills ptr with the type's typed attribute of ptr's element type.

Directories

Path Synopsis
cmd
vuka command
Command vuka transpiles Vuka source to Go and runs the go command over it.
Command vuka transpiles Vuka source to Go and runs the go command over it.
vukavet module
internal
format
Package format formats Vuka source: the Go in it exactly as gofmt does, and its JSX the way Prettier lays out markup, without changing what it renders.
Package format formats Vuka source: the Go in it exactly as gofmt does, and its JSX the way Prettier lays out markup, without changing what it renders.
load
Package load finds Vuka packages in a module and supplies what transpiling them needs from the go command: build-context file selection, export data for imports, and the overlay that puts generated files in front of the compiler.
Package load finds Vuka packages in a module and supplies what transpiling them needs from the go command: build-context file selection, export data for imports, and the overlay that puts generated files in front of the compiler.
Package templx passes children to templ components.
Package templx passes children to templ components.
Package term renders a vuka Node tree as terminal text: headings, paragraphs word-wrapped at a width, lists, tables, quotes, code, links, and inline bold/italic/underline as ANSI styles when Color is on.
Package term renders a vuka Node tree as terminal text: headings, paragraphs word-wrapped at a width, lists, tables, quotes, code, links, and inline bold/italic/underline as ANSI styles when Color is on.
Package transpile turns Vuka source into Go.
Package transpile turns Vuka source into Go.

Jump to

Keyboard shortcuts

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