Compare commits

..

8 Commits

Author SHA1 Message Date
TorchedSammy 0a5a2e727e
feat: add hilbish properties 2022-03-29 23:37:53 -04:00
TorchedSammy 8714f54915
feat: implement job management 2022-03-29 21:43:36 -04:00
TorchedSammy c46807613e
refactor: make loader functions for go modules unexported 2022-03-29 21:05:46 -04:00
TorchedSammy a45b3fe1fa
chore: fix dofile comment doc 2022-03-29 21:04:50 -04:00
TorchedSammy 245400e43d
chore: add comments to document util functions 2022-03-29 21:02:15 -04:00
TorchedSammy 6848b59cbf
feat: implement syntax highlight and hints 2022-03-29 20:57:29 -04:00
TorchedSammy ad183a7208
style: use comma separated cases instead of fallthrough 2022-03-29 20:57:05 -04:00
TorchedSammy 3bea73460a
feat: implement runner mode 2022-03-29 20:16:03 -04:00
11 changed files with 167 additions and 157 deletions

View File

@ -66,13 +66,14 @@ func (a *aliasHandler) Resolve(cmdstr string) string {
// lua section // lua section
func (a *aliasHandler) Loader(rtm *rt.Runtime) *rt.Table { func (a *aliasHandler) Loader(rtm *rt.Runtime) *rt.Table {
// create a lua module with our functions // create a lua module with our functions
hshaliasesLua := map[string]util.LuaExport{ hshaliasesLua := map[string]util.LuaExport{
"add": util.LuaExport{a.luaAdd, 2, false}, "add": util.LuaExport{a.luaAdd, 2, false},
"list": util.LuaExport{a.luaList, 0, false}, "list": util.LuaExport{a.luaList, 0, false},
"del": util.LuaExport{a.luaDelete, 1, false}, "del": util.LuaExport{a.luaDelete, 1, false},
} }
mod := rt.NewTable() mod := rt.NewTable()
util.SetExports(rtm, mod, hshaliasesLua) util.SetExports(rtm, mod, hshaliasesLua)

101
api.go
View File

@ -31,10 +31,14 @@ var exports = map[string]util.LuaExport{
"cwd": util.LuaExport{hlcwd, 0, false}, "cwd": util.LuaExport{hlcwd, 0, false},
/* /*
"exec": hlexec, "exec": hlexec,
"runnerMode": hlrunnerMode, */
"runnerMode": util.LuaExport{hlrunnerMode, 1, false},
/*
"goro": hlgoro, "goro": hlgoro,
"highlighter": hlhighlighter, */
"hinter": hlhinter, "highlighter": util.LuaExport{hlhighlighter, 1, false},
"hinter": util.LuaExport{hlhinter, 1, false},
/*
"multiprompt": hlmlprompt, "multiprompt": hlmlprompt,
"prependPath": hlprependPath, "prependPath": hlprependPath,
*/ */
@ -61,7 +65,7 @@ func hilbishLoad(rtm *rt.Runtime) (rt.Value, func()) {
util.SetExports(rtm, mod, exports) util.SetExports(rtm, mod, exports)
hshMod = mod hshMod = mod
// host, _ := os.Hostname() host, _ := os.Hostname()
username := curuser.Username username := curuser.Username
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
@ -72,22 +76,17 @@ func hilbishLoad(rtm *rt.Runtime) (rt.Value, func()) {
The nice lil shell for {blue}Lua{reset} fanatics! The nice lil shell for {blue}Lua{reset} fanatics!
Check out the {blue}{bold}guide{reset} command to get started. Check out the {blue}{bold}guide{reset} command to get started.
` `
/* util.SetField(rtm, mod, "ver", rt.StringValue(version), "Hilbish version")
util.SetField(L, mod, "ver", lua.LString(version), "Hilbish version") util.SetField(rtm, mod, "user", rt.StringValue(username), "Username of user")
util.SetField(L, mod, "user", lua.LString(username), "Username of user") util.SetField(rtm, mod, "host", rt.StringValue(host), "Host name of the machine")
util.SetField(L, mod, "host", lua.LString(host), "Host name of the machine")
*/
util.SetField(rtm, mod, "home", rt.StringValue(curuser.HomeDir), "Home directory of the user") util.SetField(rtm, mod, "home", rt.StringValue(curuser.HomeDir), "Home directory of the user")
util.SetField(rtm, mod, "dataDir", rt.StringValue(dataDir), "Directory for Hilbish's data files") util.SetField(rtm, mod, "dataDir", rt.StringValue(dataDir), "Directory for Hilbish's data files")
/* util.SetField(rtm, mod, "interactive", rt.BoolValue(interactive), "If this is an interactive shell")
util.SetField(L, mod, "interactive", lua.LBool(interactive), "If this is an interactive shell") util.SetField(rtm, mod, "login", rt.BoolValue(login), "Whether this is a login shell")
util.SetField(L, mod, "login", lua.LBool(interactive), "Whether this is a login shell")
*/
util.SetField(rtm, mod, "greeting", rt.StringValue(greeting), "Hilbish's welcome message for interactive shells. It has Lunacolors formatting.") util.SetField(rtm, mod, "greeting", rt.StringValue(greeting), "Hilbish's welcome message for interactive shells. It has Lunacolors formatting.")
/*util.SetField(l, mod, "vimMode", lua.LNil, "Current Vim mode of Hilbish (nil if not in Vim mode)") util.SetField(rtm, mod, "vimMode", rt.NilValue, "Current Vim mode of Hilbish (nil if not in Vim mode)")
util.SetField(l, hshMod, "exitCode", lua.LNumber(0), "Exit code of last exected command") util.SetField(rtm, hshMod, "exitCode", rt.IntValue(0), "Exit code of last exected command")
util.Document(L, mod, "Hilbish's core API, containing submodules and functions which relate to the shell itself.") //util.Document(rtm, mod, "Hilbish's core API, containing submodules and functions which relate to the shell itself.")
*/
// hilbish.userDir table // hilbish.userDir table
hshuser := rt.NewTable() hshuser := rt.NewTable()
@ -129,19 +128,17 @@ Check out the {blue}{bold}guide{reset} command to get started.
util.Document(L, hshcomp, "Completions interface for Hilbish.") util.Document(L, hshcomp, "Completions interface for Hilbish.")
L.SetField(mod, "completion", hshcomp) L.SetField(mod, "completion", hshcomp)
// hilbish.runner table
runnerModule := runnerModeLoader(L)
util.Document(L, runnerModule, "Runner/exec interface for Hilbish.")
L.SetField(mod, "runner", runnerModule)
*/ */
// hilbish.runner table
runnerModule := runnerModeLoader(rtm)
//util.Document(L, runnerModule, "Runner/exec interface for Hilbish.")
mod.Set(rt.StringValue("runner"), rt.TableValue(runnerModule))
// hilbish.jobs table // hilbish.jobs table
jobs = newJobHandler() jobs = newJobHandler()
/* jobModule := jobs.loader(rtm)
jobModule := jobs.loader(L) // util.Document(L, jobModule, "(Background) job interface.")
util.Document(L, jobModule, "(Background) job interface.") mod.Set(rt.StringValue("jobs"), rt.TableValue(jobModule))
L.SetField(mod, "jobs", jobModule)
*/
return rt.TableValue(mod), nil return rt.TableValue(mod), nil
} }
@ -545,7 +542,6 @@ func hlinputMode(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return c.Next(), nil return c.Next(), nil
} }
/*
// runnerMode(mode) // runnerMode(mode)
// Sets the execution/runner mode for interactive Hilbish. This determines whether // Sets the execution/runner mode for interactive Hilbish. This determines whether
// Hilbish wll try to run input as Lua and/or sh or only do one of either. // Hilbish wll try to run input as Lua and/or sh or only do one of either.
@ -553,24 +549,24 @@ func hlinputMode(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
// sh, and lua. It also accepts a function, to which if it is passed one // sh, and lua. It also accepts a function, to which if it is passed one
// will call it to execute user input instead. // will call it to execute user input instead.
// --- @param mode string|function // --- @param mode string|function
func hlrunnerMode(L *lua.LState) int { func hlrunnerMode(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
mode := L.CheckAny(1) if err := c.Check1Arg(); err != nil {
return nil, err
}
mode := c.Arg(0)
switch mode.Type() { switch mode.Type() {
case lua.LTString: case rt.StringType:
switch mode.String() { switch mode.AsString() {
// no fallthrough doesnt work so eh // no fallthrough doesnt work so eh
case "hybrid": fallthrough case "hybrid", "hybridRev", "lua", "sh": runnerMode = mode
case "hybridRev": fallthrough default: return nil, errors.New("execMode: expected either a function or hybrid, hybridRev, lua, sh. Received " + mode.AsString())
case "lua": fallthrough
case "sh":
runnerMode = mode
default: L.RaiseError("execMode: expected either a function or hybrid, hybridRev, lua, sh. Received %v", mode)
} }
case lua.LTFunction: runnerMode = mode case rt.FunctionType: runnerMode = mode
default: L.RaiseError("execMode: expected either a function or hybrid, hybridRev, lua, sh. Received %v", mode) default: return nil, errors.New("execMode: expected either a function or hybrid, hybridRev, lua, sh. Received " + mode.TypeName())
} }
return 0 return c.Next(), nil
} }
// hinter(cb) // hinter(cb)
@ -579,11 +575,17 @@ func hlrunnerMode(L *lua.LState) int {
// the current line and the position. It is expected to return a string // the current line and the position. It is expected to return a string
// which will be used for the hint. // which will be used for the hint.
// --- @param cb function // --- @param cb function
func hlhinter(L *lua.LState) int { func hlhinter(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
hinterCb := L.CheckFunction(1) if err := c.Check1Arg(); err != nil {
return nil, err
}
hinterCb, err := c.ClosureArg(0)
if err != nil {
return nil, err
}
hinter = hinterCb hinter = hinterCb
return 0 return c.Next(), err
} }
// highlighter(cb) // highlighter(cb)
@ -592,10 +594,15 @@ func hlhinter(L *lua.LState) int {
// is passed the current line as typed and is expected to return a line that will // is passed the current line as typed and is expected to return a line that will
// be used to display in the line. // be used to display in the line.
// --- @param cb function // --- @param cb function
func hlhighlighter(L *lua.LState) int { func hlhighlighter(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
highlighterCb := L.CheckFunction(1) if err := c.Check1Arg(); err != nil {
return nil, err
}
highlighterCb, err := c.ClosureArg(0)
if err != nil {
return nil, err
}
highlighter = highlighterCb highlighter = highlighterCb
return 0 return c.Next(), err
} }
*/

28
exec.go
View File

@ -24,15 +24,15 @@ import (
) )
var errNotExec = errors.New("not executable") var errNotExec = errors.New("not executable")
//var runnerMode lua.LValue = lua.LString("hybrid") var runnerMode rt.Value = rt.StringValue("hybrid")
func runInput(input string, priv bool) { func runInput(input string, priv bool) {
running = true running = true
cmdString := aliases.Resolve(input) cmdString := aliases.Resolve(input)
hooks.Em.Emit("command.preexec", input, cmdString) hooks.Em.Emit("command.preexec", input, cmdString)
// if runnerMode.Type() == lua.LTString { if runnerMode.Type() == rt.StringType {
switch /*runnerMode.String()*/ "hybrid" { switch runnerMode.AsString() {
case "hybrid": case "hybrid":
_, err := handleLua(cmdString) _, err := handleLua(cmdString)
if err == nil { if err == nil {
@ -68,35 +68,29 @@ func runInput(input string, priv bool) {
} }
cmdFinish(exitCode, cmdString, priv) cmdFinish(exitCode, cmdString, priv)
} }
// } else { } else {
// can only be a string or function so // can only be a string or function so
/* term := rt.NewTerminationWith(l.MainThread().CurrentCont(), 2, false)
err := l.CallByParam(lua.P{ err := rt.Call(l.MainThread(), runnerMode, []rt.Value{rt.StringValue(cmdString)}, term)
Fn: runnerMode,
NRet: 2,
Protect: true,
}, lua.LString(cmdString))
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, err) fmt.Fprintln(os.Stderr, err)
cmdFinish(124, cmdString, priv) cmdFinish(124, cmdString, priv)
return return
} }
luaexitcode := l.Get(-2) // first return value (makes sense right i love stacks) luaexitcode := term.Get(0) // first return value (makes sense right i love stacks)
runErr := l.Get(-1) runErr := term.Get(1)
l.Pop(2)
var exitCode uint8 var exitCode uint8
if code, ok := luaexitcode.(lua.LNumber); luaexitcode != lua.LNil && ok { if code, ok := luaexitcode.TryInt(); ok {
exitCode = uint8(code) exitCode = uint8(code)
} }
if runErr != lua.LNil { if runErr != rt.NilValue {
fmt.Fprintln(os.Stderr, runErr) fmt.Fprintln(os.Stderr, runErr)
} }
cmdFinish(exitCode, cmdString, priv) cmdFinish(exitCode, cmdString, priv)
*/ }
// }
} }
func handleLua(cmdString string) (uint8, error) { func handleLua(cmdString string) (uint8, error) {

View File

@ -24,14 +24,14 @@ func New() Bait {
Em: emitter, Em: emitter,
} }
b.Loader = packagelib.Loader{ b.Loader = packagelib.Loader{
Load: b.LoaderFunc, Load: b.loaderFunc,
Name: "bait", Name: "bait",
} }
return b return b
} }
func (b *Bait) LoaderFunc(rtm *rt.Runtime) (rt.Value, func()) { func (b *Bait) loaderFunc(rtm *rt.Runtime) (rt.Value, func()) {
exports := map[string]util.LuaExport{ exports := map[string]util.LuaExport{
"catch": util.LuaExport{b.bcatch, 2, false}, "catch": util.LuaExport{b.bcatch, 2, false},
"catchOnce": util.LuaExport{b.bcatchOnce, 2, false}, "catchOnce": util.LuaExport{b.bcatchOnce, 2, false},

View File

@ -18,14 +18,14 @@ func New() Commander {
Events: emission.NewEmitter(), Events: emission.NewEmitter(),
} }
c.Loader = packagelib.Loader{ c.Loader = packagelib.Loader{
Load: c.LoaderFunc, Load: c.loaderFunc,
Name: "commander", Name: "commander",
} }
return c return c
} }
func (c *Commander) LoaderFunc(rtm *rt.Runtime) (rt.Value, func()) { func (c *Commander) loaderFunc(rtm *rt.Runtime) (rt.Value, func()) {
exports := map[string]util.LuaExport{ exports := map[string]util.LuaExport{
"register": util.LuaExport{c.cregister, 2, false}, "register": util.LuaExport{c.cregister, 2, false},
"deregister": util.LuaExport{c.cderegister, 1, false}, "deregister": util.LuaExport{c.cderegister, 1, false},

View File

@ -12,11 +12,11 @@ import (
) )
var Loader = packagelib.Loader{ var Loader = packagelib.Loader{
Load: LoaderFunc, Load: loaderFunc,
Name: "fs", Name: "fs",
} }
func LoaderFunc(rtm *rt.Runtime) (rt.Value, func()) { func loaderFunc(rtm *rt.Runtime) (rt.Value, func()) {
exports := map[string]util.LuaExport{ exports := map[string]util.LuaExport{
"cd": util.LuaExport{fcd, 1, false}, "cd": util.LuaExport{fcd, 1, false},
"mkdir": util.LuaExport{fmkdir, 2, false}, "mkdir": util.LuaExport{fmkdir, 2, false},

79
job.go
View File

@ -3,6 +3,10 @@ package main
import ( import (
"sync" "sync"
"os" "os"
"hilbish/util"
rt "github.com/arnodel/golua/runtime"
) )
var jobs *jobHandler var jobs *jobHandler
@ -19,7 +23,7 @@ type job struct {
func (j *job) start(pid int) { func (j *job) start(pid int) {
j.pid = pid j.pid = pid
j.running = true j.running = true
// hooks.Em.Emit("job.start", j.lua()) hooks.Em.Emit("job.start", j.lua())
} }
func (j *job) stop() { func (j *job) stop() {
@ -29,39 +33,36 @@ func (j *job) stop() {
func (j *job) finish() { func (j *job) finish() {
j.running = false j.running = false
// hooks.Em.Emit("job.done", j.lua()) hooks.Em.Emit("job.done", j.lua())
} }
func (j *job) setHandle(handle *os.Process) { func (j *job) setHandle(handle *os.Process) {
j.proc = handle j.proc = handle
} }
/* func (j *job) lua() rt.Value {
func (j *job) lua() *lua.LTable { jobFuncs := map[string]util.LuaExport{
// returns lua table for job "stop": {j.luaStop, 0, false},
// because userdata is gross
jobFuncs := map[string]lua.LGFunction{
"stop": j.luaStop,
} }
luaJob := l.SetFuncs(l.NewTable(), jobFuncs) luaJob := rt.NewTable()
util.SetExports(l, luaJob, jobFuncs)
l.SetField(luaJob, "cmd", lua.LString(j.cmd)) luaJob.Set(rt.StringValue("cmd"), rt.StringValue(j.cmd))
l.SetField(luaJob, "running", lua.LBool(j.running)) luaJob.Set(rt.StringValue("running"), rt.BoolValue(j.running))
l.SetField(luaJob, "id", lua.LNumber(j.id)) luaJob.Set(rt.StringValue("id"), rt.IntValue(int64(j.id)))
l.SetField(luaJob, "pid", lua.LNumber(j.pid)) luaJob.Set(rt.StringValue("pid"), rt.IntValue(int64(j.pid)))
l.SetField(luaJob, "exitCode", lua.LNumber(j.exitCode)) luaJob.Set(rt.StringValue("exitCode"), rt.IntValue(int64(j.exitCode)))
return luaJob return rt.TableValue(luaJob)
} }
func (j *job) luaStop(L *lua.LState) int { func (j *job) luaStop(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if j.running { if j.running {
j.stop() j.stop()
} }
return 0 return c.Next(), nil
} }
*/
type jobHandler struct { type jobHandler struct {
jobs map[int]*job jobs map[int]*job
@ -96,42 +97,46 @@ func (j *jobHandler) getLatest() *job {
return j.jobs[j.latestID] return j.jobs[j.latestID]
} }
/* func (j *jobHandler) loader(rtm *rt.Runtime) *rt.Table {
func (j *jobHandler) loader(L *lua.LState) *lua.LTable { jobFuncs := map[string]util.LuaExport{
jobFuncs := map[string]lua.LGFunction{ "all": {j.luaAllJobs, 0, false},
"all": j.luaAllJobs, "get": {j.luaGetJob, 1, false},
"get": j.luaGetJob,
} }
luaJob := l.SetFuncs(l.NewTable(), jobFuncs) luaJob := rt.NewTable()
util.SetExports(rtm, luaJob, jobFuncs)
return luaJob return luaJob
} }
func (j *jobHandler) luaGetJob(L *lua.LState) int { func (j *jobHandler) luaGetJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
j.mu.RLock() j.mu.RLock()
defer j.mu.RUnlock() defer j.mu.RUnlock()
jobID := L.CheckInt(1) if err := c.Check1Arg(); err != nil {
job := j.jobs[jobID] return nil, err
if job != nil { }
return 0 jobID, err := c.IntArg(0)
if err != nil {
return nil, err
} }
L.Push(job.lua())
return 1 job := j.jobs[int(jobID)]
if job == nil {
return c.Next(), nil
}
return c.PushingNext1(t.Runtime, job.lua()), nil
} }
func (j *jobHandler) luaAllJobs(L *lua.LState) int { func (j *jobHandler) luaAllJobs(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
j.mu.RLock() j.mu.RLock()
defer j.mu.RUnlock() defer j.mu.RUnlock()
jobTbl := L.NewTable() jobTbl := rt.NewTable()
for id, job := range j.jobs { for id, job := range j.jobs {
jobTbl.Insert(id, job.lua()) jobTbl.Set(rt.IntValue(int64(id)), job.lua())
} }
L.Push(jobTbl) return c.PushingNext1(t.Runtime, rt.TableValue(jobTbl)), nil
return 1
} }
*/

36
rl.go
View File

@ -13,10 +13,8 @@ type lineReader struct {
rl *readline.Instance rl *readline.Instance
} }
var fileHist *fileHistory var fileHist *fileHistory
/* var hinter *rt.Closure
var hinter lua.LValue = lua.LNil var highlighter *rt.Closure
var highlighter lua.LValue = lua.LNil
*/
func newLineReader(prompt string, noHist bool) *lineReader { func newLineReader(prompt string, noHist bool) *lineReader {
rl := readline.NewInstance() rl := readline.NewInstance()
@ -47,53 +45,43 @@ func newLineReader(prompt string, noHist bool) *lineReader {
} }
hooks.Em.Emit("hilbish.vimAction", actionStr, args) hooks.Em.Emit("hilbish.vimAction", actionStr, args)
} }
/*
rl.HintText = func(line []rune, pos int) []rune { rl.HintText = func(line []rune, pos int) []rune {
if hinter == lua.LNil { if hinter == nil {
return []rune{} return []rune{}
} }
err := l.CallByParam(lua.P{ retVal, err := rt.Call1(l.MainThread(), rt.FunctionValue(highlighter),
Fn: hinter, rt.StringValue(string(line)), rt.IntValue(int64(pos)))
NRet: 1,
Protect: true,
}, lua.LString(string(line)), lua.LNumber(pos))
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
return []rune{} return []rune{}
} }
retVal := l.Get(-1)
hintText := "" hintText := ""
if luaStr, ok := retVal.(lua.LString); retVal != lua.LNil && ok { if luaStr, ok := retVal.TryString(); ok {
hintText = luaStr.String() hintText = luaStr
} }
return []rune(hintText) return []rune(hintText)
} }
rl.SyntaxHighlighter = func(line []rune) string { rl.SyntaxHighlighter = func(line []rune) string {
if highlighter == lua.LNil { if highlighter == nil {
return string(line) return string(line)
} }
err := l.CallByParam(lua.P{ retVal, err := rt.Call1(l.MainThread(), rt.FunctionValue(highlighter),
Fn: highlighter, rt.StringValue(string(line)))
NRet: 1,
Protect: true,
}, lua.LString(string(line)))
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
return string(line) return string(line)
} }
retVal := l.Get(-1)
highlighted := "" highlighted := ""
if luaStr, ok := retVal.(lua.LString); retVal != lua.LNil && ok { if luaStr, ok := retVal.TryString(); ok {
highlighted = luaStr.String() highlighted = luaStr
} }
return highlighted return highlighted
} }
*/
rl.TabCompleter = func(line []rune, pos int, _ readline.DelayedTabContext) (string, []*readline.CompletionGroup) { rl.TabCompleter = func(line []rune, pos int, _ readline.DelayedTabContext) (string, []*readline.CompletionGroup) {
ctx := string(line) ctx := string(line)
var completions []string var completions []string

View File

@ -1,47 +1,56 @@
package main package main
/*
import ( import (
"hilbish/util"
rt "github.com/arnodel/golua/runtime"
) )
func runnerModeLoader(L *lua.LState) *lua.LTable { func runnerModeLoader(rtm *rt.Runtime) *rt.Table {
exports := map[string]lua.LGFunction{ exports := map[string]util.LuaExport{
"sh": shRunner, "sh": {shRunner, 1, false},
"lua": luaRunner, "lua": {luaRunner, 1, false},
"setMode": hlrunnerMode, "setMode": {hlrunnerMode, 1, false},
} }
mod := L.SetFuncs(L.NewTable(), exports) mod := rt.NewTable()
L.SetField(mod, "mode", runnerMode) util.SetExports(rtm, mod, exports)
return mod return mod
} }
func shRunner(L *lua.LState) int { func shRunner(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
cmd := L.CheckString(1) if err := c.Check1Arg(); err != nil {
return nil, err
}
cmd, err := c.StringArg(0)
if err != nil {
return nil, err
}
exitCode, err := handleSh(cmd) exitCode, err := handleSh(cmd)
var luaErr lua.LValue = lua.LNil var luaErr rt.Value = rt.NilValue
if err != nil { if err != nil {
luaErr = lua.LString(err.Error()) luaErr = rt.StringValue(err.Error())
} }
L.Push(lua.LNumber(exitCode)) return c.PushingNext(t.Runtime, rt.IntValue(int64(exitCode)), luaErr), nil
L.Push(luaErr)
return 2
} }
func luaRunner(L *lua.LState) int { func luaRunner(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
cmd := L.CheckString(1) if err := c.Check1Arg(); err != nil {
return nil, err
}
cmd, err := c.StringArg(0)
if err != nil {
return nil, err
}
exitCode, err := handleLua(cmd) exitCode, err := handleLua(cmd)
var luaErr lua.LValue = lua.LNil var luaErr rt.Value = rt.NilValue
if err != nil { if err != nil {
luaErr = lua.LString(err.Error()) luaErr = rt.StringValue(err.Error())
} }
L.Push(lua.LNumber(exitCode)) return c.PushingNext(t.Runtime, rt.IntValue(int64(exitCode)), luaErr), nil
L.Push(luaErr)
return 2
} }
*/

View File

@ -4,12 +4,14 @@ import (
rt "github.com/arnodel/golua/runtime" rt "github.com/arnodel/golua/runtime"
) )
// LuaExport represents a Go function which can be exported to Lua.
type LuaExport struct { type LuaExport struct {
Function rt.GoFunctionFunc Function rt.GoFunctionFunc
ArgNum int ArgNum int
Variadic bool Variadic bool
} }
// SetExports puts the Lua function exports in the table.
func SetExports(rtm *rt.Runtime, tbl *rt.Table, exports map[string]LuaExport) { func SetExports(rtm *rt.Runtime, tbl *rt.Table, exports map[string]LuaExport) {
for name, export := range exports { for name, export := range exports {
rtm.SetEnvGoFunc(tbl, name, export.Function, export.ArgNum, export.Variadic) rtm.SetEnvGoFunc(tbl, name, export.Function, export.ArgNum, export.Variadic)

View File

@ -39,6 +39,7 @@ func SetField(rtm *rt.Runtime, module *rt.Table, field string, value rt.Value, d
module.Set(rt.StringValue(field), value) module.Set(rt.StringValue(field), value)
} }
// DoString runs the code string in the Lua runtime.
func DoString(rtm *rt.Runtime, code string) error { func DoString(rtm *rt.Runtime, code string) error {
chunk, err := rtm.CompileAndLoadLuaChunk("", []byte(code), rt.TableValue(rtm.GlobalEnv())) chunk, err := rtm.CompileAndLoadLuaChunk("", []byte(code), rt.TableValue(rtm.GlobalEnv()))
if chunk != nil { if chunk != nil {
@ -48,6 +49,7 @@ func DoString(rtm *rt.Runtime, code string) error {
return err return err
} }
// DoFile runs the contents of the file in the Lua runtime.
func DoFile(rtm *rt.Runtime, filename string) error { func DoFile(rtm *rt.Runtime, filename string) error {
data, err := os.ReadFile(filename) data, err := os.ReadFile(filename)
if err != nil { if err != nil {
@ -57,6 +59,8 @@ func DoFile(rtm *rt.Runtime, filename string) error {
return DoString(rtm, string(data)) return DoString(rtm, string(data))
} }
// HandleStrCallback handles function parameters for Go functions which take
// a string and a closure.
func HandleStrCallback(t *rt.Thread, c *rt.GoCont) (string, *rt.Closure, error) { func HandleStrCallback(t *rt.Thread, c *rt.GoCont) (string, *rt.Closure, error) {
if err := c.CheckNArgs(2); err != nil { if err := c.CheckNArgs(2); err != nil {
return "", nil, err return "", nil, err