Help us shape the future of Go! Take the 2026 Go Developer Survey

script

package
v0.13.1 Latest Latest
Warning

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

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

Documentation

Overview

Package script runs user Go scripts with the yaegi interpreter, exposing the sdb API plus the Go standard library.

Index

Constants

View Source
const (
	SevError   = "error"
	SevWarning = "warning"
)

The two severities. An error means Run would fail (or never start); a warning is legal Go that probably does not do what was meant.

View Source
const NotOnSymbol = "rename works on a name the script declares: a variable, constant, type, function, method, field, label or import"

NotOnSymbol is the sentence for a caret on nothing renamable, shared with the editor's rename box so both say it in the same words.

Variables

This section is empty.

Functions

func FitPluginName added in v0.13.0

func FitPluginName(text, file string, taken func(name string) bool) (out, from, to string)

FitPluginName returns text with its Plugin.Name rewritten to file's own name when the Name it has is taken (taken: another plugin, built in or a file's, already has it); from and to say what changed, both "" when nothing did. The new name is made free with -2, -3 … when the file's own is taken too.

func HasError added in v0.9.0

func HasError(diags []Diag) bool

HasError reports whether any diag is an error rather than a warning.

func LoadPluginFile added in v0.13.0

func LoadPluginFile(path string) *pipeline.PluginProblem

LoadPluginFile loads one plugin file on its own — compiled, var Plugin read and checked, its funcs bound — without registering it, and says why it cannot be a plugin, or nil. Its name is checked against the built-ins, not against other plugin files. For `dbc plugins --check`.

func LoadPlugins added in v0.13.0

func LoadPlugins(dir string) []pipeline.PluginProblem

LoadPlugins loads every plugin file in dir now, whatever changed, and returns the files that did not load. A missing directory is no plugins and no problem.

func PluginNameFor added in v0.13.0

func PluginNameFor(file string) string

PluginNameFor is the plugin name a file's name suggests, as the examples pair them: the stem, its underscores as dots ("mask_email.go" → "mask.email", "gen_series-2.go" → "gen.series-2"). A stem that would make no valid name (a trailing "_") keeps its underscores.

func PluginNameTaken added in v0.13.0

func PluginNameTaken(name string) bool

PluginNameTaken says whether a plugin is already called name: one built into dbc, one a file loaded, or one a file declares that did not load (its problem names it), which would take the name back once fixed. The hosts' taken for FitPluginName.

func Run

func Run(path string, s *sdb.S) error

Run interprets the Go script at path and invokes its Run(s *sdb.S) error.

func RunSource added in v0.9.0

func RunSource(name, src string, s *sdb.S) error

RunSource is Run for a script that is text rather than a file: a sample built into the binary, run by `dbc script NAME` without being copied out first. name stands in for the path in errors.

func SyncPlugins added in v0.13.0

func SyncPlugins(dir string) bool

SyncPlugins loads the plugin files in dir when the directory changed since the last load (or nothing was loaded yet, or dir is another directory), and reports whether it did. Cheap when nothing changed: one directory read and a stat per file.

func WrapSnippet added in v0.13.0

func WrapSnippet(code string) (src string, headerLines int)

WrapSnippet makes a whole script of a snippet: with a package clause it is returned as it is (and headerLines is 0); without one, "package main" and an import block of the known packages it names go before it, and headerLines says how many lines that added, so a diag's line can be mapped back to the snippet's. A snippet that does not parse gets every known import, and the compile pass says what is wrong.

Types

type Diag added in v0.9.0

type Diag struct {
	Line     int    `json:"line"`
	Col      int    `json:"col"`
	Severity string `json:"severity"` // SevError or SevWarning
	Msg      string `json:"msg"`
}

Diag is one problem Check found, at a 1-based line and column (column 0 when only the line is known).

func Check added in v0.9.0

func Check(name, src string) []Diag

Check finds what is wrong with a script without running it, so an editor can mark errors on their lines as the user types, and `dbc script --check` can gate a scripts repo in CI. It never executes the script: not Run, not init(), not a package-level initializer.

