sammyette 2024-07-19 21:43:36 +00:00 committed by GitHub
commit 0c61db54da
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 455 additions and 250 deletions

View File

@ -1,4 +1,4 @@
<img src="./assets/hilbish-logo-and-text.png" width=512><br> <img src="./assets/hilbish-logo-and-text-midnight-edition.png" width=512><br>
<blockquote> <blockquote>
🌓 The Moon-powered shell! A comfy and extensible shell for Lua fans! 🌺 ✨ 🌓 The Moon-powered shell! A comfy and extensible shell for Lua fans! 🌺 ✨
</blockquote> </blockquote>
@ -9,6 +9,26 @@
<a href="https://discord.gg/3PDdcQz"><img alt="Discord" src="https://img.shields.io/discord/732357621503229962?color=blue&style=flat-square"></a> <a href="https://discord.gg/3PDdcQz"><img alt="Discord" src="https://img.shields.io/discord/732357621503229962?color=blue&style=flat-square"></a>
<br> <br>
# Midnight Edition
> [!CAUTION]
> This is a **HEAVILY** WORK IN PROGRESS branch which makes a lot of internal changes.
Functionality **will** be missing if you use this branch,
and you may see crashes too. Tread lightly.
Progress on Midnight Edition is tracked in this PR: [#314](https://github.com/Rosettea/Hilbish/pull/314)
Hilbish: Midinight Edition is a version of Hilbish meant to be compatible with
the original C implementation of Lua by using a Go library binding. The end goal
is to offer Midnight Edition as a separate, "not as supported" build for users
that *really* want to access a certain library made for C Lua or want the
most performance with their Lua code.
**The standard edition, which is all native Go,
will always be more supported than Midnight Edition.**
# Back the original README
Hilbish is an extensible shell designed to be highly customizable. Hilbish is an extensible shell designed to be highly customizable.
It is configured in Lua and provides a good range of features. It is configured in Lua and provides a good range of features.
It aims to be easy to use for anyone but powerful enough for It aims to be easy to use for anyone but powerful enough for

View File

@ -97,7 +97,7 @@ func (a *aliasModule) Resolve(cmdstr string) string {
func (a *aliasModule) Loader(rtm *rt.Runtime) *rt.Table { func (a *aliasModule) 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{hlalias, 2, false}, //"add": util.LuaExport{hlalias, 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},
"resolve": util.LuaExport{a.luaResolve, 1, false}, "resolve": util.LuaExport{a.luaResolve, 1, false},

176
api.go
View File

@ -15,56 +15,52 @@ package main
import ( import (
"bytes" "bytes"
"errors" "errors"
"fmt" //"fmt"
"io" "io"
"os" "os"
"os/exec" //"os/exec"
"runtime" "runtime"
"strings" "strings"
"syscall" //"syscall"
"time" //"time"
"hilbish/util" //"hilbish/util"
"hilbish/moonlight"
rt "github.com/arnodel/golua/runtime" rt "github.com/arnodel/golua/runtime"
"github.com/arnodel/golua/lib/packagelib" //"github.com/arnodel/golua/lib/packagelib"
"github.com/arnodel/golua/lib/iolib" "github.com/arnodel/golua/lib/iolib"
"github.com/maxlandon/readline" "github.com/maxlandon/readline"
"mvdan.cc/sh/v3/interp" "mvdan.cc/sh/v3/interp"
) )
var exports = map[string]util.LuaExport{ var hshMod *moonlight.Table
"alias": {hlalias, 2, false},
"appendPath": {hlappendPath, 1, false},
"complete": {hlcomplete, 2, false},
"cwd": {hlcwd, 0, false},
"exec": {hlexec, 1, false},
"runnerMode": {hlrunnerMode, 1, false},
"goro": {hlgoro, 1, true},
"highlighter": {hlhighlighter, 1, false},
"hinter": {hlhinter, 1, false},
"multiprompt": {hlmultiprompt, 1, false},
"prependPath": {hlprependPath, 1, false},
"prompt": {hlprompt, 1, true},
"inputMode": {hlinputMode, 1, false},
"interval": {hlinterval, 2, false},
"read": {hlread, 1, false},
"run": {hlrun, 1, true},
"timeout": {hltimeout, 2, false},
"which": {hlwhich, 1, false},
}
var hshMod *rt.Table func hilbishLoader(mlr *moonlight.Runtime) moonlight.Value {
var hilbishLoader = packagelib.Loader{ var exports = map[string]moonlight.Export{
Load: hilbishLoad, "alias": {hlalias, 2, false},
Name: "hilbish", /*
} "appendPath": {hlappendPath, 1, false},
"complete": {hlcomplete, 2, false},
func hilbishLoad(rtm *rt.Runtime) (rt.Value, func()) { "cwd": {hlcwd, 0, false},
mod := rt.NewTable() "exec": {hlexec, 1, false},
"runnerMode": {hlrunnerMode, 1, false},
util.SetExports(rtm, mod, exports) "goro": {hlgoro, 1, true},
hshMod = mod "highlighter": {hlhighlighter, 1, false},
"hinter": {hlhinter, 1, false},
"multiprompt": {hlmultiprompt, 1, false},
"prependPath": {hlprependPath, 1, false},
"prompt": {hlprompt, 1, true},
"inputMode": {hlinputMode, 1, false},
"interval": {hlinterval, 2, false},
"read": {hlread, 1, false},
"run": {hlrun, 1, true},
"timeout": {hltimeout, 2, false},
"which": {hlwhich, 1, false},
*/
}
hshMod = moonlight.NewTable()
mlr.SetExports(hshMod, exports)
host, _ := os.Hostname() host, _ := os.Hostname()
username := curuser.Username username := curuser.Username
@ -73,68 +69,68 @@ func hilbishLoad(rtm *rt.Runtime) (rt.Value, func()) {
username = strings.Split(username, "\\")[1] // for some reason Username includes the hostname on windows username = strings.Split(username, "\\")[1] // for some reason Username includes the hostname on windows
} }
util.SetField(rtm, mod, "ver", rt.StringValue(getVersion())) hshMod.SetField("ver", moonlight.StringValue(getVersion()))
util.SetField(rtm, mod, "goVersion", rt.StringValue(runtime.Version())) hshMod.SetField("goVersion", moonlight.StringValue(runtime.Version()))
util.SetField(rtm, mod, "user", rt.StringValue(username)) hshMod.SetField("user", moonlight.StringValue(username))
util.SetField(rtm, mod, "host", rt.StringValue(host)) hshMod.SetField("host", moonlight.StringValue(host))
util.SetField(rtm, mod, "home", rt.StringValue(curuser.HomeDir)) hshMod.SetField("home", moonlight.StringValue(curuser.HomeDir))
util.SetField(rtm, mod, "dataDir", rt.StringValue(dataDir)) hshMod.SetField("dataDir", moonlight.StringValue(dataDir))
util.SetField(rtm, mod, "interactive", rt.BoolValue(interactive)) hshMod.SetField("interactive", moonlight.BoolValue(interactive))
util.SetField(rtm, mod, "login", rt.BoolValue(login)) hshMod.SetField("login", moonlight.BoolValue(login))
util.SetField(rtm, mod, "vimMode", rt.NilValue) hshMod.SetField("exitCode", moonlight.IntValue(0))
util.SetField(rtm, mod, "exitCode", rt.IntValue(0)) //util.SetField(rtm, mod, "vimMode", rt.NilValue)
// hilbish.userDir table // hilbish.userDir table
hshuser := userDirLoader(rtm) //hshuser := userDirLoader(rtm)
mod.Set(rt.StringValue("userDir"), rt.TableValue(hshuser)) //mod.Set(rt.StringValue("userDir"), rt.TableValue(hshuser))
// hilbish.os table // hilbish.os table
hshos := hshosLoader(rtm) //hshos := hshosLoader(rtm)
mod.Set(rt.StringValue("os"), rt.TableValue(hshos)) //mod.Set(rt.StringValue("os"), rt.TableValue(hshos))
// hilbish.aliases table // hilbish.aliases table
aliases = newAliases() //aliases = newAliases()
aliasesModule := aliases.Loader(rtm) //aliasesModule := aliases.Loader(rtm)
mod.Set(rt.StringValue("aliases"), rt.TableValue(aliasesModule)) //mod.Set(rt.StringValue("aliases"), rt.TableValue(aliasesModule))
// hilbish.history table // hilbish.history table
historyModule := lr.Loader(rtm) //historyModule := lr.Loader(rtm)
mod.Set(rt.StringValue("history"), rt.TableValue(historyModule)) //mod.Set(rt.StringValue("history"), rt.TableValue(historyModule))
// hilbish.completion table // hilbish.completion table
hshcomp := completionLoader(rtm) //hshcomp := completionLoader(rtm)
// TODO: REMOVE "completion" AND ONLY USE "completions" WITH AN S // TODO: REMOVE "completion" AND ONLY USE "completions" WITH AN S
mod.Set(rt.StringValue("completion"), rt.TableValue(hshcomp)) //mod.Set(rt.StringValue("completion"), rt.TableValue(hshcomp))
mod.Set(rt.StringValue("completions"), rt.TableValue(hshcomp)) //mod.Set(rt.StringValue("completions"), rt.TableValue(hshcomp))
// hilbish.runner table // hilbish.runner table
runnerModule := runnerModeLoader(rtm) //runnerModule := runnerModeLoader(rtm)
mod.Set(rt.StringValue("runner"), rt.TableValue(runnerModule)) //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(rtm)
mod.Set(rt.StringValue("jobs"), rt.TableValue(jobModule)) //mod.Set(rt.StringValue("jobs"), rt.TableValue(jobModule))
// hilbish.timers table // hilbish.timers table
timers = newTimersModule() //timers = newTimersModule()
timersModule := timers.loader(rtm) //timersModule := timers.loader(rtm)
mod.Set(rt.StringValue("timers"), rt.TableValue(timersModule)) //mod.Set(rt.StringValue("timers"), rt.TableValue(timersModule))
editorModule := editorLoader(rtm) //editorModule := editorLoader(rtm)
mod.Set(rt.StringValue("editor"), rt.TableValue(editorModule)) //mod.Set(rt.StringValue("editor"), rt.TableValue(editorModule))
versionModule := rt.NewTable() //versionModule := rt.NewTable()
util.SetField(rtm, versionModule, "branch", rt.StringValue(gitBranch)) //util.SetField(rtm, versionModule, "branch", rt.StringValue(gitBranch))
util.SetField(rtm, versionModule, "full", rt.StringValue(getVersion())) //util.SetField(rtm, versionModule, "full", rt.StringValue(getVersion()))
util.SetField(rtm, versionModule, "commit", rt.StringValue(gitCommit)) //util.SetField(rtm, versionModule, "commit", rt.StringValue(gitCommit))
util.SetField(rtm, versionModule, "release", rt.StringValue(releaseName)) //util.SetField(rtm, versionModule, "release", rt.StringValue(releaseName))
mod.Set(rt.StringValue("version"), rt.TableValue(versionModule)) //mod.Set(rt.StringValue("version"), rt.TableValue(versionModule))
pluginModule := moduleLoader(rtm) //pluginModule := moduleLoader(rtm)
mod.Set(rt.StringValue("module"), rt.TableValue(pluginModule)) //mod.Set(rt.StringValue("module"), rt.TableValue(pluginModule))
return rt.TableValue(mod), nil return moonlight.TableValue(hshMod)
} }
func getenv(key, fallback string) string { func getenv(key, fallback string) string {
@ -146,12 +142,12 @@ func getenv(key, fallback string) string {
} }
func setVimMode(mode string) { func setVimMode(mode string) {
util.SetField(l, hshMod, "vimMode", rt.StringValue(mode)) hshMod.SetField("vimMode", rt.StringValue(mode))
hooks.Emit("hilbish.vimMode", mode) hooks.Emit("hilbish.vimMode", mode)
} }
func unsetVimMode() { func unsetVimMode() {
util.SetField(l, hshMod, "vimMode", rt.NilValue) hshMod.SetField("vimMode", rt.NilValue)
} }
func handleStream(v rt.Value, strms *streams, errStream bool) error { func handleStream(v rt.Value, strms *streams, errStream bool) error {
@ -429,15 +425,17 @@ hilbish.alias('dircount', 'ls %1 | wc -l')
-- "dircount ~" would count how many files are in ~ (home directory). -- "dircount ~" would count how many files are in ~ (home directory).
#example #example
*/ */
func hlalias(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { //func hlalias(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.CheckNArgs(2); err != nil { func hlalias(mlr *moonlight.Runtime, c *moonlight.GoCont) (moonlight.Cont, error) {
if err := mlr.CheckNArgs(c, 2); err != nil {
return nil, err return nil, err
} }
cmd, err := c.StringArg(0)
cmd, err := mlr.StringArg(c, 0)
if err != nil { if err != nil {
return nil, err return nil, err
} }
orig, err := c.StringArg(1) orig, err := mlr.StringArg(c, 1)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -461,7 +459,6 @@ hilbish.appendPath {
'~/.local/bin' '~/.local/bin'
} }
#example #example
*/
func hlappendPath(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { func hlappendPath(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.Check1Arg(); err != nil { if err := c.Check1Arg(); err != nil {
return nil, err return nil, err
@ -529,7 +526,9 @@ func hlexec(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return c.Next(), nil return c.Next(), nil
} }
*/
/*
// goro(fn) // goro(fn)
// Puts `fn` in a Goroutine. // Puts `fn` in a Goroutine.
// This can be used to run any function in another thread at the same time as other Lua code. // This can be used to run any function in another thread at the same time as other Lua code.
@ -613,6 +612,7 @@ func hlinterval(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return c.PushingNext1(t.Runtime, rt.UserDataValue(timer.ud)), nil return c.PushingNext1(t.Runtime, rt.UserDataValue(timer.ud)), nil
} }
*/
// complete(scope, cb) // complete(scope, cb)
// Registers a completion handler for the specified scope. // Registers a completion handler for the specified scope.
@ -648,7 +648,6 @@ hilbish.complete('command.sudo', function(query, ctx, fields)
return {compGroup}, pfx return {compGroup}, pfx
end) end)
#example #example
*/
func hlcomplete(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { func hlcomplete(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
scope, cb, err := util.HandleStrCallback(t, c) scope, cb, err := util.HandleStrCallback(t, c)
if err != nil { if err != nil {
@ -658,7 +657,9 @@ func hlcomplete(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return c.Next(), nil return c.Next(), nil
} }
*/
/*
// prependPath(dir) // prependPath(dir)
// Prepends `dir` to $PATH. // Prepends `dir` to $PATH.
// #param dir string // #param dir string
@ -769,6 +770,7 @@ func hlrunnerMode(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return c.Next(), nil return c.Next(), nil
} }
*/
// hinter(line, pos) // hinter(line, pos)
// The command line hint handler. It gets called on every key insert to // The command line hint handler. It gets called on every key insert to
@ -786,6 +788,7 @@ function hilbish.hinter(line, pos)
end end
#example #example
*/ */
/*
func hlhinter(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { func hlhinter(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return c.Next(), nil return c.Next(), nil
} }
@ -815,3 +818,4 @@ func hlhighlighter(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return c.PushingNext1(t.Runtime, rt.StringValue(line)), nil return c.PushingNext1(t.Runtime, rt.StringValue(line)), nil
} }
*/

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

View File

@ -1,14 +1,14 @@
package main package main
import ( import (
"errors" //"errors"
"path/filepath" "path/filepath"
"strings" "strings"
"os" "os"
"hilbish/util" "hilbish/util"
rt "github.com/arnodel/golua/runtime" //rt "github.com/arnodel/golua/runtime"
) )
var charEscapeMap = []string{ var charEscapeMap = []string{
@ -191,6 +191,7 @@ func escapeFilename(fname string) string {
// #interface completion // #interface completion
// tab completions // tab completions
// The completions interface deals with tab completions. // The completions interface deals with tab completions.
/*
func completionLoader(rtm *rt.Runtime) *rt.Table { func completionLoader(rtm *rt.Runtime) *rt.Table {
exports := map[string]util.LuaExport{ exports := map[string]util.LuaExport{
"bins": {hcmpBins, 3, false}, "bins": {hcmpBins, 3, false},
@ -204,6 +205,7 @@ func completionLoader(rtm *rt.Runtime) *rt.Table {
return mod return mod
} }
*/
// #interface completion // #interface completion
// bins(query, ctx, fields) -> entries (table), prefix (string) // bins(query, ctx, fields) -> entries (table), prefix (string)
@ -231,6 +233,7 @@ hilbish.complete('command.sudo', function(query, ctx, fields)
end) end)
#example #example
*/ */
/*
func hcmpBins(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { func hcmpBins(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
query, ctx, fds, err := getCompleteParams(t, c) query, ctx, fds, err := getCompleteParams(t, c)
if err != nil { if err != nil {
@ -246,6 +249,7 @@ func hcmpBins(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return c.PushingNext(t.Runtime, rt.TableValue(luaComps), rt.StringValue(pfx)), nil return c.PushingNext(t.Runtime, rt.TableValue(luaComps), rt.StringValue(pfx)), nil
} }
*/
// #interface completion // #interface completion
// call(name, query, ctx, fields) -> completionGroups (table), prefix (string) // call(name, query, ctx, fields) -> completionGroups (table), prefix (string)
@ -256,6 +260,7 @@ func hcmpBins(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
// #param query string // #param query string
// #param ctx string // #param ctx string
// #param fields table // #param fields table
/*
func hcmpCall(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { func hcmpCall(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.CheckNArgs(4); err != nil { if err := c.CheckNArgs(4); err != nil {
return nil, err return nil, err
@ -283,11 +288,15 @@ func hcmpCall(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return nil, errors.New("completer " + completer + " does not exist") return nil, errors.New("completer " + completer + " does not exist")
} }
// we must keep the holy 80 cols
cont := c.Next() cont := c.Next()
err = rt.Call(l.MainThread(), rt.FunctionValue(completecb), err = l.Call(moonlight.FunctionValue(completecb), []moonlight.Value{
[]rt.Value{rt.StringValue(query), rt.StringValue(ctx), rt.TableValue(fields)}, moonlight.StringValue(query),
cont) moonlight.StringValue(ctx),
moonlight.TableValue(fields)
}, cont)
err = rt.Call(l.MainThread(), rt.FunctionValue(completecb), []rt.Value{
rt.StringValue(query), rt.StringValue(ctx), rt.TableValue(fields)
}, cont)
if err != nil { if err != nil {
return nil, err return nil, err
@ -295,6 +304,7 @@ func hcmpCall(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return cont, nil return cont, nil
} }
*/
// #interface completion // #interface completion
// files(query, ctx, fields) -> entries (table), prefix (string) // files(query, ctx, fields) -> entries (table), prefix (string)
@ -303,6 +313,7 @@ func hcmpCall(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
// #param query string // #param query string
// #param ctx string // #param ctx string
// #param fields table // #param fields table
/*
func hcmpFiles(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { func hcmpFiles(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
query, ctx, fds, err := getCompleteParams(t, c) query, ctx, fds, err := getCompleteParams(t, c)
if err != nil { if err != nil {
@ -318,6 +329,7 @@ func hcmpFiles(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return c.PushingNext(t.Runtime, rt.TableValue(luaComps), rt.StringValue(pfx)), nil return c.PushingNext(t.Runtime, rt.TableValue(luaComps), rt.StringValue(pfx)), nil
} }
*/
// #interface completion // #interface completion
// handler(line, pos) // handler(line, pos)
@ -340,11 +352,11 @@ function hilbish.completion.handler(line, pos)
end end
#example #example
*/ */
/*
func hcmpHandler(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { func hcmpHandler(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return c.Next(), nil return c.Next(), nil
} }
func getCompleteParams(t *rt.Thread, c *rt.GoCont) (string, string, []string, error) { func getCompleteParams(t *rt.Thread, c *rt.GoCont) (string, string, []string, error) {
if err := c.CheckNArgs(3); err != nil { if err := c.CheckNArgs(3); err != nil {
return "", "", []string{}, err return "", "", []string{}, err
@ -371,3 +383,4 @@ func getCompleteParams(t *rt.Thread, c *rt.GoCont) (string, string, []string, er
return query, ctx, fds, err return query, ctx, fds, err
} }
*/

16
exec.go
View File

@ -14,7 +14,8 @@ import (
"syscall" "syscall"
"time" "time"
"hilbish/util" "hilbish/moonlight"
//"hilbish/util"
rt "github.com/arnodel/golua/runtime" rt "github.com/arnodel/golua/runtime"
"mvdan.cc/sh/v3/shell" "mvdan.cc/sh/v3/shell"
@ -170,15 +171,13 @@ func reprompt(input string) (string, error) {
} }
func runLuaRunner(runr rt.Value, userInput string) (input string, exitCode uint8, continued bool, runnerErr, err error) { func runLuaRunner(runr rt.Value, userInput string) (input string, exitCode uint8, continued bool, runnerErr, err error) {
term := rt.NewTerminationWith(l.MainThread().CurrentCont(), 3, false) runnerRet, err := l.Call1(runr, moonlight.StringValue(userInput))
err = rt.Call(l.MainThread(), runr, []rt.Value{rt.StringValue(userInput)}, term)
if err != nil { if err != nil {
return "", 124, false, nil, err return "", 124, false, nil, err
} }
var runner *rt.Table var runner *rt.Table
var ok bool var ok bool
runnerRet := term.Get(0)
if runner, ok = runnerRet.TryTable(); !ok { if runner, ok = runnerRet.TryTable(); !ok {
fmt.Fprintln(os.Stderr, "runner did not return a table") fmt.Fprintln(os.Stderr, "runner did not return a table")
exitCode = 125 exitCode = 125
@ -207,7 +206,8 @@ func runLuaRunner(runr rt.Value, userInput string) (input string, exitCode uint8
func handleLua(input string) (string, uint8, error) { func handleLua(input string) (string, uint8, error) {
cmdString := aliases.Resolve(input) cmdString := aliases.Resolve(input)
// First try to load input, essentially compiling to bytecode // First try to load input, essentially compiling to bytecode
chunk, err := l.CompileAndLoadLuaChunk("", []byte(cmdString), rt.TableValue(l.GlobalEnv())) rtm := l.UnderlyingRuntime()
chunk, err := rtm.CompileAndLoadLuaChunk("", []byte(cmdString), moonlight.TableValue(l.GlobalTable()))
if err != nil && noexecute { if err != nil && noexecute {
fmt.Println(err) fmt.Println(err)
/* if lerr, ok := err.(*lua.ApiError); ok { /* if lerr, ok := err.(*lua.ApiError); ok {
@ -221,7 +221,7 @@ func handleLua(input string) (string, uint8, error) {
// And if there's no syntax errors and -n isnt provided, run // And if there's no syntax errors and -n isnt provided, run
if !noexecute { if !noexecute {
if chunk != nil { if chunk != nil {
_, err = rt.Call1(l.MainThread(), rt.FunctionValue(chunk)) _, err = l.Call1(rt.FunctionValue(chunk))
} }
} }
if err == nil { if err == nil {
@ -353,7 +353,7 @@ func execHandle(bg bool) interp.ExecHandlerFunc {
sinks.Set(rt.StringValue("out"), rt.UserDataValue(stdout.ud)) sinks.Set(rt.StringValue("out"), rt.UserDataValue(stdout.ud))
sinks.Set(rt.StringValue("err"), rt.UserDataValue(stderr.ud)) sinks.Set(rt.StringValue("err"), rt.UserDataValue(stderr.ud))
luaexitcode, err := rt.Call1(l.MainThread(), rt.FunctionValue(cmd), rt.TableValue(luacmdArgs), rt.TableValue(sinks)) luaexitcode, err := l.Call1(rt.FunctionValue(cmd), rt.TableValue(luacmdArgs), rt.TableValue(sinks))
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "Error in command:\n" + err.Error()) fmt.Fprintln(os.Stderr, "Error in command:\n" + err.Error())
return interp.NewExitStatus(1) return interp.NewExitStatus(1)
@ -580,7 +580,7 @@ func splitInput(input string) ([]string, string) {
} }
func cmdFinish(code uint8, cmdstr string, private bool) { func cmdFinish(code uint8, cmdstr string, private bool) {
util.SetField(l, hshMod, "exitCode", rt.IntValue(int64(code))) hshMod.SetField("exitCode", rt.IntValue(int64(code)))
// using AsValue (to convert to lua type) on an interface which is an int // using AsValue (to convert to lua type) on an interface which is an int
// results in it being unknown in lua .... ???? // results in it being unknown in lua .... ????
// so we allow the hook handler to take lua runtime Values // so we allow the hook handler to take lua runtime Values

View File

@ -14,7 +14,7 @@ type luaHistory struct {}
func (h *luaHistory) Write(line string) (int, error) { func (h *luaHistory) Write(line string) (int, error) {
histWrite := hshMod.Get(rt.StringValue("history")).AsTable().Get(rt.StringValue("add")) histWrite := hshMod.Get(rt.StringValue("history")).AsTable().Get(rt.StringValue("add"))
ln, err := rt.Call1(l.MainThread(), histWrite, rt.StringValue(line)) ln, err := l.Call1(histWrite, rt.StringValue(line))
var num int64 var num int64
if ln.Type() == rt.IntType { if ln.Type() == rt.IntType {
@ -26,7 +26,7 @@ func (h *luaHistory) Write(line string) (int, error) {
func (h *luaHistory) GetLine(idx int) (string, error) { func (h *luaHistory) GetLine(idx int) (string, error) {
histGet := hshMod.Get(rt.StringValue("history")).AsTable().Get(rt.StringValue("get")) histGet := hshMod.Get(rt.StringValue("history")).AsTable().Get(rt.StringValue("get"))
lcmd, err := rt.Call1(l.MainThread(), histGet, rt.IntValue(int64(idx))) lcmd, err := l.Call1(histGet, rt.IntValue(int64(idx)))
var cmd string var cmd string
if lcmd.Type() == rt.StringType { if lcmd.Type() == rt.StringType {
@ -38,7 +38,7 @@ func (h *luaHistory) GetLine(idx int) (string, error) {
func (h *luaHistory) Len() int { func (h *luaHistory) Len() int {
histSize := hshMod.Get(rt.StringValue("history")).AsTable().Get(rt.StringValue("size")) histSize := hshMod.Get(rt.StringValue("history")).AsTable().Get(rt.StringValue("size"))
ln, _ := rt.Call1(l.MainThread(), histSize) ln, _ := l.Call1(histSize)
var num int64 var num int64
if ln.Type() == rt.IntType { if ln.Type() == rt.IntType {

17
job.go
View File

@ -10,6 +10,7 @@ import (
"sync" "sync"
"syscall" "syscall"
"hilbish/moonlight"
"hilbish/util" "hilbish/util"
rt "github.com/arnodel/golua/runtime" rt "github.com/arnodel/golua/runtime"
@ -310,7 +311,8 @@ Manage interactive jobs in Hilbish via Lua.
Jobs are the name of background tasks/commands. A job can be started via Jobs are the name of background tasks/commands. A job can be started via
interactive usage or with the functions defined below for use in external runners. */ interactive usage or with the functions defined below for use in external runners. */
func (j *jobHandler) loader(rtm *rt.Runtime) *rt.Table { func (j *jobHandler) loader() *moonlight.Table {
/*
jobMethods := rt.NewTable() jobMethods := rt.NewTable()
jFuncs := map[string]util.LuaExport{ jFuncs := map[string]util.LuaExport{
"stop": {luaStopJob, 1, false}, "stop": {luaStopJob, 1, false},
@ -319,7 +321,9 @@ func (j *jobHandler) loader(rtm *rt.Runtime) *rt.Table {
"background": {luaBackgroundJob, 1, false}, "background": {luaBackgroundJob, 1, false},
} }
util.SetExports(l, jobMethods, jFuncs) util.SetExports(l, jobMethods, jFuncs)
*/
/*
jobMeta := rt.NewTable() jobMeta := rt.NewTable()
jobIndex := func(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { jobIndex := func(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
j, _ := jobArg(c, 0) j, _ := jobArg(c, 0)
@ -348,17 +352,20 @@ func (j *jobHandler) loader(rtm *rt.Runtime) *rt.Table {
jobMeta.Set(rt.StringValue("__index"), rt.FunctionValue(rt.NewGoFunction(jobIndex, "__index", 2, false))) jobMeta.Set(rt.StringValue("__index"), rt.FunctionValue(rt.NewGoFunction(jobIndex, "__index", 2, false)))
l.SetRegistry(jobMetaKey, rt.TableValue(jobMeta)) l.SetRegistry(jobMetaKey, rt.TableValue(jobMeta))
*/
jobFuncs := map[string]util.LuaExport{ jobFuncs := map[string]moonlight.Export{
/*
"all": {j.luaAllJobs, 0, false}, "all": {j.luaAllJobs, 0, false},
"last": {j.luaLastJob, 0, false}, "last": {j.luaLastJob, 0, false},
"get": {j.luaGetJob, 1, false}, "get": {j.luaGetJob, 1, false},
"add": {j.luaAddJob, 3, false}, "add": {j.luaAddJob, 3, false},
"disown": {j.luaDisownJob, 1, false}, "disown": {j.luaDisownJob, 1, false},
*/
} }
luaJob := rt.NewTable() luaJob := moonlight.NewTable()
util.SetExports(rtm, luaJob, jobFuncs) l.SetExports(luaJob, jobFuncs)
return luaJob return luaJob
} }
@ -383,7 +390,7 @@ func valueToJob(val rt.Value) (*job, bool) {
} }
func jobUserData(j *job) *rt.UserData { func jobUserData(j *job) *rt.UserData {
jobMeta := l.Registry(jobMetaKey) jobMeta := l.UnderlyingRuntime().Registry(jobMetaKey)
return rt.NewUserData(j, jobMeta.AsTable()) return rt.NewUserData(j, jobMeta.AsTable())
} }

38
lua.go
View File

@ -4,32 +4,27 @@ import (
"fmt" "fmt"
"os" "os"
"hilbish/util" //"hilbish/util"
"hilbish/golibs/bait" //"hilbish/golibs/bait"
"hilbish/golibs/commander" //"hilbish/golibs/commander"
"hilbish/golibs/fs" //"hilbish/golibs/fs"
"hilbish/golibs/terminal" //"hilbish/golibs/terminal"
rt "github.com/arnodel/golua/runtime" "hilbish/moonlight"
"github.com/arnodel/golua/lib"
"github.com/arnodel/golua/lib/debuglib"
) )
var minimalconf = `hilbish.prompt '& '` var minimalconf = `hilbish.prompt '& '`
func luaInit() { func luaInit() {
l = rt.New(os.Stdout) l = moonlight.NewRuntime()
l.PushContext(rt.RuntimeContextDef{ setupSinkType()
MessageHandler: debuglib.Traceback,
})
lib.LoadAll(l)
setupSinkType(l)
lib.LoadLibs(l, hilbishLoader) l.LoadLibrary(hilbishLoader, "hilbish")
// yes this is stupid, i know // yes this is stupid, i know
util.DoString(l, "hilbish = require 'hilbish'") l.DoString("hilbish = require 'hilbish'")
// Add fs and terminal module module to Lua // Add fs and terminal module module to Lua
/*
lib.LoadLibs(l, fs.Loader) lib.LoadLibs(l, fs.Loader)
lib.LoadLibs(l, terminal.Loader) lib.LoadLibs(l, terminal.Loader)
@ -54,16 +49,17 @@ func luaInit() {
lr.rl.RawInputCallback = func(r []rune) { lr.rl.RawInputCallback = func(r []rune) {
hooks.Emit("hilbish.rawInput", string(r)) hooks.Emit("hilbish.rawInput", string(r))
} }
*/
// Add more paths that Lua can require from // Add more paths that Lua can require from
_, err := util.DoString(l, "package.path = package.path .. " + requirePaths) _, err := l.DoString("package.path = package.path .. " + requirePaths)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "Could not add Hilbish require paths! Libraries will be missing. This shouldn't happen.") fmt.Fprintln(os.Stderr, "Could not add Hilbish require paths! Libraries will be missing. This shouldn't happen.")
} }
err1 := util.DoFile(l, "nature/init.lua") err1 := l.DoFile("nature/init.lua")
if err1 != nil { if err1 != nil {
err2 := util.DoFile(l, preloadPath) err2 := l.DoFile(preloadPath)
if err2 != nil { if err2 != nil {
fmt.Fprintln(os.Stderr, "Missing nature module, some functionality and builtins will be missing.") fmt.Fprintln(os.Stderr, "Missing nature module, some functionality and builtins will be missing.")
fmt.Fprintln(os.Stderr, "local error:", err1) fmt.Fprintln(os.Stderr, "local error:", err1)
@ -76,9 +72,9 @@ func runConfig(confpath string) {
if !interactive { if !interactive {
return return
} }
err := util.DoFile(l, confpath) err := l.DoFile(confpath)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, err, "\nAn error has occured while loading your config! Falling back to minimal default config.") fmt.Fprintln(os.Stderr, err, "\nAn error has occured while loading your config! Falling back to minimal default config.")
util.DoString(l, minimalconf) l.DoString(minimalconf)
} }
} }

View File

@ -16,6 +16,7 @@ import (
"hilbish/util" "hilbish/util"
"hilbish/golibs/bait" "hilbish/golibs/bait"
"hilbish/golibs/commander" "hilbish/golibs/commander"
"hilbish/moonlight"
rt "github.com/arnodel/golua/runtime" rt "github.com/arnodel/golua/runtime"
"github.com/pborman/getopt" "github.com/pborman/getopt"
@ -24,7 +25,7 @@ import (
) )
var ( var (
l *rt.Runtime l *moonlight.Runtime
lr *lineReader lr *lineReader
luaCompletions = map[string]*rt.Closure{} luaCompletions = map[string]*rt.Closure{}
@ -171,8 +172,8 @@ func main() {
luaArgs.Set(rt.IntValue(int64(i)), rt.StringValue(arg)) luaArgs.Set(rt.IntValue(int64(i)), rt.StringValue(arg))
} }
l.GlobalEnv().Set(rt.StringValue("args"), rt.TableValue(luaArgs)) l.GlobalTable().SetField("args", rt.TableValue(luaArgs))
err := util.DoFile(l, getopt.Arg(0)) err := l.DoFile(getopt.Arg(0))
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, err) fmt.Fprintln(os.Stderr, err)
exit(1) exit(1)

View File

@ -0,0 +1,13 @@
package moonlight
type Export struct{
Function GoToLuaFunc
ArgNum int
Variadic bool
}
func (mlr *Runtime) SetExports(tbl *Table, exports map[string]Export) {
for name, export := range exports {
mlr.rt.SetEnvGoFunc(tbl.lt, name, mlr.GoFunction(export.Function), export.ArgNum, export.Variadic)
}
}

View File

@ -0,0 +1,3 @@
package moonlight
type GoToLuaFunc func(mlr *Runtime, c *GoCont) (Cont, error)

View File

@ -0,0 +1,29 @@
package moonlight
import (
rt "github.com/arnodel/golua/runtime"
)
type GoFunctionFunc = rt.GoFunctionFunc
type GoCont = rt.GoCont
type Cont = rt.Cont
func (mlr *Runtime) CheckNArgs(c *GoCont, num int) error {
return c.CheckNArgs(num)
}
func (mlr *Runtime) StringArg(c *GoCont, num int) (string, error) {
return c.StringArg(num)
}
func (mlr *Runtime) GoFunction(fun GoToLuaFunc) rt.GoFunctionFunc {
return func(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
gocont := GoCont(*c)
return fun(mlr, &gocont)
}
}
func (mlr *Runtime) Call1(val Value, args ...Value) (Value, error) {
return rt.Call1(mlr.rt.MainThread(), val, args...)
}

View File

@ -0,0 +1,22 @@
package moonlight
import (
rt "github.com/arnodel/golua/runtime"
"github.com/arnodel/golua/lib"
"github.com/arnodel/golua/lib/packagelib"
)
type Loader func(*Runtime) Value
func (mlr *Runtime) LoadLibrary(ldr Loader, name string) {
goluaLoader := packagelib.Loader{
Load: func(rt *rt.Runtime) (rt.Value, func()) {
val := ldr(specificRuntimeToGeneric(rt))
return val, nil
},
Name: name,
}
lib.LoadLibs(mlr.rt, goluaLoader)
}

View File

@ -0,0 +1,35 @@
package moonlight
import (
"os"
rt "github.com/arnodel/golua/runtime"
"github.com/arnodel/golua/lib"
"github.com/arnodel/golua/lib/debuglib"
)
type Runtime struct{
rt *rt.Runtime
}
func NewRuntime() *Runtime {
r := rt.New(os.Stdout)
r.PushContext(rt.RuntimeContextDef{
MessageHandler: debuglib.Traceback,
})
lib.LoadAll(r)
return specificRuntimeToGeneric(r)
}
func specificRuntimeToGeneric(rtm *rt.Runtime) *Runtime {
rr := Runtime{
rt: rtm,
}
return &rr
}
func (mlr *Runtime) UnderlyingRuntime() *rt.Runtime {
return mlr.rt
}

View File

@ -0,0 +1,29 @@
package moonlight
import (
rt "github.com/arnodel/golua/runtime"
)
type Table struct{
lt *rt.Table
}
func NewTable() *Table {
return &Table{
lt: rt.NewTable(),
}
}
func (t *Table) Get(val Value) Value {
return t.lt.Get(val)
}
func (t *Table) SetField(key string, value Value) {
t.lt.Set(rt.StringValue(key), value)
}
func (mlr *Runtime) GlobalTable() *Table {
return &Table{
lt: mlr.rt.GlobalEnv(),
}
}

View File

@ -0,0 +1,71 @@
package moonlight
import (
"bufio"
"io"
"os"
rt "github.com/arnodel/golua/runtime"
)
// DoString runs the code string in the Lua runtime.
func (mlr *Runtime) DoString(code string) (rt.Value, error) {
chunk, err := mlr.rt.CompileAndLoadLuaChunk("<string>", []byte(code), rt.TableValue(mlr.rt.GlobalEnv()))
var ret rt.Value
if chunk != nil {
ret, err = rt.Call1(mlr.rt.MainThread(), rt.FunctionValue(chunk))
}
return ret, err
}
// DoFile runs the contents of the file in the Lua runtime.
func (mlr *Runtime) DoFile(path string) error {
f, err := os.Open(path)
defer f.Close()
if err != nil {
return err
}
reader := bufio.NewReader(f)
c, err := reader.ReadByte()
if err != nil && err != io.EOF {
return err
}
// unread so a char won't be missing
err = reader.UnreadByte()
if err != nil {
return err
}
var buf []byte
if c == byte('#') {
// shebang - skip that line
_, err := reader.ReadBytes('\n')
if err != nil && err != io.EOF {
return err
}
buf = []byte{'\n'}
}
for {
line, err := reader.ReadBytes('\n')
if err != nil {
if err == io.EOF {
break
}
return err
}
buf = append(buf, line...)
}
clos, err := mlr.rt.LoadFromSourceOrCode(path, buf, "bt", rt.TableValue(mlr.rt.GlobalEnv()), false)
if clos != nil {
_, err = rt.Call1(mlr.rt.MainThread(), rt.FunctionValue(clos))
}
return err
}

View File

@ -0,0 +1,23 @@
package moonlight
import (
rt "github.com/arnodel/golua/runtime"
)
type Value = rt.Value
func StringValue(str string) Value {
return rt.StringValue(str)
}
func IntValue(i int) Value {
return rt.IntValue(int64(i))
}
func BoolValue(b bool) Value {
return rt.BoolValue(b)
}
func TableValue(t *Table) Value {
return rt.TableValue(t.lt)
}

13
os.go
View File

@ -1,7 +1,8 @@
package main package main
import ( import (
"hilbish/util" "hilbish/moonlight"
//"hilbish/util"
rt "github.com/arnodel/golua/runtime" rt "github.com/arnodel/golua/runtime"
"github.com/blackfireio/osinfo" "github.com/blackfireio/osinfo"
@ -14,13 +15,13 @@ import (
// #field family Family name of the current OS // #field family Family name of the current OS
// #field name Pretty name of the current OS // #field name Pretty name of the current OS
// #field version Version of the current OS // #field version Version of the current OS
func hshosLoader(rtm *rt.Runtime) *rt.Table { func hshosLoader() *moonlight.Table {
info, _ := osinfo.GetOSInfo() info, _ := osinfo.GetOSInfo()
mod := rt.NewTable() mod := moonlight.NewTable()
util.SetField(rtm, mod, "family", rt.StringValue(info.Family)) mod.SetField("family", rt.StringValue(info.Family))
util.SetField(rtm, mod, "name", rt.StringValue(info.Name)) mod.SetField("name", rt.StringValue(info.Name))
util.SetField(rtm, mod, "version", rt.StringValue(info.Version)) mod.SetField("version", rt.StringValue(info.Version))
return mod return mod
} }

12
rl.go
View File

@ -27,7 +27,7 @@ func newLineReader(prompt string, noHist bool) *lineReader {
regexSearcher := rl.Searcher regexSearcher := rl.Searcher
rl.Searcher = func(needle string, haystack []string) []string { rl.Searcher = func(needle string, haystack []string) []string {
fz, _ := util.DoString(l, "return hilbish.opts.fuzzy") fz, _ := l.DoString("return hilbish.opts.fuzzy")
fuzz, ok := fz.TryBool() fuzz, ok := fz.TryBool()
if !fuzz || !ok { if !fuzz || !ok {
return regexSearcher(needle, haystack) return regexSearcher(needle, haystack)
@ -71,8 +71,7 @@ func newLineReader(prompt string, noHist bool) *lineReader {
} }
rl.HintText = func(line []rune, pos int) []rune { rl.HintText = func(line []rune, pos int) []rune {
hinter := hshMod.Get(rt.StringValue("hinter")) hinter := hshMod.Get(rt.StringValue("hinter"))
retVal, err := rt.Call1(l.MainThread(), hinter, retVal, err := l.Call1(hinter, rt.StringValue(string(line)), rt.IntValue(int64(pos)))
rt.StringValue(string(line)), rt.IntValue(int64(pos)))
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
return []rune{} return []rune{}
@ -87,8 +86,7 @@ func newLineReader(prompt string, noHist bool) *lineReader {
} }
rl.SyntaxHighlighter = func(line []rune) string { rl.SyntaxHighlighter = func(line []rune) string {
highlighter := hshMod.Get(rt.StringValue("highlighter")) highlighter := hshMod.Get(rt.StringValue("highlighter"))
retVal, err := rt.Call1(l.MainThread(), highlighter, retVal, err := l.Call1(highlighter, rt.StringValue(string(line)))
rt.StringValue(string(line)))
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
return string(line) return string(line)
@ -102,9 +100,9 @@ func newLineReader(prompt string, noHist bool) *lineReader {
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) {
term := rt.NewTerminationWith(l.MainThread().CurrentCont(), 2, false) term := rt.NewTerminationWith(l.UnderlyingRuntime().MainThread().CurrentCont(), 2, false)
compHandle := hshMod.Get(rt.StringValue("completion")).AsTable().Get(rt.StringValue("handler")) compHandle := hshMod.Get(rt.StringValue("completion")).AsTable().Get(rt.StringValue("handler"))
err := rt.Call(l.MainThread(), compHandle, []rt.Value{rt.StringValue(string(line)), err := rt.Call(l.UnderlyingRuntime().MainThread(), compHandle, []rt.Value{rt.StringValue(string(line)),
rt.IntValue(int64(pos))}, term) rt.IntValue(int64(pos))}, term)
var compGroups []*readline.CompletionGroup var compGroups []*readline.CompletionGroup

View File

@ -51,9 +51,11 @@ end)
*/ */
func runnerModeLoader(rtm *rt.Runtime) *rt.Table { func runnerModeLoader(rtm *rt.Runtime) *rt.Table {
exports := map[string]util.LuaExport{ exports := map[string]util.LuaExport{
/*
"sh": {shRunner, 1, false}, "sh": {shRunner, 1, false},
"lua": {luaRunner, 1, false}, "lua": {luaRunner, 1, false},
"setMode": {hlrunnerMode, 1, false}, "setMode": {hlrunnerMode, 1, false},
*/
} }
mod := rt.NewTable() mod := rt.NewTable()

20
sink.go
View File

@ -7,7 +7,8 @@ import (
"os" "os"
"strings" "strings"
"hilbish/util" //"hilbish/util"
"hilbish/moonlight"
rt "github.com/arnodel/golua/runtime" rt "github.com/arnodel/golua/runtime"
) )
@ -25,20 +26,22 @@ type sink struct{
autoFlush bool autoFlush bool
} }
func setupSinkType(rtm *rt.Runtime) { func setupSinkType() {
sinkMeta := rt.NewTable() //sinkMeta := moonlight.NewTable()
sinkMethods := rt.NewTable() sinkMethods := moonlight.NewTable()
sinkFuncs := map[string]util.LuaExport{ sinkFuncs := map[string]moonlight.Export{
/*
"flush": {luaSinkFlush, 1, false}, "flush": {luaSinkFlush, 1, false},
"read": {luaSinkRead, 1, false}, "read": {luaSinkRead, 1, false},
"readAll": {luaSinkReadAll, 1, false}, "readAll": {luaSinkReadAll, 1, false},
"autoFlush": {luaSinkAutoFlush, 2, false}, "autoFlush": {luaSinkAutoFlush, 2, false},
"write": {luaSinkWrite, 2, false}, "write": {luaSinkWrite, 2, false},
"writeln": {luaSinkWriteln, 2, false}, "writeln": {luaSinkWriteln, 2, false},
*/
} }
util.SetExports(l, sinkMethods, sinkFuncs) l.SetExports(sinkMethods, sinkFuncs)
/*
sinkIndex := func(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { sinkIndex := func(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
s, _ := sinkArg(c, 0) s, _ := sinkArg(c, 0)
@ -65,6 +68,7 @@ func setupSinkType(rtm *rt.Runtime) {
sinkMeta.Set(rt.StringValue("__index"), rt.FunctionValue(rt.NewGoFunction(sinkIndex, "__index", 2, false))) sinkMeta.Set(rt.StringValue("__index"), rt.FunctionValue(rt.NewGoFunction(sinkIndex, "__index", 2, false)))
l.SetRegistry(sinkMetaKey, rt.TableValue(sinkMeta)) l.SetRegistry(sinkMetaKey, rt.TableValue(sinkMeta))
*/
} }
@ -255,6 +259,6 @@ func valueToSink(val rt.Value) (*sink, bool) {
} }
func sinkUserData(s *sink) *rt.UserData { func sinkUserData(s *sink) *rt.UserData {
sinkMeta := l.Registry(sinkMetaKey) sinkMeta := l.UnderlyingRuntime().Registry(sinkMetaKey)
return rt.NewUserData(s, sinkMeta.AsTable()) return rt.NewUserData(s, sinkMeta.AsTable())
} }

View File

@ -47,7 +47,7 @@ func (t *timer) start() error {
for { for {
select { select {
case <-t.ticker.C: case <-t.ticker.C:
_, err := rt.Call1(l.MainThread(), rt.FunctionValue(t.fun)) _, err := l.Call1(rt.FunctionValue(t.fun))
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "Error in function:\n", err) fmt.Fprintln(os.Stderr, "Error in function:\n", err)
t.stop() t.stop()

View File

@ -5,7 +5,8 @@ import (
"sync" "sync"
"time" "time"
"hilbish/util" "hilbish/moonlight"
//"hilbish/util"
rt "github.com/arnodel/golua/runtime" rt "github.com/arnodel/golua/runtime"
) )
@ -133,13 +134,15 @@ t:start()
print(t.running) // true print(t.running) // true
``` ```
*/ */
func (th *timersModule) loader(rtm *rt.Runtime) *rt.Table { func (th *timersModule) loader() *moonlight.Table {
timerMethods := rt.NewTable() timerMethods := moonlight.NewTable()
timerFuncs := map[string]util.LuaExport{ timerFuncs := map[string]moonlight.Export{
/*
"start": {timerStart, 1, false}, "start": {timerStart, 1, false},
"stop": {timerStop, 1, false}, "stop": {timerStop, 1, false},
*/
} }
util.SetExports(rtm, timerMethods, timerFuncs) l.SetExports(timerMethods, timerFuncs)
timerMeta := rt.NewTable() timerMeta := rt.NewTable()
timerIndex := func(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { timerIndex := func(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
@ -164,18 +167,20 @@ func (th *timersModule) loader(rtm *rt.Runtime) *rt.Table {
} }
timerMeta.Set(rt.StringValue("__index"), rt.FunctionValue(rt.NewGoFunction(timerIndex, "__index", 2, false))) timerMeta.Set(rt.StringValue("__index"), rt.FunctionValue(rt.NewGoFunction(timerIndex, "__index", 2, false)))
l.SetRegistry(timerMetaKey, rt.TableValue(timerMeta)) l.UnderlyingRuntime().SetRegistry(timerMetaKey, rt.TableValue(timerMeta))
thExports := map[string]util.LuaExport{ thExports := map[string]moonlight.Export{
/*
"create": {th.luaCreate, 3, false}, "create": {th.luaCreate, 3, false},
"get": {th.luaGet, 1, false}, "get": {th.luaGet, 1, false},
*/
} }
luaTh := rt.NewTable() luaTh := moonlight.NewTable()
util.SetExports(rtm, luaTh, thExports) l.SetExports(luaTh, thExports)
util.SetField(rtm, luaTh, "INTERVAL", rt.IntValue(0)) luaTh.SetField("INTERVAL", rt.IntValue(0))
util.SetField(rtm, luaTh, "TIMEOUT", rt.IntValue(1)) luaTh.SetField("TIMEOUT", rt.IntValue(1))
return luaTh return luaTh
} }
@ -200,6 +205,6 @@ func valueToTimer(val rt.Value) (*timer, bool) {
} }
func timerUserData(j *timer) *rt.UserData { func timerUserData(j *timer) *rt.UserData {
timerMeta := l.Registry(timerMetaKey) timerMeta := l.UnderlyingRuntime().Registry(timerMetaKey)
return rt.NewUserData(j, timerMeta.AsTable()) return rt.NewUserData(j, timerMeta.AsTable())
} }

View File

@ -1,7 +1,8 @@
package main package main
import ( import (
"hilbish/util" "hilbish/moonlight"
//"hilbish/util"
rt "github.com/arnodel/golua/runtime" rt "github.com/arnodel/golua/runtime"
) )
@ -13,11 +14,11 @@ import (
// for configs and data. // for configs and data.
// #field config The user's config directory // #field config The user's config directory
// #field data The user's directory for program data // #field data The user's directory for program data
func userDirLoader(rtm *rt.Runtime) *rt.Table { func userDirLoader() *moonlight.Table {
mod := rt.NewTable() mod := moonlight.NewTable()
util.SetField(rtm, mod, "config", rt.StringValue(confDir)) mod.SetField("config", rt.StringValue(confDir))
util.SetField(rtm, mod, "data", rt.StringValue(userDataDir)) mod.SetField("data", rt.StringValue(userDataDir))
return mod return mod
} }

View File

@ -1,12 +1,14 @@
package util package util
import ( import (
"hilbish/moonlight"
rt "github.com/arnodel/golua/runtime" rt "github.com/arnodel/golua/runtime"
) )
// LuaExport represents a Go function which can be exported to Lua. // LuaExport represents a Go function which can be exported to Lua.
type LuaExport struct { type LuaExport struct {
Function rt.GoFunctionFunc Function moonlight.GoFunctionFunc
ArgNum int ArgNum int
Variadic bool Variadic bool
} }

View File

@ -1,10 +1,7 @@
package util package util
import ( import (
"bufio"
"io"
"strings" "strings"
"os"
"os/user" "os/user"
rt "github.com/arnodel/golua/runtime" rt "github.com/arnodel/golua/runtime"
@ -12,81 +9,10 @@ import (
// SetField sets a field in a table, adding docs for it. // SetField sets a field in a table, adding docs for it.
// It is accessible via the __docProp metatable. It is a table of the names of the fields. // It is accessible via the __docProp metatable. It is a table of the names of the fields.
func SetField(rtm *rt.Runtime, module *rt.Table, field string, value rt.Value) { func SetField(module *rt.Table, field string, value rt.Value) {
// TODO: ^ rtm isnt needed, i should remove it
module.Set(rt.StringValue(field), value) module.Set(rt.StringValue(field), value)
} }
// SetFieldProtected sets a field in a protected table. A protected table
// is one which has a metatable proxy to ensure no overrides happen to it.
// It sets the field in the table and sets the __docProp metatable on the
// user facing table.
func SetFieldProtected(module, realModule *rt.Table, field string, value rt.Value) {
realModule.Set(rt.StringValue(field), value)
}
// DoString runs the code string in the Lua runtime.
func DoString(rtm *rt.Runtime, code string) (rt.Value, error) {
chunk, err := rtm.CompileAndLoadLuaChunk("<string>", []byte(code), rt.TableValue(rtm.GlobalEnv()))
var ret rt.Value
if chunk != nil {
ret, err = rt.Call1(rtm.MainThread(), rt.FunctionValue(chunk))
}
return ret, err
}
// DoFile runs the contents of the file in the Lua runtime.
func DoFile(rtm *rt.Runtime, path string) error {
f, err := os.Open(path)
defer f.Close()
if err != nil {
return err
}
reader := bufio.NewReader(f)
c, err := reader.ReadByte()
if err != nil && err != io.EOF {
return err
}
// unread so a char won't be missing
err = reader.UnreadByte()
if err != nil {
return err
}
var buf []byte
if c == byte('#') {
// shebang - skip that line
_, err := reader.ReadBytes('\n')
if err != nil && err != io.EOF {
return err
}
buf = []byte{'\n'}
}
for {
line, err := reader.ReadBytes('\n')
if err != nil {
if err == io.EOF {
break
}
return err
}
buf = append(buf, line...)
}
clos, err := rtm.LoadFromSourceOrCode(path, buf, "bt", rt.TableValue(rtm.GlobalEnv()), false)
if clos != nil {
_, err = rt.Call1(rtm.MainThread(), rt.FunctionValue(clos))
}
return err
}
// HandleStrCallback handles function parameters for Go functions which take // HandleStrCallback handles function parameters for Go functions which take
// a string and a closure. // 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) {