friendscript

package module
v1.7.0 Latest Latest
Warning

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

Go to latest
Published: Feb 22, 2022 License: LGPL-2.1 Imports: 29 Imported by: 3

README

Friendscript

Friendscript is an imperative scripting language that is familiar and easy to use in a variety of applications that wish to provide scripting support. It is intended to be a lightweight, embeddable language that authors can extend in many ways to make adding simple scripting capabilities to your program easy.

Uses for Friendscript

  • Extending your applications by providing a simple yet robust scripting environment that can be used directly by your users or as an intermediate format for storing complex actions.

  • Create a DSL (domain specific language) that you can use to expose your application's functionality in a scripting context.

  • Creating a safe alternative to a fully-featured scripting language (e.g.: Lua, Python, Ruby) by having tight control over which language features and functionality is exposed to the end user.

Language Overview

Read the language introduction and overview here

Usage Examples

"But Grimace, why did you invent a completely new language? Aren't there so many other powerful scripting languages out there, and isn't doing so considered a little....unhinged?!"

Short answer, "yes" with an "if." Long answer, "no" with a "but."

Truth be told, my original intent here was largely organized around being curious about language design, the level of difficulty in creating the syntax and logical structure of a language, and all-around just challenging myself to take the risk.

That being said, I think there might actually be something to this. In any given scenario, there are literally dozens of options to choose from with respect to scripting languages, especially embedded ones. Lua, Tcl, and GNU Guile all come to mind; and if you're willing to roll your sleeves up a little (or find someone else that already has), Python and Ruby are perfectly valid options.

But I find something interesting about the idea of a soup-to-nuts Golang implementation with a clear, unambiguous API in service of the specific mission of providing familiar scripting constructs to end users, while also giving developers a high degree of flexibility in choosing which language features are available. I think that last bit is important, because its not always desireable to provide the full breadth of a Turing complete environment; for example in the context of something that might be intended for use in a configuration context. Configuration is a tricky beast because there are times it requires a middleground between "static, pure data" (e.g.: YAML) and Ruby or Python (powerful, but now your config files can SSH into servers.) This is just one example where Friendscript might be that middleground.

I think there are some interesting possibilities in this space-- check Friendscript out; perhaps you might too!

Documentation

Index

Constants

View Source
const DefaultEnvironmentName = `friendscript`
View Source
const Version = `0.8.4`

Variables

View Source
var MaxReaderWait = time.Duration(5) * time.Second

Functions

This section is empty.

Types

type ContextHandlerFunc

type ContextHandlerFunc func(ctx *scripting.Context, isCompleted bool)

type Environment

type Environment struct {
	Name string
	// contains filtered or unexported fields
}

func NewEnvironment

func NewEnvironment(data ...map[string]interface{}) *Environment

Create a new scripting environment.

func (*Environment) Commands

func (self *Environment) Commands() []string

List all commands supported by all registered modules.

func (*Environment) DisableCommand

func (self *Environment) DisableCommand(module string, cmdname string)

Specify a command that should not be permitted to execute.

func (*Environment) EnableCommand

func (self *Environment) EnableCommand(module string, cmdname string)

Specify a command that should be permitted to execute.

func (*Environment) Evaluate

func (self *Environment) Evaluate(script *scripting.Friendscript, scope ...*scripting.Scope) (*scripting.Scope, error)

func (*Environment) EvaluateFile

func (self *Environment) EvaluateFile(path string, scope ...*scripting.Scope) (*scripting.Scope, error)

func (*Environment) EvaluateReader

func (self *Environment) EvaluateReader(reader io.Reader, scope ...*scripting.Scope) (*scripting.Scope, error)

func (*Environment) EvaluateString

func (self *Environment) EvaluateString(data string, scope ...*scripting.Scope) (*scripting.Scope, error)

func (*Environment) Get

func (self *Environment) Get(key string, fallback ...interface{}) interface{}

func (*Environment) GetReaderForPath

func (self *Environment) GetReaderForPath(path string) (io.ReadCloser, error)

Takes a path string and consults all registered PathReaderFuncs. The first one to claim it can handle the path will be responsible for returning an io.ReadCloser that represents the stream of data being sought.

