func MessThingTellallMethod(state *lua.State, thing *Thing) int { state.PushGoFunction(func(state *lua.State) int { place := checkThing(state, 1) text := state.CheckString(2) // If arg 3 is present, it should be a table of Things to exclude. excludes := make(map[ThingId]bool) if 2 < state.GetTop() { if !state.IsTable(3) { state.ArgError(3, "expected `table` for exclude argument if present") } numExcludes := int(state.ObjLen(3)) for i := 0; i < numExcludes; i++ { state.RawGeti(3, i+1) exclude := checkThing(state, -1) excludes[exclude.Id] = true } } for _, content := range place.GetContents() { if excludes[content.Id] { continue } if content.Client != nil { content.Client.Send(text) } } return 0 }) return 1 }
func (p *Plugin) apiProcessNew(l *lua.State) int { callback := luar.NewLuaObject(l, 1) command := l.ToString(2) args := make([]string, l.GetTop()-2) for i := 3; i <= l.GetTop(); i++ { args[i-3] = l.ToString(i) } proc := &process{ cmd: exec.Command(command, args...), } go func() { var str string bytes, err := proc.cmd.Output() if err == nil { if bytes != nil { str = string(bytes) } p.callValue(callback, proc.cmd.ProcessState.Success(), str) } else { p.callValue(callback, false, "") } callback.Close() }() obj := luar.NewLuaObjectFromValue(l, proc) obj.Push() obj.Close() return 1 }
func printStackTypes(state *lua.State) { topIndex := state.GetTop() segments := make([]interface{}, topIndex+1) segments[0] = "Stack types:" for i := 1; i <= topIndex; i++ { segments[i] = state.LTypename(i) } log.Println(segments...) }
// GoLuaFunc converts an arbitrary Go function into a Lua-compatible GoFunction. // There are special optimized cases for functions that go from strings to strings, // and doubles to doubles, but otherwise Go // reflection is used to provide a generic wrapper function func GoLuaFunc(L *lua.State, fun interface{}) lua.LuaGoFunction { switch f := fun.(type) { case func(*lua.State) int: return f case func(string) string: return func(L *lua.State) int { L.PushString(f(L.ToString(1))) return 1 } case func(float64) float64: return func(L *lua.State) int { L.PushNumber(f(L.ToNumber(1))) return 1 } default: } var funv reflect.Value switch ff := fun.(type) { case reflect.Value: funv = ff default: funv = valueOf(fun) } funt := funv.Type() targs, tout := functionArgRetTypes(funt) return func(L *lua.State) int { var lastT reflect.Type orig_targs := targs isVariadic := funt.IsVariadic() if isVariadic { n := len(targs) lastT = targs[n-1].Elem() targs = targs[0 : n-1] } args := make([]reflect.Value, len(targs)) for i, t := range targs { val := LuaToGo(L, t, i+1) args[i] = valueOfNil(val) //println(i,args[i].String()) } if isVariadic { n := L.GetTop() for i := len(targs) + 1; i <= n; i++ { ival := LuaToGo(L, lastT, i) args = append(args, valueOfNil(ival)) } targs = orig_targs } resv := callGo(L, funv, args) for i, val := range resv { GoToLua(L, tout[i], val, false) } return len(resv) } }
func goLuaFunc(L *lua.State, fun reflect.Value) lua.LuaGoFunction { switch f := fun.Interface().(type) { case func(*lua.State) int: return f } funT := fun.Type() tArgs := make([]reflect.Type, funT.NumIn()) for i := range tArgs { tArgs[i] = funT.In(i) } return func(L *lua.State) int { var lastT reflect.Type origTArgs := tArgs isVariadic := funT.IsVariadic() if isVariadic { n := len(tArgs) lastT = tArgs[n-1].Elem() tArgs = tArgs[0 : n-1] } args := make([]reflect.Value, len(tArgs)) for i, t := range tArgs { val := LuaToGo(L, t, i+1) args[i] = valueOfNil(val) } if isVariadic { n := L.GetTop() for i := len(tArgs) + 1; i <= n; i++ { iVal := LuaToGo(L, lastT, i) args = append(args, valueOfNil(iVal)) } tArgs = origTArgs } resV := callGo(L, fun, args) for _, val := range resV { if val.Kind() == reflect.Struct { // If the function returns a struct (and not a pointer to a struct), // calling GoToLua directly will convert it to a table, making the // mathods inaccessible. We work around that issue by forcibly passing a // pointer to a struct. n := reflect.New(val.Type()) n.Elem().Set(val) val = n } GoToLua(L, nil, val, false) } return len(resV) } }
func (p *Plugin) apiAudioSetTarget(l *lua.State) int { if l.GetTop() == 0 { p.instance.Client.VoiceTarget = nil return 0 } voiceTarget, ok := luar.LuaToGo(l, nil, 1).(*gumble.VoiceTarget) if !ok { l.PushBoolean(false) return 1 } p.instance.Client.Send(voiceTarget) p.instance.Client.VoiceTarget = voiceTarget return 0 }
func LuaIntColumnQuery(L *lua.State) int { if (L.GetTop() != 1) && (L.GetTop() != 3) { panic(errors.New("Wrong number of arguments to columnq")) return 0 } name := L.ToString(1) op := "" value := "" if L.GetTop() == 3 { op = L.ToString(2) value = L.ToString(3) L.Pop(3) } else { L.Pop(1) } if name[0] == ':' { panic(errors.New("Column name can not start with ':'")) return 0 } L.CheckStack(1) tl := GetTasklistFromLua(L) tl.luaState.PushGoStruct(&SimpleExpr{name, op, value, nil, 0, ""}) return 1 }
func LuaIntGetterSetterFunction(fname string, L *lua.State, getter func(tl *Tasklist, entry *Entry) string, setter func(tl *Tasklist, entry *Entry, value string)) int { argNum := L.GetTop() if argNum == 0 { entry := GetEntryFromLua(L, CURSOR, fname) tl := GetTasklistFromLua(L) L.PushString(getter(tl, entry)) return 1 } else if argNum == 1 { value := L.ToString(1) entry := GetEntryFromLua(L, CURSOR, fname) tl := GetTasklistFromLua(L) setter(tl, entry, value) if !tl.luaFlags.cursorCloned { tl.luaFlags.cursorEdited = true } return 0 } panic(errors.New(fmt.Sprintf("Incorrect number of argoments to %s (only 0 or 1 accepted)", fname))) return 0 }
func LuaIntBoolQuery(L *lua.State, operator, name string) int { if L.GetTop() < 2 { panic(errors.New("Wrong number of arguments to " + name)) return 0 } L.CheckStack(1) tl := GetTasklistFromLua(L) r := &BoolExpr{operator, make([]Clausable, 0)} for i := 1; i <= L.GetTop(); i++ { clausable := GetQueryObject(tl, i) if clausable == nil { panic(errors.New("Wrong argument type to " + name + " only query objects accepted as arguments")) return 0 } r.subExpr = append(r.subExpr, clausable) } tl.luaState.PushGoStruct(r) return 1 }
func LuaIntColumn(L *lua.State) int { argNum := L.GetTop() if argNum == 1 { name := L.ToString(1) entry := GetEntryFromLua(L, CURSOR, "column()") L.PushString(entry.Column(name)) return 1 } else if argNum == 2 { name := L.ToString(1) value := L.ToString(2) entry := GetEntryFromLua(L, CURSOR, "column()") entry.SetColumn(name, value) tl := GetTasklistFromLua(L) if !tl.luaFlags.cursorCloned { tl.luaFlags.cursorEdited = true } return 0 } panic(errors.New("Incorrect number of arguments to column (only 1 or 2 accepted)")) return 0 }
func LuaIntSearch(L *lua.State) int { if (L.GetTop() < 1) || (L.GetTop() > 2) { panic(errors.New("Wrong number of arguments to search()")) return 0 } L.CheckStack(2) tl := GetTasklistFromLua(L) if !tl.luaFlags.freeCursor { panic(errors.New("search() function only available on a free cursor")) return 0 } query := L.ToString(1) var luaClausable Clausable = nil if L.GetTop() == 2 { luaClausable = GetQueryObject(tl, 2) } theselect, _, _, _, _, _, _, perr := tl.ParseSearch(query, luaClausable) Must(perr) entries, serr := tl.Retrieve(theselect, "", false) Must(serr) Logf(INFO, "Searching from lua interface <%s> clausable: <%v> yields %d results\n", query, luaClausable, len(entries)) r := []string{} for _, entry := range entries { r = append(r, entry.Id()) } PushStringVec(L, r) return 1 }
func LuaIntSplit(L *lua.State) int { if L.GetTop() < 2 { panic(errors.New("Wrong number of arguments to split()")) return 0 } instr := L.ToString(1) sepstr := L.ToString(2) n := -1 if L.GetTop() == 3 { n = L.ToInteger(3) } if L.GetTop() > 3 { panic(errors.New("Wrong number of arguments to split()")) return 0 } PushStringVec(L, strings.SplitN(instr, sepstr, n)) return 1 }
func register(L *lua.State, table string, values Map, convertFun bool) { pop := true if table == "*" { pop = false } else if len(table) > 0 { L.GetGlobal(table) if L.IsNil(-1) { L.NewTable() L.SetGlobal(table) L.GetGlobal(table) } } else { L.GetGlobal("_G") } for name, val := range values { t := reflect.TypeOf(val) if t.Kind() == reflect.Func { if convertFun { L.PushGoFunction(GoLuaFunc(L, val)) } else { lf := val.(func(*lua.State) int) L.PushGoFunction(lf) } } else { GoToLua(L, t, valueOf(val), false) } L.SetField(-2, name) if t.Kind() == reflect.Func { var lf func(*lua.State) int if convertFun { lf = GoLuaFunc(L, val) } else { lf = val.(func(*lua.State) int) } L.PushGoFunction(func(L *lua.State) (ret int) { defer func() { if err2 := recover(); err2 != nil { GoToLua(L, typeof(err2), valueOf(err2), false) ret = 1 return } }() ret = lf(L) pos := L.GetTop() - ret + 1 L.PushNil() L.Insert(pos) for i := 0; i < L.GetTop(); i++ { fmt.Println(L.Typename(int(L.Type(i + 1)))) } return ret + 1 }) L.SetField(-2, "safe_"+name) } } if pop { L.Pop(1) } }
func luaAssertArgnum(L *lua.State, n int, fname string) { if L.GetTop() != n { panic(errors.New("Incorrect number of arguments to " + fname)) } }