src ─► 1. parse (go/parser) ── syntax errors? ──► those, and stop
        │                                         (the passes below need a tree)
        ├► 2. signature: package main, func Run(s *sdb.S) error, from the AST
        ├► 3. lint: m[k], _ = …  (yaegi drops the write)
        └► 4. compile (yaegi, newInterp + Compile, no Execute)

Why each pass:

  1. go/parser first, because its positions are exact and it reports up to ten errors; yaegi stops at its first and words it less helpfully.
  2. Run's signature from the AST, not the interpreter: asking yaegi for main.Run needs Execute first, which runs init() and the package's var initializers — exactly what a check must never do.
  3. The lint is the one case that has cost real time: yaegi compiles and runs a two-value assignment into a map element and stores nothing (traefik/yaegi#1655). Without types it cannot tell a map from a slice, so it flags both and says so; a slice there is rare.
  4. yaegi's compile pass (type analysis and control flow, no code run) catches what the parser cannot: an undefined name, a type mismatch, an import a script cannot have. It is the same interpreter Run builds (newInterp), so the two agree on what a script may import. It reports only its first error, and does not catch everything the Go compiler would (an unused variable passes).

Diags come back sorted by position. A clean script is nil.

func CheckPlugin added in v0.13.0

func CheckPlugin(name, src string) []Diag

CheckPlugin finds what is wrong with a plugin file without running it — the plugin file's script.Check, for the web's markers, the TUI's check when $EDITOR exits and `dbc plugins --check`:

  1. parse syntax errors (and stop)
  2. shape, from the AST package main; var Plugin = sdb.Plugin{…}; its Name and Kind when written as literals; the funcs that Kind calls, with their signatures
  3. lint m[k], _ = … (yaegi drops the write)
  4. compile yaegi's compile pass: undefined names, types

Like Check it never executes the file — not var Plugin's initializer either — so what it can say about the descriptor is what the source spells out literally; the loader, which does run it, has the last word.

func (Diag) String added in v0.9.0

func (d Diag) String() string

String is the diag as a compiler prints one, after the file name: "12:5: undefined: foo", with "warning: " before a warning's message.

type Edit added in v0.12.0

type Edit struct {
	From int    `json:"from"`
	To   int    `json:"to"`
	Text string `json:"text"`
}

Edit replaces [From, To) of the script with Text. From == To inserts.

func Rename added in v0.12.0

func Rename(text string, caret int, name string) (edits []Edit, err error)

Rename is the edits that rename the symbol at byte offset caret of src to name. The error is a sentence for the user: nothing renamable there, the symbol cannot be renamed (Symbol.Fixed), the name is not a Go name, or the renamed script would mean something else.

A snippet (a pipeline's go field) is renamed in as its node runs it, with WrapSnippet's header before it (symbol.go, A SNIPPET); the edits come back in the snippet's own offsets.

type Span added in v0.11.0

type Span struct {
	From int `json:"from"`
	To   int `json:"to"`
}

Span is a byte range of the script, [From, To).

type Symbol added in v0.11.0

type Symbol struct {
	Kind string `json:"kind"` // var, const, type, func, method, field, package, label, builtin
	Name string `json:"name"`
	At   Span   `json:"at"`  // the occurrence under the caret
	Def  *Span  `json:"def"` // nil: declared outside the script
	Uses []Span `json:"uses"`
	// Fixed says why F2 cannot rename it; "" when it can (rename.go).
	Fixed string `json:"fixed,omitempty"`
}

Symbol is what the caret is on. Kind "" means nothing that resolves (a keyword, a literal, white space): the editor has nowhere to go. Def is nil when the declaration is not in the script (a builtin such as len or error, or a member of an imported package); Uses then still lists every occurrence. Uses includes the declaration itself, in buffer order.

func Resolve added in v0.11.0

func Resolve(src string, caret int) (sym Symbol)

Resolve finds the symbol at byte offset caret of src. A caret just past a name (where it rests after typing one) counts as on it.

A script with syntax errors still resolves: go/parser hands back the tree it could build, and the checker binds what is in it. A panic deep in the checker over odd input is a symbol with no kind, never a crash of the server that asked.

Jump to

Keyboard shortcuts

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