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

script

package
v0.2.6 Latest Latest
Warning

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

Go to latest
Published: Aug 15, 2026 License: Apache-2.0 Imports: 2 Imported by: 0

Documentation

Overview

Package script turns a .rysh file — a bash script whose statement-position "##" lines are rysh commands — into plain bash (design 021).

The whole design rests on one property of bash: "#" opens a comment at the start of any WORD, not just a line. That means a file full of "##pane info" lines is already a valid bash script in which those lines do nothing, so the same file can be read by bash and by rysh. It also means "##" can only ever appear in statement position: `X=$(##pane info)` is not a comment, it is an unterminated `$(` — a hard syntax error. So there is no expression form, and capture happens through $RYSH_OUT instead (see Prelude).

Transpiling to bash rather than interpreting the file ourselves is what keeps the language honest. Every construct bash has — loops, conditionals, functions, quoting, heredocs, pipes, `set -e`, traps, `$?` — keeps working because bash is still the thing running the script. An interpreter of our own would have to re-implement all of it, and would be subtly wrong about heredocs and multi-line constructs forever.

Index

Constants

View Source
const PromptCommand = "prompt"

PromptCommand is the one command word that is a SCRIPT builtin rather than an entry in the daemon's ## dispatch table.

It cannot be a table command: running it means waiting for an agentic turn to finish, and the table's handlers run inside the WorkspaceActor, where blocking would freeze the whole workspace. So `##prompt refactor the parser` compiles to a call to `rysh prompt`, which watches the pane's phase events from outside the actor and blocks there instead.

Spelling it "##prompt" rather than making scripts call `rysh prompt` directly is what keeps the polyglot property: a "##" line is a comment to bash, so the file still parses and still runs with the rysh work skipped. A bare `rysh prompt ...` line would be a command plain bash would try — and fail — to run.

View Source
const PromptFunc = "__rysh_prompt"

PromptFunc is the shell function `##prompt <text>` is rewritten into.

View Source
const RyshFunc = "__rysh"

RyshFunc is the shell function a rysh line is rewritten into. It is defined by Prelude.

View Source
const Version = "1"

Version is exported to scripts as $RYSH_SCRIPT_VERSION so a script can detect what contract it is running under. Bump it when the prelude's observable behaviour changes.

Variables

This section is empty.

Functions

func Prelude

func Prelude(bodyPath string) string

Prelude renders the bash that defines RyshFunc and then sources the transpiled body.

It is a SEPARATE file that sources the script rather than a header prepended to it, and that is load-bearing: prepending would shift every line number, so a bash syntax error or `set -x` trace would name a line the author never wrote. Sourcing resets $LINENO and $BASH_SOURCE to the sourced file, so diagnostics read exactly as if bash had run the .rysh directly. Verified: a syntax error on line 5 of the body reports "<name>.rysh: line 5".

The __rysh body has one subtlety worth the comment it carries: `local x=$(…)` returns local's status, not the command's. Written that way, every exit code in the language would silently be 0 — the single most destructive bug this file could have — so the declaration and the assignment are separate statements.

Types

type Error

type Error struct {
	Line int
	Msg  string
}

Error is a transpile failure tied to a source line.

func (*Error) Error

func (e *Error) Error() string

type Result

type Result struct {
	// Bash is the transpiled source. It has exactly as many lines as the input
	// (see the package doc on line fidelity).
	Bash string
	// RyshLines are the 1-based source line numbers that were rewritten.
	RyshLines []int
}

Result is a transpiled script.

func Transpile

func Transpile(src string) (*Result, error)

Transpile rewrites the "##" lines of src into calls to RyshFunc.

Line fidelity is an invariant, not an aspiration: every source line produces exactly one output line, so bash's own diagnostics, `set -x` traces and $LINENO all point at the real line of the .rysh file. Nothing may be inserted — which is why the prelude is a separate file that sources this one rather than a header prepended to it.

Jump to

Keyboard shortcuts

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