func main() { L := lua.NewState() L.OpenLibs() defer L.Close() watcher, err := fsnotify.NewWatcher() if err != nil { panic(err) } luasPath := "./" if len(os.Args) == 2 { luasPath = os.Args[1] } watcher.WatchFlags(luasPath, fsnotify.FSN_MODIFY) ls := luas{} var ev *fsnotify.FileEvent ls.Collect(luasPath) ls.Load(L) newev: ls.Handle(ev, L) ev = <-watcher.Event goto newev }
// Init makes and initialize a new pre-configured Lua state. // // It populates the 'luar' table with some helper functions/values: // // method: ProxyMethod // type: ProxyType // unproxify: Unproxify // // chan: MakeChan // complex: MakeComplex // map: MakeMap // slice: MakeSlice // // null: Null // // It replaces the pairs/ipairs functions so that __pairs/__ipairs can be used, // Lua 5.2 style. It allows for looping over Go composite types and strings. // // It is not required for using the 'GoToLua' and 'LuaToGo' functions. func Init() *lua.State { var L = lua.NewState() L.OpenLibs() Register(L, "luar", Map{ // Functions. "unproxify": Unproxify, "map2table": MapToTable, // deprecated "slice2table": SliceToTable, // deprecated "array2table": ArrayToTable, // deprecated "struct2table": StructToTable, // deprecated "raw": ProxyRaw, // deprecated "method": ProxyMethod, "type": ProxyType, // TODO: Replace with the version from the 'proxytype' branch. "chan": MakeChan, "complex": Complex, "map": MakeMap, "slice": MakeSlice, "real": ComplexReal, // deprecated "imag": ComplexImag, // deprecated "sub": SliceSub, // deprecated "append": SliceAppend, // deprecated // Values. "null": Null, }) Register(L, "", Map{ "ipairs": ProxyIpairs, "pairs": ProxyPairs, }) return L }
func LoadConf(path string, c *Conf) error { L := lua.NewState() defer L.Close() L.OpenLibs() err := L.DoFile(path) if err != nil { return err } L.GetGlobal("CENTER_IP") L.GetGlobal("CENTER_PORT") p := L.ToInteger(-1) s := L.ToString(-2) c.Center = fmt.Sprintf("%s:%d", s, p) L.Pop(2) L.GetGlobal("dbproxy") L.GetField(-1, "database") L.PushNil() // read database for L.Next(-2) != 0 { L.GetField(-1, "redis_url") L.PushNil() for L.Next(-2) != 0 { c.RedisAddr = append(c.RedisAddr, L.ToString(-1)) L.Pop(1) } L.Pop(2) } return nil }
// New creates a new Luna instance, opening all libs provided. func New(libs Lib) *Luna { l := &Luna{lua.NewState(), libs, &sync.Mutex{}} if libs == AllLibs { l.L.OpenLibs() } else { if libs&LibBase != 0 { l.L.OpenBase() } if libs&LibIO != 0 { l.L.OpenIO() } if libs&LibMath != 0 { l.L.OpenMath() } if libs&LibPackage != 0 { l.L.OpenPackage() } if libs&LibString != 0 { l.L.OpenString() } if libs&LibTable != 0 { l.L.OpenTable() } if libs&LibOS != 0 { l.L.OpenOS() } } return l }
func (p *LuaPlugin) runScript(req *http.Request, ctx *apiplexy.APIContext) error { if p.pathFilter { run := false for _, path := range p.paths { if strings.HasPrefix(req.URL.Path, path) { run = true } } if !run { return nil } } L := lua.NewState() L.OpenBase() L.OpenString() L.OpenTable() L.OpenMath() defer L.Close() p.prepContext(L, req, ctx) if p.debug { p.enableDebug(L) } if load := L.LoadString(p.script); load != 0 { return fmt.Errorf("Lua script error (%d): %s", load, L.ToString(-1)) } if err := L.Call(0, 2); err != nil { return err } if !L.IsNoneOrNil(1) { var msg string var status int if !L.IsString(1) { return fmt.Errorf("Return errors from Lua like so: 'return \"my error message\", 400'") } msg = L.ToString(1) if L.IsNumber(2) { status = L.ToInteger(2) } else { status = 500 } L.Pop(2) return apiplexy.Abort(status, msg) } L.GetGlobal("context") newctx := popMap(L) ctx.Cost = newctx["cost"].(int) ctx.DoNotLog = newctx["donotlog"].(bool) ctx.Data = newctx["data"].(map[string]interface{}) ctx.Log = newctx["log"].(map[string]interface{}) return nil }
// MakeSandbox initializes a Lua state, removes all elements not in the // whitelist, sets up the debug function if necessary and adds some Go helper // functions. // The caller is responsible for closing the Lua state. // Add a `defer L.Close()` to the calling code if there is no error. func MakeSandbox(logPrint func(v ...interface{})) (*lua.State, error) { L := lua.NewState() L.OpenLibs() unicode.GoLuaReplaceFuncs(L) // Store the whitelist in registry to avoid tampering it. L.PushString(registryWhitelist) err := L.DoString(luaWhitelist) if err != nil { log.Fatal("Spurious sandbox", err) } L.SetTable(lua.LUA_REGISTRYINDEX) // Register before setting up the sandbox: these functions will be restored // together with the sandbox. // The closure allows access to the external logger. luaDebug := func(L *lua.State) int { return 0 } if logPrint != nil { luaDebug = func(L *lua.State) int { var arglist []interface{} nargs := L.GetTop() for i := 1; i <= nargs; i++ { if L.IsString(i) { arglist = append(arglist, L.ToString(i)) } } logPrint(arglist...) return 0 } } sandboxRegister(L, "debug", luaDebug) sandboxRegister(L, "stringnorm", stringNorm) sandboxRegister(L, "stringrel", stringRel) // Purge _G from everything but the content of the whitelist. err = L.DoString(luaSetSandbox) if err != nil { log.Fatal("Cannot load function to set sandbox", err) } L.PushString(registryWhitelist) L.GetTable(lua.LUA_REGISTRYINDEX) err = L.Call(1, 0) if err != nil { log.Fatal("Failed to set sandbox", err) } // Init script table. L.PushString(registryScripts) L.NewTable() L.SetTable(lua.LUA_REGISTRYINDEX) // Init action table. L.PushString(registryActions) L.NewTable() L.SetTable(lua.LUA_REGISTRYINDEX) return L, nil }
// make and initialize a new Lua state func Init() *lua.State { var L = lua.NewState() L.OpenLibs() initializeProxies(L) RawRegister(L, "luar", Map{ "map2table": map2table, "slice2table": slice2table, }) return L }
func ExampleGoToLua() { // The luar's Init function is only required for proxy use. L := lua.NewState() defer L.Close() L.OpenLibs() input := "Hello world!" luar.GoToLua(L, nil, reflect.ValueOf(input), true) L.SetGlobal("input") luar.GoToLua(L, nil, reflect.ValueOf(fmt.Println), true) L.SetGlobal("Print") L.DoString("Print(input)") // Output: // Hello world! }
func (p *ThingProgram) compile() error { state := lua.NewState() state.OpenBase() state.OpenMath() state.OpenString() state.OpenTable() // Not IO & not OS. // Not package: all our packages are preloaded. // Install the `world` package. installWorld(state) err := state.DoString(p.Text) if err != nil { p.Error = err } else { p.state = state } return err }
func newScriptHandler(man *Manager) *ScriptHandler { luaVm := lua.NewState() luaVm.OpenLibs() jsVm := otto.New() h := &ScriptHandler{man, luaVm, jsVm, false, "", make(ScriptDatastore)} client := &httpHelper{} cres, _ := h.jsVm.ToValue(client) h.jsVm.Set("Http", cres) db := &dataHelper{make(map[string]interface{})} dres, _ := h.jsVm.ToValue(db) h.jsVm.Set("Data", dres) irc := &ircHelper{h.man.conn} ires, _ := h.jsVm.ToValue(irc) h.jsVm.Set("Irc", ires) return h }
// Make and initialize a new Lua state. Populates luar table with five functions: // map2table, slice2table, map, slice, type, and value. // This makes customized pairs/ipairs // functions available so that __pairs/__ipairs // can be used, Lua 5.2 style. func Init() *lua.State { var L = lua.NewState() L.OpenLibs() initializeProxies(L) L.DoString(setup) RawRegister(L, "luar", Map{ "map2table": map2table, "slice2table": slice2table, "map": makeMap, "slice": makeSlice, "type": proxyType, "sub": sliceSub, "append": sliceAppend, "raw": proxyRaw, "null": null, }) Register(L, "luar", Map{ "value": reflect.ValueOf, }) return L }
func serveLua(dir string, w http.ResponseWriter, r *http.Request) { file := filepath.Join(dir, r.URL.Path) content, err := ioutil.ReadFile(file) if err != nil { panic(err) } luaPrint := func(L *lua.State) int { s := L.ToString(1) io.WriteString(w, s) io.WriteString(w, "\n") if f, ok := w.(http.Flusher); ok { f.Flush() } return 0 } L := lua.NewState() defer L.Close() L.OpenLibs() L.Register("print", luaPrint) L.MustDoString(string(content)) }
func MakeLuaState() *lua.State { L := lua.NewState() L.CheckStack(1) //L.OpenLibs() L.OpenBase() L.OpenString() L.OpenTable() L.OpenMath() NilGlobal(L, "collectgarbage") NilGlobal(L, "dofile") NilGlobal(L, "_G") NilGlobal(L, "getfenv") NilGlobal(L, "getmetatable") NilGlobal(L, "load") NilGlobal(L, "loadfile") NilGlobal(L, "loadstring") NilGlobal(L, "print") NilGlobal(L, "rawequal") NilGlobal(L, "rawget") NilGlobal(L, "rawset") NilGlobal(L, "setfenv") NilGlobal(L, "setmetatable") NilGlobal(L, "coroutine") // cursor examination functions L.Register("id", LuaIntId) L.Register("title", LuaIntTitle) L.Register("text", LuaIntText) L.Register("priority", LuaIntPriority) L.Register("when", LuaIntWhen) L.Register("sortfield", LuaIntSortField) L.Register("column", LuaIntColumn) L.Register("rmcolumn", LuaIntRmColumn) // search results control functions L.Register("filterout", LuaIntFilterOut) L.Register("filterin", LuaIntFilterIn) // cursor control functions L.Register("visit", LuaIntVisit) // editing functions L.Register("persist", LuaIntPersist) L.Register("remove", LuaIntRemove) L.Register("clonecursor", LuaIntCloneCursor) L.Register("writecursor", LuaIntWriteCursor) // time utility functions L.Register("utctime", LuaIntUTCTime) L.Register("localtime", LuaIntLocalTime) L.Register("timestamp", LuaIntTimestamp) L.Register("parsedatetime", LuaIntParseDateTime) // string utility functions L.Register("split", LuaIntSplit) // query construction functions L.Register("idq", LuaIntIdQuery) L.Register("titleq", LuaIntTitleQuery) L.Register("textq", LuaIntTextQuery) L.Register("whenq", LuaIntWhenQuery) L.Register("searchq", LuaIntSearchQuery) L.Register("priorityq", LuaIntPriorityQuery) L.Register("columnq", LuaIntColumnQuery) L.Register("andq", LuaIntAndQuery) L.Register("orq", LuaIntOrQuery) L.Register("notq", LuaIntNotQuery) // Loads initialization file L.DoString(decodeStatic("init.lua")) // advanced interface functions L.Register("search", LuaIntSearch) L.Register("showreturnvalue", LuaIntShowRet) //L.Register("debulog", LuaIntDebulog) return L }