Documentation
¶
Index ¶
- Constants
- Variables
- func AbsFloat(x float64) float64
- func AbsInt(x int64) int64
- func AddInternalFuncs()
- func BuildDocsFull() string
- func BuildDocsTOC() string
- func CalculateCorrectedIndex(rawIdx, length int64, clamp bool) int64
- func ErrIndexOutOfBounds(i *Interpreter, node rl.Node, idx int64, length int64)
- func ExitCodeFor(name string) int
- func FuzzyMatchFold(source, target string) bool
- func GetDocFuncs() []string
- func GetDocPage(slug string) (string, bool)
- func GetDocSlugs() []string
- func GetDocTopic(topic string) (string, bool)
- func GetEmbeddedCommandSrc(name string) *string
- func GetEnumColor(value string, possibleSortedValues []string) (r, g, b int, err error)
- func GetErrorDoc(code string) string
- func GetFuncDoc(name string) (string, bool)
- func GetInvocationLogPath() string
- func GetInvocationLogsDir() string
- func GetTermWidth() int
- func InputConfirm(title string, prompt string) (bool, error)
- func IsTerminatingSignal(name string) bool
- func IsWindows() bool
- func JsonToString(jsonVal interface{}) string
- func Levenshtein(a, b string) int
- func ListErrorCodes() []string
- func LoadPickResource(i *Interpreter, callNode rl.Node, jsonPath string) (PickResource, *RadError)
- func LogInvocation(entry InvocationLogEntry)
- func MaybeRotate()
- func NormalizeLineEndings(s string) string
- func NormalizePath(path string) string
- func ParseDuration(s string) (time.Duration, error)
- func ParseDurationString(s string) (int64, error)
- func RadToJsonType(arg RadValue) interface{}
- func RegisterInvocationLogging()
- func ResetGlobals()
- func RunRepl() error
- func SetScriptPath(path string)
- func ToPrintable(val interface{}) string
- func ToPrintableQuoteStr(val interface{}, quoteStrings bool) string
- func TransformRadArgs(args []RadArg, transformer func(RadArg) string) []string
- func TypeAsString(val interface{}) string
- type ArgPrompter
- type ArgRangeConstraint
- type BaseRadArg
- func (f *BaseRadArg) Configured() bool
- func (f *BaseRadArg) DefaultAsString() string
- func (f *BaseRadArg) Excludes(otherArg RadArg) bool
- func (f *BaseRadArg) GetArgUsage() string
- func (f *BaseRadArg) GetDescription() string
- func (f *BaseRadArg) GetExternalName() string
- func (f *BaseRadArg) GetIdentifier() string
- func (f *BaseRadArg) GetShort() string
- func (f *BaseRadArg) GetSpan() *rl.Span
- func (f *BaseRadArg) HasNonZeroDefault() bool
- func (f *BaseRadArg) Hidden(hide bool)
- func (f *BaseRadArg) IsDefined() bool
- func (f *BaseRadArg) IsHidden() bool
- func (f *BaseRadArg) IsNullable() bool
- func (f *BaseRadArg) IsOptional() bool
- func (f *BaseRadArg) IsVariadic() bool
- func (f *BaseRadArg) SetBypassValidation(bypass bool)
- func (f *BaseRadArg) SetValue(_ string)
- type BoolListRadArg
- type BoolRadArg
- type BufferReader
- type BuiltInFunc
- type CallFrame
- type Capture
- type CheckableReader
- type Clock
- type CodeCtx
- type ColumnSort
- type ConstraintCtx
- type CtrlKind
- type DefaultReplSession
- type DeferBlock
- type Delimiter
- type Diagnostic
- type DiagnosticCollector
- func (c *DiagnosticCollector) Add(d Diagnostic) bool
- func (c *DiagnosticCollector) AtLimit() bool
- func (c *DiagnosticCollector) Count() int
- func (c *DiagnosticCollector) Diagnostics() []Diagnostic
- func (c *DiagnosticCollector) HasErrors() bool
- func (c *DiagnosticCollector) IsEmpty() bool
- func (c *DiagnosticCollector) Remaining() int
- func (c *DiagnosticCollector) TotalEmitted() int
- type DiagnosticRenderer
- type DocPage
- type EmbeddedCmd
- type Env
- func (e *Env) AllVarNames() []string
- func (e *Env) FindSimilarVars(name string, maxResults int) []string
- func (e *Env) GetJsonFieldVar(name string) (*JsonFieldVar, bool)
- func (e *Env) GetVar(name string) (RadValue, bool)
- func (e *Env) GetVarElseBug(i *Interpreter, node rl.Node, name string) RadValue
- func (e *Env) NewChildEnv() Env
- func (e *Env) PrintShellExports()
- func (e *Env) SetJsonFieldVar(jsonFieldVar *JsonFieldVar)
- func (e *Env) SetVar(name string, v RadValue)
- func (e *Env) SetVarUpdatingEnclosing(name string, v RadValue, updateEnclosing bool)
- type ErrorCtx
- type EvalResult
- type ExecutionResult
- type ExpectedOutput
- type FakeSignalSource
- func (f *FakeSignalSource) Fire(sig os.Signal)
- func (f *FakeSignalSource) FiredCount(sig os.Signal) int
- func (f *FakeSignalSource) Ignore(sigs ...os.Signal)
- func (f *FakeSignalSource) Notify(ch chan<- os.Signal, sigs ...os.Signal)
- func (f *FakeSignalSource) Stop(ch chan<- os.Signal)
- func (f *FakeSignalSource) WasIgnored(sig os.Signal) bool
- type FileReader
- type FixedClock
- type FloatListRadArg
- type FloatRadArg
- type FuncInvocation
- func (f FuncInvocation) GetArg(name string) RadValue
- func (f FuncInvocation) GetBool(name string) bool
- func (f FuncInvocation) GetFloat(name string) float64
- func (f FuncInvocation) GetFn(name string) RadFn
- func (f FuncInvocation) GetInt(name string) int64
- func (f FuncInvocation) GetIntAllowingBool(name string) int64
- func (f FuncInvocation) GetList(name string) *RadList
- func (f FuncInvocation) GetMap(name string) *RadMap
- func (f FuncInvocation) GetStr(name string) RadString
- func (f FuncInvocation) Return(vals ...interface{}) RadValue
- func (f FuncInvocation) ReturnErrf(code rl.Error, msg string, args ...interface{}) RadValue
- type GeneralSort
- type GlobalFlagScope
- type HttpRequest
- type InputReader
- type IntListRadArg
- type IntRadArg
- type InteractiveDriver
- type Interpreter
- func (i *Interpreter) CallStack() []CallFrame
- func (i *Interpreter) Checkpoint()
- func (i *Interpreter) EvaluateStatement(input string) (RadValue, error)
- func (i *Interpreter) GetScriptName() string
- func (i *Interpreter) GetSrc() string
- func (i *Interpreter) GetSrcForSpan(span rl.Span) string
- func (i *Interpreter) InitArgs(args []RadArg)
- func (i *Interpreter) InitBuiltIns()
- func (i *Interpreter) NewRadPanic(node rl.Node, err RadValue) *RadPanic
- func (i *Interpreter) RegisterWithExit()
- func (i *Interpreter) Run()
- func (i *Interpreter) Signals() *SignalManager
- func (i *Interpreter) WithTmpSrc(tmpSrc string, fn func())
- type InterpreterInput
- type InvocationLogEntry
- type InvocationLoggingConfig
- type InvocationType
- type JsonFieldVar
- type JsonPath
- type JsonPathSegment
- type JsonPathSegmentIdx
- type Label
- type MockResponse
- type MockResponseSlice
- type NullWriter
- type PickResource
- type PickResourceOpt
- type PickResourceOptionSerde
- type PickResourceSerde
- type PosArg
- type Printer
- type RadArg
- type RadArgTypeT
- type RadConfig
- type RadError
- type RadExitHandler
- type RadFn
- type RadHome
- func (r *RadHome) GetStash() *string
- func (r *RadHome) GetStashForId(id string) string
- func (r *RadHome) GetStashSub(subPath string, node rl.Node) (string, *RadError)
- func (r *RadHome) LoadState(i *Interpreter, node rl.Node) (RadValue, bool, *RadError)
- func (r *RadHome) SaveState(i *Interpreter, node rl.Node, value RadValue) *RadError
- func (r *RadHome) SetStashId(id string)
- type RadIo
- type RadList
- func (l *RadList) Append(value RadValue)
- func (l *RadList) AsActualStringList(i *Interpreter, node rl.Node) []string
- func (l *RadList) AsStringList(quoteStrings bool) []string
- func (l *RadList) Contains(val RadValue) bool
- func (l *RadList) Equals(r *RadList) bool
- func (l *RadList) IndexAt(i *Interpreter, node rl.Node, idx int64) RadValue
- func (l *RadList) IsEmpty() bool
- func (l *RadList) Join(sep string, prefix string, suffix string) RadString
- func (l *RadList) JoinWith(other *RadList) RadValue
- func (l *RadList) Len() int64
- func (l *RadList) LenInt() int
- func (l *RadList) RemoveIdx(i *Interpreter, node rl.Node, idx int)
- func (l *RadList) Reverse() *RadList
- func (l *RadList) ShallowCopy() *RadList
- func (l *RadList) SortAccordingToIndices(i *Interpreter, node rl.Node, indices []int64)
- func (l *RadList) ToGoList() []interface{}
- func (l *RadList) ToString() string
- type RadMap
- func (m *RadMap) AsErrMsg(i *Interpreter, node rl.Node) string
- func (m *RadMap) ContainsKey(key RadValue) bool
- func (m *RadMap) Delete(key RadValue)
- func (l *RadMap) Equals(right *RadMap) bool
- func (m *RadMap) Get(key RadValue) (RadValue, bool)
- func (m *RadMap) GetByKey(i *Interpreter, node rl.Node, key RadValue) RadValue
- func (m *RadMap) Keys() []RadValue
- func (m *RadMap) Len() int64
- func (m *RadMap) Range(fn func(key, value RadValue) bool)
- func (m *RadMap) Set(key RadValue, value RadValue)
- func (m *RadMap) SetPrimitiveBool(key string, value bool)
- func (m *RadMap) SetPrimitiveFloat(key string, value float64)
- func (m *RadMap) SetPrimitiveInt(key string, value int)
- func (m *RadMap) SetPrimitiveInt64(key string, value int64)
- func (m *RadMap) SetPrimitiveList(key string, value *RadList)
- func (m *RadMap) SetPrimitiveMap(key string, value *RadMap)
- func (m *RadMap) SetPrimitiveStr(key string, value string)
- func (m *RadMap) ShallowCopy() *RadMap
- func (m *RadMap) ToGoMap() map[string]interface{}
- func (m *RadMap) ToString() string
- func (m *RadMap) Values() []RadValue
- type RadNull
- type RadPanic
- type RadRunner
- type RadString
- func (s *RadString) Compare(other RadString) int
- func (s RadString) Concat(other RadString) RadString
- func (s RadString) ConcatStr(other string) RadString
- func (s RadString) CopyAttrTo(otherStr string) RadString
- func (s *RadString) CopyWithAttr(attr RadTextAttr) RadString
- func (s *RadString) DeepCopy() RadString
- func (s RadString) Equals(other RadString) bool
- func (s *RadString) Hyperlink(link RadString) RadString
- func (s *RadString) IndexAt(idx int64) RadString
- func (s RadString) Len() int64
- func (s RadString) Lower() RadString
- func (s RadString) Plain() string
- func (s RadString) Repeat(multiplier int64) RadString
- func (s *RadString) Reverse() RadString
- func (s RadString) Runes() []rune
- func (s *RadString) SetAttr(attr RadTextAttr)
- func (s RadString) SetRgb(red int, green int, blue int)
- func (s RadString) SetRgb64(red int64, green int64, blue int64)
- func (s *RadString) SetSegmentsHyperlink(link RadString)
- func (s RadString) String() string
- func (s *RadString) SubSlice(startRune, endRune int64) RadString
- func (s *RadString) ToRuneList() *RadList
- func (s *RadString) Trim(chars string) RadString
- func (s *RadString) TrimLeft(chars string) RadString
- func (s *RadString) TrimPrefix(prefix string) RadString
- func (s *RadString) TrimRight(chars string) RadString
- func (s *RadString) TrimSuffix(suffix string) RadString
- func (s RadString) Upper() RadString
- type RadTextAttr
- type RadTypeVisitor
- func (v *RadTypeVisitor) ForBool(handler func(RadValue, bool)) *RadTypeVisitor
- func (v *RadTypeVisitor) ForDefault(handler func(RadValue)) *RadTypeVisitor
- func (v *RadTypeVisitor) ForError(handler func(RadValue, *RadError)) *RadTypeVisitor
- func (v *RadTypeVisitor) ForFloat(handler func(RadValue, float64)) *RadTypeVisitor
- func (v *RadTypeVisitor) ForFn(handler func(RadValue, RadFn)) *RadTypeVisitor
- func (v *RadTypeVisitor) ForInt(handler func(RadValue, int64)) *RadTypeVisitor
- func (v *RadTypeVisitor) ForList(handler func(RadValue, *RadList)) *RadTypeVisitor
- func (v *RadTypeVisitor) ForMap(handler func(RadValue, *RadMap)) *RadTypeVisitor
- func (v *RadTypeVisitor) ForNull(handler func(RadValue, RadNull)) *RadTypeVisitor
- func (v *RadTypeVisitor) ForString(handler func(RadValue, RadString)) *RadTypeVisitor
- func (v *RadTypeVisitor) UnhandledTypeError(val RadValue)
- func (v *RadTypeVisitor) Visit(acceptor RadTypeVisitorAcceptor)
- type RadTypeVisitorAcceptor
- type RadValue
- func (v RadValue) Accept(visitor *RadTypeVisitor)
- func (left RadValue) Equals(right RadValue) bool
- func (v RadValue) GoMapKey() string
- func (v RadValue) Hash() string
- func (v RadValue) Index(i *Interpreter, node rl.Node, key RadValue) RadValue
- func (v RadValue) IsError() bool
- func (v RadValue) IsNull() bool
- func (v RadValue) ModifyByKey(i *Interpreter, node rl.Node, key RadValue, rightValue RadValue)
- func (v RadValue) RequireBool(i *Interpreter, node rl.Node) bool
- func (v RadValue) RequireError(i *Interpreter, node rl.Node) *RadError
- func (v RadValue) RequireFloatAllowingInt(i *Interpreter, node rl.Node) float64
- func (v RadValue) RequireFn(i *Interpreter, node rl.Node) RadFn
- func (v RadValue) RequireInt(i *Interpreter, node rl.Node) int64
- func (v RadValue) RequireIntAllowingBool(i *Interpreter, node rl.Node) int64
- func (v RadValue) RequireList(i *Interpreter, node rl.Node) *RadList
- func (v RadValue) RequireMap(i *Interpreter, node rl.Node) *RadMap
- func (v RadValue) RequireNonVoid(i *Interpreter, node rl.Node) RadValue
- func (v RadValue) RequireNotType(i *Interpreter, node rl.Node, errPrefix string, disallowedTypes ...rl.RadType) RadValue
- func (v RadValue) RequireStr(i *Interpreter, node rl.Node) RadString
- func (v RadValue) RequireType(i *Interpreter, node rl.Node, errPrefix string, allowedTypes ...rl.RadType) RadValue
- func (v RadValue) ToCompatSubject() (out rl.TypingCompatVal)
- func (v RadValue) ToGoValue() (out interface{})
- func (v RadValue) TruthyFalsy() bool
- func (v RadValue) TryGetBool() (bool, bool)
- func (v RadValue) TryGetError() (*RadError, bool)
- func (v RadValue) TryGetFloatAllowingInt() (float64, bool)
- func (v RadValue) TryGetFn() (RadFn, bool)
- func (v RadValue) TryGetList() (*RadList, bool)
- func (v RadValue) TryGetMap() (*RadMap, bool)
- func (v RadValue) TryGetStr() (RadString, bool)
- func (v RadValue) Type() rl.RadType
- type ReadlineInputReader
- type RealClock
- type RegistrationMode
- type ReplSession
- type RequestDef
- type Requester
- func (r *Requester) AddMockedResponse(urlRegex string, jsonPath string)
- func (r *Requester) ClearMockedResponses()
- func (r *Requester) IsInsecure() bool
- func (r *Requester) Request(ctx context.Context, def RequestDef) ResponseDef
- func (r *Requester) RequestJson(ctx context.Context, url string, insecure bool, quiet bool) (interface{}, error)
- func (r *Requester) SetCaptureCallback(cb func(HttpRequest))
- func (r *Requester) SetInsecure(insecure bool)
- type ResponseDef
- type RunnerInput
- type ScopedGlobalFlag
- type ScriptArg
- type ScriptCommand
- type ScriptData
- type Severity
- type ShellExecutor
- type ShellInvocation
- type SignalManager
- func (sm *SignalManager) ClearInHandler()
- func (sm *SignalManager) Ctx() context.Context
- func (sm *SignalManager) DrainPending() (string, bool)
- func (sm *SignalManager) Handler(name string) (RadFn, bool)
- func (sm *SignalManager) Ignore(name string) error
- func (sm *SignalManager) MarkInHandler(name string)
- func (sm *SignalManager) NotifyCh() chan<- os.Signal
- func (sm *SignalManager) RefreshCtx()
- func (sm *SignalManager) Start()
- func (sm *SignalManager) Stop()
- func (sm *SignalManager) Trap(name string, fn RadFn) error
- type SignalSource
- type SingleLineInputReader
- type SortDir
- type StringListRadArg
- type StringRadArg
- type TblWriter
- type Trie
- type TrieNode
Constants ¶
const ( EmbCmdNew = "new" EmbCmdDocs = "docs" EmbCmdHome = "home" EmbCmdGenId = "gen-id" EmbCmdStash = "stash" EmbCmdCheck = "check" EmbCmdFmt = "fmt" EmbCmdExplain = "explain" )
const ( UNREACHABLE = "Bug! This should be unreachable" NOT_IMPLEMENTED = "not implemented" NO_NUM_RETURN_VALUES_CONSTRAINT = -1 USAGE_ALIGNMENT_CHAR = "\x00" PADDING_CHAR = "\x00" )
const ( WILDCARD = "*" MACRO_STASH_ID = "stash_id" MACRO_ENABLE_GLOBAL_OPTIONS = "enable_global_options" MACRO_ENABLE_ARGS_BLOCK = "enable_args_block" )
const ( COLOR_AUTO = "auto" COLOR_ALWAYS = "always" COLOR_NEVER = "never" FLAG_HELP = "help" FLAG_H = "h" FLAG_DEBUG = "debug" FLAG_D = "d" FLAG_RAD_DEBUG = "rad-debug" FLAG_COLOR = "color" FLAG_QUIET = "quiet" FLAG_Q = "q" FLAG_SHELL = "shell" FLAG_VERSION = "version" FLAG_V = "v" FLAG_CONFIRM_SHELL = "confirm-shell" FLAG_SRC = "src" FLAG_CST_TREE = "cst-tree" FLAG_AST_TREE = "ast-tree" FLAG_RAD_ARGS_DUMP = "rad-args-dump" FLAG_MOCK_RESPONSE = "mock-response" FLAG_REPL = "repl" FLAG_R = "r" FLAG_TLS_INSECURE = "tls-insecure" FLAG_INTERACTIVE = "interactive" FLAG_I = "i" )
const ( FUNC_PRINT = "print" FUNC_PRINT_ERR = "print_err" FUNC_PPRINT = "pprint" FUNC_DEBUG = "debug" FUNC_EXIT = "exit" FUNC_SLEEP = "sleep" FUNC_SEED_RANDOM = "seed_random" FUNC_RAND = "rand" FUNC_RAND_INT = "rand_int" FUNC_REPLACE = "replace" FUNC_LEN = "len" FUNC_SORT = "sort" FUNC_NOW = "now" FUNC_PARSE_EPOCH = "parse_epoch" FUNC_PARSE_DATE = "parse_date" FUNC_TYPE_OF = "type_of" FUNC_JOIN = "join" FUNC_UPPER = "upper" FUNC_LOWER = "lower" FUNC_STARTS_WITH = "starts_with" FUNC_ENDS_WITH = "ends_with" FUNC_PICK = "pick" FUNC_PICK_KV = "pick_kv" FUNC_PICK_FROM_RESOURCE = "pick_from_resource" FUNC_MULTIPICK = "multipick" FUNC_KEYS = "keys" FUNC_VALUES = "values" FUNC_TRUNCATE = "truncate" FUNC_SPLIT = "split" FUNC_SPLIT_LINES = "split_lines" FUNC_RANGE = "range" FUNC_UNIQUE = "unique" FUNC_INDEX_OF = "index_of" FUNC_CONFIRM = "confirm" FUNC_INPUT = "input" FUNC_PARSE_JSON = "parse_json" FUNC_TO_JSON = "to_json" FUNC_PARSE_INT = "parse_int" FUNC_PARSE_FLOAT = "parse_float" FUNC_HTTP_GET = "http_get" FUNC_HTTP_POST = "http_post" FUNC_HTTP_PUT = "http_put" FUNC_HTTP_PATCH = "http_patch" FUNC_HTTP_DELETE = "http_delete" FUNC_HTTP_HEAD = "http_head" FUNC_HTTP_OPTIONS = "http_options" FUNC_HTTP_TRACE = "http_trace" FUNC_HTTP_CONNECT = "http_connect" FUNC_ABS = "abs" FUNC_POW = "pow" FUNC_ERROR = "error" FUNC_GET_PATH = "get_path" FUNC_FIND_PATHS = "find_paths" FUNC_DELETE_PATH = "delete_path" FUNC_COUNT = "count" FUNC_ZIP = "zip" FUNC_STR = "str" FUNC_INT = "int" FUNC_FLOAT = "float" FUNC_SUM = "sum" FUNC_TRIM = "trim" FUNC_TRIM_PREFIX = "trim_prefix" FUNC_TRIM_SUFFIX = "trim_suffix" FUNC_TRIM_LEFT = "trim_left" FUNC_TRIM_RIGHT = "trim_right" FUNC_READ_FILE = "read_file" FUNC_WRITE_FILE = "write_file" FUNC_READ_STDIN = "read_stdin" FUNC_HAS_STDIN = "has_stdin" FUNC_ROUND = "round" FUNC_CEIL = "ceil" FUNC_FLOOR = "floor" FUNC_MIN = "min" FUNC_MAX = "max" FUNC_MATCHES = "matches" FUNC_CLAMP = "clamp" FUNC_REVERSE = "reverse" FUNC_IS_DEFINED = "is_defined" // todo might be poorly named. should focus on vars. Or maybe just embrace works for anything, name it 'exists'? FUNC_HYPERLINK = "hyperlink" FUNC_UUID_V4 = "uuid_v4" FUNC_UUID_V7 = "uuid_v7" FUNC_GEN_FID = "gen_fid" FUNC_GET_RAD_HOME = "get_rad_home" FUNC_GET_STASH_PATH = "get_stash_path" FUNC_LOAD_STATE = "load_state" FUNC_SAVE_STATE = "save_state" FUNC_LOAD_STASH_FILE = "load_stash_file" FUNC_WRITE_STASH_FILE = "write_stash_file" FUNC_GET_ENV = "get_env" FUNC_GET_PID = "get_pid" FUNC_HASH = "hash" FUNC_ENCODE_BASE64 = "encode_base64" FUNC_DECODE_BASE64 = "decode_base64" FUNC_ENCODE_BASE16 = "encode_base16" FUNC_DECODE_BASE16 = "decode_base16" FUNC_MAP = "map" FUNC_FILTER = "filter" FUNC_FLAT_MAP = "flat_map" FUNC_LOAD = "load" FUNC_COLOR_RGB = "color_rgb" FUNC_COLORIZE = "colorize" FUNC_PARSE_DURATION = "parse_duration" FUNC_CONVERT_DURATION = "convert_duration" FUNC_GET_ARGS = "get_args" FUNC_SIGNAL_IGNORE = "signal_ignore" FUNC_SIGNAL_TRAP = "signal_trap" INTERNAL_FUNC_GET_STASH_ID = "_rad_get_stash_id" INTERNAL_FUNC_DELETE_STASH = "_rad_delete_stash" INTERNAL_FUNC_RUN_CHECK = "_rad_run_check" INTERNAL_FUNC_FMT = "_rad_fmt" INTERNAL_FUNC_CHECK_FROM_LOGS = "_rad_check_from_logs" INTERNAL_FUNC_EXPLAIN = "_rad_explain" INTERNAL_FUNC_EXPLAIN_LIST = "_rad_explain_list" INTERNAL_FUNC_DOCS_TOC = "_rad_docs_toc" INTERNAL_FUNC_DOCS_GET = "_rad_docs_get" INTERNAL_FUNC_DOCS_FULL = "_rad_docs_full" INTERNAL_FUNC_DOCS_SLUGS = "_rad_docs_slugs" INTERNAL_FUNC_DOCS_FUNCS = "_rad_docs_funcs" INTERNAL_FUNC_RENDER = "_rad_render" )
Note: when adding functions, update the docs! docs-web/docs/reference/functions.md
const DefaultDiagnosticLimit = 10
DefaultDiagnosticLimit is the default maximum number of diagnostics to collect.
const ENV_RAD_HOME = "RAD_HOME"
const (
Version = "v0.11.0"
)
Variables ¶
var ( MODES = []string{COLOR_AUTO, COLOR_ALWAYS, COLOR_NEVER} NO_CONSTRAINTS []string FlagHelp BoolRadArg FlagDebug BoolRadArg FlagRadDebug BoolRadArg FlagColor StringRadArg FlagQuiet BoolRadArg FlagShell BoolRadArg FlagVersion BoolRadArg FlagConfirmShellCommands BoolRadArg FlagSrc BoolRadArg FlagCstTree BoolRadArg FlagAstTree BoolRadArg FlagRadArgsDump BoolRadArg FlagMockResponse StringRadArg FlagRepl BoolRadArg FlagTlsInsecure BoolRadArg FlagInteractive BoolRadArg // GlobalFlagScopes is the single source of truth for global flag ordering // (as printed in usage) and scope. Rebuilt by CreateAndRegisterGlobalFlags. GlobalFlagScopes []ScopedGlobalFlag )
var ( RRootCmd *ra.Cmd RConfig *RadConfig RP Printer RIo RadIo RExit *RadExitHandler RForceExit func(int) // hard exit that skips defers; for double-Ctrl+C RReq *Requester RClock Clock RSleep func(ctx context.Context, duration time.Duration) RShell ShellExecutor RConfirm func(title string, prompt string) (bool, error) RSignal SignalSource RInteractive InteractiveDriver RNG *rand.Rand HasScript bool ScriptPath string ScriptDir string ScriptName string IsTest bool AlreadyExportedShellVars bool RTermWidth *int // nil = use real terminal width; non-nil overrides for tests StartEpochMillis int64 )
var ATTR_STRINGS = make([]string, 0)
var COLOR_STRINGS = make([]string, 0)
var Cmds []EmbeddedCmd
var CmdsByName map[string]EmbeddedCmd
var EMPTY_STR = NewRadString("")
var FuncColorize = BuiltInFunc{ Name: FUNC_COLORIZE, Execute: func(f FuncInvocation) RadValue { strVal := ToPrintableQuoteStr(f.GetArg("_val"), false) enum := lo.Uniq(f.GetList("_enum").AsStringList(false)) skipIfSingle := f.GetBool("skip_if_single") if len(enum) == 0 { return f.ReturnErrf(rl.ErrEmptyList, "Possible values list cannot be empty, but was.") } if skipIfSingle && len(enum) == 1 { s := NewRadString(strVal) return f.Return(s) } sort.Strings(enum) if !lo.Contains(enum, strVal) { return f.ReturnErrf(rl.ErrColorizeValNotInEnum, "Value '%s' not found in the provided list of possible values: %s", strVal, enum) } r, g, b, err := GetEnumColor(strVal, enum) if err != nil { return f.ReturnErrf(rl.ErrEmptyList, "Failed to get color for value '%s': %s", strVal, err.Error()) } s := NewRadString(strVal) s.SetRgb(r, g, b) return f.Return(s) }, }
var FuncConvertDuration = BuiltInFunc{ Name: FUNC_CONVERT_DURATION, Execute: func(f FuncInvocation) RadValue { value := f.GetFloat("_value") unit := f.GetStr("_unit").Plain() var nanosFloat float64 switch unit { case "nanos": nanosFloat = value case "micros": nanosFloat = value * float64(time.Microsecond) case "millis": nanosFloat = value * float64(time.Millisecond) case "seconds": nanosFloat = value * float64(time.Second) case "minutes": nanosFloat = value * float64(time.Minute) case "hours": nanosFloat = value * float64(time.Hour) case "days": nanosFloat = value * 24 * float64(time.Hour) default: bugIncorrectTypes(FUNC_CONVERT_DURATION) panic(UNREACHABLE) } if math.IsNaN(nanosFloat) || math.IsInf(nanosFloat, 0) || math.Abs(nanosFloat) > float64(math.MaxInt64) { return f.ReturnErrf(rl.ErrNumInvalidRange, "Duration overflow: value too large for %s", unit) } return f.Return(NewDurationMap(int64(nanosFloat))) }, }
var FuncDebug = BuiltInFunc{ Name: FUNC_DEBUG, Execute: func(f FuncInvocation) RadValue { RP.ScriptDebug(resolvePrintStr(f)) return VOID_SENTINEL }, }
var FuncExit = BuiltInFunc{ Name: FUNC_EXIT, Execute: func(f FuncInvocation) RadValue { err := f.GetIntAllowingBool("_code") exit(f.i, err) return VOID_SENTINEL }, }
var FuncInternalCheckFromLogs = BuiltInFunc{ Name: INTERNAL_FUNC_CHECK_FROM_LOGS, Execute: func(f FuncInvocation) RadValue { raw := strings.TrimSpace(f.GetStr("_duration").Plain()) d, err := ParseDuration(raw) if err != nil { return f.ReturnErrf(rl.ErrInvalidCheckDuration, "Invalid duration: %s", err.Error()) } if d < 0 { return f.ReturnErrf(rl.ErrInvalidCheckDuration, "Duration cannot be negative: %s", raw) } durationMillis := d.Milliseconds() verbose := f.GetBool("_verbose") strict := f.GetBool("_strict") scripts := parseInvocationLogs(f.i, f.callNode, durationMillis) sortScriptsByLastOccurrence(scripts) durationDesc := raw if durationMillis == 0 { durationDesc = "all time" } RP.Printf("Found %d scripts in invocation logs (checking within %s)...\n\n", len(scripts), durationDesc) chk, err := check.NewChecker() if err != nil { chk = nil RP.RadStderrf("Warning! Failed to init checker once, will init per file: %v\n", err) } if chk != nil { chk.SetStrict(strict) } results := make([]scriptResult, 0, len(scripts)) maxPathLen := 0 for i, script := range scripts { RP.RadDebugf("Checking script %d/%d: %s", i+1, len(scripts), script.Path) if !com.IsRegularFile(script.Path) { RP.RadDebugf(" skipped (not a regular file)") results = append(results, scriptResult{Path: script.Path, Skipped: true}) continue } checkStart := time.Now() counts, ok := checkScriptWith(script.Path, chk, strict) RP.RadDebugf(" checked in %s (ok=%t, errors=%d)", time.Since(checkStart), ok, counts.Errors) r := scriptResult{Path: script.Path, Counts: counts, Ok: ok} results = append(results, r) if len(script.Path) > maxPathLen { maxPathLen = len(script.Path) } } // Column headers and their widths type col struct { Header string Width int } cols := []col{ {"Errors", 6}, {"Warns", 5}, {"Info", 5}, {"Hints", 5}, } faint := color.New(color.Faint) green := color.New(color.FgGreen) red := color.New(color.FgRed) yellow := color.New(color.FgYellow) cyan := color.New(color.FgCyan) blue := color.New(color.FgBlue) colsWidth := 0 for _, c := range cols { colsWidth += 2 + c.Width } tableWidth := 4 + maxPathLen + colsWidth hasDataRows := false for _, r := range results { if !r.Skipped { hasDataRows = true break } } if hasDataRows { headerLine := fmt.Sprintf(" %-*s", maxPathLen, "") for _, c := range cols { headerLine += fmt.Sprintf(" %*s", c.Width, c.Header) } RP.Printf("%s\n", faint.Sprint(headerLine)) } totalChecked, passed, failed, skipped, loadErrors := 0, 0, 0, 0, 0 var totalCounts diagCounts for _, r := range results { if r.Skipped { skipped++ if verbose { RP.Printf(" %s\n", faint.Sprintf("- %s (not found or not a regular file)", r.Path)) } continue } totalChecked++ totalCounts.Errors += r.Counts.Errors totalCounts.Warnings += r.Counts.Warnings totalCounts.Infos += r.Counts.Infos totalCounts.Hints += r.Counts.Hints isFail := !r.Ok || r.Counts.Errors > 0 if isFail { failed++ } else { passed++ } if !r.Ok { loadErrors++ } // Status icon var icon string if isFail { icon = red.Sprint("✗") } else { icon = green.Sprint("✓") } line := fmt.Sprintf(" %s %-*s", icon, maxPathLen, r.Path) if r.Ok { line += formatCount(r.Counts.Errors, cols[0].Width, red, faint) line += formatCount(r.Counts.Warnings, cols[1].Width, yellow, faint) line += formatCount(r.Counts.Infos, cols[2].Width, cyan, faint) line += formatCount(r.Counts.Hints, cols[3].Width, blue, faint) } else { line += " " + faint.Sprint("(load error)") } RP.Printf("%s\n", line) } sepWidth := tableWidth if sepWidth < 40 { sepWidth = 40 } RP.Printf("\n%s\n", strings.Repeat("─", sepWidth)) bold := color.New(color.Bold) summary := fmt.Sprintf("Checked %d scripts: %s passed, %s failed", totalChecked, green.Sprintf("%d", passed), red.Sprintf("%d", failed)) // Append non-zero diagnostic/status details in a single parenthetical var detailParts []string if totalCounts.Errors > 0 { noun := "errors" if totalCounts.Errors == 1 { noun = "error" } detailParts = append(detailParts, red.Sprintf("%d %s", totalCounts.Errors, noun)) } if loadErrors > 0 { noun := "load errors" if loadErrors == 1 { noun = "load error" } detailParts = append(detailParts, faint.Sprintf("%d %s", loadErrors, noun)) } if totalCounts.Warnings > 0 { noun := "warnings" if totalCounts.Warnings == 1 { noun = "warning" } detailParts = append(detailParts, yellow.Sprintf("%d %s", totalCounts.Warnings, noun)) } if totalCounts.Infos > 0 { noun := "info diagnostics" if totalCounts.Infos == 1 { noun = "info diagnostic" } detailParts = append(detailParts, cyan.Sprintf("%d %s", totalCounts.Infos, noun)) } if totalCounts.Hints > 0 { noun := "hints" if totalCounts.Hints == 1 { noun = "hint" } detailParts = append(detailParts, blue.Sprintf("%d %s", totalCounts.Hints, noun)) } if skipped > 0 { detailParts = append(detailParts, faint.Sprintf("%d skipped", skipped)) } if len(detailParts) > 0 { summary += " (" + strings.Join(detailParts, ", ") + ")" } RP.Printf("%s.\n", bold.Sprint(summary)) if failed > 0 { RExit.Exit(1) } else { RExit.Exit(0) } return VOID_SENTINEL }, }
FuncInternalCheckFromLogs implements _rad_check_from_logs, which checks rad scripts from invocation logs for syntax/semantic errors. This is an internal function used by the rad CLI for bulk checking recently-used scripts.
var FuncMatches = BuiltInFunc{ Name: FUNC_MATCHES, Execute: func(f FuncInvocation) RadValue { input := f.GetStr("_str").Plain() pattern := f.GetStr("_pattern").Plain() partial := f.GetBool("partial") re, err := regexp.Compile(pattern) if err != nil { return f.ReturnErrf(rl.ErrInvalidRegex, "Error compiling regex pattern: %s", err) } var matches bool if partial { matches = re.FindString(input) != "" } else { anchoredPattern := "^(?:" + pattern + ")$" anchoredRe, err := regexp.Compile(anchoredPattern) if err != nil { return f.ReturnErrf(rl.ErrInvalidRegex, "Error compiling regex pattern: %s", err) } matches = anchoredRe.MatchString(input) } return f.Return(matches) }, }
var FuncMultipick = BuiltInFunc{ Name: FUNC_MULTIPICK, Execute: func(f FuncInvocation) RadValue { options := f.GetList("_options").AsStringList(false) if len(options) == 0 { return f.Return(NewErrorStrf("Cannot multipick from empty options list")) } minArg := f.GetArg("min") maxArg := f.GetArg("max") promptArg := f.GetArg("prompt") min := int64(0) if !minArg.IsNull() { min = minArg.RequireInt(f.i, f.callNode) } if min < 0 { return f.Return(NewErrorStrf("min must be non-negative, got %d", min)) } // Get max value (optional) var max *int64 if !maxArg.IsNull() { maxVal := maxArg.RequireInt(f.i, f.callNode) max = &maxVal if maxVal <= 0 { return f.Return(NewErrorStrf("max must be positive, got %d", maxVal)) } if min > maxVal { return f.Return(NewErrorStrf("min (%d) cannot be greater than max (%d)", min, maxVal)) } } if min > int64(len(options)) { if min == 1 { return f.Return(NewErrorStrf("min is 1 but there are no options available")) } else { return f.Return(NewErrorStrf("min is %d but only %d options available", min, len(options))) } } // Generate smart default prompt if not provided var prompt string if promptArg.IsNull() { prompt = generateMultipickPrompt(min, max) } else { prompt = f.GetStr("prompt").Plain() } model := radish.NewMultiSelect(). Title(prompt). Options(options...). Min(int(min)). Width(GetTermWidth()) if max != nil { model.Max(int(*max)) } res, _, err := RInteractive.Run(model) if err != nil { if errors.Is(err, radish.ErrNotInteractive) { return f.Return(NewErrorStrf("multipick requires an interactive terminal")) } return f.Return(NewErrorStrf("Error running multipick: %v", err)) } if res.Canceled { return f.Return(NewErrorStrf("multipick canceled")) } result := NewRadList() for _, item := range model.Selected() { result.Append(newRadValueStr(item)) } return f.Return(result) }, }
var FuncPPrint = BuiltInFunc{ Name: FUNC_PPRINT, Execute: func(f FuncInvocation) RadValue { item := f.GetArg("_item") jsonStruct := RadToJsonType(item) output := prettify(f.i, f.callNode, jsonStruct) RP.Print(output) return VOID_SENTINEL }, }
var FuncParseDate = BuiltInFunc{ Name: FUNC_PARSE_DATE, Execute: func(f FuncInvocation) RadValue { dateStr := f.GetStr("_date").Plain() formatArg := f.GetArg("format") tz := f.GetStr("tz").Plain() // Resolve output timezone var location *time.Location if tz == "local" { location = RClock.Local() } else { var err error location, err = time.LoadLocation(tz) if err != nil { return f.ReturnErrf(rl.ErrInvalidTimeZone, "Invalid time zone '%s'", tz) } } if dateStr == "" { return f.Return(NewErrorStr("Cannot parse an empty date string").SetCode(rl.ErrParseDate)) } var parsedTime time.Time if !formatArg.IsNull() { format := formatArg.RequireStr(f.i, f.callNode).Plain() if format == "" { return f.Return(NewErrorStr("Cannot parse date with an empty format string").SetCode(rl.ErrParseDate)) } goLayout := convertFormatToGoLayout(format) t, err := time.ParseInLocation(goLayout, dateStr, location) if err != nil { errMsg := fmt.Sprintf("Failed to parse date %q with format %q", dateStr, format) return f.Return(NewErrorStr(errMsg).SetCode(rl.ErrParseDate)) } parsedTime = t } else { // Auto-detect: try known unambiguous formats var parsed bool for _, af := range autoDetectFormats { if af.hasTz { t, err := time.Parse(af.layout, dateStr) if err == nil { parsedTime = t.In(location) parsed = true break } } else { t, err := time.ParseInLocation(af.layout, dateStr, location) if err == nil { parsedTime = t parsed = true break } } } if !parsed { errMsg := fmt.Sprintf( "Failed to parse date %q. Supported formats: YYYY-MM-DD, YYYY-MM-DDTHH:mm:ss, "+ "YYYY-MM-DD HH:mm:ss (with optional timezone offset and fractional seconds). "+ "Use 'format' to specify a custom format, e.g. parse_date(%q, format=\"DD/MM/YYYY\").", dateStr, dateStr, ) return f.Return(NewErrorStr(errMsg).SetCode(rl.ErrParseDate)) } } return f.Return(NewTimeMap(parsedTime)) }, }
var FuncParseDuration = BuiltInFunc{ Name: FUNC_PARSE_DURATION, Execute: func(f FuncInvocation) RadValue { durStr := f.GetStr("_duration").Plain() nanos, err := ParseDurationString(durStr) if err != nil { return f.ReturnErrf(rl.ErrParseDuration, "Failed to parse duration %q: %s", durStr, err) } return f.Return(NewDurationMap(nanos)) }, }
var FuncPick = BuiltInFunc{ Name: FUNC_PICK, Execute: func(f FuncInvocation) RadValue { options := f.GetList("_options").AsStringList(false) filterArg := f.GetArg("_filter") filters := make([]string, 0) if !filterArg.IsNull() { switch coerced := filterArg.Val.(type) { case RadString: filters = append(filters, coerced.Plain()) case *RadList: for _, item := range coerced.Values { filters = append(filters, item.RequireStr(f.i, f.callNode).Plain()) } default: bugIncorrectTypes(FUNC_PICK) } } keyGroups := lo.Map(options, func(key string, _ int) []string { return []string{key} }) prioExact := f.GetBool(namedArgPreferExact) str, err := pickKv(f, keyGroups, keyGroups, filters, prioExact) if err != nil { return f.Return(err) } return f.Return(str[0]) }, }
var FuncPickFromResource = BuiltInFunc{ Name: FUNC_PICK_FROM_RESOURCE, Execute: func(f FuncInvocation) RadValue { path := f.GetStr("path").Plain() filter := f.GetArg("_filter") resource, err := LoadPickResource(f.i, f.callNode, path) if err != nil { return f.Return(err) } var keyGroups [][]string var valueGroups [][]RadValue for _, opt := range resource.Opts { keyGroups = append(keyGroups, opt.Keys) valueGroups = append(valueGroups, opt.Values) } filters := make([]string, 0) if !filter.IsNull() { switch coerced := filter.Val.(type) { case RadString: filters = append(filters, coerced.Plain()) case *RadList: for _, item := range coerced.Values { filters = append(filters, item.RequireStr(f.i, f.callNode).Plain()) } default: bugIncorrectTypes(FUNC_PICK_KV) } } prioExact := f.GetBool(namedArgPreferExact) out, err := pickKv(f, keyGroups, valueGroups, filters, prioExact) if err != nil { return f.Return(err) } if len(out) == 1 { return newRadValues(f.i, f.callNode, out[0]) } else { return newRadValues(f.i, f.callNode, out) } }, }
var FuncPickKv = BuiltInFunc{ Name: FUNC_PICK_KV, Execute: func(f FuncInvocation) RadValue { keys := f.GetList("keys").AsStringList(false) values := f.GetList("values").Values filter := f.GetArg("_filter") filters := make([]string, 0) if !filter.IsNull() { switch coerced := filter.Val.(type) { case RadString: filters = append(filters, coerced.Plain()) case *RadList: for _, item := range coerced.Values { filters = append(filters, item.RequireStr(f.i, f.callNode).Plain()) } default: bugIncorrectTypes(FUNC_PICK_KV) } } keyGroups := lo.Map(keys, func(key string, _ int) []string { return []string{key} }) valueGroups := lo.Map(values, func(value RadValue, _ int) []RadValue { return []RadValue{value} }) prioExact := f.GetBool(namedArgPreferExact) out, err := pickKv(f, keyGroups, valueGroups, filters, prioExact) if err != nil { return f.Return(err) } return f.Return(out[0]) }, }
var FuncPrint = BuiltInFunc{ Name: FUNC_PRINT, Execute: func(f FuncInvocation) RadValue { RP.Print(resolvePrintStr(f)) return VOID_SENTINEL }, }
var FuncPrintErr = BuiltInFunc{ Name: FUNC_PRINT_ERR, Execute: func(f FuncInvocation) RadValue { RP.ScriptStderrf(resolvePrintStr(f)) return VOID_SENTINEL }, }
var FuncRand = BuiltInFunc{ Name: FUNC_RAND, Execute: func(f FuncInvocation) RadValue { return f.Return(RNG.Float64()) }, }
var FuncRandInt = BuiltInFunc{ Name: FUNC_RAND_INT, Execute: func(f FuncInvocation) RadValue { arg1 := f.GetInt("_arg1") arg2 := f.GetArg("_arg2") var min, max int64 if arg2.IsNull() { min = 0 max = arg1 } else { min = arg1 max = arg2.RequireInt(f.i, f.callNode) } if min >= max { return f.ReturnErrf(rl.ErrArgsContradict, "min (%d) must be less than max (%d).", min, max) } n := max - min return newRadValues(f.i, f.callNode, min+RNG.Int63n(n)) }, }
var FuncRange = BuiltInFunc{ Name: FUNC_RANGE, Execute: func(f FuncInvocation) RadValue { useFloats := false arg1 := f.GetArg("_arg1") arg2 := f.GetArg("_arg2") step := f.GetArg("_step") for _, arg := range []RadValue{arg1, arg2, step} { switch arg.Type() { case rl.RadFloatT: useFloats = true case rl.RadIntT, rl.RadNullT: default: bugIncorrectTypes(FUNC_RANGE) } } if useFloats { return runFloatRange(f, arg1, arg2, step) } else { return runIntRange(f, arg1, arg2, step) } }, }
var FuncReplace = BuiltInFunc{ Name: FUNC_REPLACE, Execute: func(f FuncInvocation) RadValue { original := f.GetStr("_original").Plain() find := f.GetStr("_find").Plain() replace := f.GetStr("_replace").Plain() re, err := regexp.Compile(find) if err != nil { return f.ReturnErrf(rl.ErrInvalidRegex, "Error compiling regex pattern: %s", err) } replacementFunc := func(match string) string { submatches := re.FindStringSubmatch(match) if len(submatches) == 0 { return match } result := replace for i, submatch := range submatches { placeholder := fmt.Sprintf("$%d", i) result = strings.ReplaceAll(result, placeholder, submatch) } return result } newString := re.ReplaceAllStringFunc(original, replacementFunc) return f.Return(newString) }, }
Allows capture group replacing, for example replace("Name: abc", "a(b)c", "$1o$1") will return "Name: bobby"
var FuncSeedRandom = BuiltInFunc{ Name: FUNC_SEED_RANDOM, Execute: func(f FuncInvocation) RadValue { RNG = rand.New(rand.NewSource(f.GetInt("_seed"))) return VOID_SENTINEL }, }
var FuncSignalIgnore = BuiltInFunc{ Name: FUNC_SIGNAL_IGNORE, Execute: func(f FuncInvocation) RadValue { names, err := extractSignalNames(f, "_signal", FUNC_SIGNAL_IGNORE) if err != nil { return f.Return(err) } for _, name := range names { if ierr := f.i.signals.Ignore(name); ierr != nil { return f.Return(NewErrorStrf("%v", ierr).SetCode(rl.ErrGenericRuntime)) } } return VOID_SENTINEL }, }
FuncSignalIgnore installs OS-level SIG_IGN for one or more signals. Most useful for SIGPIPE: a script that pipes its output (e.g. `script | head`) will otherwise crash when the downstream consumer closes the pipe.
Distinct from `signal_trap(sig, fn(){})`: a no-op handler still wakes the process and runs Rad-side dispatch on every delivery, whereas SIG_IGN tells the kernel to drop the signal before it reaches us. For SIGPIPE in particular this also affects subprocess inheritance.
var FuncSignalTrap = BuiltInFunc{ Name: FUNC_SIGNAL_TRAP, Execute: func(f FuncInvocation) RadValue { names, err := extractSignalNames(f, "_signal", FUNC_SIGNAL_TRAP) if err != nil { return f.Return(err) } handler := f.GetFn("_handler") for _, name := range names { if terr := f.i.signals.Trap(name, handler); terr != nil { return f.Return(NewErrorStrf("%v", terr).SetCode(rl.ErrGenericRuntime)) } } return VOID_SENTINEL }, }
FuncSignalTrap registers a Rad function to run when one of the named signals is delivered to the process. The handler is invoked with a single argument: a map containing the signal name and the conventional exit code.
Replaces any previously-registered handler for the same signal. There is no current way to restore the platform default - once a signal is trapped, it stays trapped for the lifetime of the interpreter.
After the handler returns, execution always continues - the handler must explicitly call exit() if it wants to terminate. This matches Bash, Ruby, Python, and Node, which all converge on always-continue. The user pays a small ergonomic cost (every SIGINT handler needs `exit(ctx.exit_code)`) in exchange for a predictable single-rule mental model.
var FuncSleep = BuiltInFunc{ Name: FUNC_SLEEP, Execute: func(f FuncInvocation) RadValue { duration := f.GetArg("_duration") switch coerced := duration.Val.(type) { case int64: err := sleep(f.i, time.Duration(coerced)*time.Second, f.namedArgs) if err != nil { return f.Return(err) } return VOID_SENTINEL case float64: err := sleep(f.i, time.Duration(coerced*1000)*time.Millisecond, f.namedArgs) if err != nil { return f.Return(err) } return VOID_SENTINEL case RadString: durStr := coerced.Plain() floatVal, err := rts.ParseFloat(durStr) if err == nil { err := sleep(f.i, time.Duration(floatVal*1000)*time.Millisecond, f.namedArgs) if err != nil { return f.Return(err) } return VOID_SENTINEL } nanos, err := ParseDurationString(durStr) if err == nil { err := sleep(f.i, time.Duration(nanos), f.namedArgs) if err != nil { return f.Return(err) } return VOID_SENTINEL } return f.ReturnErrf(rl.ErrSleepStr, "Invalid string argument: %q", coerced.Plain()) default: bugIncorrectTypes(FUNC_SLEEP) panic(UNREACHABLE) } }, }
var FuncSplit = BuiltInFunc{ Name: FUNC_SPLIT, Execute: func(f FuncInvocation) RadValue { toSplit := f.GetStr("_val").Plain() splitter := f.GetStr("_sep").Plain() limitArg := f.GetArg("limit") limit := -1 if !limitArg.IsNull() { limitVal := limitArg.RequireInt(f.i, f.callNode) if limitVal < 1 { return f.Return(NewErrorStrf("limit must be at least 1, got %d", limitVal).SetCode(rl.ErrNumInvalidRange)) } limit = int(limitVal) + 1 } return f.Return(regexSplit(f.i, f.callNode, toSplit, splitter, limit)) }, }
var FuncSplitLines = BuiltInFunc{ Name: FUNC_SPLIT_LINES, Execute: func(f FuncInvocation) RadValue { toSplit := f.GetStr("_val").Plain() return f.Return(splitLines(f.i, f.callNode, toSplit)) }, }
var FuncToJson = BuiltInFunc{ Name: FUNC_TO_JSON, Execute: func(f FuncInvocation) RadValue { indent := f.GetInt("indent") if indent < 0 { return f.ReturnErrf(rl.ErrNumInvalidRange, "Indent must be non-negative, got %d", indent) } jsonStruct := RadToJsonType(f.GetArg("_val")) buf := &bytes.Buffer{} enc := json.NewEncoder(buf) enc.SetEscapeHTML(false) if indent > 0 { enc.SetIndent("", strings.Repeat(" ", int(indent))) } if err := enc.Encode(jsonStruct); err != nil { return f.ReturnErrf(rl.ErrInternalBug, "Failed to serialize to JSON: %v", err) } return f.Return(strings.TrimSuffix(buf.String(), "\n")) }, }
var FunctionsByName map[string]BuiltInFunc
var (
NO_NAMED_ARGS_INPUT = map[string]namedArg{}
)
var RAD_NULL = RadNull{}
var RAD_NULL_VAL = newRadValue(nil, nil, RAD_NULL)
var VOID_SENTINEL = RadValue{Val: 0x0}
used to internally delete things e.g. vars from env, but also empty returns. too much? subtle bugs?
var VoidBreak = NewEvalResult(VOID_SENTINEL, CtrlBreak)
var VoidContinue = NewEvalResult(VOID_SENTINEL, CtrlContinue)
var VoidNormal = NewEvalResult(VOID_SENTINEL, CtrlNormal)
Functions ¶
func AddInternalFuncs ¶
func AddInternalFuncs()
func BuildDocsFull ¶ added in v0.11.0
func BuildDocsFull() string
BuildDocsFull renders the entire embedded corpus: the TOC followed by every page's content, H1-wrapped and separated by horizontal rules. This mirrors llms-full.txt so `rad docs all` is the "load everything" mode agents reach for.
func BuildDocsTOC ¶ added in v0.11.0
func BuildDocsTOC() string
BuildDocsTOC renders the topic index: sections, titles, the command to print each page, and an H2 preview. It's the `rad docs` (no-arg) listing and the header of `rad docs all`.
func CalculateCorrectedIndex ¶
CalculateCorrectedIndex 'corrects' negative indices into their positive equivalents
func ErrIndexOutOfBounds ¶
func ErrIndexOutOfBounds(i *Interpreter, node rl.Node, idx int64, length int64)
func ExitCodeFor ¶ added in v0.11.0
ExitCodeFor returns the conventional exit code (128 + signal number) for the named signal. Returns 0 if the signal is not supported.
func FuzzyMatchFold ¶ added in v0.9.0
FuzzyMatchFold returns true if each character in source can be found in target in order, using case-insensitive matching. This is a simplified fuzzy search - not Levenshtein distance.
For example:
- FuzzyMatchFold("abc", "AbraCadabra") -> true (a...b...c found in order)
- FuzzyMatchFold("adc", "abcd") -> false (d comes before c in target)
func GetDocFuncs ¶ added in v0.11.0
func GetDocFuncs() []string
GetDocFuncs returns the names of every built-in with an embedded per-function doc page (i.e. every `rad docs <name>` that resolves).
func GetDocPage ¶ added in v0.11.0
GetDocPage returns the raw markdown for one page slug (e.g. "guide/basics"), or false if no such page is embedded.
func GetDocSlugs ¶ added in v0.11.0
func GetDocSlugs() []string
GetDocSlugs returns every page slug, in nav order. Used to validate `rad docs <topic>` and to list valid topics on a miss.
func GetDocTopic ¶ added in v0.11.0
GetDocTopic resolves a `rad docs <topic>` argument to raw markdown. It's the single entry point, accepting (in precedence order) error codes, built-in function names, and page slugs: `rad docs RAD10001` explains an error, `rad docs len` prints a function's doc, and `rad docs guide/basics` prints a page. Precedence is unambiguous - error codes are digits, function names are bare identifiers, and page slugs always contain a "/". Returns false if nothing matches.
func GetEmbeddedCommandSrc ¶
func GetEnumColor ¶
GetEnumColor generates a visually distinct and appealing RGB color for a given value from a list. It returns R, G, B values (0-255) and an error if the value is not found.
func GetErrorDoc ¶ added in v0.9.0
GetErrorDoc returns the documentation for an error code, or empty string if not found. The code should be just the numeric part (e.g., "10001" not "RAD10001").
func GetFuncDoc ¶ added in v0.11.0
GetFuncDoc returns the per-function doc page for a built-in (e.g. "len"), or false if no such function is documented.
func GetInvocationLogPath ¶ added in v0.6.11
func GetInvocationLogPath() string
GetInvocationLogPath returns the path to the current invocation log file
func GetInvocationLogsDir ¶ added in v0.6.11
func GetInvocationLogsDir() string
GetInvocationLogsDir returns the directory containing invocation logs
func GetTermWidth ¶ added in v0.10.0
func GetTermWidth() int
GetTermWidth returns the terminal width to use for rendering. This is the canonical way to obtain terminal width in production code - callers do not need to concern themselves with testing overrides. Tests can inject a fixed width via RunnerInput.RTermWidth.
func InputConfirm ¶
todo allow controlling 'yes' response?
func IsTerminatingSignal ¶ added in v0.11.0
IsTerminatingSignal reports whether the named signal's default action is to terminate the process. Used by the checkpoint when no handler is registered: terminating signals cause RExit.Exit(128+sig), non-terminating ones (only SIGWINCH today) are no-ops.
func IsWindows ¶ added in v0.7.1
func IsWindows() bool
IsWindows returns true if running on Windows.
func JsonToString ¶
func JsonToString(jsonVal interface{}) string
func Levenshtein ¶ added in v0.9.0
Levenshtein calculates the Levenshtein distance between two strings. Used for "did you mean?" suggestions.
func ListErrorCodes ¶ added in v0.9.0
func ListErrorCodes() []string
ListErrorCodes returns all documented error codes.
func LoadPickResource ¶
func LoadPickResource(i *Interpreter, callNode rl.Node, jsonPath string) (PickResource, *RadError)
func LogInvocation ¶ added in v0.6.11
func LogInvocation(entry InvocationLogEntry)
LogInvocation appends an invocation log entry to the JSONL log file Creates directory and file if they don't exist
func MaybeRotate ¶ added in v0.6.11
func MaybeRotate()
MaybeRotate checks if the current log file exceeds the size threshold and rotates it if necessary. Non-fatal: warns on errors but doesn't crash.
func NormalizeLineEndings ¶ added in v0.7.1
NormalizeLineEndings converts Windows-style line endings (\r\n) to Unix-style (\n). This ensures consistent text handling across platforms.
func NormalizePath ¶ added in v0.7.1
NormalizePath converts OS-specific path separators to forward slashes. This ensures Rad scripts are portable across platforms.
func ParseDuration ¶ added in v0.6.11
ParseDuration parses a human-readable duration string into time.Duration Supported formats:
- Simple: "30d", "2w", "24h", "1y"
- Combinations: "2w3d", "1y2w", "3d12h30m"
- Special: "all" returns 0 (no time filtering)
Units:
- y: years (365 days, ignores leap years)
- w: weeks (7 days)
- d: days (24 hours)
- h: hours
- m: minutes
- s: seconds
func ParseDurationString ¶ added in v0.9.0
ParseDurationString parses a human-readable duration string into nanoseconds. Extends Go's time.ParseDuration with support for "d" (days, where 1d = 24h) and "w" (weeks, where 1w = 7d). Spaces are stripped, and a leading "-" negates the whole duration.
func RadToJsonType ¶
func RadToJsonType(arg RadValue) interface{}
converts a Rad data structure to a JSON-schema-adhering structure.
func RegisterInvocationLogging ¶ added in v0.6.11
func RegisterInvocationLogging()
func SetScriptPath ¶
func SetScriptPath(path string)
func ToPrintable ¶
func ToPrintable(val interface{}) string
func ToPrintableQuoteStr ¶
func TransformRadArgs ¶
func TypeAsString ¶
func TypeAsString(val interface{}) string
Types ¶
type ArgPrompter ¶ added in v0.11.0
type ArgPrompter interface {
Select(title string, options []string, summarize func(choice string) string) (string, error)
MultiSelect(title string, options, preselected []string, summarize func(chosen []string) string) ([]string, error)
Input(title, placeholder string, validate func(string) error, summarize func(value string) string) (string, error)
}
ArgPrompter abstracts the prompt shapes the --interactive walk needs, so the walk logic is unit-testable with a fake. The production implementation builds radish models and runs them through the RInteractive driver seam. Each prompt takes a summarize renderer producing the collapsed line left in the transcript after the prompt ends (compact flag-form, previewing the equivalent invocation); an empty result collapses to nothing.
type ArgRangeConstraint ¶
type BaseRadArg ¶
type BaseRadArg struct {
ExternalName string // User-facing arg they'll set in CLI
Identifier string // Identifier in script. If non-script arg, then equal to ExternalName
Short string
ArgUsage string
Description string
// contains filtered or unexported fields
}
func (*BaseRadArg) Configured ¶
func (f *BaseRadArg) Configured() bool
func (*BaseRadArg) DefaultAsString ¶
func (f *BaseRadArg) DefaultAsString() string
func (*BaseRadArg) Excludes ¶
func (f *BaseRadArg) Excludes(otherArg RadArg) bool
func (*BaseRadArg) GetArgUsage ¶
func (f *BaseRadArg) GetArgUsage() string
func (*BaseRadArg) GetDescription ¶
func (f *BaseRadArg) GetDescription() string
func (*BaseRadArg) GetExternalName ¶
func (f *BaseRadArg) GetExternalName() string
func (*BaseRadArg) GetIdentifier ¶
func (f *BaseRadArg) GetIdentifier() string
func (*BaseRadArg) GetShort ¶
func (f *BaseRadArg) GetShort() string
func (*BaseRadArg) GetSpan ¶ added in v0.9.0
func (f *BaseRadArg) GetSpan() *rl.Span
func (*BaseRadArg) HasNonZeroDefault ¶
func (f *BaseRadArg) HasNonZeroDefault() bool
func (*BaseRadArg) Hidden ¶
func (f *BaseRadArg) Hidden(hide bool)
func (*BaseRadArg) IsDefined ¶
func (f *BaseRadArg) IsDefined() bool
func (*BaseRadArg) IsHidden ¶
func (f *BaseRadArg) IsHidden() bool
func (*BaseRadArg) IsNullable ¶
func (f *BaseRadArg) IsNullable() bool
func (*BaseRadArg) IsOptional ¶
func (f *BaseRadArg) IsOptional() bool
func (*BaseRadArg) IsVariadic ¶ added in v0.6.0
func (f *BaseRadArg) IsVariadic() bool
func (*BaseRadArg) SetBypassValidation ¶ added in v0.5.59
func (f *BaseRadArg) SetBypassValidation(bypass bool)
func (*BaseRadArg) SetValue ¶
func (f *BaseRadArg) SetValue(_ string)
type BoolListRadArg ¶
type BoolListRadArg struct {
BaseRadArg
Value []bool
Default []bool
}
func NewBoolListRadArg ¶
func NewBoolListRadArg(name, short, argUsage, description string, hasDefault bool, defaultValue []bool, requires, excludes []string, ) BoolListRadArg
func (*BoolListRadArg) GetType ¶
func (f *BoolListRadArg) GetType() RadArgTypeT
func (*BoolListRadArg) Register ¶
func (f *BoolListRadArg) Register(cmd *ra.Cmd, mode RegistrationMode)
func (*BoolListRadArg) SetValue ¶
func (f *BoolListRadArg) SetValue(arg string)
type BoolRadArg ¶
type BoolRadArg struct {
BaseRadArg
Value bool
Default bool
}
func NewBoolRadArg ¶
func NewBoolRadArg(name, short, description string, hasDefault bool, defaultValue bool, requires, excludes []string, ) BoolRadArg
func (*BoolRadArg) GetType ¶
func (f *BoolRadArg) GetType() RadArgTypeT
func (*BoolRadArg) Register ¶
func (f *BoolRadArg) Register(cmd *ra.Cmd, mode RegistrationMode)
func (*BoolRadArg) SetValue ¶
func (f *BoolRadArg) SetValue(arg string)
type BufferReader ¶
type BufferReader struct {
// contains filtered or unexported fields
}
func (*BufferReader) HasContent ¶
func (br *BufferReader) HasContent() bool
func (*BufferReader) SetPiped ¶ added in v0.6.10
func (br *BufferReader) SetPiped(piped bool)
func (*BufferReader) Unwrap ¶
func (br *BufferReader) Unwrap() io.Reader
type BuiltInFunc ¶
type BuiltInFunc struct {
Name string
Signature *rts.FnSignature
Execute func(FuncInvocation) RadValue
}
todo add 'usage' to each function? self-documenting errors when incorrectly using
type CallFrame ¶ added in v0.9.0
type CallFrame struct {
FunctionName string // Name of the function (or "<anonymous>" for lambdas)
CallSite *rl.Span // Where the function was called from
DefSite *rl.Span // Where the function is defined
}
CallFrame represents a function call in the Rad call stack. Used for providing stack traces in error messages.
type CheckableReader ¶
type CheckableReader interface {
Read(p []byte) (n int, err error)
HasContent() bool
Unwrap() io.Reader
}
func NewBufferReader ¶
func NewBufferReader(buffer *bytes.Buffer) CheckableReader
func NewFileReader ¶
func NewFileReader(file *os.File) CheckableReader
type ConstraintCtx ¶
func NewConstraintCtx ¶
func NewConstraintCtx(scriptArgs []RadArg) ConstraintCtx
type DefaultReplSession ¶ added in v0.5.59
type DefaultReplSession struct {
// contains filtered or unexported fields
}
DefaultReplSession implements the ReplSession interface
func (*DefaultReplSession) ExecuteStatement ¶ added in v0.5.59
func (s *DefaultReplSession) ExecuteStatement(input string) (*ExecutionResult, error)
ExecuteStatement executes a single statement and returns the result
func (*DefaultReplSession) GetEnvironment ¶ added in v0.5.59
func (s *DefaultReplSession) GetEnvironment() *Env
GetEnvironment returns the current interpreter environment
func (*DefaultReplSession) Run ¶ added in v0.5.59
func (s *DefaultReplSession) Run() error
Run starts the main REPL loop
func (*DefaultReplSession) Shutdown ¶ added in v0.5.59
func (s *DefaultReplSession) Shutdown() error
Shutdown performs cleanup when REPL session ends
type DeferBlock ¶
func NewDeferBlock ¶
type Diagnostic ¶ added in v0.9.0
type Diagnostic struct {
Severity Severity
Code rl.Error // From rts/rl/errors.go
Message string // One-line summary
Labels []Label // Primary + secondary spans
Hints []string // "= help: ..." lines
Source string // Complete source for rendering
CallStack []CallFrame // Rad call stack at time of error (most recent first)
}
Diagnostic represents a single diagnostic message with optional multi-span context.
func NewDiagnostic ¶ added in v0.9.0
func NewDiagnostic(severity Severity, code rl.Error, message string, source string, primarySpan rl.Span) Diagnostic
NewDiagnostic creates a diagnostic with a single primary label.
func NewDiagnosticFromCheck ¶ added in v0.9.0
func NewDiagnosticFromCheck(d check.Diagnostic, file string) Diagnostic
NewDiagnosticFromCheck converts a check.Diagnostic to a core.Diagnostic. The file parameter is used for the span's file path.
func NewDiagnosticWithLabels ¶ added in v0.9.0
func NewDiagnosticWithLabels(severity Severity, code rl.Error, message string, source string, labels []Label) Diagnostic
NewDiagnosticWithLabels creates a diagnostic with multiple labels.
func (Diagnostic) PrimarySpan ¶ added in v0.9.0
func (d Diagnostic) PrimarySpan() *rl.Span
PrimarySpan returns the first primary span, or nil if none exists.
func (Diagnostic) WithCallStack ¶ added in v0.9.0
func (d Diagnostic) WithCallStack(stack []CallFrame) Diagnostic
WithCallStack attaches a call stack to the diagnostic and returns the modified diagnostic.
func (Diagnostic) WithHint ¶ added in v0.9.0
func (d Diagnostic) WithHint(hint string) Diagnostic
WithHint adds a hint to the diagnostic and returns the modified diagnostic.
func (Diagnostic) WithHints ¶ added in v0.9.0
func (d Diagnostic) WithHints(hints ...string) Diagnostic
WithHints adds multiple hints to the diagnostic and returns the modified diagnostic.
func (Diagnostic) WithSecondaryLabel ¶ added in v0.9.0
func (d Diagnostic) WithSecondaryLabel(span rl.Span, message string) Diagnostic
WithSecondaryLabel adds a secondary label to the diagnostic and returns the modified diagnostic.
type DiagnosticCollector ¶ added in v0.9.0
type DiagnosticCollector struct {
// contains filtered or unexported fields
}
DiagnosticCollector accumulates diagnostics up to a configurable limit. Tree-sitter's error recovery can cause cascades where one real error spawns many, so limiting prevents wall-of-text noise while still showing patterns.
func NewDiagnosticCollector ¶ added in v0.9.0
func NewDiagnosticCollector() *DiagnosticCollector
NewDiagnosticCollector creates a collector with the default limit.
func NewDiagnosticCollectorWithLimit ¶ added in v0.9.0
func NewDiagnosticCollectorWithLimit(limit int) *DiagnosticCollector
NewDiagnosticCollectorWithLimit creates a collector with a custom limit.
func (*DiagnosticCollector) Add ¶ added in v0.9.0
func (c *DiagnosticCollector) Add(d Diagnostic) bool
Add adds a diagnostic to the collector. Returns false when the limit is reached, signaling that the caller should stop producing diagnostics.
func (*DiagnosticCollector) AtLimit ¶ added in v0.9.0
func (c *DiagnosticCollector) AtLimit() bool
AtLimit returns true if the collector has reached its limit.
func (*DiagnosticCollector) Count ¶ added in v0.9.0
func (c *DiagnosticCollector) Count() int
Count returns the number of diagnostics collected.
func (*DiagnosticCollector) Diagnostics ¶ added in v0.9.0
func (c *DiagnosticCollector) Diagnostics() []Diagnostic
Diagnostics returns all collected diagnostics.
func (*DiagnosticCollector) HasErrors ¶ added in v0.9.0
func (c *DiagnosticCollector) HasErrors() bool
HasErrors returns true if there are any error-severity diagnostics.
func (*DiagnosticCollector) IsEmpty ¶ added in v0.9.0
func (c *DiagnosticCollector) IsEmpty() bool
IsEmpty returns true if no diagnostics have been collected.
func (*DiagnosticCollector) Remaining ¶ added in v0.9.0
func (c *DiagnosticCollector) Remaining() int
Remaining returns how many more diagnostics were emitted beyond the limit.
func (*DiagnosticCollector) TotalEmitted ¶ added in v0.9.0
func (c *DiagnosticCollector) TotalEmitted() int
TotalEmitted returns the total number of diagnostics that were attempted to be added, including those beyond the limit.
type DiagnosticRenderer ¶ added in v0.9.0
type DiagnosticRenderer struct {
// contains filtered or unexported fields
}
DiagnosticRenderer renders diagnostics in Rust-style format.
func NewDiagnosticRenderer ¶ added in v0.9.0
func NewDiagnosticRenderer(w io.Writer) *DiagnosticRenderer
NewDiagnosticRenderer creates a renderer that writes to the given writer.
func (*DiagnosticRenderer) Render ¶ added in v0.9.0
func (r *DiagnosticRenderer) Render(d Diagnostic)
Render renders a single diagnostic.
func (*DiagnosticRenderer) RenderAll ¶ added in v0.9.0
func (r *DiagnosticRenderer) RenderAll(c *DiagnosticCollector)
RenderAll renders all diagnostics in a collector and displays truncation message if needed.
type DocPage ¶ added in v0.11.0
type DocPage struct {
Slug string `json:"slug"`
Section string `json:"section"`
Title string `json:"title"`
H2s []string `json:"h2s"`
}
DocPage is one entry in the embedded docs manifest.
func GetDocsManifest ¶ added in v0.11.0
func GetDocsManifest() []DocPage
GetDocsManifest returns the embedded doc pages in nav order.
type EmbeddedCmd ¶
type Env ¶
type Env struct {
Enclosing *Env
Vars map[string]RadValue
JsonFieldVars map[string]*JsonFieldVar // not pointer?
// contains filtered or unexported fields
}
func NewEnv ¶
func NewEnv(i *Interpreter) *Env
func (*Env) AllVarNames ¶ added in v0.9.0
AllVarNames returns all variable names visible from this environment.
func (*Env) FindSimilarVars ¶ added in v0.9.0
FindSimilarVars finds variable names similar to the given name. Returns at most maxResults names, sorted by similarity.
func (*Env) GetJsonFieldVar ¶
func (e *Env) GetJsonFieldVar(name string) (*JsonFieldVar, bool)
func (*Env) GetVarElseBug ¶
func (*Env) NewChildEnv ¶
func (*Env) PrintShellExports ¶
func (e *Env) PrintShellExports()
func (*Env) SetJsonFieldVar ¶
func (e *Env) SetJsonFieldVar(jsonFieldVar *JsonFieldVar)
type ErrorCtx ¶
type ErrorCtx struct {
CodeCtx
OneLiner string
Details string
Suggestion *string // Optional suggestion for fixing the error (rendered as "Try: ...")
}
TODO require RadError code? TODO perhaps include a map[node]string for multiple explanations for different parts of the code?
type EvalResult ¶
func NewEvalResult ¶
func NewEvalResult(val RadValue, ctrl CtrlKind) EvalResult
func NormalVal ¶
func NormalVal(val RadValue) EvalResult
func ReturnVal ¶
func ReturnVal(val RadValue) EvalResult
func YieldVal ¶
func YieldVal(val RadValue) EvalResult
type ExecutionResult ¶ added in v0.5.59
ExecutionResult represents the result of executing a statement
func NewExecutionResult ¶ added in v0.5.59
func NewExecutionResult(value RadValue, shouldPrint bool, err *RadError) *ExecutionResult
NewExecutionResult creates a new execution result
type ExpectedOutput ¶
type ExpectedOutput int
const ( Zero ExpectedOutput = iota One NoConstraint )
func (ExpectedOutput) Acceptable ¶
func (e ExpectedOutput) Acceptable(actual int) bool
func (ExpectedOutput) String ¶
func (e ExpectedOutput) String() string
type FakeSignalSource ¶ added in v0.11.0
type FakeSignalSource struct {
// contains filtered or unexported fields
}
FakeSignalSource is a test-only SignalSource that lets tests deliver signals deterministically rather than sending real OS signals.
Production code goes through realSignalSource (signals.go), which wraps os/signal. Tests inject a FakeSignalSource via RunnerInput.RSignal; calls to Notify record the subscription, and Fire delivers the named signal to every channel subscribed for it.
Lives in the production package (not _test.go) so test packages outside core/ can use it. Not part of the Rad public API.
func NewFakeSignalSource ¶ added in v0.11.0
func NewFakeSignalSource() *FakeSignalSource
func (*FakeSignalSource) Fire ¶ added in v0.11.0
func (f *FakeSignalSource) Fire(sig os.Signal)
Fire delivers sig to every channel currently subscribed to it.
Writes are non-blocking; if a channel's buffer is full the signal is dropped (mirrors how os/signal behaves under burst conditions). The SignalManager uses a 4-deep buffer so single-shot Fires are reliable.
Note: signal processing happens asynchronously on the SignalManager dispatch goroutine. Tests that need to observe the result should either (a) use a control flow that naturally synchronizes (e.g. assert defers ran after script exit), or (b) call FireAndWait below.
func (*FakeSignalSource) FiredCount ¶ added in v0.11.0
func (f *FakeSignalSource) FiredCount(sig os.Signal) int
FiredCount returns how many times sig has been fired since the source was created. Useful for assertions in tests.
func (*FakeSignalSource) Ignore ¶ added in v0.11.0
func (f *FakeSignalSource) Ignore(sigs ...os.Signal)
Ignore records the SIG_IGN request without touching the real process. Tests assert against WasIgnored to verify signal_ignore plumbs through to the OS seam (we can't deterministically test "process survives SIGPIPE" in-process).
func (*FakeSignalSource) Notify ¶ added in v0.11.0
func (f *FakeSignalSource) Notify(ch chan<- os.Signal, sigs ...os.Signal)
Notify records that ch wants to receive sigs. Mirrors signal.Notify, including its additive-but-idempotent semantics: subscribing the same channel+signal twice does NOT cause two deliveries on Fire. Without this dedup, Start() subscribes SIGINT then signal_trap("sigint", ...) subscribes it again, and a single Fire would deliver SIGINT twice - confusing the SignalManager's double-SIGINT detection.
func (*FakeSignalSource) Stop ¶ added in v0.11.0
func (f *FakeSignalSource) Stop(ch chan<- os.Signal)
Stop removes ch from all subscriptions.
func (*FakeSignalSource) WasIgnored ¶ added in v0.11.0
func (f *FakeSignalSource) WasIgnored(sig os.Signal) bool
WasIgnored reports whether sig was passed to Ignore since the source was created. Used by tests asserting signal_ignore behavior.
type FileReader ¶
type FileReader struct {
// contains filtered or unexported fields
}
func (*FileReader) HasContent ¶
func (fr *FileReader) HasContent() bool
func (*FileReader) Unwrap ¶
func (fr *FileReader) Unwrap() io.Reader
type FixedClock ¶
func (*FixedClock) Local ¶ added in v0.6.7
func (f *FixedClock) Local() *time.Location
func (*FixedClock) Now ¶
func (f *FixedClock) Now() time.Time
type FloatListRadArg ¶
type FloatListRadArg struct {
BaseRadArg
Value []float64
Default []float64
}
func NewFloatListRadArg ¶
func NewFloatListRadArg( name, short, argUsage, description string, hasDefault bool, defaultValue []float64, requires, excludes []string, ) FloatListRadArg
func (*FloatListRadArg) GetType ¶
func (f *FloatListRadArg) GetType() RadArgTypeT
func (*FloatListRadArg) Register ¶
func (f *FloatListRadArg) Register(cmd *ra.Cmd, mode RegistrationMode)
func (*FloatListRadArg) SetValue ¶
func (f *FloatListRadArg) SetValue(arg string)
type FloatRadArg ¶
type FloatRadArg struct {
BaseRadArg
Value float64
Default float64
RangeConstraint *ArgRangeConstraint
}
func NewFloatRadArg ¶
func NewFloatRadArg( name, short, argUsage, description string, hasDefault bool, defaultValue float64, constraint *ArgRangeConstraint, requires, excludes []string, ) FloatRadArg
func (*FloatRadArg) GetDescription ¶
func (f *FloatRadArg) GetDescription() string
func (*FloatRadArg) GetType ¶
func (f *FloatRadArg) GetType() RadArgTypeT
func (*FloatRadArg) Register ¶
func (f *FloatRadArg) Register(cmd *ra.Cmd, mode RegistrationMode)
func (*FloatRadArg) SetValue ¶
func (f *FloatRadArg) SetValue(arg string)
type FuncInvocation ¶
type FuncInvocation struct {
// contains filtered or unexported fields
}
func NewFnInvocation ¶
func NewFnInvocation( i *Interpreter, callNode rl.Node, funcName string, args []PosArg, namedArgs map[string]namedArg, isBuiltIn bool, ) FuncInvocation
func (FuncInvocation) GetArg ¶
func (f FuncInvocation) GetArg(name string) RadValue
func (FuncInvocation) GetBool ¶
func (f FuncInvocation) GetBool(name string) bool
func (FuncInvocation) GetFloat ¶
func (f FuncInvocation) GetFloat(name string) float64
func (FuncInvocation) GetFn ¶
func (f FuncInvocation) GetFn(name string) RadFn
func (FuncInvocation) GetInt ¶
func (f FuncInvocation) GetInt(name string) int64
func (FuncInvocation) GetIntAllowingBool ¶
func (f FuncInvocation) GetIntAllowingBool(name string) int64
func (FuncInvocation) GetList ¶
func (f FuncInvocation) GetList(name string) *RadList
func (FuncInvocation) GetMap ¶
func (f FuncInvocation) GetMap(name string) *RadMap
func (FuncInvocation) GetStr ¶
func (f FuncInvocation) GetStr(name string) RadString
func (FuncInvocation) Return ¶
func (f FuncInvocation) Return(vals ...interface{}) RadValue
func (FuncInvocation) ReturnErrf ¶
func (f FuncInvocation) ReturnErrf(code rl.Error, msg string, args ...interface{}) RadValue
type GeneralSort ¶
type GlobalFlagScope ¶ added in v0.11.0
type GlobalFlagScope int
GlobalFlagScope classifies which invocations a global flag applies to. Script-execution flags (e.g. --shell) and rad-level flags (e.g. --version) make no sense on embedded commands like `rad fmt`; those invocations reject them rather than silently changing behavior (issue #149).
const ( ScopeUniversal GlobalFlagScope = iota // any invocation, including embedded commands ScopeScriptOnly // configures Rad script execution ScopeRootOnly // rad itself, e.g. `rad --version` )
type HttpRequest ¶ added in v0.6.13
type HttpRequest struct {
RequestDef RequestDef
ResponseDef ResponseDef
}
type InputReader ¶ added in v0.5.59
type InputReader interface {
ReadStatement() (string, error)
SupportsMultiLine() bool
SetPrompt(primary, continuation string)
Shutdown() error
}
InputReader abstracts input handling (designed for future multi-line extension)
func NewSingleLineInputReader ¶ added in v0.5.59
func NewSingleLineInputReader() InputReader
NewSingleLineInputReader creates a new single-line input reader using RadIo
type IntListRadArg ¶
type IntListRadArg struct {
BaseRadArg
Value []int64
Default []int64
}
func NewIntListRadArg ¶
func NewIntListRadArg( name, short, argUsage, description string, hasDefault bool, defaultValue []int64, requires, excludes []string, ) IntListRadArg
func (*IntListRadArg) GetType ¶
func (f *IntListRadArg) GetType() RadArgTypeT
func (*IntListRadArg) Register ¶
func (f *IntListRadArg) Register(cmd *ra.Cmd, mode RegistrationMode)
func (*IntListRadArg) SetValue ¶
func (f *IntListRadArg) SetValue(arg string)
type IntRadArg ¶
type IntRadArg struct {
BaseRadArg
Value int64
Default int64
RangeConstraint *ArgRangeConstraint
}
func NewIntRadArg ¶
func (*IntRadArg) GetDescription ¶
func (*IntRadArg) GetType ¶
func (f *IntRadArg) GetType() RadArgTypeT
type InteractiveDriver ¶ added in v0.11.0
InteractiveDriver runs a radish prompt Model to completion. Production wraps the real terminal; tests inject a scripted driver (radish.ScriptDriver) so the real prompt logic and rendering run end-to-end without a TTY.
The no-TTY policy lives here, not in radish: the production driver delegates to radish.RunTerminal, which returns radish.ErrNotInteractive when stdin is not a terminal. Callers map that to a clear, actionable error. A scripted driver never reports ErrNotInteractive, which is exactly why interactive prompts become testable.
type Interpreter ¶
type Interpreter struct {
// contains filtered or unexported fields
}
func NewInterpreter ¶
func NewInterpreter(input InterpreterInput) *Interpreter
func (*Interpreter) CallStack ¶ added in v0.9.0
func (i *Interpreter) CallStack() []CallFrame
CallStack returns a copy of the current call stack (most recent first).
func (*Interpreter) Checkpoint ¶ added in v0.11.0
func (i *Interpreter) Checkpoint()
Checkpoint is called by the interpreter between statements. If a signal is pending it dispatches according to the current policy:
If a Rad handler is registered for the signal, invoke it with a single map argument: { signal, exit_code }. After it returns, always continue execution (Bash/Python/Ruby/Node semantics). The handler must call exit() explicitly if it wants to terminate.
If no handler is registered and the signal is terminating, route through RExit.Exit(128+sig) so defer blocks run and the exit code reflects the signal.
If no handler and the signal is non-terminating (SIGWINCH), drop it.
Checkpoint runs on the main interpreter goroutine, so it can safely touch the interpreter env / call deferred blocks / invoke Rad handlers.
Drains the entire pending queue in FIFO order before returning. The dispatching guard ensures nested checkpoints (e.g. those inside runBlock while a handler body is executing) become no-ops, so handler invocations stay in queue order rather than interleaving depth-first.
func (*Interpreter) EvaluateStatement ¶ added in v0.5.59
func (i *Interpreter) EvaluateStatement(input string) (RadValue, error)
EvaluateStatement evaluates a single statement string and returns the result This is designed for REPL use where individual statements are evaluated against a persistent interpreter environment
func (*Interpreter) GetScriptName ¶ added in v0.9.0
func (i *Interpreter) GetScriptName() string
GetScriptName returns the name/path of the current script.
func (*Interpreter) GetSrc ¶
func (i *Interpreter) GetSrc() string
func (*Interpreter) GetSrcForSpan ¶ added in v0.9.0
func (i *Interpreter) GetSrcForSpan(span rl.Span) string
func (*Interpreter) InitArgs ¶
func (i *Interpreter) InitArgs(args []RadArg)
func (*Interpreter) InitBuiltIns ¶
func (i *Interpreter) InitBuiltIns()
func (*Interpreter) NewRadPanic ¶
func (i *Interpreter) NewRadPanic(node rl.Node, err RadValue) *RadPanic
func (*Interpreter) RegisterWithExit ¶
func (i *Interpreter) RegisterWithExit()
func (*Interpreter) Run ¶
func (i *Interpreter) Run()
func (*Interpreter) Signals ¶ added in v0.11.0
func (i *Interpreter) Signals() *SignalManager
Signals exposes the interpreter's SignalManager. Used by builtins (signal_trap, signal_ignore) and by blocking-op call sites that need the signal-cancellation context.
func (*Interpreter) WithTmpSrc ¶
func (i *Interpreter) WithTmpSrc(tmpSrc string, fn func())
todo this is somewhat hacky, not a fan. only use when you're extremely sure fn won't panic
type InterpreterInput ¶ added in v0.6.16
type InterpreterInput struct {
Src string
Tree *rts.RadTree
ScriptName string
InvokedCommand *ScriptCommand
}
type InvocationLogEntry ¶ added in v0.6.11
type InvocationLogEntry struct {
EpochMillis int64 `json:"epoch_millis"`
ScriptPath string `json:"script_path"`
Args []string `json:"args,omitempty"` // omitempty when include_args=false
RadVersion string `json:"rad_version"`
DurationMillis int64 `json:"duration_millis"`
}
InvocationLogEntry represents a single script execution log entry
type InvocationLoggingConfig ¶ added in v0.6.11
type InvocationType ¶ added in v0.5.59
type InvocationType int
const ( NoScript InvocationType = iota // help, version, no args ScriptFile // existing file StdinScript // "rad -" EmbeddedCommand // built-in commands Repl // interactive REPL mode )
type JsonFieldVar ¶
type JsonFieldVar struct {
Name string
Path JsonPath
Span *rl.Span // source location for error reporting
}
func NewJsonFieldVar ¶
func NewJsonFieldVar(i *Interpreter, name string, span rl.Span, segments []JsonPathSegment) *JsonFieldVar
NewJsonFieldVar creates a JsonFieldVar from explicit path segments.
func NewJsonFieldVarSimple ¶ added in v0.9.0
func NewJsonFieldVarSimple(name string, span rl.Span) *JsonFieldVar
NewJsonFieldVarSimple creates a JsonFieldVar with a simple single-segment path. Used by the AST-based rad block interpreter for plain field names.
type JsonPath ¶
type JsonPath struct {
Segments []JsonPathSegment
}
type JsonPathSegment ¶
type JsonPathSegment struct {
Identifier string
SegmentSpan rl.Span
IdxSegments []JsonPathSegmentIdx
}
type JsonPathSegmentIdx ¶
type Label ¶ added in v0.9.0
type Label struct {
Span rl.Span
Message string
Primary bool // true = ^^^^ (red), false = ---- (blue)
}
Label represents a labeled span in a diagnostic.
func NewPrimaryLabel ¶ added in v0.9.0
NewPrimaryLabel creates a primary label (shown with ^^^^ in red).
type MockResponse ¶
type MockResponseSlice ¶
type MockResponseSlice []MockResponse
func (*MockResponseSlice) Set ¶
func (m *MockResponseSlice) Set(value string) error
func (*MockResponseSlice) String ¶
func (m *MockResponseSlice) String() string
func (*MockResponseSlice) Type ¶
func (m *MockResponseSlice) Type() string
type NullWriter ¶
type NullWriter struct{}
type PickResource ¶
type PickResource struct {
Opts []PickResourceOpt
}
type PickResourceOpt ¶
type PickResourceOptionSerde ¶
type PickResourceOptionSerde struct {
Keys []string `json:"keys"`
Values []interface{} `json:"values"`
}
type PickResourceSerde ¶
type PickResourceSerde struct {
Options []PickResourceOptionSerde `json:"options"`
}
type Printer ¶
type Printer interface {
// For Rad writers to debug their scripts. They input their debug logs with debug(). Enabled with --debug.
ScriptDebug(msg string)
// For Rad (tool) developers to debug the Rad tool, not Rad scripts. Enabled with --rad-debug.
// Rad writers should generally not need to use this.
RadDebugf(format string, args ...interface{})
// For regular output to the script user (literal string, no format interpretation)
Print(msg string)
// For regular output to the script user (with format string)
Printf(format string, args ...interface{})
// For secondary output to the user from Rad, usually to give some feedback, for example querying a URL.
// Goes to stderr.
RadStderrf(format string, args ...interface{})
// Used to print messages from the Rad script to stderr.
ScriptStderrf(format string, args ...interface{})
// For output that will be evaluated by the shell, used by --SHELL.
PrintForShellEval(msg string)
// For errors related to running the Rad script, with no token available for context.
// Exits.
ErrorExit(msg string)
// Like ErrorExit but takes an error code.
ErrorExitCode(msg string, errorCode int)
// TODO
CtxErrorExit(ctx ErrorCtx)
// TODO
CtxErrorCodeExit(ctx ErrorCtx, errorCode int)
ErrorCodeExitf(errorCode int, msgFmt string, args ...interface{})
// For errors not related to the Rad script, but to rad itself and its usage (probably misuse or rad bugs).
// Exits.
RadErrorExit(msg string)
// Similar to RadErrorExit, but prints usage after errors, and before exiting.
UsageErrorExit(msg string)
// Returns the appropriate writer for regular/standard (non-error) output.
GetStdWriter() io.Writer
}
todo make global instance, rather than passing into everything For all output to the user, except perhaps pflag-handled help/parsing errors.
func NewPrinter ¶
func NewPrinter(runner *RadRunner, isShellMode bool, isQuiet bool, isScriptDebug bool, isRadDebug bool) Printer
isShellMode directs all regular output to stderr, to avoid interfering with shell evals
isQuiet suppresses all output except shell eval prints and rad usage errors, unless isDebug is true, in which case it will also print rl errors stdout, and all debug messages
isScriptDebug will enable script debug messages isRadDebug will enable rad debug messages, and include stack traces for errors
type RadArg ¶
type RadArg interface {
GetExternalName() string
GetIdentifier() string
GetShort() string
GetArgUsage() string
GetDescription() string
DefaultAsString() string
HasNonZeroDefault() bool // todo
GetType() RadArgTypeT
Register(cmd *ra.Cmd, mode RegistrationMode)
Configured() bool // configured by the user in some way
IsDefined() bool // either configured or has a default
SetValue(value string)
IsOptional() bool
IsNullable() bool
GetSpan() *rl.Span // nil if not a script arg
Hidden(bool)
IsHidden() bool
Excludes(otherArg RadArg) bool
IsVariadic() bool
}
func CreateAndRegisterGlobalFlags ¶
func CreateAndRegisterGlobalFlags(invocationType InvocationType) []RadArg
func CreateFlag ¶
type RadArgTypeT ¶
type RadArgTypeT int
const ( ArgStringT RadArgTypeT = iota ArgIntT ArgFloatT ArgBoolT ArgStrListT ArgIntListT ArgFloatListT ArgBoolListT )
func ToRadArgTypeT ¶
func ToRadArgTypeT(str string) RadArgTypeT
type RadConfig ¶ added in v0.6.11
type RadConfig struct {
InvocationLogging *InvocationLoggingConfig `toml:"invocation_logging"`
}
func DefaultRadConfig ¶ added in v0.6.11
func DefaultRadConfig() *RadConfig
func LoadRadConfig ¶ added in v0.6.11
func LoadRadConfig() *RadConfig
LoadRadConfig loads the invocation logging configuration from ~/.rad/config.toml (configurable) Returns defaults if file doesn't exist or on parse errors (with warnings)
type RadError ¶
type RadError struct {
Span *rl.Span // source location where the error originated (nil if unknown)
Code rl.Error
// contains filtered or unexported fields
}
func NewErrorStr ¶ added in v0.11.0
NewErrorStr wraps a plain string (no format processing). Use this when the message is built upstream or comes from another error - it avoids the fmt.Sprintf pitfall where stray '%' characters in the message get treated as format directives. Use NewErrorStrf when you actually have format args.
func NewErrorStrf ¶
type RadExitHandler ¶ added in v0.6.11
type RadExitHandler struct {
// contains filtered or unexported fields
}
func NewExitHandler ¶ added in v0.6.11
func NewExitHandler(delegate func(int)) *RadExitHandler
func (*RadExitHandler) AddPreExitCallback ¶ added in v0.6.11
func (h *RadExitHandler) AddPreExitCallback(cb func())
func (*RadExitHandler) Exit ¶ added in v0.6.11
func (h *RadExitHandler) Exit(code int)
func (*RadExitHandler) SetExecuteDeferredStmtsFunc ¶ added in v0.6.11
func (h *RadExitHandler) SetExecuteDeferredStmtsFunc(f func(code int))
type RadFn ¶
type RadFn struct {
BuiltInFunc *BuiltInFunc // if this represents a built-in function
// below for non-built-in functions
ReprSpan *rl.Span // representative span (can point at this for errors)
Typing *rl.TypingFnT
Stmts []rl.Node
IsBlock bool // if this is a block function or expr. Block functions can only return with a 'return' stmt.
Env *Env // for closures
}
func NewBuiltIn ¶
func NewBuiltIn(inFunc BuiltInFunc) RadFn
func NewFnFromAST ¶ added in v0.9.0
func NewFnFromAST(i *Interpreter, typing *rl.TypingFnT, body []rl.Node, isBlock bool, defSpan *rl.Span) RadFn
NewFnFromAST creates a RadFn from AST components (FnDef or Lambda).
func (RadFn) Execute ¶
func (fn RadFn) Execute(f FuncInvocation) (out RadValue)
func (RadFn) ParamCount ¶ added in v0.7.0
ParamCount returns the number of parameters this function accepts. Returns 0 if typing information is unavailable.
type RadHome ¶
var RadHomeInst *RadHome
func NewRadHome ¶
func (*RadHome) GetStashForId ¶
func (*RadHome) GetStashSub ¶
func (*RadHome) SetStashId ¶
type RadList ¶
type RadList struct {
Values []RadValue
}
RadList does not carry a declared element type. Type enforcement happens only at function call boundaries via TypingT.IsCompatibleWith - mutations like Append are unchecked. See docs/type_system.md.
func NewRadList ¶
func NewRadList() *RadList
func NewRadListFromGeneric ¶
func NewRadListFromGeneric[T any](i *Interpreter, node rl.Node, list []T) *RadList
func (*RadList) AsActualStringList ¶
func (l *RadList) AsActualStringList(i *Interpreter, node rl.Node) []string
requires contents to actually be strings
func (*RadList) AsStringList ¶
func (*RadList) ShallowCopy ¶ added in v0.7.0
ShallowCopy creates a shallow copy of the list (values are not deep copied)
func (*RadList) SortAccordingToIndices ¶
func (l *RadList) SortAccordingToIndices(i *Interpreter, node rl.Node, indices []int64)
type RadMap ¶
type RadMap struct {
// contains filtered or unexported fields
}
RadMap does not carry declared key/value types. Type enforcement happens only at function call boundaries via TypingT.IsCompatibleWith - mutations like Set are unchecked. See docs/type_system.md.
func NewDurationMap ¶ added in v0.9.0
NewDurationMap builds a RadMap from a nanosecond value, providing conversions to all common time units.
func NewTimeMap ¶
func (*RadMap) ContainsKey ¶
func (*RadMap) SetPrimitiveBool ¶
func (*RadMap) SetPrimitiveFloat ¶
func (*RadMap) SetPrimitiveInt ¶
func (*RadMap) SetPrimitiveInt64 ¶
func (*RadMap) SetPrimitiveList ¶
func (*RadMap) SetPrimitiveMap ¶
func (*RadMap) SetPrimitiveStr ¶
func (*RadMap) ShallowCopy ¶ added in v0.7.0
ShallowCopy creates a shallow copy of the map (keys and values are not deep copied)
type RadPanic ¶
type RadPanic struct {
ErrV RadValue
ShellResult *shellResult // For shell command errors, contains exit code/stdout/stderr
}
RadPanic vs emitError:
Use RadPanic (catchable) for recoverable runtime errors that user code can reasonably handle via ?? or catch:
- Missing map keys, index out of bounds
- Null indexing (null.x, null[0])
- Failed parsing (parse_int, parse_json)
- Shell command failures
Use emitError (hard exit) for unrecoverable programming errors:
- Indexing into non-indexable types (int, float, bool)
- Undefined variables
- Type mismatches in built-in operations
Rule of thumb: if the error stems from data (user input, missing keys, nullable values), use RadPanic. If it stems from a logic bug in the script, use emitError.
type RadRunner ¶
type RadRunner struct {
// contains filtered or unexported fields
}
func NewRadRunner ¶
func NewRadRunner(runnerInput RunnerInput) *RadRunner
type RadString ¶
type RadString struct {
Segments []radStringSegment
}
func NewRadString ¶
todo should these methods be returning *RadString?
func RenderMarkdownForTerminal ¶ added in v0.9.0
RenderMarkdownForTerminal converts markdown text to a styled RadString for terminal display. It's a simple line-by-line renderer designed for the well-structured error documentation format.
func (RadString) CopyAttrTo ¶
Copies only the attributes of the first segment. Maybe could change somehow?
func (*RadString) CopyWithAttr ¶
func (s *RadString) CopyWithAttr(attr RadTextAttr) RadString
func (*RadString) SetAttr ¶
func (s *RadString) SetAttr(attr RadTextAttr)
func (*RadString) SetSegmentsHyperlink ¶
func (*RadString) SubSlice ¶ added in v0.9.0
SubSlice returns a substring from startRune (inclusive) to endRune (exclusive), preserving per-segment attributes. Callers must ensure 0 <= startRune <= endRune.
func (*RadString) ToRuneList ¶
func (*RadString) TrimPrefix ¶
func (*RadString) TrimSuffix ¶
type RadTextAttr ¶
type RadTextAttr int
const ( PLAIN RadTextAttr = iota BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE ORANGE PINK BOLD DIM ITALIC STRIKETHROUGH UNDERLINE )
when adding color attrs, update: enum, attrEnumToStrings, ToTblColor, AddAttrTo. when adding style attrs (bold, dim, etc.), update: enum, attrEnumToStrings, AddAttrTo. Style attrs are not supported in rad block color modifiers (no ToTblColor mapping).
func AttrFromString ¶
func AttrFromString(i *Interpreter, node rl.Node, str string) RadTextAttr
func TryColorFromString ¶
func TryColorFromString(str string) (RadTextAttr, bool)
func (RadTextAttr) AddAttrTo ¶
func (a RadTextAttr) AddAttrTo(clr *color.Color)
func (RadTextAttr) Colorize ¶
func (a RadTextAttr) Colorize(str string) string
func (RadTextAttr) IsColor ¶ added in v0.10.0
func (a RadTextAttr) IsColor() bool
func (RadTextAttr) String ¶
func (a RadTextAttr) String() string
func (RadTextAttr) ToTblColor ¶
func (a RadTextAttr) ToTblColor() tblwriter.Color
type RadTypeVisitor ¶
type RadTypeVisitor struct {
// contains filtered or unexported fields
}
RadTypeVisitor is my best attempt at trying to work around the fact that Go doesn't have an exhaustive switch on sealed types/enums. This visitor is verbose, but should make it easy to update existing code when adding a new type to Rad.
func NewTypeVisitor ¶
func NewTypeVisitor(i *Interpreter, node rl.Node) *RadTypeVisitor
func NewTypeVisitorUnsafe ¶
func NewTypeVisitorUnsafe() *RadTypeVisitor
func (*RadTypeVisitor) ForBool ¶
func (v *RadTypeVisitor) ForBool(handler func(RadValue, bool)) *RadTypeVisitor
func (*RadTypeVisitor) ForDefault ¶
func (v *RadTypeVisitor) ForDefault(handler func(RadValue)) *RadTypeVisitor
func (*RadTypeVisitor) ForError ¶
func (v *RadTypeVisitor) ForError(handler func(RadValue, *RadError)) *RadTypeVisitor
func (*RadTypeVisitor) ForFloat ¶
func (v *RadTypeVisitor) ForFloat(handler func(RadValue, float64)) *RadTypeVisitor
func (*RadTypeVisitor) ForFn ¶
func (v *RadTypeVisitor) ForFn(handler func(RadValue, RadFn)) *RadTypeVisitor
func (*RadTypeVisitor) ForInt ¶
func (v *RadTypeVisitor) ForInt(handler func(RadValue, int64)) *RadTypeVisitor
func (*RadTypeVisitor) ForList ¶
func (v *RadTypeVisitor) ForList(handler func(RadValue, *RadList)) *RadTypeVisitor
func (*RadTypeVisitor) ForMap ¶
func (v *RadTypeVisitor) ForMap(handler func(RadValue, *RadMap)) *RadTypeVisitor
func (*RadTypeVisitor) ForNull ¶
func (v *RadTypeVisitor) ForNull(handler func(RadValue, RadNull)) *RadTypeVisitor
func (*RadTypeVisitor) ForString ¶
func (v *RadTypeVisitor) ForString(handler func(RadValue, RadString)) *RadTypeVisitor
func (*RadTypeVisitor) UnhandledTypeError ¶
func (v *RadTypeVisitor) UnhandledTypeError(val RadValue)
func (*RadTypeVisitor) Visit ¶
func (v *RadTypeVisitor) Visit(acceptor RadTypeVisitorAcceptor)
type RadTypeVisitorAcceptor ¶
type RadTypeVisitorAcceptor interface {
Accept(visitor *RadTypeVisitor)
}
type RadValue ¶
type RadValue struct {
// int64, float64, RadString, bool stored as values
// collections (lists, maps) stored as pointers
// lists are *RadList
// maps are *RadMap
// functions are RadFn
// nulls are RadNull
// errors are *RadError
Val interface{}
}
func ConvertToNativeTypes ¶
func ConvertToNativeTypes(i *Interpreter, node rl.Node, val interface{}) RadValue
it was originally implemented because we might capture JSON as a list of unhandled types, but now we should be able to capture json and convert it entirely to native Rad types up front
func ConvertValuesToNativeTypes ¶
func ConvertValuesToNativeTypes(i *Interpreter, node rl.Node, vals []interface{}) []RadValue
func TryConvertJsonToNativeTypes ¶
func TryConvertJsonToNativeTypes(i *Interpreter, node rl.Node, maybeJsonStr string) (RadValue, error)
Convert a json interface{} into native Rad types
func (RadValue) Accept ¶
func (v RadValue) Accept(visitor *RadTypeVisitor)
func (RadValue) GoMapKey ¶ added in v0.9.2
GoMapKey returns a plain string representation suitable for Go map keys (e.g. JSON serialization). Unlike Hash(), it has no type prefix. Note: since Go maps / JSON require string keys, maps with distinct Rad keys that share a string representation (e.g. int 1 and string "1") will collide in the Go map. This is an inherent limitation of the target format.
func (RadValue) ModifyByKey ¶ added in v0.9.0
func (RadValue) RequireBool ¶
func (v RadValue) RequireBool(i *Interpreter, node rl.Node) bool
func (RadValue) RequireError ¶
func (v RadValue) RequireError(i *Interpreter, node rl.Node) *RadError
func (RadValue) RequireFloatAllowingInt ¶
func (v RadValue) RequireFloatAllowingInt(i *Interpreter, node rl.Node) float64
func (RadValue) RequireInt ¶
func (v RadValue) RequireInt(i *Interpreter, node rl.Node) int64
func (RadValue) RequireIntAllowingBool ¶
func (v RadValue) RequireIntAllowingBool(i *Interpreter, node rl.Node) int64
func (RadValue) RequireList ¶
func (v RadValue) RequireList(i *Interpreter, node rl.Node) *RadList
func (RadValue) RequireMap ¶
func (v RadValue) RequireMap(i *Interpreter, node rl.Node) *RadMap
func (RadValue) RequireNonVoid ¶ added in v0.9.2
func (v RadValue) RequireNonVoid(i *Interpreter, node rl.Node) RadValue
RequireNonVoid emits ErrVoidValue if v is VOID_SENTINEL.
func (RadValue) RequireNotType ¶
func (RadValue) RequireStr ¶
func (v RadValue) RequireStr(i *Interpreter, node rl.Node) RadString
func (RadValue) RequireType ¶
func (RadValue) ToCompatSubject ¶
func (v RadValue) ToCompatSubject() (out rl.TypingCompatVal)
func (RadValue) TruthyFalsy ¶
func (RadValue) TryGetBool ¶
func (RadValue) TryGetError ¶
func (RadValue) TryGetFloatAllowingInt ¶
func (RadValue) TryGetList ¶
type ReadlineInputReader ¶ added in v0.5.59
type ReadlineInputReader struct {
}
Future: ReadlineInputReader for enhanced input with history This interface design allows us to swap in a readline-based implementation later
type RegistrationMode ¶ added in v0.6.16
type RegistrationMode int
RegistrationMode defines how an argument should be registered on a Ra command. These modes enforce the correct combination of positional capability and Ra global behavior.
const ( // AsScriptArg: Script args on root when NO commands exist // - Positional + flag capable (flagOnly=false) // - Not a Ra global (asRaGlobal=false) AsScriptArg RegistrationMode = iota // AsCommandArg: Command-specific args on a subcommand // - Positional + flag capable (flagOnly=false) // - Not a Ra global (asRaGlobal=false) AsCommandArg // AsScriptFlagOnly: Script args on subcommands when commands exist // - Flag-only (flagOnly=true) // - Not a Ra global (asRaGlobal=false) // - Script args are shared across commands but don't interfere with command positionals AsScriptFlagOnly // AsGlobalFlag: Rad's built-in global flags (--help, --version, --color, etc.) // - Flag-only (flagOnly=true) // - Ra global (asRaGlobal=true, inherits to all subcommands) AsGlobalFlag )
type ReplSession ¶ added in v0.5.59
type ReplSession interface {
Run() error
ExecuteStatement(input string) (*ExecutionResult, error)
GetEnvironment() *Env
Shutdown() error
}
ReplSession represents the main REPL session contract
func CreateReplSession ¶ added in v0.5.59
func CreateReplSession() (ReplSession, error)
CreateReplSession creates a new REPL session with default configuration
func NewReplSession ¶ added in v0.5.59
func NewReplSession(interpreter *Interpreter, inputReader InputReader) ReplSession
NewReplSession creates a new REPL session with the given interpreter and input reader
type RequestDef ¶
type RequestDef struct {
Method string
Url string
Headers map[string][]string
Body *string
Insecure bool
Quiet bool
}
func NewRequestDef ¶
func NewRequestDef(method, url string, headers map[string][]string, body *string) RequestDef
func (RequestDef) BodyReader ¶
func (r RequestDef) BodyReader() io.Reader
type Requester ¶
type Requester struct {
// contains filtered or unexported fields
}
func NewRequester ¶
func NewRequester() *Requester
func (*Requester) AddMockedResponse ¶
func (*Requester) ClearMockedResponses ¶ added in v0.6.18
func (r *Requester) ClearMockedResponses()
func (*Requester) IsInsecure ¶ added in v0.9.0
func (*Requester) Request ¶
func (r *Requester) Request(ctx context.Context, def RequestDef) ResponseDef
Request executes an HTTP request. ctx is the signal-cancellation context; if it fires (e.g. SIGINT), the in-flight request is aborted. Tests can pass context.Background() if signal handling is not relevant.
func (*Requester) RequestJson ¶
func (*Requester) SetCaptureCallback ¶ added in v0.6.13
func (r *Requester) SetCaptureCallback(cb func(HttpRequest))
func (*Requester) SetInsecure ¶ added in v0.9.0
type ResponseDef ¶
type ResponseDef struct {
Success bool // true if 2xx response, else false
StatusCode *int
Headers *map[string][]string
Body *string
Error *string // signifies error making request
DurationSeconds float64
}
todo we should add more e.g. reason, message
func NewResponseDef ¶
func (ResponseDef) ToRadMap ¶
func (r ResponseDef) ToRadMap(i *Interpreter, callNode rl.Node) *RadMap
type RunnerInput ¶
type RunnerInput struct {
RIo *RadIo
RExit *func(int)
// RForceExit is the raw hard-exit (no defers/callbacks), distinct from
// RExit which wraps into a RadExitHandler. Tests inject a record-only
// variant; see global RForceExit.
RForceExit *func(int)
RReq *Requester
RClock Clock
RSleep *func(ctx context.Context, duration time.Duration)
RShell *func(ctx context.Context, invocation ShellInvocation) (string, string, int)
RConfirm *func(title string, prompt string) (bool, error)
RSignal SignalSource
RadHome *string
RTermWidth *int
// RInteractive overrides the interactive-prompt driver. nil uses the real
// terminal; tests inject a scripted driver. See InteractiveDriver.
RInteractive InteractiveDriver
}
type ScopedGlobalFlag ¶ added in v0.11.0
type ScopedGlobalFlag struct {
Arg RadArg
Scope GlobalFlagScope
}
type ScriptArg ¶
type ScriptArg struct {
Name string // Internal (as written in script)
ExternalName string // External (hyphenated for CLI)
Span rl.Span
Src string // Full script source, for error context rendering
Short *string
Type RadArgTypeT
Description *string
IsNullable bool // aka is optional. e.g. 'string?' syntax
HasDefaultValue bool
IsVariadic bool // whether this is a variadic argument (*options str)
EnumConstraint *[]string
RegexConstraint *regexp.Regexp
RangeConstraint *ArgRangeConstraint
RequiresConstraint []string
ExcludesConstraint []string
// first check the Type and HasDefaultValue, then get the value
DefaultString *string
DefaultStringList *[]string
DefaultInt *int64
DefaultIntList *[]int64
DefaultFloat *float64
DefaultFloatList *[]float64
DefaultBool *bool
DefaultBoolList *[]bool
}
func FromArgDecl ¶
func FromArgDecl( decl rl.ArgDecl, src string, enumConstraint *rl.ArgEnumConstraint, regexConstraint *rl.ArgRegexConstraint, rangeConstraint *rl.ArgRangeConstraint, requiresConstraint []string, excludesConstraint []string, ) *ScriptArg
type ScriptCommand ¶ added in v0.6.16
type ScriptCommand struct {
Name string // Internal (as written in script)
ExternalName string // External (hyphenated for CLI)
Description *string
Args []*ScriptArg // Command-specific arguments
IsLambdaCallback bool
CallbackName *string // For function reference callbacks
CallbackLambda *rl.Lambda // Eagerly converted AST lambda
}
ScriptCommand represents a command defined in a Rad script's command: block
func FromCmdBlock ¶ added in v0.6.16
func FromCmdBlock(cmdBlock *rl.CmdBlock, src string) (*ScriptCommand, error)
type ScriptData ¶
type ScriptData struct {
ScriptName string
Args []*ScriptArg
Commands []*ScriptCommand
Description *string
Tree *rts.RadTree
Src string
DisableGlobalOpts bool
DisableArgsBlock bool
HasArgsBlock bool
}
func ExtractMetadata ¶
func ExtractMetadata(src string) *ScriptData
func (*ScriptData) ValidateNoErrors ¶
func (sd *ScriptData) ValidateNoErrors()
type Severity ¶ added in v0.9.0
type Severity int
Severity indicates the severity level of a diagnostic.
type ShellExecutor ¶ added in v0.6.13
ShellExecutor is the function type for executing shell commands. Returns: (stdout, stderr, exitCode) - only returns captured output based on invocation.Capture* fields. The ctx is the interpreter's signal-cancellation context; the executor should wake up promptly when it's canceled (the subprocess shares Rad's process group, so it will have received the signal too).
type ShellInvocation ¶ added in v0.6.13
type ShellInvocation struct {
Command string
CaptureStdout bool
CaptureStderr bool
IsQuiet bool
// IsConfirm is informational: the confirmation prompt is handled in
// executeShellCmd before the executor runs, so executors don't act on it.
// Kept for callers/observability (e.g. test assertions).
IsConfirm bool
}
ShellInvocation captures the details of a shell command invocation
type SignalManager ¶ added in v0.11.0
type SignalManager struct {
// contains filtered or unexported fields
}
SignalManager owns signal-handling state for an Interpreter.
It coordinates between the OS signal source (or a test fake) and the interpreter's per-statement checkpoint. The OS-facing side runs in a dedicated goroutine that drains signals from notifyCh and records them in pendingSig; the interpreter side reads pendingSig at safe points between statements and dispatches to the registered Rad handler.
Blocking operations (sleep, shell exec, HTTP) consult Ctx() so they can wake promptly when a signal arrives - otherwise the handler would not run until the blocking call returned on its own.
func NewSignalManager ¶ added in v0.11.0
func NewSignalManager() *SignalManager
NewSignalManager constructs an inactive SignalManager. The dispatch goroutine is started lazily by Start (called from Interpreter.Run).
func (*SignalManager) ClearInHandler ¶ added in v0.11.0
func (sm *SignalManager) ClearInHandler()
func (*SignalManager) Ctx ¶ added in v0.11.0
func (sm *SignalManager) Ctx() context.Context
Ctx returns the current signal-cancellation context. Blocking operations should pass this to select{} or http.NewRequestWithContext so they can wake up promptly when a signal arrives.
func (*SignalManager) DrainPending ¶ added in v0.11.0
func (sm *SignalManager) DrainPending() (string, bool)
DrainPending returns the next pending signal (if any) and removes it from the queue. Called by the interpreter's checkpoint between statements.
func (*SignalManager) Handler ¶ added in v0.11.0
func (sm *SignalManager) Handler(name string) (RadFn, bool)
Handler returns the registered handler for the named signal. The second return is false if no handler is registered.
func (*SignalManager) Ignore ¶ added in v0.11.0
func (sm *SignalManager) Ignore(name string) error
Ignore installs OS-level SIG_IGN for the named signal. Useful for SIGPIPE when the script pipes its output (e.g. `script | head`) and should not terminate when the downstream consumer closes the pipe.
func (*SignalManager) MarkInHandler ¶ added in v0.11.0
func (sm *SignalManager) MarkInHandler(name string)
MarkInHandler / ClearInHandler bracket handler execution for double-Ctrl+C detection.
func (*SignalManager) NotifyCh ¶ added in v0.11.0
func (sm *SignalManager) NotifyCh() chan<- os.Signal
NotifyCh returns the channel that subscribed signals are delivered to. Tests use this with FakeSignalSource to inject signals deterministically (write to this channel directly, then wait for DrainPending to observe the result). Not part of the public Rad API.
func (*SignalManager) RefreshCtx ¶ added in v0.11.0
func (sm *SignalManager) RefreshCtx()
RefreshCtx is called after a handler returns (or a default-terminate decision is made and forgone) so the next blocking op gets a fresh (non-canceled) context.
func (*SignalManager) Start ¶ added in v0.11.0
func (sm *SignalManager) Start()
Start launches the background dispatch goroutine and subscribes to the signals Rad handles by default (SIGINT, SIGTERM). Idempotent.
Other signals are subscribed lazily when the script calls signal_trap or signal_ignore. This keeps the default behavior minimal: Rad takes over SIGINT/SIGTERM so it can route them through RExit.Exit (and thereby run defer blocks); everything else inherits Go's default behavior until the script opts in.
func (*SignalManager) Stop ¶ added in v0.11.0
func (sm *SignalManager) Stop()
Stop tears down the dispatch goroutine and OS subscriptions. Safe to call multiple times. Called from Interpreter.Run's defer so embedded/test usage doesn't accumulate leaked goroutines across interpreter lifetimes.
func (*SignalManager) Trap ¶ added in v0.11.0
func (sm *SignalManager) Trap(name string, fn RadFn) error
Trap registers fn as the handler for the named signal (e.g. "sigint"). Replacing an existing handler is allowed; the previous handler is dropped. Returns an error if the signal name is not supported on the current platform.
type SignalSource ¶ added in v0.11.0
type SignalSource interface {
Notify(ch chan<- os.Signal, sigs ...os.Signal)
Stop(ch chan<- os.Signal)
Ignore(sigs ...os.Signal)
}
SignalSource is the seam between the SignalManager and the OS signal machinery. The production implementation wraps os/signal directly; tests inject a fake whose Fire method synchronously delivers a signal to the channel without involving the OS (so tests do not race against the real process signal queue).
type SingleLineInputReader ¶ added in v0.5.59
type SingleLineInputReader struct {
// contains filtered or unexported fields
}
SingleLineInputReader implements InputReader for single-line input (MVP) Uses RadIo abstractions for full testability
func (*SingleLineInputReader) ReadStatement ¶ added in v0.5.59
func (r *SingleLineInputReader) ReadStatement() (string, error)
ReadStatement reads a single line of input from the user
func (*SingleLineInputReader) SetPrompt ¶ added in v0.5.59
func (r *SingleLineInputReader) SetPrompt(primary, continuation string)
SetPrompt allows customizing the prompts
func (*SingleLineInputReader) Shutdown ¶ added in v0.5.59
func (r *SingleLineInputReader) Shutdown() error
Shutdown cleans up resources
func (*SingleLineInputReader) SupportsMultiLine ¶ added in v0.5.59
func (r *SingleLineInputReader) SupportsMultiLine() bool
SupportsMultiLine returns false for MVP (single-line only)
type StringListRadArg ¶
type StringListRadArg struct {
BaseRadArg
Value []string
Default []string
}
func NewStringListRadArg ¶
func NewStringListRadArg( name, short, argUsage, description string, hasDefault bool, defaultValue, requires, excludes []string, ) StringListRadArg
func (*StringListRadArg) GetType ¶
func (f *StringListRadArg) GetType() RadArgTypeT
func (*StringListRadArg) Register ¶
func (f *StringListRadArg) Register(cmd *ra.Cmd, mode RegistrationMode)
func (*StringListRadArg) SetValue ¶
func (f *StringListRadArg) SetValue(arg string)
type StringRadArg ¶
type StringRadArg struct {
BaseRadArg
Value string
Default string
EnumConstraint *[]string
RegexConstraint *regexp.Regexp
}
func NewStringRadArg ¶
func (*StringRadArg) GetDescription ¶
func (f *StringRadArg) GetDescription() string
func (*StringRadArg) GetType ¶
func (f *StringRadArg) GetType() RadArgTypeT
func (*StringRadArg) Register ¶
func (f *StringRadArg) Register(cmd *ra.Cmd, mode RegistrationMode)
func (*StringRadArg) SetValue ¶
func (f *StringRadArg) SetValue(arg string)
type TblWriter ¶
type TblWriter struct {
// contains filtered or unexported fields
}
TblWriter wraps go-tbl for Rad's table rendering, adding terminal-width-aware truncation and column coloring. Single-use: Render() mutates internal state (truncating cells/headers), so a fresh instance must be created for each table.
func NewTblWriter ¶
func NewTblWriter() *TblWriter
func (*TblWriter) SetColumnColoring ¶
func (*TblWriter) SetTranspose ¶ added in v0.10.0
type Trie ¶
type Trie struct {
// contains filtered or unexported fields
}
func CreateTrie ¶
func CreateTrie(i *Interpreter, radKeywordNode rl.Node, jsonFields []JsonFieldVar) *Trie
func (*Trie) Insert ¶
func (t *Trie) Insert(field JsonFieldVar)
func (*Trie) TraverseTrie ¶
func (t *Trie) TraverseTrie(data interface{})
Source Files
¶
- arg_types.go
- args.go
- args_helpers.go
- args_mock.go
- clock.go
- cmds.go
- command_types.go
- completion.go
- config.go
- consts.go
- defer.go
- diagnostic.go
- diagnostic_render.go
- docs.go
- env.go
- error_docs.go
- errors.go
- eval_ctx.go
- exit.go
- expr_ops.go
- flags_global.go
- func_colorize.go
- func_convert_duration.go
- func_exit.go
- func_helpers.go
- func_matches.go
- func_multipick.go
- func_parse_date.go
- func_parse_duration.go
- func_pick.go
- func_print.go
- func_rand.go
- func_range.go
- func_replace.go
- func_signal_ignore.go
- func_signal_trap.go
- func_sleep.go
- func_split.go
- func_split_lines.go
- func_to_json.go
- funcs.go
- funcs_internal.go
- funcs_internal_check_from_logs.go
- funcs_stat_linux.go
- fuzzy.go
- global.go
- home_stash.go
- input.go
- interactive.go
- interactive_args.go
- interpreter.go
- io.go
- json_algo.go
- json_algo_trie.go
- json_path.go
- logging_invocation.go
- logging_rotation.go
- logging_rotation_unix.go
- markdown_render.go
- parsed_types.go
- platform.go
- printer.go
- rad_block.go
- rad_duration.go
- rad_time.go
- repl.go
- repl_input.go
- repl_session.go
- requester.go
- resources.go
- runner.go
- runner_usage.go
- script_meta.go
- shell.go
- signals.go
- signals_unix.go
- slicing.go
- sorting.go
- tbl.go
- test_signals.go
- text_attr.go
- type_error.go
- type_fn.go
- type_list.go
- type_map.go
- type_null.go
- type_rad_value.go
- type_string.go
- type_visitor.go
- utils.go
- version.go