func (*Environment) GetWriterForPath

func (self *Environment) GetWriterForPath(path string) (string, io.Writer, error)

Takes a path string and consults all registered PathWriterFuncs. The first one to claim it can handle the path will be responsible for returning a possibly-rewritten path string and an io.Writer that will accept the data being written.

func (*Environment) Module

func (self *Environment) Module(name string) (Module, bool)

Retrieve the named module.

func (*Environment) Modules

func (self *Environment) Modules() map[string]Module

Retrieve a copy of the currently registered modules.

func (*Environment) MustModule

func (self *Environment) MustModule(name string) Module

Retrieve the named module, or panic if it is not registered.

func (*Environment) Open

func (self *Environment) Open(fileOrReader interface{}) (io.ReadCloser, error)

Open a readable destination file for reading. If fileOrReader is a string, it will be treated as a path and will be sent to GetReaderForPath(). If it is an io.Reader, it will be returned without reading from it.

func (*Environment) REPL

func (self *Environment) REPL() (*scripting.Scope, error)

func (*Environment) RegisterCommandHandler

func (self *Environment) RegisterCommandHandler(command string, handler InteractiveHandlerFunc) error

Registers a function to handle a specific REPL command. If command is an empty string, the function will be called for each command entered into the REPL.

func (*Environment) RegisterContextHandler

func (self *Environment) RegisterContextHandler(handler ContextHandlerFunc) int

Registers a handler that will receive updates on execution context and state as the script is running. Will return an integer that can be used to remove the handler at a later point.

func (*Environment) RegisterModule

func (self *Environment) RegisterModule(prefix string, module Module)

Registers a command module to the given prefix. If a module with the same prefix already exists, it will be replaced with the given module. Prefixes will be stripped of spaces and converted to snake_case. If an empty prefix is given, the default UnqualifiedModuleName ("core") will be used.

func (*Environment) RegisterPathReader

func (self *Environment) RegisterPathReader(handler utils.PathReaderFunc)

Registers a new handler function that will be used for turning paths into readable streams.

func (*Environment) RegisterPathWriter

func (self *Environment) RegisterPathWriter(handler utils.PathWriterFunc)

Registers a new handler function that will be used for turning paths into writable streams.

func (*Environment) Run

func (self *Environment) Run(scriptName string, options *utils.RunOptions) (interface{}, error)

func (*Environment) Scope

func (self *Environment) Scope() *scripting.Scope

func (*Environment) Set

func (self *Environment) Set(key string, value interface{})

func (*Environment) SetData

func (self *Environment) SetData(data map[string]interface{})

func (*Environment) UnregisterContextHandler

func (self *Environment) UnregisterContextHandler(id int)

Remove the context handler with the given ID.

func (*Environment) UnregisterModule

func (self *Environment) UnregisterModule(prefix string)

Removes a registered module at the given prefix.

type InteractiveContext

type InteractiveContext struct {
	Command string
	Line    string
}

type InteractiveHandlerFunc

type InteractiveHandlerFunc func(ctx *InteractiveContext, environment *Environment) ([]string, error)

type Module

type Module = utils.Module

func CreateModule

func CreateModule(from interface{}) Module

Directories

Path Synopsis
commands
assert
Suite of testing-oriented commands that will trigger errors or failures if they aren't satistifed.
Suite of testing-oriented commands that will trigger errors or failures if they aren't satistifed.
core
This package provides default implementations of commands that can be used when creating modules.
This package provides default implementations of commands that can be used when creating modules.
file
Commands for reading and writing files.
Commands for reading and writing files.
fmt
Suite of string formatting utilities.
Suite of string formatting utilities.
http
Commands for interacting with HTTP resources
Commands for interacting with HTTP resources
parse
Commands used to load and parse various formats of serialized data (JSON, YAML, etc.)
Commands used to load and parse various formats of serialized data (JSON, YAML, etc.)
url
Commands for processing and working with URLs.
Commands for processing and working with URLs.
utils
Contains miscellaneous utility commands.
Contains miscellaneous utility commands.
vars
Commands for manipulating the current Friendscript variable scope.
Commands for manipulating the current Friendscript variable scope.
examples

Jump to

Keyboard shortcuts

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