Documentation
¶
Overview ¶
Package fynerisor provides Risor v2 language bindings for the Fyne GUI framework.
Fynerisor enables building cross-platform desktop applications using Risor v2 scripts with full access to Fyne's widget and container system. Create interactive GUIs with buttons, forms, tables, charts, and more through simple factory functions.
Version ¶
Current Version: 0.3.0 Risor Compatibility: v2.1+ (arrow functions required) Fyne Compatibility: v2.7+
Features ¶
- 34 widget bindings (60% coverage - all high/medium priority complete)
- Button importance levels and validation
- Entry validation with visual feedback
- SQL module for MySQL, PostgreSQL, SQLite, SQL Server
- HTTP module for REST API calls
- Layout containers (VBox, HBox, Border, Split, Scroll)
- Canvas objects and charts
- Thread-safe callback handling
- Property access and modification from scripts
- Constants global for Fyne enums
Quick Start ¶
Create a simple GUI application:
package main
import "github.com/uidbz/fynerisor"
func main() {
fw := fynerisor.NewApp("Hello",
fynerisor.WithHTTP(),
fynerisor.WithSQL(),
)
script := `
require(["v0.3", "@gui", "@http"])
let btn = widget.NewButton("Click Me", () => {
window.SetStatus("Button clicked!")
})
btn.Importance = constants.ImportanceHigh
window.SetContent(btn)
`
fw.LoadScript(script)
fw.Execute()
fw.ShowAndRun()
}
Requirements ¶
Scripts can declare version and module requirements:
require(["v0.2", "@sql", "@http"]) // Multiple requirements
require("v0.2.0") // Minimum version
require("@sql") // Module must be enabled
Global Objects ¶
Risor scripts have access to the following global objects:
- window: Main window control (SetContent, SetStatus, Title property)
- widget: Factory for all widgets
- container: Factory for layouts
- canvas: Factory for canvas objects
- chart: Factory for charts
- constants: Fyne constants (button importance, etc.)
- app: Application metadata (app.name)
Options ¶
Enable additional modules using options:
fw := fynerisor.NewApp("My App",
fynerisor.WithHTTP(), // HTTP client
fynerisor.WithSQL(), // Database connectivity
fynerisor.WithOS(), // OS utilities
fynerisor.WithIO(), // File I/O (cp, etc.)
fynerisor.WithStrings(), // String manipulation
fynerisor.WithFilepath(), // Path utilities
fynerisor.WithTime(), // Time operations
fynerisor.WithStatusCallback(func(status string) {
log.Println("Status:", status)
}),
fynerisor.WithAppName("myapp"),
)
Risor v2 Syntax ¶
Fynerisor requires Risor v2 with arrow function syntax:
// Correct
let onClick = () => { print("clicked") }
let process = (x) => x * 2
// Wrong - func keyword not supported
func onClick() { print("clicked") }
No for/while loops - use functional methods:
// Correct
let doubled = [1, 2, 3].map(x => x * 2)
list.each(item => print(item))
// Wrong - no loop keywords
for i in list { }
while (condition) { }
Thread Safety ¶
The Risor VM is single-threaded and NOT thread-safe. All widget callbacks execute synchronously in the UI thread. Never spawn goroutines or use async patterns inside callbacks.
See CONCURRENCY.md for detailed information about the race condition bug that was fixed in v0.2.0.
SQL Module ¶
The SQL module supports MySQL, PostgreSQL, SQLite, and SQL Server:
let conn = sql.connect("sqlite3::memory:")
conn.exec("CREATE TABLE users (id INT, name TEXT)")
conn.exec("INSERT INTO users VALUES (?, ?)", 1, "Alice")
// Query returns streaming iterator with .map() and .each()
let names = conn.query("SELECT * FROM users").map(row => row["name"])
// Or use .each() for side effects
conn.query("SELECT * FROM users").each(row => print(row["name"]))
// Or .collect() to load all into memory first
let rows = conn.query("SELECT * FROM users").collect()
conn.close()
HTTP Module ¶
Make HTTP requests from Risor scripts:
let response = http.get("https://api.example.com/data")
let data = response.json() // parse JSON response
print(data["items"])
Examples ¶
See the examples/ directory for 21 complete working examples:
- 01-hello-world: Simple label display
- 02-button-callback: Interactive button with state
- 03-form-input: Form with validation
- 04-table-display: Paginated table
- 05-progress-widgets: Progress bars and sliders
- 11-list: Virtualized scrolling list
- 12-tree: Hierarchical tree widget
- 13-http-fetch: HTTP requests and JSON
- 15-sql-test: Database connectivity
- 17-gridwrap: Grid layout
- 18-textgrid: Code display
- 19-richtext: Markdown formatting
- 20-button-importance: Button styling
- 21-form-validation: Entry validation
CLI Tool ¶
The fynerisor command-line tool runs Risor GUI scripts:
fynerisor app.risor fynerisor --watch app.risor # auto-reload on changes fynerisor --width 1024 --height 768 app.risor fynerisor --headless app.risor # for testing fynerisor --globals data.json app.risor # custom globals
Custom Globals ¶
Inject custom data or functions into scripts:
import "github.com/deepnoodle-ai/risor/v2"
customData := risor.WithEnv(map[string]any{
"api": myAPIObject,
"config": configData,
})
fw := fynerisor.NewApp("My App",
fynerisor.WithGlobals(customData),
)
Scripts can then access: api.someMethod() and config.someProperty
Index ¶
- Constants
- func GetAppVersion() string
- func SetAppVersion(version string)
- type App
- func (a *App) Attrs() []object.AttrSpec
- func (a *App) Cost() int
- func (a *App) Equals(other object.Object) bool
- func (a *App) GetAttr(name string) (object.Object, bool)
- func (a *App) Inspect() string
- func (a *App) Interface() interface{}
- func (a *App) IsTruthy() bool
- func (a *App) RunOperation(opType op.BinaryOpType, right object.Object) (object.Object, error)
- func (a *App) SetAttr(name string, value object.Object) error
- func (a *App) String() string
- func (a *App) Type() object.Type
- type Binding
- func (obj *Binding) Attrs() []object.AttrSpec
- func (obj *Binding) Cost() int
- func (obj *Binding) Equals(other object.Object) bool
- func (obj *Binding) GetAttr(name string) (object.Object, bool)
- func (obj *Binding) Inspect() string
- func (obj *Binding) Interface() interface{}
- func (obj *Binding) IsTruthy() bool
- func (obj *Binding) MarshalJSON() ([]byte, error)
- func (obj *Binding) RunOperation(opType op.BinaryOpType, right object.Object) (object.Object, error)
- func (obj *Binding) SetAttr(name string, value object.Object) error
- func (obj *Binding) Type() object.Type
- type Canvas
- func (obj *Canvas) Attrs() []object.AttrSpec
- func (obj *Canvas) Equals(other object.Object) bool
- func (obj *Canvas) GetAttr(name string) (object.Object, bool)
- func (obj *Canvas) Inspect() string
- func (obj *Canvas) Interface() interface{}
- func (obj *Canvas) IsTruthy() bool
- func (obj *Canvas) MarshalJSON() ([]byte, error)
- func (obj *Canvas) RunOperation(opType op.BinaryOpType, right object.Object) (object.Object, error)
- func (obj *Canvas) SetAttr(name string, value object.Object) error
- func (obj *Canvas) Type() object.Type
- type Chart
- func (obj *Chart) Attrs() []object.AttrSpec
- func (obj *Chart) Equals(other object.Object) bool
- func (obj *Chart) GetAttr(name string) (object.Object, bool)
- func (obj *Chart) Inspect() string
- func (obj *Chart) Interface() interface{}
- func (obj *Chart) IsTruthy() bool
- func (obj *Chart) MarshalJSON() ([]byte, error)
- func (obj *Chart) RunOperation(opType op.BinaryOpType, right object.Object) (object.Object, error)
- func (obj *Chart) SetAttr(name string, value object.Object) error
- func (obj *Chart) Type() object.Type
- type Constants
- func (obj *Constants) Attrs() []object.AttrSpec
- func (obj *Constants) Cost() int
- func (obj *Constants) Equals(other object.Object) bool
- func (obj *Constants) GetAttr(name string) (object.Object, bool)
- func (obj *Constants) Inspect() string
- func (obj *Constants) Interface() interface{}
- func (obj *Constants) IsTruthy() bool
- func (obj *Constants) MarshalJSON() ([]byte, error)
- func (obj *Constants) RunOperation(opType op.BinaryOpType, right object.Object) (object.Object, error)
- func (obj *Constants) SetAttr(name string, value object.Object) error
- func (obj *Constants) Type() object.Type
- type Container
- func (obj *Container) Attrs() []object.AttrSpec
- func (obj *Container) Equals(other object.Object) bool
- func (obj *Container) GetAttr(name string) (object.Object, bool)
- func (obj *Container) Inspect() string
- func (obj *Container) Interface() interface{}
- func (obj *Container) IsTruthy() bool
- func (obj *Container) MarshalJSON() ([]byte, error)
- func (obj *Container) RunOperation(opType op.BinaryOpType, right object.Object) (object.Object, error)
- func (obj *Container) SetAttr(name string, value object.Object) error
- func (obj *Container) Type() object.Type
- type ContextBuilder
- func (cb *ContextBuilder) EnabledModules() map[string]bool
- func (cb *ContextBuilder) Eval(script string) (any, error)
- func (cb *ContextBuilder) EvalWithImports(script string, fetchFunc func(path string) (string, error)) (any, error)
- func (cb *ContextBuilder) ImportScript(source string) error
- func (cb *ContextBuilder) LoadScript(script string)
- type Fyne
- func (obj *Fyne) Attrs() []object.AttrSpec
- func (obj *Fyne) Cost() int
- func (obj *Fyne) Equals(other object.Object) bool
- func (obj *Fyne) GetAttr(name string) (object.Object, bool)
- func (obj *Fyne) Inspect() string
- func (obj *Fyne) Interface() interface{}
- func (obj *Fyne) IsTruthy() bool
- func (obj *Fyne) MarshalJSON() ([]byte, error)
- func (obj *Fyne) RunOperation(opType op.BinaryOpType, right object.Object) (object.Object, error)
- func (obj *Fyne) SetAttr(name string, value object.Object) error
- func (obj *Fyne) Type() object.Type
- type IsCanvasObject
- type Menu
- func (obj *Menu) Attrs() []object.AttrSpec
- func (obj *Menu) Cost() int
- func (obj *Menu) Equals(other object.Object) bool
- func (obj *Menu) GetAttr(name string) (object.Object, bool)
- func (obj *Menu) Inspect() string
- func (obj *Menu) Instance() *fyne.Menu
- func (obj *Menu) Interface() interface{}
- func (obj *Menu) IsTruthy() bool
- func (obj *Menu) MarshalJSON() ([]byte, error)
- func (obj *Menu) RunOperation(opType op.BinaryOpType, right object.Object) (object.Object, error)
- func (obj *Menu) SetAttr(name string, value object.Object) error
- func (obj *Menu) Type() object.Type
- type Option
- func WithAppName(name string) Option
- func WithFilepath() Option
- func WithGlobal(name string, value any) Option
- func WithGlobals(globals ...risor.Option) Option
- func WithHTTP() Option
- func WithIO() Option
- func WithOS() Option
- func WithResultCallback(callback func(string)) Option
- func WithSQL() Option
- func WithStatusCallback(callback func(string)) Option
- func WithStrings() Option
- func WithTime() Option
- type Requirements
- type ScriptRunner
- type VersionInfo
- type Widget
- func (obj *Widget) Attrs() []object.AttrSpec
- func (obj *Widget) Equals(other object.Object) bool
- func (obj *Widget) GetAttr(name string) (object.Object, bool)
- func (obj *Widget) Inspect() string
- func (obj *Widget) Interface() interface{}
- func (obj *Widget) IsTruthy() bool
- func (obj *Widget) MarshalJSON() ([]byte, error)
- func (obj *Widget) RunOperation(opType op.BinaryOpType, right object.Object) (object.Object, error)
- func (obj *Widget) SetAttr(name string, value object.Object) error
- func (obj *Widget) Type() object.Type
- type Window
- func (w *Window) Attrs() []object.AttrSpec
- func (w *Window) Canvas() fyne.Canvas
- func (w *Window) Clear()
- func (w *Window) Cost() int
- func (w *Window) Do(fn func())
- func (w *Window) Equals(other object.Object) bool
- func (w *Window) Execute()
- func (w *Window) GetAttr(name string) (object.Object, bool)
- func (w *Window) GetContentContainer() *fyne.Container
- func (w *Window) ImportScript(source string) error
- func (w *Window) Inspect() string
- func (w *Window) Interface() interface{}
- func (w *Window) IsTruthy() bool
- func (w *Window) LoadScript(script string)
- func (w *Window) MarshalJSON() ([]byte, error)
- func (w *Window) Resize(width, height float32)
- func (w *Window) RunOperation(opType op.BinaryOpType, right object.Object) (object.Object, error)
- func (w *Window) SetAttr(name string, value object.Object) error
- func (w *Window) SetStatus(status string)
- func (w *Window) ShowAndRun()
- func (w *Window) Type() object.Type
Constants ¶
const AppType object.Type = "app"
const BindingType object.Type = "binding"
const CanvasType object.Type = "canvas"
const ChartType object.Type = "chart"
const ConstantsType object.Type = "constants"
const ContainerType object.Type = "container"
const FyneType object.Type = "fyne"
const Version = "0.4.1"
Version is the current version of the fynerisor library
const WidgetType object.Type = "widget"
const WindowType object.Type = "window"
Variables ¶
This section is empty.
Functions ¶
func GetAppVersion ¶
func GetAppVersion() string
GetAppVersion returns the embedding application's version. Returns empty string if not set.
func SetAppVersion ¶
func SetAppVersion(version string)
SetAppVersion sets the embedding application's version. This version is used when scripts call require(["vX.Y.Z"]) to check compatibility with the embedding application, not fynerisor itself.
Example:
func main() {
fynerisor.SetAppVersion("1.2.3")
w := fynerisor.NewApp("My App")
// Scripts can now use: require(["v1.2"])
w.LoadScript(script)
w.ShowAndRun()
}
Scripts should use semantic versioning format: "v1.2.3" or "v1.2"
Types ¶
type App ¶
type App struct {
// contains filtered or unexported fields
}
App provides information about the embedding application. Available in Risor scripts as the global 'app' object.
func (*App) RunOperation ¶
type Binding ¶
type Binding struct{}
Binding is a factory object that provides data binding creation functions to Risor scripts. Data bindings allow widgets to automatically sync with data sources.
Available in Risor scripts as the global 'binding' object.
Example usage:
let data = binding.NewString()
data.Set("Hello")
let label = widget.NewLabelWithData(data)
data.Set("Updated!") // Label automatically updates
func NewBinding ¶
func NewBinding() *Binding
func (*Binding) MarshalJSON ¶
func (*Binding) RunOperation ¶
type Canvas ¶
type Canvas struct {
}
Canvas is a factory object that provides canvas drawing functions to Risor scripts. It implements object.Object and exposes methods via GetAttr() for creating canvas objects like lines and images.
Available in Risor scripts as the global 'canvas' object.
Example usage in Risor:
let line = canvas.NewLine("red")
let img = canvas.NewImageFromURI("file:///path/to/image.png")
Thread Safety: All canvas object creation is thread-safe.
func NewFyneCanvas ¶
func NewFyneCanvas() *Canvas
func (*Canvas) MarshalJSON ¶
func (*Canvas) RunOperation ¶
type Chart ¶
type Chart struct {
}
Chart is a factory object that provides chart creation functions to Risor scripts. It implements object.Object and exposes methods via GetAttr() for creating visualization widgets like bar charts.
Available in Risor scripts as the global 'chart' object.
Example usage in Risor:
let bars = chart.NewBarChart("Sales", "Revenue", ["Q1", "Q2", "Q3"], [100, 150, 200])
func (*Chart) MarshalJSON ¶
func (*Chart) RunOperation ¶
type Constants ¶
type Constants struct{}
Constants provides access to Fyne constants and enums in Risor scripts. It exposes all Fyne enumeration values as integer constants.
Available in scripts as the global 'constants' object:
// Button importance btn.Importance = constants.ImportanceHigh btn.Importance = constants.SuccessImportance // Text wrapping label.Wrapping = constants.TextWrapWord // Scroll direction container.Scroll = constants.ScrollVerticalOnly
Button Importance (visual hierarchy):
- ImportanceHigh, ImportanceMedium, ImportanceLow
Button Importance (semantic):
- SuccessImportance, WarningImportance, DangerImportance
Button Icon Placement:
- ButtonIconLeadingText, ButtonIconTrailingText
Button Alignment:
- ButtonAlignCenter, ButtonAlignLeading, ButtonAlignTrailing
Text Wrapping:
- TextWrapOff, TextWrapBreak, TextWrapWord
Text Truncation:
- TextTruncateOff, TextTruncateClip, TextTruncateEllipsis
Scroll Direction:
- ScrollBoth, ScrollHorizontalOnly, ScrollVerticalOnly, ScrollNone
Orientation:
- Horizontal, Vertical
func (*Constants) MarshalJSON ¶
func (*Constants) RunOperation ¶
type Container ¶
type Container struct {
}
Container is a factory object that provides layout container creation functions to Risor scripts. It implements object.Object and exposes methods via GetAttr() for creating layout containers that organize widgets (VBox, HBox, Border, Split, Scroll).
Available in Risor scripts as the global 'container' object.
Example usage in Risor:
let vbox = container.NewVBox(widget1, widget2, widget3) let hbox = container.NewHBox(left, center, right) let border = container.NewBorder(top, bottom, left, right, center) let scroll = container.NewScroll(content)
Thread Safety: All container creation is thread-safe.
func NewFyneContainer ¶
func NewFyneContainer() *Container
func (*Container) MarshalJSON ¶
func (*Container) RunOperation ¶
type ContextBuilder ¶
type ContextBuilder struct {
// contains filtered or unexported fields
}
ContextBuilder builds Risor contexts for non-GUI applications. It provides access to the same module system (HTTP, SQL, OS, etc.) and import functionality as fynerisor Window, but without GUI dependencies.
This is useful for headless scripts, CLI tools, or server applications that need Risor scripting with modules but don't require a GUI.
func NewContext ¶
func NewContext(opts ...Option) *ContextBuilder
NewContext creates a new Risor context builder for non-GUI applications.
Parameters:
- opts: Optional configuration using functional options (WithHTTP, WithSQL, etc.)
Returns:
- *ContextBuilder: Builder for creating Risor contexts
Example:
ctx := fynerisor.NewContext(
fynerisor.WithHTTP(),
fynerisor.WithSQL(),
fynerisor.WithOS(),
)
script := `
require(["@http", "@sql"])
let data = http.get("https://api.example.com/data").json()
print(data)
`
result, err := ctx.Eval(script)
func (*ContextBuilder) EnabledModules ¶
func (cb *ContextBuilder) EnabledModules() map[string]bool
EnabledModules returns a map of enabled module names.
func (*ContextBuilder) Eval ¶
func (cb *ContextBuilder) Eval(script string) (any, error)
Eval evaluates a Risor script and returns the result.
Parameters:
- script: The Risor script source code
Returns:
- any: The script result (converted to Go types)
- error: Any evaluation error
Example:
// Direct eval
ctx := fynerisor.NewContext(fynerisor.WithHTTP())
result, err := ctx.Eval(`http.get("https://example.com").status`)
// With imports
ctx.ImportScript("utils.risor")
ctx.LoadScript(`let result = myUtil(42)`)
result, err := ctx.Eval("")
func (*ContextBuilder) EvalWithImports ¶
func (cb *ContextBuilder) EvalWithImports(script string, fetchFunc func(path string) (string, error)) (any, error)
EvalWithImports analyzes the script for imports, loads them in order, then evaluates the main script. This method creates a shared Risor context so imported scripts can define functions/variables used by the main script.
Parameters:
- script: The Risor script source code
- fetchFunc: Function to fetch import sources by path/URL
Returns:
- any: The script result (converted to Go types)
- error: Any evaluation error
Example:
ctx := fynerisor.NewContext(fynerisor.WithContextHTTP())
fetchFunc := func(path string) (string, error) {
data, err := os.ReadFile(path)
return string(data), err
}
script := `
import("utils.risor")
require("@http")
let result = myUtil(42)
`
result, err := ctx.EvalWithImports(script, fetchFunc)
func (*ContextBuilder) ImportScript ¶
func (cb *ContextBuilder) ImportScript(source string) error
ImportScript loads a script from a path or URL and adds it to the import list. The script will be executed before the main script when Eval() is called.
Parameters:
- source: Path to a local file or HTTP(S) URL
Returns:
- error: Any error encountered while fetching the script
Example:
ctx := fynerisor.NewContext(fynerisor.WithHTTP())
ctx.ImportScript("utils.risor")
ctx.ImportScript("https://example.com/helpers.risor")
result, err := ctx.Eval(mainScript)
func (*ContextBuilder) LoadScript ¶
func (cb *ContextBuilder) LoadScript(script string)
LoadScript sets the main script to be executed. Call this after all ImportScript() calls.
type Fyne ¶
type Fyne struct {
// contains filtered or unexported fields
}
Fyne provides access to fyne package types like Menu and MenuItem. Available in scripts as the global 'fyne' object.
func (*Fyne) MarshalJSON ¶
func (*Fyne) RunOperation ¶
type IsCanvasObject ¶
type IsCanvasObject interface {
CanvasObject() fyne.CanvasObject
}
type Menu ¶
type Menu struct {
// contains filtered or unexported fields
}
Menu wraps fyne.Menu
func (*Menu) MarshalJSON ¶
func (*Menu) RunOperation ¶
type Option ¶
type Option interface {
// contains filtered or unexported methods
}
Option configures a Window or ContextBuilder during creation. Module options (WithHTTP, WithSQL, etc.) work with both. Callback options (WithStatusCallback, WithResultCallback) only work with Window.
func WithAppName ¶
WithAppName sets the application name exposed to Risor scripts via app.name. This allows scripts to detect which application is running them. Works with both Window and ContextBuilder.
Example:
window := fynerisor.NewWindow(w,
fynerisor.WithAppName("lars"),
)
Usage in script:
if (app.name == "lars") {
print("Running in LARS")
}
func WithFilepath ¶
func WithFilepath() Option
WithFilepath enables the filepath module for file path manipulation from Risor scripts.
func WithGlobal ¶
WithGlobal adds a custom global variable to the Risor environment. This allows you to expose custom Go types and their methods to scripts.
Example:
type MyDatabase struct { ... }
func (db *MyDatabase) GetAttr(name string) (object.Object, bool) { ... }
db := &MyDatabase{}
w := fynerisor.NewApp("My App",
fynerisor.WithGlobal("db", db),
)
// In scripts: db.query("SELECT * FROM users")
func WithGlobals ¶
WithGlobals adds custom global objects to the Risor script environment. The globals parameter should be created using risor.WithEnv().
Example:
customGlobals := map[string]any{
"myAPI": myAPIObject,
}
window := fynerisor.NewWindow(w,
fynerisor.WithGlobals(risor.WithEnv(customGlobals)),
)
func WithHTTP ¶
func WithHTTP() Option
WithHTTP enables the HTTP module for making HTTP requests from Risor scripts. The module provides functions: get, post, put, delete, and fetch.
Example:
window := fynerisor.NewWindow(w,
fynerisor.WithHTTP(),
)
Usage in script:
let response = http.get("https://api.example.com/data")
print(response.status)
print(response.body)
func WithIO ¶
func WithIO() Option
WithIO enables the io module for file operations from Risor scripts. The module provides functions: cp (copy file).
Example:
window := fynerisor.NewWindow(w,
fynerisor.WithIO(),
)
Usage in script:
io.cp("source.txt", "destination.txt")
func WithOS ¶
func WithOS() Option
WithOS enables the OS module for accessing OS functionality from Risor scripts. The module provides functions: goos, current_user, and open_browser.
Example:
window := fynerisor.NewWindow(w,
fynerisor.WithOS(),
)
Usage in script:
let platform = os.goos()
let user = os.current_user()
os.open_browser("https://example.com")
func WithResultCallback ¶
WithResultCallback sets a callback that is called when script execution completes with a non-nil result value. This option only works with Window, not ContextBuilder.
Example:
window := fynerisor.NewWindow(w,
fynerisor.WithResultCallback(func(result string) {
log.Println("Result:", result)
}),
)
func WithSQL ¶
func WithSQL() Option
WithSQL enables the SQL module for database connectivity from Risor scripts. The module provides functions: connect, query, exec, and close.
Supports: MySQL, PostgreSQL, SQLite, SQL Server
Example:
window := fynerisor.NewWindow(w,
fynerisor.WithSQL(),
)
Usage in script:
let conn = sql.connect("sqlite3://./test.db")
let rows = conn.query("SELECT * FROM users")
conn.exec("INSERT INTO users (name) VALUES (?)", "Alice")
conn.close()
func WithStatusCallback ¶
WithStatusCallback sets a callback that is called when script execution status changes. The callback receives status strings like "Ready!", "ERROR: ...", etc. This option only works with Window, not ContextBuilder.
Example:
window := fynerisor.NewWindow(w,
fynerisor.WithStatusCallback(func(status string) {
log.Println("Status:", status)
}),
)
func WithStrings ¶
func WithStrings() Option
WithStrings enables the strings module for string manipulation from Risor scripts.
func WithTime ¶
func WithTime() Option
WithTime enables the time module for date and time operations from Risor scripts. The module provides functions: now, date, and parse.
Example:
window := fynerisor.NewWindow(w,
fynerisor.WithTime(),
)
Usage in script:
let now = time.now()
let date = time.date(2026, 5, 1)
let parsed = time.parse("2026-05-01")
type Requirements ¶
type Requirements struct {
MinVersion string // Minimum version (e.g., "0.2.0")
ExactVersion string // Exact version if ==v syntax used
RequiredModules []string // List of required modules (e.g., ["sql", "http"])
Imports []string // List of import paths/URLs (e.g., ["utils.risor", "http://..."])
Raw []string // Raw requirement strings
}
Requirements represents parsed script requirements
func AnalyzeRequirements ¶
func AnalyzeRequirements(script string) (*Requirements, error)
AnalyzeRequirements parses a Risor script and extracts all require() calls. This function is useful for external applications that need to understand script dependencies before execution.
It compiles the script and inspects require() calls without executing the full script logic.
Example:
script := `
require(["v0.2", "@sql", "@http"])
let btn = widget.NewButton("Hello", () => {})
`
reqs, err := fynerisor.AnalyzeRequirements(script)
if err != nil {
log.Fatal(err)
}
fmt.Println("Requires version:", reqs.MinVersion)
fmt.Println("Requires modules:", reqs.RequiredModules)
func (*Requirements) RequiresGUI ¶
func (r *Requirements) RequiresGUI() bool
RequiresGUI returns true if the script requires a GUI window (@gui)
func (*Requirements) String ¶
func (r *Requirements) String() string
String returns a human-readable representation of requirements
type ScriptRunner ¶
type ScriptRunner struct {
// contains filtered or unexported fields
}
ScriptRunner manages script execution with import support. Shared by both Window and ContextBuilder.
func NewScriptRunner ¶
func NewScriptRunner(globals []risor.Option) *ScriptRunner
NewScriptRunner creates a new script runner with the given globals.
func (*ScriptRunner) Clear ¶
func (sr *ScriptRunner) Clear()
Clear clears all loaded scripts (both imports and main script).
func (*ScriptRunner) Eval ¶
func (sr *ScriptRunner) Eval() (any, error)
Eval executes all imported scripts followed by the main script. Returns the result of the final script.
Returns:
- any: The result of script execution
- error: Any execution error
func (*ScriptRunner) ImportScript ¶
func (sr *ScriptRunner) ImportScript(source string) error
ImportScript loads a script from a path or URL and adds it to the import list. The script will be executed before the main script when Eval() is called.
Parameters:
- source: Path to a local file or HTTP(S) URL
Returns:
- error: Any error encountered while fetching the script
Example:
runner.ImportScript("utils.risor")
runner.ImportScript("https://example.com/helpers.risor")
func (*ScriptRunner) LoadScript ¶
func (sr *ScriptRunner) LoadScript(script string)
LoadScript adds the main script to be executed. This should be called after all ImportScript() calls.
type VersionInfo ¶
type VersionInfo struct {
Version string // Fynerisor library version
AppVersion string // Embedding application version (if set)
RisorCompat string // Compatible Risor version
FyneCompat string // Compatible Fyne version
}
VersionInfo provides detailed version information
func GetVersion ¶
func GetVersion() VersionInfo
GetVersion returns version information for this fynerisor release
type Widget ¶
type Widget struct {
// contains filtered or unexported fields
}
Widget is a factory object that provides widget creation functions to Risor scripts. It implements object.Object and exposes methods via GetAttr() for creating UI components like buttons, labels, forms, tables, and more.
Available in Risor scripts as the global 'widget' object.
Example usage in Risor:
let btn = widget.NewButton("Click Me", () => { print("Clicked!") })
let lbl = widget.NewLabel("Hello World")
let entry = widget.NewEntry()
let table = widget.NewTable("Data", 20)
Thread Safety: All widget creation and property access is thread-safe. Callbacks are automatically marshalled to the GUI thread.
func (*Widget) MarshalJSON ¶
func (*Widget) RunOperation ¶
type Window ¶
type Window struct {
FyneWindow fyne.Window
Status string
// contains filtered or unexported fields
}
Window wraps a fyne.Window and provides Risor scripting capabilities. It exposes global objects (window, widget, container, canvas, chart) to Risor scripts and manages script execution in a separate goroutine with callback support.
The Window implements object.Object to be accessible from Risor scripts. Scripts can call window.SetContent() to update the UI, window.OnDropped() to handle file drops, and window.CaptureStdout() to capture printed output.
func NewApp ¶
NewApp is a convenience function that creates a new Fyne application and fynerisor Window in one call. It's equivalent to calling app.New(), app.NewWindow(), and NewWindow() but more concise.
This is the recommended way to create a fynerisor application for simple use cases where you don't need direct access to the Fyne app object.
Parameters:
- title: The window title
- opts: Optional configuration using functional options (WithGlobals, WithStatusCallback, etc.)
Returns:
- *Window: The fynerisor window ready for script execution
Example:
fw := fynerisor.NewApp("My Application",
fynerisor.WithHTTP(),
fynerisor.WithSQL(),
)
fw.LoadScript(`
require(["v0.2", "@sql"])
let btn = widget.NewButton("Hello", () => {
window.SetStatus("Clicked!")
})
window.SetContent(btn)
`)
fw.Execute()
fw.ShowAndRun()
For more control over the Fyne app, use NewWindow instead:
a := app.New()
a.Settings().SetTheme(theme.DarkTheme())
w := a.NewWindow("My App")
fw := fynerisor.NewWindow(w, fynerisor.WithHTTP())
func NewWindow ¶
NewWindow creates a new fynerisor Window that wraps a Fyne window.
Parameters:
- window: The fyne.Window to wrap
- opts: Optional configuration using functional options (WithGlobals, WithStatusCallback, etc.)
The window automatically provides these global objects to Risor scripts:
- window: This Window instance
- widget: Widget factory for creating UI components
- container: Container factory for layouts (VBox, HBox, Border, etc.)
- canvas: Canvas object factory (lines, images)
- chart: Chart factory (bar charts)
Example:
a := app.New()
w := a.NewWindow("My App")
fyneWindow := fynerisor.NewWindow(w,
fynerisor.WithStatusCallback(func(status string) {
log.Println("Status:", status)
}),
)
fyneWindow.LoadScript("window.SetContent(widget.NewLabel('Hello'))")
fyneWindow.Execute()
fyneWindow.ShowAndRun()
func (*Window) Canvas ¶
Canvas returns the Fyne canvas for this window. This allows scripts to create PopUp widgets.
func (*Window) Clear ¶
func (w *Window) Clear()
Clear clears all loaded scripts (imports and main script). Call this before loading a new script to avoid accumulation.
func (*Window) Execute ¶
func (w *Window) Execute()
Execute executes the loaded Risor script in a goroutine. It evaluates the script with all configured globals and processes any queued function calls from callbacks. Sets status to "ERROR: ..." on failure or "Ready!" on success.
This method returns immediately; script execution happens asynchronously. Call LoadScript() before calling this method.
Multiple calls to Execute() are safe. Previous execution will be cancelled to prevent resource leaks from abandoned goroutines.
func (*Window) GetContentContainer ¶
GetContentContainer returns the fynerisor Window's content container. This allows external code to use the same container that window.SetContent() updates.
func (*Window) ImportScript ¶
ImportScript loads an additional script to be prepended to the main script. The imported script's code will be executed before the main script. Multiple imports are executed in the order they are added. Can load from local files or HTTP(S) URLs.
func (*Window) LoadScript ¶
LoadScript loads a Risor script that will be executed when Execute() is called. If ImportScript() was called before LoadScript(), the imports will be prepended.
func (*Window) MarshalJSON ¶
func (*Window) Resize ¶
Resize changes the size of the window. This is useful when creating windows with NewApp and needing custom sizes.
Example:
fw := fynerisor.NewApp("My App")
fw.Resize(800, 600)
fw.LoadScript(script)
fw.Execute()
fw.ShowAndRun()
func (*Window) RunOperation ¶
func (*Window) SetStatus ¶
SetStatus updates the window status and calls the status callback if provided.
func (*Window) ShowAndRun ¶
func (w *Window) ShowAndRun()
ShowAndRun displays the window and runs the Fyne application main loop. This is a blocking call that runs until the window is closed.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
fynerisor
command
|
|
|
examples
|
|
|
01-hello-world
command
|
|
|
02-button-callback
command
|
|
|
03-form-input
command
|
|
|
04-table-display
command
|
|
|
05-progress-widgets
command
|
|
|
06-icon-hyperlink-card
command
|
|
|
07-radiogroup
command
|
|
|
08-accordion
command
|
|
|
09-toolbar
command
|
|
|
10-calendar
command
|
|
|
11-list
command
|
|
|
12-tree
command
|
|
|
13-http-fetch
command
|
|
|
14-imports
command
|
|
|
15-sql-test
command
|
|
|
16-context-builder
command
|
|
|
17-gridwrap
command
|
|
|
18-textgrid
command
|
|
|
19-richtext
command
|
|
|
20-button-importance
command
|
|
|
21-form-validation
command
|
|
|
22-popup
command
|
|
|
23-menu
command
|
|
|
24-constants
command
|
|
|
25-data-binding
command
|
|
|
26-data-binding-types
command
|
|
|
27-app-versioning
command
|
|
|
28-custom-struct
command
|
|
|
modules
|
|
|
filepath
Package filepath provides file path manipulation functions for Risor scripts.
|
Package filepath provides file path manipulation functions for Risor scripts. |
|
http
Package http provides HTTP client functionality for Risor scripts.
|
Package http provides HTTP client functionality for Risor scripts. |
|
os
Package os provides basic OS functionality for Risor scripts.
|
Package os provides basic OS functionality for Risor scripts. |
|
strings
Package strings provides string manipulation functions for Risor scripts.
|
Package strings provides string manipulation functions for Risor scripts. |
|
time
Package time provides time and date functions for Risor scripts.
|
Package time provides time and date functions for Risor scripts. |
|
Package widget provides Risor bindings for Fyne GUI widgets.
|
Package widget provides Risor bindings for Fyne GUI widgets. |