diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index f1fe1b1..d0b59b4 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -10,10 +10,11 @@ on:
jobs:
build:
- name: ${{ matrix.goos }}-${{ matrix.goarch }}
+ name: ${{ matrix.goos }}-${{ matrix.goarch }}${{ matrix.midnight == 'true' && ' (Midnight Edition)' || ''}}
runs-on: ubuntu-latest
strategy:
matrix:
+ midnight: [false, true]
goos: [linux, windows, darwin]
goarch: ["386", amd64, arm64]
exclude:
@@ -33,11 +34,11 @@ jobs:
- name: Download Task
run: 'sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d'
- name: Build
- run: GOOS=${{ matrix.goos }} GOARCH=${{ matrix.goarch }} ./bin/task
+ run: GOOS=${{ matrix.goos }} GOARCH=${{ matrix.goarch }} ./bin/task ${{ matrix.midnight == 'true' && 'midnight' || ''}}
- uses: actions/upload-artifact@v4
if: matrix.goos == 'windows'
with:
- name: hilbish-${{ matrix.goos }}-${{ matrix.goarch }}
+ name: hilbish${{ matrix.midnight == 'true' && '-midnight-edition' || ''}}-${{ matrix.goos }}-${{ matrix.goarch }}
path: |
hilbish.exe
LICENSE
@@ -51,7 +52,7 @@ jobs:
- uses: actions/upload-artifact@v4
if: matrix.goos != 'windows'
with:
- name: hilbish-${{ matrix.goos }}-${{ matrix.goarch }}
+ name: hilbish${{ matrix.midnight == 'true' && '-midnight-edition' || ''}}-${{ matrix.goos }}-${{ matrix.goarch }}
path: |
hilbish
LICENSE
diff --git a/README.md b/README.md
index 4566c30..c34ea12 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,4 @@
-> [!TIP]
-> Check out [Hilbish: Midnight Edition](https://github.com/Rosettea/Hilbish/tree/midnight-edition) if you want to use C Lua, LuaJIT or anything related!
-
-
+
🌓 The Moon-powered shell! A comfy and extensible shell for Lua fans! 🌺 ✨
@@ -12,6 +9,27 @@
+# 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.
+
+Build instructions and 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.
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
@@ -53,13 +71,13 @@ go get -d ./...
To build, run:
```
-task
+go-task
```
Or, if you want a stable branch, run these commands:
```
git checkout $(git describe --tags `git rev-list --tags --max-count=1`)
-task build
+go-task build
```
After you did all that, run `sudo task install` to install Hilbish globally.
diff --git a/Taskfile.yaml b/Taskfile.yaml
index 264e7d5..04f7667 100644
--- a/Taskfile.yaml
+++ b/Taskfile.yaml
@@ -10,6 +10,8 @@ vars:
LIBDIR: '{{default .libdir__ .LIBDIR}}'
goflags__: '-ldflags "-s -w -X main.dataDir={{.LIBDIR}}"'
GOFLAGS: '{{default .goflags__ .GOFLAGS}}'
+ lua__: 'lua'
+ LUA: '{{default .lua__ .LUA}}'
tasks:
default:
@@ -24,6 +26,12 @@ tasks:
vars:
GOFLAGS: '-ldflags "-s -w -X main.dataDir={{.LIBDIR}} -X main.gitCommit=$(git rev-parse --short HEAD) -X main.gitBranch=$(git rev-parse --abbrev-ref HEAD)"'
+ midnight:
+ cmds:
+ - go build -tags midnight,{{.LUA}} {{.GOFLAGS}}
+ vars:
+ GOFLAGS: '-ldflags "-s -w -X main.dataDir={{.LIBDIR}} -X main.gitCommit=$(git rev-parse --short HEAD) -X main.gitBranch=$(git rev-parse --abbrev-ref HEAD)"'
+
build:
cmds:
- go build {{.GOFLAGS}}
diff --git a/aliases.go b/aliases.go
index 8c90fe5..a6c46fe 100644
--- a/aliases.go
+++ b/aliases.go
@@ -97,10 +97,12 @@ func (a *aliasModule) Resolve(cmdstr string) string {
func (a *aliasModule) Loader(rtm *rt.Runtime) *rt.Table {
// create a lua module with our functions
hshaliasesLua := map[string]util.LuaExport{
+ /*
"add": util.LuaExport{hlalias, 2, false},
"list": util.LuaExport{a.luaList, 0, false},
"del": util.LuaExport{a.luaDelete, 1, false},
"resolve": util.LuaExport{a.luaResolve, 1, false},
+ */
}
mod := rt.NewTable()
diff --git a/api.go b/api.go
index 43e361a..aaf4dfa 100644
--- a/api.go
+++ b/api.go
@@ -15,56 +15,59 @@ package main
import (
"bytes"
"errors"
- "fmt"
+ //"fmt"
"io"
"os"
- "os/exec"
+ //"os/exec"
"runtime"
"strings"
- "syscall"
- "time"
+ //"syscall"
+ //"time"
- "hilbish/util"
+ //"hilbish/util"
+ "hilbish/moonlight"
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/maxlandon/readline"
"mvdan.cc/sh/v3/interp"
)
-var exports = map[string]util.LuaExport{
- "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 *moonlight.Table
-var hshMod *rt.Table
-var hilbishLoader = packagelib.Loader{
- Load: hilbishLoad,
- Name: "hilbish",
-}
-
-func hilbishLoad(rtm *rt.Runtime) (rt.Value, func()) {
- mod := rt.NewTable()
-
- util.SetExports(rtm, mod, exports)
- hshMod = mod
+func hilbishLoader(mlr *moonlight.Runtime) moonlight.Value {
+ println("hilbish loader called")
+ var exports = map[string]moonlight.Export{
+ "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},
+ */
+ }
+ hshMod = moonlight.NewTable()
+ mlr.SetExports(hshMod, exports)
host, _ := os.Hostname()
username := curuser.Username
@@ -73,68 +76,69 @@ func hilbishLoad(rtm *rt.Runtime) (rt.Value, func()) {
username = strings.Split(username, "\\")[1] // for some reason Username includes the hostname on windows
}
- util.SetField(rtm, mod, "ver", rt.StringValue(getVersion()))
- util.SetField(rtm, mod, "goVersion", rt.StringValue(runtime.Version()))
- util.SetField(rtm, mod, "user", rt.StringValue(username))
- util.SetField(rtm, mod, "host", rt.StringValue(host))
- util.SetField(rtm, mod, "home", rt.StringValue(curuser.HomeDir))
- util.SetField(rtm, mod, "dataDir", rt.StringValue(dataDir))
- util.SetField(rtm, mod, "interactive", rt.BoolValue(interactive))
- util.SetField(rtm, mod, "login", rt.BoolValue(login))
- util.SetField(rtm, mod, "vimMode", rt.NilValue)
- util.SetField(rtm, mod, "exitCode", rt.IntValue(0))
+ hshMod.SetField("ver", moonlight.StringValue(getVersion()))
+ hshMod.SetField("goVersion", moonlight.StringValue(runtime.Version()))
+ hshMod.SetField("user", moonlight.StringValue(username))
+ hshMod.SetField("host", moonlight.StringValue(host))
+ hshMod.SetField("home", moonlight.StringValue(curuser.HomeDir))
+ hshMod.SetField("dataDir", moonlight.StringValue(dataDir))
+ hshMod.SetField("interactive", moonlight.BoolValue(interactive))
+ hshMod.SetField("login", moonlight.BoolValue(login))
+ hshMod.SetField("exitCode", moonlight.IntValue(0))
+ //util.SetField(rtm, mod, "vimMode", rt.NilValue)
// hilbish.userDir table
- hshuser := userDirLoader(rtm)
- mod.Set(rt.StringValue("userDir"), rt.TableValue(hshuser))
+ hshuser := userDirLoader()
+ hshMod.SetField("userDir", moonlight.TableValue(hshuser))
// hilbish.os table
- hshos := hshosLoader(rtm)
- mod.Set(rt.StringValue("os"), rt.TableValue(hshos))
+ //hshos := hshosLoader(rtm)
+ //mod.Set(rt.StringValue("os"), rt.TableValue(hshos))
// hilbish.aliases table
aliases = newAliases()
- aliasesModule := aliases.Loader(rtm)
- mod.Set(rt.StringValue("aliases"), rt.TableValue(aliasesModule))
+ //aliasesModule := aliases.Loader(rtm)
+ //mod.Set(rt.StringValue("aliases"), rt.TableValue(aliasesModule))
// hilbish.history table
- historyModule := lr.Loader(rtm)
- mod.Set(rt.StringValue("history"), rt.TableValue(historyModule))
+ //historyModule := lr.Loader(rtm)
+ //mod.Set(rt.StringValue("history"), rt.TableValue(historyModule))
// hilbish.completion table
- hshcomp := completionLoader(rtm)
+ //hshcomp := completionLoader(rtm)
// TODO: REMOVE "completion" AND ONLY USE "completions" WITH AN S
- mod.Set(rt.StringValue("completion"), rt.TableValue(hshcomp))
- mod.Set(rt.StringValue("completions"), rt.TableValue(hshcomp))
+ //mod.Set(rt.StringValue("completion"), rt.TableValue(hshcomp))
+ //mod.Set(rt.StringValue("completions"), rt.TableValue(hshcomp))
// hilbish.runner table
- runnerModule := runnerModeLoader(rtm)
- mod.Set(rt.StringValue("runner"), rt.TableValue(runnerModule))
+ runnerModule := runnerModeLoader(mlr)
+ hshMod.SetField("runner", moonlight.TableValue(runnerModule))
// hilbish.jobs table
jobs = newJobHandler()
- jobModule := jobs.loader(rtm)
- mod.Set(rt.StringValue("jobs"), rt.TableValue(jobModule))
+ //jobModule := jobs.loader(rtm)
+ //mod.Set(rt.StringValue("jobs"), rt.TableValue(jobModule))
// hilbish.timers table
timers = newTimersModule()
- timersModule := timers.loader(rtm)
- mod.Set(rt.StringValue("timers"), rt.TableValue(timersModule))
+ //timersModule := timers.loader(rtm)
+ //mod.Set(rt.StringValue("timers"), rt.TableValue(timersModule))
- editorModule := editorLoader(rtm)
- mod.Set(rt.StringValue("editor"), rt.TableValue(editorModule))
+ //editorModule := editorLoader(rtm)
+ //mod.Set(rt.StringValue("editor"), rt.TableValue(editorModule))
- versionModule := rt.NewTable()
- util.SetField(rtm, versionModule, "branch", rt.StringValue(gitBranch))
- util.SetField(rtm, versionModule, "full", rt.StringValue(getVersion()))
- util.SetField(rtm, versionModule, "commit", rt.StringValue(gitCommit))
- util.SetField(rtm, versionModule, "release", rt.StringValue(releaseName))
- mod.Set(rt.StringValue("version"), rt.TableValue(versionModule))
+ //versionModule := rt.NewTable()
+ //util.SetField(rtm, versionModule, "branch", rt.StringValue(gitBranch))
+ //util.SetField(rtm, versionModule, "full", rt.StringValue(getVersion()))
+ //util.SetField(rtm, versionModule, "commit", rt.StringValue(gitCommit))
+ //util.SetField(rtm, versionModule, "release", rt.StringValue(releaseName))
+ //mod.Set(rt.StringValue("version"), rt.TableValue(versionModule))
- pluginModule := moduleLoader(rtm)
- mod.Set(rt.StringValue("module"), rt.TableValue(pluginModule))
+ // very meta
+ moduleModule := moduleLoader(mlr)
+ hshMod.SetField("module", moonlight.TableValue(moduleModule))
- return rt.TableValue(mod), nil
+ return moonlight.TableValue(hshMod)
}
func getenv(key, fallback string) string {
@@ -146,12 +150,12 @@ func getenv(key, fallback string) string {
}
func setVimMode(mode string) {
- util.SetField(l, hshMod, "vimMode", rt.StringValue(mode))
+ hshMod.SetField("vimMode", moonlight.StringValue(mode))
hooks.Emit("hilbish.vimMode", mode)
}
func unsetVimMode() {
- util.SetField(l, hshMod, "vimMode", rt.NilValue)
+ hshMod.SetField("vimMode", moonlight.NilValue)
}
func handleStream(v rt.Value, strms *streams, errStream bool) error {
@@ -292,10 +296,10 @@ func hlrun(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
// cwd() -> string
// Returns the current directory of the shell.
// #returns string
-func hlcwd(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
+func hlcwd(mlr *moonlight.Runtime, c *moonlight.GoCont) (moonlight.Cont, error) {
cwd, _ := os.Getwd()
- return c.PushingNext1(t.Runtime, rt.StringValue(cwd)), nil
+ return mlr.PushNext1(c, moonlight.StringValue(cwd)), nil
}
@@ -348,17 +352,18 @@ hilbish.prompt '%u@%h :%d $'
-- prompt: user@hostname: ~/directory $
#example
*/
-func hlprompt(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
- err := c.Check1Arg()
+func hlprompt(mlr *moonlight.Runtime, c *moonlight.GoCont) (moonlight.Cont, error) {
+ err := mlr.Check1Arg(c)
if err != nil {
return nil, err
}
- p, err := c.StringArg(0)
+ p, err := mlr.StringArg(c, 0)
if err != nil {
return nil, err
}
typ := "left"
// optional 2nd arg
+ /*
if len(c.Etc()) != 0 {
ltyp := c.Etc()[0]
var ok bool
@@ -367,6 +372,7 @@ func hlprompt(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return nil, errors.New("bad argument to run (expected string, got " + ltyp.TypeName() + ")")
}
}
+ */
switch typ {
case "left":
@@ -429,15 +435,17 @@ hilbish.alias('dircount', 'ls %1 | wc -l')
-- "dircount ~" would count how many files are in ~ (home directory).
#example
*/
-func hlalias(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
- if err := c.CheckNArgs(2); err != nil {
+//func hlalias(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
+func hlalias(mlr *moonlight.Runtime, c *moonlight.GoCont) (moonlight.Cont, error) {
+ if err := mlr.CheckNArgs(c, 2); err != nil {
return nil, err
}
- cmd, err := c.StringArg(0)
+
+ cmd, err := mlr.StringArg(c, 0)
if err != nil {
return nil, err
}
- orig, err := c.StringArg(1)
+ orig, err := mlr.StringArg(c, 1)
if err != nil {
return nil, err
}
@@ -462,20 +470,20 @@ hilbish.appendPath {
}
#example
*/
-func hlappendPath(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
- if err := c.Check1Arg(); err != nil {
+func hlappendPath(mlr *moonlight.Runtime, c *moonlight.GoCont) (moonlight.Cont, error) {
+ if err := mlr.Check1Arg(c); err != nil {
return nil, err
}
- arg := c.Arg(0)
+ arg := mlr.Arg(c, 0)
// check if dir is a table or a string
- if arg.Type() == rt.TableType {
- util.ForEach(arg.AsTable(), func(k rt.Value, v rt.Value) {
- if v.Type() == rt.StringType {
- appendPath(v.AsString())
+ if moonlight.Type(arg) == moonlight.TableType {
+ moonlight.ForEach(moonlight.ToTable(arg), func(_ moonlight.Value, v moonlight.Value) {
+ if moonlight.Type(v) == moonlight.StringType {
+ appendPath(moonlight.ToString(v))
}
})
- } else if arg.Type() == rt.StringType {
+ } else if moonlight.Type(arg) == moonlight.StringType {
appendPath(arg.AsString())
} else {
return nil, errors.New("bad argument to appendPath (expected string or table, got " + arg.TypeName() + ")")
@@ -494,6 +502,7 @@ func appendPath(dir string) {
}
}
+/*
// exec(cmd)
// Replaces the currently running Hilbish instance with the supplied command.
// This can be used to do an in-place restart.
@@ -529,7 +538,9 @@ func hlexec(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return c.Next(), nil
}
+*/
+/*
// goro(fn)
// Puts `fn` in a Goroutine.
// This can be used to run any function in another thread at the same time as other Lua code.
@@ -613,6 +624,7 @@ func hlinterval(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return c.PushingNext1(t.Runtime, rt.UserDataValue(timer.ud)), nil
}
+*/
// complete(scope, cb)
// Registers a completion handler for the specified scope.
@@ -648,7 +660,6 @@ hilbish.complete('command.sudo', function(query, ctx, fields)
return {compGroup}, pfx
end)
#example
-*/
func hlcomplete(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
scope, cb, err := util.HandleStrCallback(t, c)
if err != nil {
@@ -658,7 +669,9 @@ func hlcomplete(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return c.Next(), nil
}
+*/
+/*
// prependPath(dir)
// Prepends `dir` to $PATH.
// #param dir string
@@ -741,6 +754,7 @@ func hlinputMode(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return c.Next(), nil
}
+*/
// runnerMode(mode)
// Sets the execution/runner mode for interactive Hilbish.
@@ -751,19 +765,19 @@ func hlinputMode(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
// will call it to execute user input instead.
// Read [about runner mode](../features/runner-mode) for more information.
// #param mode string|function
-func hlrunnerMode(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
- if err := c.Check1Arg(); err != nil {
+func hlrunnerMode(mlr *moonlight.Runtime, c *moonlight.GoCont) (moonlight.Cont, error) {
+ if err := mlr.Check1Arg(c); err != nil {
return nil, err
}
- mode := c.Arg(0)
+ mode := mlr.Arg(c, 0)
- switch mode.Type() {
- case rt.StringType:
+ switch moonlight.Type(mode) {
+ case moonlight.StringType:
switch mode.AsString() {
case "hybrid", "hybridRev", "lua", "sh": runnerMode = mode
default: return nil, errors.New("execMode: expected either a function or hybrid, hybridRev, lua, sh. Received " + mode.AsString())
}
- case rt.FunctionType: runnerMode = mode
+ case moonlight.FunctionType: runnerMode = mode
default: return nil, errors.New("execMode: expected either a function or hybrid, hybridRev, lua, sh. Received " + mode.TypeName())
}
@@ -786,6 +800,7 @@ function hilbish.hinter(line, pos)
end
#example
*/
+/*
func hlhinter(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return c.Next(), nil
}
@@ -815,3 +830,4 @@ func hlhighlighter(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return c.PushingNext1(t.Runtime, rt.StringValue(line)), nil
}
+*/
diff --git a/assets/hilbish-logo-and-text-midnight-edition.png b/assets/hilbish-logo-and-text-midnight-edition.png
new file mode 100644
index 0000000..19332c4
Binary files /dev/null and b/assets/hilbish-logo-and-text-midnight-edition.png differ
diff --git a/complete.go b/complete.go
index 1c40b20..45a932f 100644
--- a/complete.go
+++ b/complete.go
@@ -1,14 +1,14 @@
package main
import (
- "errors"
+ //"errors"
"path/filepath"
"strings"
"os"
"hilbish/util"
- rt "github.com/arnodel/golua/runtime"
+ //rt "github.com/arnodel/golua/runtime"
)
var charEscapeMap = []string{
@@ -191,6 +191,7 @@ func escapeFilename(fname string) string {
// #interface completion
// tab completions
// The completions interface deals with tab completions.
+/*
func completionLoader(rtm *rt.Runtime) *rt.Table {
exports := map[string]util.LuaExport{
"bins": {hcmpBins, 3, false},
@@ -204,6 +205,7 @@ func completionLoader(rtm *rt.Runtime) *rt.Table {
return mod
}
+*/
// #interface completion
// bins(query, ctx, fields) -> entries (table), prefix (string)
@@ -231,6 +233,7 @@ hilbish.complete('command.sudo', function(query, ctx, fields)
end)
#example
*/
+/*
func hcmpBins(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
query, ctx, fds, err := getCompleteParams(t, c)
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
}
+*/
// #interface completion
// 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 ctx string
// #param fields table
+/*
func hcmpCall(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.CheckNArgs(4); err != nil {
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")
}
- // we must keep the holy 80 cols
cont := c.Next()
- err = rt.Call(l.MainThread(), rt.FunctionValue(completecb),
- []rt.Value{rt.StringValue(query), rt.StringValue(ctx), rt.TableValue(fields)},
- cont)
+ err = l.Call(moonlight.FunctionValue(completecb), []moonlight.Value{
+ moonlight.StringValue(query),
+ 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 {
return nil, err
@@ -295,6 +304,7 @@ func hcmpCall(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return cont, nil
}
+*/
// #interface completion
// 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 ctx string
// #param fields table
+/*
func hcmpFiles(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
query, ctx, fds, err := getCompleteParams(t, c)
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
}
+*/
// #interface completion
// handler(line, pos)
@@ -340,11 +352,11 @@ function hilbish.completion.handler(line, pos)
end
#example
*/
+/*
func hcmpHandler(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return c.Next(), nil
}
-
func getCompleteParams(t *rt.Thread, c *rt.GoCont) (string, string, []string, error) {
if err := c.CheckNArgs(3); err != nil {
return "", "", []string{}, err
@@ -371,3 +383,4 @@ func getCompleteParams(t *rt.Thread, c *rt.GoCont) (string, string, []string, er
return query, ctx, fds, err
}
+*/
diff --git a/editor.go b/editor.go
index 9c49440..67248ff 100644
--- a/editor.go
+++ b/editor.go
@@ -12,11 +12,13 @@ import (
// directly interact with the line editor in use.
func editorLoader(rtm *rt.Runtime) *rt.Table {
exports := map[string]util.LuaExport{
+ /*
"insert": {editorInsert, 1, false},
"setVimRegister": {editorSetRegister, 1, false},
"getVimRegister": {editorGetRegister, 2, false},
"getLine": {editorGetLine, 0, false},
"readChar": {editorReadChar, 0, false},
+ */
}
mod := rt.NewTable()
diff --git a/exec.go b/exec.go
index 446a14d..0828e01 100644
--- a/exec.go
+++ b/exec.go
@@ -15,7 +15,8 @@ import (
"syscall"
"time"
- "hilbish/util"
+ "hilbish/moonlight"
+ //"hilbish/util"
rt "github.com/arnodel/golua/runtime"
"mvdan.cc/sh/v3/shell"
@@ -27,7 +28,7 @@ import (
var errNotExec = errors.New("not executable")
var errNotFound = errors.New("not found")
-var runnerMode rt.Value = rt.StringValue("hybrid")
+var runnerMode moonlight.Value = moonlight.StringValue("hybrid")
type streams struct {
stdout io.Writer
@@ -100,7 +101,7 @@ func runInput(input string, priv bool) {
var cont bool
// save incase it changes while prompting (For some reason)
currentRunner := runnerMode
- if currentRunner.Type() == rt.StringType {
+ if currentRunner.Type() == moonlight.StringType {
switch currentRunner.AsString() {
case "hybrid":
_, _, err = handleLua(input)
@@ -170,70 +171,41 @@ func reprompt(input string) (string, 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)
- err = rt.Call(l.MainThread(), runr, []rt.Value{rt.StringValue(userInput)}, term)
+func runLuaRunner(runr moonlight.Value, userInput string) (input string, exitCode uint8, continued bool, runnerErr, err error) {
+ runnerRet, err := l.Call1(runr, moonlight.StringValue(userInput))
if err != nil {
return "", 124, false, nil, err
}
- var runner *rt.Table
+ var runner *moonlight.Table
var ok bool
- runnerRet := term.Get(0)
- if runner, ok = runnerRet.TryTable(); !ok {
+ if runner, ok = moonlight.TryTable(runnerRet); !ok {
fmt.Fprintln(os.Stderr, "runner did not return a table")
exitCode = 125
input = userInput
return
}
- if code, ok := runner.Get(rt.StringValue("exitCode")).TryInt(); ok {
+ if code, ok := runner.Get(moonlight.StringValue("exitCode")).TryInt(); ok {
exitCode = uint8(code)
}
- if inp, ok := runner.Get(rt.StringValue("input")).TryString(); ok {
+ if inp, ok := runner.Get(moonlight.StringValue("input")).TryString(); ok {
input = inp
}
- if errStr, ok := runner.Get(rt.StringValue("err")).TryString(); ok {
+ if errStr, ok := runner.Get(moonlight.StringValue("err")).TryString(); ok {
runnerErr = fmt.Errorf("%s", errStr)
}
- if c, ok := runner.Get(rt.StringValue("continue")).TryBool(); ok {
+ if c, ok := runner.Get(moonlight.StringValue("continue")).TryBool(); ok {
continued = c
}
return
}
-func handleLua(input string) (string, uint8, error) {
- cmdString := aliases.Resolve(input)
- // First try to load input, essentially compiling to bytecode
- chunk, err := l.CompileAndLoadLuaChunk("", []byte(cmdString), rt.TableValue(l.GlobalEnv()))
- if err != nil && noexecute {
- fmt.Println(err)
- /* if lerr, ok := err.(*lua.ApiError); ok {
- if perr, ok := lerr.Cause.(*parse.Error); ok {
- print(perr.Pos.Line == parse.EOF)
- }
- }
- */
- return cmdString, 125, err
- }
- // And if there's no syntax errors and -n isnt provided, run
- if !noexecute {
- if chunk != nil {
- _, err = rt.Call1(l.MainThread(), rt.FunctionValue(chunk))
- }
- }
- if err == nil {
- return cmdString, 0, nil
- }
-
- return cmdString, 125, err
-}
-
func handleSh(cmdString string) (input string, exitCode uint8, cont bool, runErr error) {
- shRunner := hshMod.Get(rt.StringValue("runner")).AsTable().Get(rt.StringValue("sh"))
+ shRunner := hshMod.Get(moonlight.StringValue("runner")).AsTable().Get(moonlight.StringValue("sh"))
var err error
input, exitCode, cont, runErr, err = runLuaRunner(shRunner, cmdString)
if err != nil {
@@ -352,7 +324,7 @@ func execHandle(bg bool) interp.ExecHandlerFunc {
sinks.Set(rt.StringValue("out"), rt.UserDataValue(stdout.ud))
sinks.Set(rt.StringValue("err"), rt.UserDataValue(stderr.ud))
- t := rt.NewThread(l)
+ //t := rt.NewThread(l)
sig := make(chan os.Signal)
exit := make(chan bool)
@@ -368,14 +340,15 @@ func execHandle(bg bool) interp.ExecHandlerFunc {
signal.Notify(sig, os.Interrupt)
select {
case <-sig:
- t.KillContext()
+ //t.KillContext()
return
}
}()
go func() {
- luaexitcode, err = rt.Call1(t, rt.FunctionValue(cmd), rt.TableValue(luacmdArgs), rt.TableValue(sinks))
+ // TODO: call in thread function?
+ //luaexitcode, err = l.CallInThread1(t, rt.FunctionValue(cmd), rt.TableValue(luacmdArgs), rt.TableValue(sinks))
exit <- true
}()
@@ -606,9 +579,9 @@ func splitInput(input string) ([]string, string) {
}
func cmdFinish(code uint8, cmdstr string, private bool) {
- util.SetField(l, hshMod, "exitCode", rt.IntValue(int64(code)))
+ hshMod.SetField("exitCode", moonlight.IntValue(int64(code)))
// using AsValue (to convert to lua type) on an interface which is an int
// results in it being unknown in lua .... ????
// so we allow the hook handler to take lua runtime Values
- hooks.Emit("command.exit", rt.IntValue(int64(code)), cmdstr, private)
+ hooks.Emit("command.exit", moonlight.IntValue(int64(code)), cmdstr, private)
}
diff --git a/go.mod b/go.mod
index 985f2e2..19cbc60 100644
--- a/go.mod
+++ b/go.mod
@@ -5,6 +5,7 @@ go 1.21
toolchain go1.22.2
require (
+ github.com/aarzilli/golua v0.0.0-20210507130708-11106aa57765
github.com/arnodel/golua v0.0.0-20230215163904-e0b5347eaaa1
github.com/atsushinee/go-markdown-generator v0.0.0-20191121114853-83f9e1f68504
github.com/blackfireio/osinfo v1.0.5
diff --git a/go.sum b/go.sum
index 136f827..53f9b33 100644
--- a/go.sum
+++ b/go.sum
@@ -2,6 +2,8 @@ github.com/Rosettea/golua v0.0.0-20240427174124-d239074c1749 h1:jIFnWBTsYw8s7RX7
github.com/Rosettea/golua v0.0.0-20240427174124-d239074c1749/go.mod h1:9jzpYPiU2is0HVGCiuIOBSXdergHUW44IEjmuN1UrIE=
github.com/Rosettea/sh/v3 v3.4.0-0.dev.0.20240720131751-805c301321fd h1:THNle0FR2g7DMO1y3Bx1Zr7rYeiLXt3st3UkxEsMzL4=
github.com/Rosettea/sh/v3 v3.4.0-0.dev.0.20240720131751-805c301321fd/go.mod h1:YZalN5H7WNQw3DGij6IvHsEhn5YMW7M2FCwG6gnfKy4=
+github.com/aarzilli/golua v0.0.0-20210507130708-11106aa57765 h1:N6gB4UCRBZz8twlJbMFiCKj0zX5Et2nFU/LRafT4x80=
+github.com/aarzilli/golua v0.0.0-20210507130708-11106aa57765/go.mod h1:hMjfaJVSqVnxenMlsxrq3Ni+vrm9Hs64tU4M7dhUoO4=
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=
github.com/arnodel/strftime v0.1.6 h1:0hc0pUvk8KhEMXE+htyaOUV42zNcf/csIbjzEFCJqsw=
diff --git a/golibs/bait/bait.go b/golibs/bait/bait.go
index 1f85c76..b0e7bb2 100644
--- a/golibs/bait/bait.go
+++ b/golibs/bait/bait.go
@@ -26,12 +26,12 @@ this function will set the user prompt.
package bait
import (
- "errors"
+ //"errors"
+ "hilbish/moonlight"
"hilbish/util"
rt "github.com/arnodel/golua/runtime"
- "github.com/arnodel/golua/lib/packagelib"
)
type listenerType int
@@ -48,26 +48,21 @@ type Listener struct{
typ listenerType
once bool
caller func(...interface{})
- luaCaller *rt.Closure
+ luaCaller *moonlight.Closure
}
type Bait struct{
- Loader packagelib.Loader
recoverer Recoverer
handlers map[string][]*Listener
- rtm *rt.Runtime
+ rtm *moonlight.Runtime
}
// New creates a new Bait instance.
-func New(rtm *rt.Runtime) *Bait {
+func New(rtm *moonlight.Runtime) *Bait {
b := &Bait{
handlers: make(map[string][]*Listener),
rtm: rtm,
}
- b.Loader = packagelib.Loader{
- Load: b.loaderFunc,
- Name: "bait",
- }
return b
}
@@ -87,17 +82,18 @@ func (b *Bait) Emit(event string, args ...interface{}) {
}()
if handle.typ == luaListener {
- funcVal := rt.FunctionValue(handle.luaCaller)
- var luaArgs []rt.Value
+ //funcVal := moonlight.FunctionValue(handle.luaCaller)
+ var luaArgs []moonlight.Value
for _, arg := range args {
- var luarg rt.Value
+ var luarg moonlight.Value
switch arg.(type) {
- case rt.Value: luarg = arg.(rt.Value)
- default: luarg = rt.AsValue(arg)
+ case moonlight.Value: luarg = arg.(moonlight.Value)
+ default: luarg = moonlight.AsValue(arg)
}
luaArgs = append(luaArgs, luarg)
}
- _, err := rt.Call1(b.rtm.MainThread(), funcVal, luaArgs...)
+ /*
+ _, err := b.rtm.Call1(funcVal, luaArgs...)
if err != nil {
if event != "error" {
b.Emit("error", event, handle.luaCaller, err.Error())
@@ -107,6 +103,7 @@ func (b *Bait) Emit(event string, args ...interface{}) {
// (calls the go recoverer function)
panic(err)
}
+ */
} else {
handle.caller(args...)
}
@@ -129,8 +126,8 @@ func (b *Bait) On(event string, handler func(...interface{})) *Listener {
}
// OnLua adds a Lua function handler for an event.
-func (b *Bait) OnLua(event string, handler *rt.Closure) *Listener {
- listener :=&Listener{
+func (b *Bait) OnLua(event string, handler *moonlight.Closure) *Listener {
+ listener := &Listener{
typ: luaListener,
luaCaller: handler,
}
@@ -151,7 +148,7 @@ func (b *Bait) Off(event string, listener *Listener) {
}
// OffLua removes a Lua function handler for an event.
-func (b *Bait) OffLua(event string, handler *rt.Closure) {
+func (b *Bait) OffLua(event string, handler *moonlight.Closure) {
handles := b.handlers[event]
for i, handle := range handles {
@@ -174,7 +171,7 @@ func (b *Bait) Once(event string, handler func(...interface{})) *Listener {
}
// OnceLua adds a Lua function listener for an event that only runs once.
-func (b *Bait) OnceLua(event string, handler *rt.Closure) *Listener {
+func (b *Bait) OnceLua(event string, handler *moonlight.Closure) *Listener {
listener := &Listener{
typ: luaListener,
once: true,
@@ -212,18 +209,20 @@ func (b *Bait) callRecoverer(event string, handler *Listener, err interface{}) {
b.recoverer(event, handler, err)
}
-func (b *Bait) loaderFunc(rtm *rt.Runtime) (rt.Value, func()) {
- exports := map[string]util.LuaExport{
- "catch": util.LuaExport{b.bcatch, 2, false},
+func (b *Bait) Loader(rtm *moonlight.Runtime) moonlight.Value {
+ exports := map[string]moonlight.Export{
+ "catch": {b.bcatch, 2, false},
+ /*
"catchOnce": util.LuaExport{b.bcatchOnce, 2, false},
"throw": util.LuaExport{b.bthrow, 1, true},
"release": util.LuaExport{b.brelease, 2, false},
"hooks": util.LuaExport{b.bhooks, 1, false},
+ */
}
- mod := rt.NewTable()
- util.SetExports(rtm, mod, exports)
+ mod := moonlight.NewTable()
+ rtm.SetExports(mod, exports)
- return rt.TableValue(mod), nil
+ return moonlight.TableValue(mod)
}
func handleHook(t *rt.Thread, c *rt.GoCont, name string, catcher *rt.Closure, args ...interface{}) {
@@ -258,8 +257,8 @@ bait.catch('hilbish.exit', function()
end)
#example
*/
-func (b *Bait) bcatch(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
- name, catcher, err := util.HandleStrCallback(t, c)
+func (b *Bait) bcatch(mlr *moonlight.Runtime, c *moonlight.GoCont) (moonlight.Cont, error) {
+ name, catcher, err := util.HandleStrCallback(mlr, c)
if err != nil {
return nil, err
}
@@ -269,6 +268,7 @@ func (b *Bait) bcatch(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return c.Next(), nil
}
+/*
// catchOnce(name, cb)
// Catches an event, but only once. This will remove the hook immediately after it runs for the first time.
// #param name string The name of the event
@@ -315,6 +315,7 @@ func (b *Bait) bhooks(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return c.PushingNext1(t.Runtime, rt.TableValue(luaHandlers)), nil
}
+*/
// release(name, catcher)
// Removes the `catcher` for the event with `name`.
@@ -333,6 +334,7 @@ bait.release('event', hookCallback)
-- and now hookCallback will no longer be ran for the event.
#example
*/
+/*
func (b *Bait) brelease(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
name, catcher, err := util.HandleStrCallback(t, c)
if err != nil {
@@ -343,6 +345,7 @@ func (b *Bait) brelease(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return c.Next(), nil
}
+*/
// throw(name, ...args)
// #param name string The name of the hook.
@@ -358,6 +361,7 @@ bait.catch('gretting', function(greetTo)
end)
#example
*/
+/*
func (b *Bait) bthrow(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.Check1Arg(); err != nil {
return nil, err
@@ -374,3 +378,4 @@ func (b *Bait) bthrow(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return c.Next(), nil
}
+*/
diff --git a/golibs/commander/commander.go b/golibs/commander/commander.go
index 840aaa1..486db42 100644
--- a/golibs/commander/commander.go
+++ b/golibs/commander/commander.go
@@ -33,42 +33,35 @@ This sink is for writing errors, as the name would suggest.
package commander
import (
+ "hilbish/moonlight"
"hilbish/util"
"hilbish/golibs/bait"
-
- rt "github.com/arnodel/golua/runtime"
- "github.com/arnodel/golua/lib/packagelib"
)
type Commander struct{
Events *bait.Bait
- Loader packagelib.Loader
- Commands map[string]*rt.Closure
+ Commands map[string]*moonlight.Closure
}
-func New(rtm *rt.Runtime) *Commander {
+func New(rtm *moonlight.Runtime) *Commander {
c := &Commander{
Events: bait.New(rtm),
- Commands: make(map[string]*rt.Closure),
- }
- c.Loader = packagelib.Loader{
- Load: c.loaderFunc,
- Name: "commander",
+ Commands: make(map[string]*moonlight.Closure),
}
return c
}
-func (c *Commander) loaderFunc(rtm *rt.Runtime) (rt.Value, func()) {
- exports := map[string]util.LuaExport{
- "register": util.LuaExport{c.cregister, 2, false},
- "deregister": util.LuaExport{c.cderegister, 1, false},
- "registry": util.LuaExport{c.cregistry, 0, false},
+func (c *Commander) Loader(rtm *moonlight.Runtime) moonlight.Value {
+ exports := map[string]moonlight.Export{
+ "register": {c.cregister, 2, false},
+ "deregister": {c.cderegister, 1, false},
+ "registry": {c.cregistry, 0, false},
}
- mod := rt.NewTable()
- util.SetExports(rtm, mod, exports)
+ mod := moonlight.NewTable()
+ rtm.SetExports(mod, exports)
- return rt.TableValue(mod), nil
+ return moonlight.TableValue(mod)
}
// register(name, cb)
@@ -88,8 +81,8 @@ commander.register('hello', function(args, sinks)
end)
#example
*/
-func (c *Commander) cregister(t *rt.Thread, ct *rt.GoCont) (rt.Cont, error) {
- cmdName, cmd, err := util.HandleStrCallback(t, ct)
+func (c *Commander) cregister(mlr *moonlight.Runtime, ct *moonlight.GoCont) (moonlight.Cont, error) {
+ cmdName, cmd, err := util.HandleStrCallback(mlr, ct)
if err != nil {
return nil, err
}
@@ -102,11 +95,11 @@ func (c *Commander) cregister(t *rt.Thread, ct *rt.GoCont) (rt.Cont, error) {
// deregister(name)
// Removes the named command. Note that this will only remove Commander-registered commands.
// #param name string Name of the command to remove.
-func (c *Commander) cderegister(t *rt.Thread, ct *rt.GoCont) (rt.Cont, error) {
- if err := ct.Check1Arg(); err != nil {
+func (c *Commander) cderegister(mlr *moonlight.Runtime, ct *moonlight.GoCont) (moonlight.Cont, error) {
+ if err := mlr.Check1Arg(ct); err != nil {
return nil, err
}
- cmdName, err := ct.StringArg(0)
+ cmdName, err := mlr.StringArg(ct, 0)
if err != nil {
return nil, err
}
@@ -120,14 +113,16 @@ func (c *Commander) cderegister(t *rt.Thread, ct *rt.GoCont) (rt.Cont, error) {
// Returns all registered commanders. Returns a list of tables with the following keys:
// - `exec`: The function used to run the commander. Commanders require args and sinks to be passed.
// #returns table
-func (c *Commander) cregistry(t *rt.Thread, ct *rt.GoCont) (rt.Cont, error) {
- registryLua := rt.NewTable()
+func (c *Commander) cregistry(mlr *moonlight.Runtime, ct *moonlight.GoCont) (moonlight.Cont, error) {
+ registryLua := moonlight.NewTable()
for cmdName, cmd := range c.Commands {
- cmdTbl := rt.NewTable()
- cmdTbl.Set(rt.StringValue("exec"), rt.FunctionValue(cmd))
+ cmdTbl := moonlight.NewTable()
+ //cmdTbl.SetField("exec", moonlight.FunctionValue(cmd))
+ print(cmd)
+ cmdTbl.SetField("exec", moonlight.StringValue("placeholder"))
- registryLua.Set(rt.StringValue(cmdName), rt.TableValue(cmdTbl))
+ registryLua.SetField(cmdName, moonlight.TableValue(cmdTbl))
}
- return ct.PushingNext1(t.Runtime, rt.TableValue(registryLua)), nil
+ return mlr.PushNext1(ct, moonlight.TableValue(registryLua)), nil
}
diff --git a/golibs/fs/fs.go b/golibs/fs/fs.go
index 13f972d..6b3b643 100644
--- a/golibs/fs/fs.go
+++ b/golibs/fs/fs.go
@@ -14,50 +14,51 @@ import (
"os"
"strings"
+ "hilbish/moonlight"
"hilbish/util"
rt "github.com/arnodel/golua/runtime"
- "github.com/arnodel/golua/lib/packagelib"
"github.com/arnodel/golua/lib/iolib"
"mvdan.cc/sh/v3/interp"
)
type fs struct{
runner *interp.Runner
- Loader packagelib.Loader
}
func New(runner *interp.Runner) *fs {
- f := &fs{
+ return &fs{
runner: runner,
}
- f.Loader = packagelib.Loader{
- Load: f.loaderFunc,
- Name: "fs",
- }
-
- return f
}
-func (f *fs) loaderFunc(rtm *rt.Runtime) (rt.Value, func()) {
- exports := map[string]util.LuaExport{
+func (f *fs) Loader(rtm *moonlight.Runtime) moonlight.Value {
+ exports := map[string]moonlight.Export{
+ /*
"cd": util.LuaExport{f.fcd, 1, false},
"mkdir": util.LuaExport{f.fmkdir, 2, false},
"stat": util.LuaExport{f.fstat, 1, false},
- "readdir": util.LuaExport{f.freaddir, 1, false},
+ */
+ "readdir": {f.freaddir, 1, false},
+ /*
"abs": util.LuaExport{f.fabs, 1, false},
"basename": util.LuaExport{f.fbasename, 1, false},
- "dir": util.LuaExport{f.fdir, 1, false},
+ */
+ "dir": {f.fdir, 1, false},
+ /*
"glob": util.LuaExport{f.fglob, 1, false},
"join": util.LuaExport{f.fjoin, 0, true},
"pipe": util.LuaExport{f.fpipe, 0, false},
+ */
}
- mod := rt.NewTable()
- util.SetExports(rtm, mod, exports)
- mod.Set(rt.StringValue("pathSep"), rt.StringValue(string(os.PathSeparator)))
- mod.Set(rt.StringValue("pathListSep"), rt.StringValue(string(os.PathListSeparator)))
- return rt.TableValue(mod), nil
+ mod := moonlight.NewTable()
+ rtm.SetExports(mod, exports)
+
+ mod.SetField("pathSep", moonlight.StringValue(string(os.PathSeparator)))
+ mod.SetField("pathListSep", moonlight.StringValue(string(os.PathListSeparator)))
+
+ return moonlight.TableValue(mod)
}
// abs(path) -> string
@@ -124,16 +125,17 @@ func (f *fs) fcd(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
// `~/Documents/doc.txt` then this function will return `~/Documents`.
// #param path string Path to get the directory for.
// #returns string
-func (f *fs) fdir(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
- if err := c.Check1Arg(); err != nil {
+func (f *fs) fdir(mlr *moonlight.Runtime, c *moonlight.GoCont) (moonlight.Cont, error) {
+ if err := mlr.Check1Arg(c); err != nil {
return nil, err
}
- path, err := c.StringArg(0)
+ path, err := mlr.StringArg(c, 0)
if err != nil {
return nil, err
}
- return c.PushingNext(t.Runtime, rt.StringValue(filepath.Dir(path))), nil
+ next := mlr.PushNext1(c, moonlight.StringValue(filepath.Dir(path)))
+ return next, nil
}
// glob(pattern) -> matches (table)
@@ -262,26 +264,26 @@ func (f *fs) fpipe(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
// Returns a list of all files and directories in the provided path.
// #param dir string
// #returns table
-func (f *fs) freaddir(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
- if err := c.Check1Arg(); err != nil {
+func (f *fs) freaddir(mlr *moonlight.Runtime, c *moonlight.GoCont) (moonlight.Cont, error) {
+ if err := mlr.Check1Arg(c); err != nil {
return nil, err
}
- dir, err := c.StringArg(0)
+ dir, err := mlr.StringArg(c, 0)
if err != nil {
return nil, err
}
dir = util.ExpandHome(dir)
- names := rt.NewTable()
+ names := moonlight.NewTable()
dirEntries, err := os.ReadDir(dir)
if err != nil {
return nil, err
}
for i, entry := range dirEntries {
- names.Set(rt.IntValue(int64(i + 1)), rt.StringValue(entry.Name()))
+ names.Set(moonlight.IntValue(int64(i + 1)), moonlight.StringValue(entry.Name()))
}
- return c.PushingNext1(t.Runtime, rt.TableValue(names)), nil
+ return mlr.PushNext1(c, moonlight.TableValue(names)), nil
}
// stat(path) -> {}
diff --git a/golibs/terminal/terminal.go b/golibs/terminal/terminal.go
index 954a4dd..270d668 100644
--- a/golibs/terminal/terminal.go
+++ b/golibs/terminal/terminal.go
@@ -5,52 +5,46 @@ package terminal
import (
"os"
- "hilbish/util"
+ "hilbish/moonlight"
- rt "github.com/arnodel/golua/runtime"
- "github.com/arnodel/golua/lib/packagelib"
"golang.org/x/term"
)
var termState *term.State
-var Loader = packagelib.Loader{
- Load: loaderFunc,
- Name: "terminal",
-}
-func loaderFunc(rtm *rt.Runtime) (rt.Value, func()) {
- exports := map[string]util.LuaExport{
- "setRaw": util.LuaExport{termsetRaw, 0, false},
- "restoreState": util.LuaExport{termrestoreState, 0, false},
- "size": util.LuaExport{termsize, 0, false},
- "saveState": util.LuaExport{termsaveState, 0, false},
+func Loader(rtm *moonlight.Runtime) moonlight.Value {
+ exports := map[string]moonlight.Export{
+ "setRaw": {termsetRaw, 0, false},
+ "restoreState": {termrestoreState, 0, false},
+ "size": {termsize, 0, false},
+ "saveState": {termsaveState, 0, false},
}
- mod := rt.NewTable()
- util.SetExports(rtm, mod, exports)
+ mod := moonlight.NewTable()
+ rtm.SetExports(mod, exports)
- return rt.TableValue(mod), nil
+ return moonlight.TableValue(mod)
}
// size()
// Gets the dimensions of the terminal. Returns a table with `width` and `height`
// NOTE: The size refers to the amount of columns and rows of text that can fit in the terminal.
-func termsize(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
+func termsize(mlr *moonlight.Runtime, c *moonlight.GoCont) (moonlight.Cont, error) {
w, h, err := term.GetSize(int(os.Stdin.Fd()))
if err != nil {
return nil, err
}
- dimensions := rt.NewTable()
- dimensions.Set(rt.StringValue("width"), rt.IntValue(int64(w)))
- dimensions.Set(rt.StringValue("height"), rt.IntValue(int64(h)))
+ dimensions := moonlight.NewTable()
+ dimensions.SetField("width", moonlight.IntValue(int64(w)))
+ dimensions.SetField("height", moonlight.IntValue(int64(h)))
- return c.PushingNext1(t.Runtime, rt.TableValue(dimensions)), nil
+ return mlr.PushNext1(c, moonlight.TableValue(dimensions)), nil
}
// saveState()
// Saves the current state of the terminal.
-func termsaveState(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
+func termsaveState(mlr *moonlight.Runtime, c *moonlight.GoCont) (moonlight.Cont, error) {
state, err := term.GetState(int(os.Stdin.Fd()))
if err != nil {
return nil, err
@@ -62,7 +56,7 @@ func termsaveState(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
// restoreState()
// Restores the last saved state of the terminal
-func termrestoreState(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
+func termrestoreState(mlr *moonlight.Runtime, c *moonlight.GoCont) (moonlight.Cont, error) {
err := term.Restore(int(os.Stdin.Fd()), termState)
if err != nil {
return nil, err
@@ -73,7 +67,7 @@ func termrestoreState(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
// setRaw()
// Puts the terminal into raw mode.
-func termsetRaw(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
+func termsetRaw(mlr *moonlight.Runtime, c *moonlight.GoCont) (moonlight.Cont, error) {
_, err := term.MakeRaw(int(os.Stdin.Fd()))
if err != nil {
return nil, err
diff --git a/history.go b/history.go
index 51ccf27..83d7c5b 100644
--- a/history.go
+++ b/history.go
@@ -7,17 +7,17 @@ import (
"path/filepath"
"strings"
- rt "github.com/arnodel/golua/runtime"
+ "hilbish/moonlight"
)
type luaHistory struct {}
func (h *luaHistory) Write(line string) (int, error) {
- histWrite := hshMod.Get(rt.StringValue("history")).AsTable().Get(rt.StringValue("add"))
- ln, err := rt.Call1(l.MainThread(), histWrite, rt.StringValue(line))
+ histWrite := hshMod.Get(moonlight.StringValue("history")).AsTable().Get(moonlight.StringValue("add"))
+ ln, err := l.Call1(histWrite, moonlight.StringValue(line))
var num int64
- if ln.Type() == rt.IntType {
+ if ln.Type() == moonlight.IntType {
num = ln.AsInt()
}
@@ -25,11 +25,11 @@ func (h *luaHistory) Write(line string) (int, error) {
}
func (h *luaHistory) GetLine(idx int) (string, error) {
- histGet := hshMod.Get(rt.StringValue("history")).AsTable().Get(rt.StringValue("get"))
- lcmd, err := rt.Call1(l.MainThread(), histGet, rt.IntValue(int64(idx)))
+ histGet := hshMod.Get(moonlight.StringValue("history")).AsTable().Get(moonlight.StringValue("get"))
+ lcmd, err := l.Call1(histGet, moonlight.IntValue(int64(idx)))
var cmd string
- if lcmd.Type() == rt.StringType {
+ if lcmd.Type() == moonlight.StringType {
cmd = lcmd.AsString()
}
@@ -37,11 +37,11 @@ func (h *luaHistory) GetLine(idx int) (string, error) {
}
func (h *luaHistory) Len() int {
- histSize := hshMod.Get(rt.StringValue("history")).AsTable().Get(rt.StringValue("size"))
- ln, _ := rt.Call1(l.MainThread(), histSize)
+ histSize := hshMod.Get(moonlight.StringValue("history")).AsTable().Get(moonlight.StringValue("size"))
+ ln, _ := l.Call1(histSize)
var num int64
- if ln.Type() == rt.IntType {
+ if ln.Type() == moonlight.IntType {
num = ln.AsInt()
}
diff --git a/job.go b/job.go
index f5bd6f2..408619b 100644
--- a/job.go
+++ b/job.go
@@ -10,6 +10,7 @@ import (
"sync"
"syscall"
+ "hilbish/moonlight"
"hilbish/util"
rt "github.com/arnodel/golua/runtime"
@@ -260,7 +261,7 @@ func (j *jobHandler) add(cmd string, args []string, path string) *job {
stdout: &bytes.Buffer{},
stderr: &bytes.Buffer{},
}
- jb.ud = jobUserData(jb)
+ //jb.ud = jobUserData(jb)
j.jobs[j.latestID] = jb
hooks.Emit("job.add", rt.UserDataValue(jb.ud))
@@ -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
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()
jFuncs := map[string]util.LuaExport{
"stop": {luaStopJob, 1, false},
@@ -319,7 +321,9 @@ func (j *jobHandler) loader(rtm *rt.Runtime) *rt.Table {
"background": {luaBackgroundJob, 1, false},
}
util.SetExports(l, jobMethods, jFuncs)
+ */
+/*
jobMeta := rt.NewTable()
jobIndex := func(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
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)))
l.SetRegistry(jobMetaKey, rt.TableValue(jobMeta))
+*/
- jobFuncs := map[string]util.LuaExport{
+ jobFuncs := map[string]moonlight.Export{
+ /*
"all": {j.luaAllJobs, 0, false},
"last": {j.luaLastJob, 0, false},
"get": {j.luaGetJob, 1, false},
"add": {j.luaAddJob, 3, false},
"disown": {j.luaDisownJob, 1, false},
+ */
}
- luaJob := rt.NewTable()
- util.SetExports(rtm, luaJob, jobFuncs)
+ luaJob := moonlight.NewTable()
+ l.SetExports(luaJob, jobFuncs)
return luaJob
}
@@ -382,10 +389,12 @@ func valueToJob(val rt.Value) (*job, bool) {
return j, ok
}
+/*
func jobUserData(j *job) *rt.UserData {
- jobMeta := l.Registry(jobMetaKey)
+ jobMeta := l.UnderlyingRuntime().Registry(jobMetaKey)
return rt.NewUserData(j, jobMeta.AsTable())
}
+*/
// #interface jobs
// get(id) -> @Job
diff --git a/lua.go b/lua.go
index 88fedf8..b0a584a 100644
--- a/lua.go
+++ b/lua.go
@@ -4,47 +4,41 @@ import (
"fmt"
"os"
- "hilbish/util"
+ //"hilbish/util"
"hilbish/golibs/bait"
"hilbish/golibs/commander"
"hilbish/golibs/fs"
"hilbish/golibs/terminal"
- rt "github.com/arnodel/golua/runtime"
- "github.com/arnodel/golua/lib"
- "github.com/arnodel/golua/lib/debuglib"
+ "hilbish/moonlight"
)
var minimalconf = `hilbish.prompt '& '`
func luaInit() {
- l = rt.New(os.Stdout)
- l.PushContext(rt.RuntimeContextDef{
- MessageHandler: debuglib.Traceback,
- })
- lib.LoadAll(l)
- setupSinkType(l)
+ l = moonlight.NewRuntime()
+ setupSinkType()
- lib.LoadLibs(l, hilbishLoader)
+ l.LoadLibrary(hilbishLoader, "hilbish")
// 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
f := fs.New(runner)
- lib.LoadLibs(l, f.Loader)
- lib.LoadLibs(l, terminal.Loader)
+ l.LoadLibrary(f.Loader, "fs")
+
+ l.LoadLibrary(terminal.Loader, "terminal")
cmds = commander.New(l)
- lib.LoadLibs(l, cmds.Loader)
+ l.LoadLibrary(cmds.Loader, "commander")
hooks = bait.New(l)
hooks.SetRecoverer(func(event string, handler *bait.Listener, err interface{}) {
fmt.Println("Error in `error` hook handler:", err)
hooks.Off(event, handler)
})
-
- lib.LoadLibs(l, hooks.Loader)
-
+ l.LoadLibrary(hooks.Loader, "bait")
+/*
// Add Ctrl-C handler
hooks.On("signal.sigint", func(...interface{}) {
if !interactive {
@@ -55,16 +49,18 @@ func luaInit() {
lr.rl.RawInputCallback = func(r []rune) {
hooks.Emit("hilbish.rawInput", string(r))
}
+ */
// Add more paths that Lua can require from
- _, err := util.DoString(l, "package.path = package.path .. " + requirePaths)
+ _, err := l.DoString("print(type(hilbish)); package.path = package.path .. " + requirePaths)
if err != nil {
+ fmt.Fprintln(os.Stderr, err)
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 {
- err2 := util.DoFile(l, preloadPath)
+ err2 := l.DoFile(preloadPath)
if err2 != nil {
fmt.Fprintln(os.Stderr, "Missing nature module, some functionality and builtins will be missing.")
fmt.Fprintln(os.Stderr, "local error:", err1)
@@ -77,9 +73,9 @@ func runConfig(confpath string) {
if !interactive {
return
}
- err := util.DoFile(l, confpath)
+ err := l.DoFile(confpath)
if err != nil {
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)
}
}
diff --git a/lua_exec.go b/lua_exec.go
new file mode 100644
index 0000000..8fca346
--- /dev/null
+++ b/lua_exec.go
@@ -0,0 +1,37 @@
+//go:build !midnight
+package main
+
+import (
+ "fmt"
+
+ "hilbish/moonlight"
+ rt "github.com/arnodel/golua/runtime"
+)
+
+func handleLua(input string) (string, uint8, error) {
+ cmdString := aliases.Resolve(input)
+ // First try to load input, essentially compiling to bytecode
+ rtm := l.UnderlyingRuntime()
+ chunk, err := rtm.CompileAndLoadLuaChunk("", []byte(cmdString), moonlight.TableValue(l.GlobalTable()))
+ if err != nil && noexecute {
+ fmt.Println(err)
+ /* if lerr, ok := err.(*lua.ApiError); ok {
+ if perr, ok := lerr.Cause.(*parse.Error); ok {
+ print(perr.Pos.Line == parse.EOF)
+ }
+ }
+ */
+ return cmdString, 125, err
+ }
+ // And if there's no syntax errors and -n isnt provided, run
+ if !noexecute {
+ if chunk != nil {
+ _, err = l.Call1(rt.FunctionValue(chunk))
+ }
+ }
+ if err == nil {
+ return cmdString, 0, nil
+ }
+
+ return cmdString, 125, err
+}
diff --git a/lua_exec_midnight.go b/lua_exec_midnight.go
new file mode 100644
index 0000000..85e57b7
--- /dev/null
+++ b/lua_exec_midnight.go
@@ -0,0 +1,10 @@
+//go:build midnight
+package main
+
+import (
+ "errors"
+)
+
+func handleLua(input string) (string, uint8, error) {
+ return "", 7, errors.New("lua input in midnight placeholder")
+}
diff --git a/main.go b/main.go
index 41d1d35..723712e 100644
--- a/main.go
+++ b/main.go
@@ -16,6 +16,7 @@ import (
"hilbish/util"
"hilbish/golibs/bait"
"hilbish/golibs/commander"
+ "hilbish/moonlight"
rt "github.com/arnodel/golua/runtime"
"github.com/pborman/getopt"
@@ -25,7 +26,7 @@ import (
)
var (
- l *rt.Runtime
+ l *moonlight.Runtime
lr *lineReader
luaCompletions = map[string]*rt.Closure{}
@@ -169,13 +170,13 @@ func main() {
}
if getopt.NArgs() > 0 {
- luaArgs := rt.NewTable()
+ luaArgs := moonlight.NewTable()
for i, arg := range getopt.Args() {
- luaArgs.Set(rt.IntValue(int64(i)), rt.StringValue(arg))
+ luaArgs.Set(moonlight.IntValue(int64(i)), moonlight.StringValue(arg))
}
- l.GlobalEnv().Set(rt.StringValue("args"), rt.TableValue(luaArgs))
- err := util.DoFile(l, getopt.Arg(0))
+ l.GlobalTable().SetField("args", moonlight.TableValue(luaArgs))
+ err := l.DoFile(getopt.Arg(0))
if err != nil {
fmt.Fprintln(os.Stderr, err)
exit(1)
diff --git a/module.go b/module.go
index bf4e32a..e0a6efd 100644
--- a/module.go
+++ b/module.go
@@ -3,9 +3,7 @@ package main
import (
"plugin"
- "hilbish/util"
-
- rt "github.com/arnodel/golua/runtime"
+ "hilbish/moonlight"
)
// #interface module
@@ -46,13 +44,13 @@ func Loader(rtm *rt.Runtime) rt.Value {
This can be compiled with `go build -buildmode=plugin plugin.go`.
If you attempt to require and print the result (`print(require 'plugin')`), it will show "hello world!"
*/
-func moduleLoader(rtm *rt.Runtime) *rt.Table {
- exports := map[string]util.LuaExport{
+func moduleLoader(mlr *moonlight.Runtime) *moonlight.Table {
+ exports := map[string]moonlight.Export{
"load": {moduleLoad, 2, false},
}
- mod := rt.NewTable()
- util.SetExports(rtm, mod, exports)
+ mod := moonlight.NewTable()
+ mlr.SetExports(mod, exports)
return mod
}
@@ -62,12 +60,12 @@ func moduleLoader(rtm *rt.Runtime) *rt.Table {
// Loads a module at the designated `path`.
// It will throw if any error occurs.
// #param path string
-func moduleLoad(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
- if err := c.CheckNArgs(1); err != nil {
+func moduleLoad(mlr *moonlight.Runtime, c *moonlight.GoCont) (moonlight.Cont, error) {
+ if err := mlr.Check1Arg(c); err != nil {
return nil, err
}
- path, err := c.StringArg(0)
+ path, err := mlr.StringArg(c, 0)
if err != nil {
return nil, err
}
@@ -82,12 +80,12 @@ func moduleLoad(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return nil, err
}
- loader, ok := value.(func(*rt.Runtime) rt.Value)
+ loader, ok := value.(func(*moonlight.Runtime) moonlight.Value)
if !ok {
return nil, nil
}
- val := loader(t.Runtime)
+ val := loader(mlr)
- return c.PushingNext1(t.Runtime, val), nil
+ return mlr.PushNext1(c, val), nil
}
diff --git a/moonlight/closure_clua.go b/moonlight/closure_clua.go
new file mode 100644
index 0000000..549c20a
--- /dev/null
+++ b/moonlight/closure_clua.go
@@ -0,0 +1,28 @@
+//go:build midnight
+package moonlight
+
+import (
+ "fmt"
+)
+
+type Callable interface{
+ Continuation(*Runtime, Cont) Cont
+}
+
+type Closure struct{
+ refIdx int // so since we cant store the actual lua closure,
+ // we need a index to the ref in the lua registry... or something like that.
+}
+
+func (mlr *Runtime) ClosureArg(c *GoCont, num int) (*Closure, error) {
+ fmt.Println("type at ", num, "is", mlr.state.LTypename(num))
+
+ return &Closure{
+ refIdx: -1,
+ }, nil
+}
+
+/*
+func (c *Closure) Continuation(mlr *Runtime, c Cont) Cont {
+}
+*/
diff --git a/moonlight/cont_clua.go b/moonlight/cont_clua.go
new file mode 100644
index 0000000..088b8c0
--- /dev/null
+++ b/moonlight/cont_clua.go
@@ -0,0 +1,12 @@
+//go:build midnight
+package moonlight
+
+type GoCont struct{
+ vals []Value
+ f GoFunctionFunc
+}
+type Cont interface{}
+
+func (gc *GoCont) Next() Cont {
+ return gc
+}
diff --git a/moonlight/cont_golua.go b/moonlight/cont_golua.go
new file mode 100644
index 0000000..34cd858
--- /dev/null
+++ b/moonlight/cont_golua.go
@@ -0,0 +1,18 @@
+//go:build !midnight
+package moonlight
+
+import (
+ rt "github.com/arnodel/golua/runtime"
+)
+
+type GoCont struct{
+ cont *rt.GoCont
+ thread *rt.Thread
+}
+
+type Cont = rt.Cont
+type Closure = rt.Closure
+
+func (gc *GoCont) Next() Cont {
+ return gc.cont.Next()
+}
diff --git a/moonlight/export.go b/moonlight/export.go
new file mode 100644
index 0000000..2567af5
--- /dev/null
+++ b/moonlight/export.go
@@ -0,0 +1,7 @@
+package moonlight
+
+type Export struct{
+ Function GoToLuaFunc
+ ArgNum int
+ Variadic bool
+}
diff --git a/moonlight/export_clua.go b/moonlight/export_clua.go
new file mode 100644
index 0000000..8857392
--- /dev/null
+++ b/moonlight/export_clua.go
@@ -0,0 +1,8 @@
+//go:build midnight
+package moonlight
+
+func (mlr *Runtime) SetExports(tbl *Table, exports map[string]Export) {
+ for name, export := range exports {
+ tbl.SetField(name, FunctionValue(mlr.GoFunction(export.Function)))
+ }
+}
diff --git a/moonlight/export_golua.go b/moonlight/export_golua.go
new file mode 100644
index 0000000..50efdea
--- /dev/null
+++ b/moonlight/export_golua.go
@@ -0,0 +1,8 @@
+//go:build !midnight
+package moonlight
+
+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)
+ }
+}
diff --git a/moonlight/function.go b/moonlight/function.go
new file mode 100644
index 0000000..3ebdff5
--- /dev/null
+++ b/moonlight/function.go
@@ -0,0 +1,3 @@
+package moonlight
+
+type GoToLuaFunc func(mlr *Runtime, c *GoCont) (Cont, error)
diff --git a/moonlight/function_clua.go b/moonlight/function_clua.go
new file mode 100644
index 0000000..ee3d482
--- /dev/null
+++ b/moonlight/function_clua.go
@@ -0,0 +1,61 @@
+//go:build midnight
+package moonlight
+
+import (
+ "fmt"
+
+ "github.com/aarzilli/golua/lua"
+)
+
+type GoFunctionFunc struct{
+ cf lua.LuaGoFunction
+}
+
+func (gf GoFunctionFunc) Continuation(mlr *Runtime, c Cont) Cont {
+ return &GoCont{
+ f: gf,
+ vals: []Value{},
+ }
+}
+
+func (mlr *Runtime) CheckNArgs(c *GoCont, num int) error {
+ args := mlr.state.GetTop()
+ if args < num {
+ return fmt.Errorf("%d arguments needed", num)
+ }
+
+ return nil
+}
+
+func (mlr *Runtime) Check1Arg(c *GoCont) error {
+ return mlr.CheckNArgs(c, 1)
+}
+
+func (mlr *Runtime) StringArg(c *GoCont, num int) (string, error) {
+ return mlr.state.CheckString(num + 1), nil
+}
+
+func (mlr *Runtime) Arg(c *GoCont, num int) Value {
+ return c.vals[num]
+}
+
+func (mlr *Runtime) GoFunction(fun GoToLuaFunc) GoFunctionFunc {
+ return GoFunctionFunc{
+ cf: func(L *lua.State) int {
+ cont, err := fun(mlr, &GoCont{})
+ if err != nil {
+ L.RaiseError(err.Error())
+ return 0
+ }
+
+ for _, val := range cont.(*GoCont).vals {
+ switch Type(val) {
+ case StringType:
+ L.PushString(val.AsString())
+ }
+ }
+
+ return len(cont.(*GoCont).vals)
+ },
+ }
+}
diff --git a/moonlight/function_golua.go b/moonlight/function_golua.go
new file mode 100644
index 0000000..9f9b05f
--- /dev/null
+++ b/moonlight/function_golua.go
@@ -0,0 +1,38 @@
+//go:build !midnight
+package moonlight
+
+import (
+ rt "github.com/arnodel/golua/runtime"
+)
+
+type GoFunctionFunc = rt.GoFunctionFunc
+
+func (mlr *Runtime) CheckNArgs(c *GoCont, num int) error {
+ return c.cont.CheckNArgs(num)
+}
+
+func (mlr *Runtime) Check1Arg(c *GoCont) error {
+ return c.cont.CheckNArgs(1)
+}
+
+func (mlr *Runtime) StringArg(c *GoCont, num int) (string, error) {
+ return c.cont.StringArg(num)
+}
+
+func (mlr *Runtime) ClosureArg(c *GoCont, num int) (*Closure, error) {
+ return c.cont.ClosureArg(num)
+}
+
+func (mlr *Runtime) Arg(c *GoCont, num int) Value {
+ return c.cont.Arg(num)
+}
+
+func (mlr *Runtime) GoFunction(fun GoToLuaFunc) GoFunctionFunc {
+ return func(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
+ gocont := GoCont{
+ cont: c,
+ thread: t,
+ }
+ return fun(mlr, &gocont)
+ }
+}
diff --git a/moonlight/loader_clua.go b/moonlight/loader_clua.go
new file mode 100644
index 0000000..0bb2c17
--- /dev/null
+++ b/moonlight/loader_clua.go
@@ -0,0 +1,21 @@
+//go:build midnight
+package moonlight
+
+import (
+ "github.com/aarzilli/golua/lua"
+)
+
+type Loader func(*Runtime) Value
+
+func (mlr *Runtime) LoadLibrary(ldr Loader, name string) {
+ cluaLoader := func (L *lua.State) int {
+ mlr.pushToState(ldr(mlr))
+
+ return 1
+ }
+
+ mlr.state.GetGlobal("package")
+ mlr.state.GetField(-1, "loaded")
+ mlr.state.PushGoFunction(cluaLoader)
+ mlr.state.SetField(-2, name)
+}
diff --git a/moonlight/loader_golua.go b/moonlight/loader_golua.go
new file mode 100644
index 0000000..9560021
--- /dev/null
+++ b/moonlight/loader_golua.go
@@ -0,0 +1,23 @@
+//go:build !midnight
+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)
+}
diff --git a/moonlight/runtime_clua.go b/moonlight/runtime_clua.go
new file mode 100644
index 0000000..89b4643
--- /dev/null
+++ b/moonlight/runtime_clua.go
@@ -0,0 +1,49 @@
+//go:build midnight
+package moonlight
+
+import (
+ "github.com/aarzilli/golua/lua"
+)
+
+type Runtime struct{
+ state *lua.State
+}
+
+func NewRuntime() *Runtime {
+ L := lua.NewState()
+ L.OpenLibs()
+
+ return &Runtime{
+ state: L,
+ }
+}
+
+func (mlr *Runtime) PushNext1(c *GoCont, v Value) Cont {
+ c.vals = []Value{v}
+
+ return c
+}
+
+func (mlr *Runtime) Call1(f Value, args ...Value) (Value, error) {
+ for _, arg := range args {
+ mlr.pushToState(arg)
+ }
+
+ if f.refIdx > 0 {
+ mlr.state.RawGeti(lua.LUA_REGISTRYINDEX, f.refIdx)
+ mlr.state.Call(len(args), 1)
+ }
+
+ if mlr.state.GetTop() == 0 {
+ return NilValue, nil
+ }
+
+ return NilValue, nil
+}
+
+func (mlr *Runtime) pushToState(v Value) {
+ switch v.Type() {
+ case NilType: mlr.state.PushNil()
+ case StringType: mlr.state.PushString(v.AsString())
+ }
+}
diff --git a/moonlight/runtime_golua.go b/moonlight/runtime_golua.go
new file mode 100644
index 0000000..57c90d0
--- /dev/null
+++ b/moonlight/runtime_golua.go
@@ -0,0 +1,49 @@
+//go:build !midnight
+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
+}
+
+// Push will push a Lua value onto the stack.
+func (mlr *Runtime) Push(c *GoCont, v Value) {
+ c.cont.Push(c.thread.Runtime, v)
+}
+
+func (mlr *Runtime) PushNext1(c *GoCont, v Value) Cont {
+ return c.cont.PushingNext1(c.thread.Runtime, v)
+}
+
+func (mlr *Runtime) Call1(val Value, args ...Value) (Value, error) {
+ return rt.Call1(mlr.rt.MainThread(), val, args...)
+}
diff --git a/moonlight/table_clua.go b/moonlight/table_clua.go
new file mode 100644
index 0000000..75cee49
--- /dev/null
+++ b/moonlight/table_clua.go
@@ -0,0 +1,47 @@
+//go:build midnight
+package moonlight
+
+//import "github.com/aarzilli/golua/lua"
+
+type Table struct{
+ refIdx int
+}
+
+func NewTable() *Table {
+ return &Table{
+ refIdx: -1,
+ }
+}
+
+func (t *Table) Get(val Value) Value {
+ return NilValue
+}
+
+func (t *Table) SetField(key string, value Value) {
+}
+
+func (t *Table) Set(key Value, value Value) {
+}
+
+func ForEach(tbl *Table, cb func(key Value, val Value)) {
+}
+
+func (mlr *Runtime) GlobalTable() *Table {
+ return &Table{
+ refIdx: -1,
+ }
+}
+
+func ToTable(v Value) *Table {
+ return &Table{
+ refIdx: -1,
+ }
+}
+
+func TryTable(v Value) (*Table, bool) {
+ return nil, false
+}
+
+func (t *Table) setRefIdx(mlr *Runtime, i idx) {
+ t.refIdx = mlr.state.Ref(i)
+}
diff --git a/moonlight/table_golua.go b/moonlight/table_golua.go
new file mode 100644
index 0000000..b78d88a
--- /dev/null
+++ b/moonlight/table_golua.go
@@ -0,0 +1,59 @@
+//go:build !midnight
+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 (t *Table) Set(key Value, value Value) {
+ t.lt.Set(key, value)
+}
+
+func ForEach(tbl *Table, cb func(key Value, val Value)) {
+ nextVal := rt.NilValue
+ for {
+ key, val, _ := tbl.lt.Next(nextVal)
+ if key == rt.NilValue {
+ break
+ }
+ nextVal = key
+
+ cb(Value(key), Value(val))
+ }
+}
+
+func (mlr *Runtime) GlobalTable() *Table {
+ return &Table{
+ lt: mlr.rt.GlobalEnv(),
+ }
+}
+
+func convertToMoonlightTable(t *rt.Table) *Table {
+ return &Table{
+ lt: t,
+ }
+}
+
+func TryTable(v Value) (*Table, bool) {
+ t, ok := v.TryTable()
+
+ return convertToMoonlightTable(t), ok
+}
diff --git a/moonlight/util_clua.go b/moonlight/util_clua.go
new file mode 100644
index 0000000..2729cbb
--- /dev/null
+++ b/moonlight/util_clua.go
@@ -0,0 +1,13 @@
+//go:build midnight
+package moonlight
+
+func (mlr *Runtime) DoString(code string) (Value, error) {
+ err := mlr.state.DoString(code)
+
+ return NilValue, err
+}
+
+func (mlr *Runtime) DoFile(filename string) error {
+ //return mlr.state.DoFile(filename)
+ return nil
+}
diff --git a/moonlight/util_golua.go b/moonlight/util_golua.go
new file mode 100644
index 0000000..64e61cd
--- /dev/null
+++ b/moonlight/util_golua.go
@@ -0,0 +1,72 @@
+//go:build !midnight
+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) (Value, error) {
+ chunk, err := mlr.rt.CompileAndLoadLuaChunk("", []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
+}
diff --git a/moonlight/value_clua.go b/moonlight/value_clua.go
new file mode 100644
index 0000000..1662851
--- /dev/null
+++ b/moonlight/value_clua.go
@@ -0,0 +1,121 @@
+//go:build midnight
+package moonlight
+
+type Value struct{
+ iface interface{}
+ relIdx int
+ refIdx int
+}
+
+var NilValue = Value{nil, -1, -1}
+
+type ValueType uint8
+const (
+ NilType ValueType = iota
+ BoolType
+ IntType
+ StringType
+ TableType
+ FunctionType
+ UnknownType
+)
+
+func Type(v Value) ValueType {
+ return v.Type()
+}
+
+func BoolValue(b bool) Value {
+ return Value{iface: b}
+}
+
+func IntValue(i int64) Value {
+ return Value{iface: i}
+}
+
+func StringValue(str string) Value {
+ return Value{iface: str}
+}
+
+func TableValue(t *Table) Value {
+ return Value{iface: t}
+}
+
+func FunctionValue(f Callable) Value {
+ return NilValue
+}
+
+func AsValue(i interface{}) Value {
+ if i == nil {
+ return NilValue
+ }
+
+ switch v := i.(type) {
+ case bool: return BoolValue(v)
+ case int64: return IntValue(v)
+ case string: return StringValue(v)
+ case *Table: return TableValue(v)
+ case Value: return v
+ default:
+ return Value{iface: i}
+ }
+}
+
+func (v Value) Type() ValueType {
+ if v.iface == nil {
+ return NilType
+ }
+
+ switch v.iface.(type) {
+ case bool: return BoolType
+ case int: return IntType
+ case string: return StringType
+ case *Table: return TableType
+ case *Closure: return FunctionType
+ default: return UnknownType
+ }
+}
+
+func (v Value) AsInt() int64 {
+ return v.iface.(int64)
+}
+
+func (v Value) AsString() string {
+ if v.Type() != StringType {
+ panic("value type was not string")
+ }
+
+ return v.iface.(string)
+}
+
+func (v Value) AsTable() *Table {
+ panic("Value.AsTable unimplemented in midnight")
+}
+
+func ToString(v Value) string {
+ return v.AsString()
+}
+
+func (v Value) TypeName() string {
+ switch v.iface.(type) {
+ case bool: return "bool"
+ case int: return "number"
+ case string: return "string"
+ case *Table: return "table"
+ default: return ""
+ }
+}
+
+func (v Value) TryBool() (n bool, ok bool) {
+ n, ok = v.iface.(bool)
+ return
+}
+
+func (v Value) TryInt() (n int, ok bool) {
+ n, ok = v.iface.(int)
+ return
+}
+
+func (v Value) TryString() (n string, ok bool) {
+ n, ok = v.iface.(string)
+ return
+}
diff --git a/moonlight/value_golua.go b/moonlight/value_golua.go
new file mode 100644
index 0000000..5989f96
--- /dev/null
+++ b/moonlight/value_golua.go
@@ -0,0 +1,49 @@
+//go:build !midnight
+package moonlight
+
+import (
+ rt "github.com/arnodel/golua/runtime"
+)
+
+var NilValue = rt.NilValue
+
+type Value = rt.Value
+type ValueType = rt.ValueType
+const (
+ IntType = rt.IntType
+ StringType = rt.StringType
+ FunctionType = rt.FunctionType
+ TableType = rt.TableType
+)
+
+func Type(v Value) ValueType {
+ return ValueType(v.Type())
+}
+
+func StringValue(str string) Value {
+ return rt.StringValue(str)
+}
+
+func IntValue(i int64) Value {
+ return rt.IntValue(i)
+}
+
+func BoolValue(b bool) Value {
+ return rt.BoolValue(b)
+}
+
+func TableValue(t *Table) Value {
+ return rt.TableValue(t.lt)
+}
+
+func ToString(v Value) string {
+ return v.AsString()
+}
+
+func ToTable(v Value) *Table {
+ return convertToMoonlightTable(v.AsTable())
+}
+
+func AsValue(v interface{}) Value {
+ return rt.AsValue(v)
+}
diff --git a/os.go b/os.go
index 46e3d3c..b2f8530 100644
--- a/os.go
+++ b/os.go
@@ -1,9 +1,9 @@
package main
import (
- "hilbish/util"
+ "hilbish/moonlight"
+ //"hilbish/util"
- rt "github.com/arnodel/golua/runtime"
"github.com/blackfireio/osinfo"
)
@@ -14,13 +14,13 @@ import (
// #field family Family name of the current OS
// #field name Pretty name 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()
- mod := rt.NewTable()
+ mod := moonlight.NewTable()
- util.SetField(rtm, mod, "family", rt.StringValue(info.Family))
- util.SetField(rtm, mod, "name", rt.StringValue(info.Name))
- util.SetField(rtm, mod, "version", rt.StringValue(info.Version))
+ mod.SetField("family", moonlight.StringValue(info.Family))
+ mod.SetField("name", moonlight.StringValue(info.Name))
+ mod.SetField("version", moonlight.StringValue(info.Version))
return mod
}
diff --git a/rl.go b/rl.go
index 231d04b..50151b1 100644
--- a/rl.go
+++ b/rl.go
@@ -5,6 +5,7 @@ import (
"io"
"strings"
+ "hilbish/moonlight"
"hilbish/util"
rt "github.com/arnodel/golua/runtime"
@@ -27,7 +28,7 @@ func newLineReader(prompt string, noHist bool) *lineReader {
regexSearcher := rl.Searcher
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()
if !fuzz || !ok {
return regexSearcher(needle, haystack)
@@ -70,9 +71,8 @@ func newLineReader(prompt string, noHist bool) *lineReader {
hooks.Emit("hilbish.vimAction", actionStr, args)
}
rl.HintText = func(line []rune, pos int) []rune {
- hinter := hshMod.Get(rt.StringValue("hinter"))
- retVal, err := rt.Call1(l.MainThread(), hinter,
- rt.StringValue(string(line)), rt.IntValue(int64(pos)))
+ hinter := hshMod.Get(moonlight.StringValue("hinter"))
+ retVal, err := l.Call1(hinter, moonlight.StringValue(string(line)), moonlight.IntValue(int64(pos)))
if err != nil {
fmt.Println(err)
return []rune{}
@@ -86,9 +86,8 @@ func newLineReader(prompt string, noHist bool) *lineReader {
return []rune(hintText)
}
rl.SyntaxHighlighter = func(line []rune) string {
- highlighter := hshMod.Get(rt.StringValue("highlighter"))
- retVal, err := rt.Call1(l.MainThread(), highlighter,
- rt.StringValue(string(line)))
+ highlighter := hshMod.Get(moonlight.StringValue("highlighter"))
+ retVal, err := l.Call1(highlighter, moonlight.StringValue(string(line)))
if err != nil {
fmt.Println(err)
return string(line)
@@ -101,93 +100,7 @@ func newLineReader(prompt string, noHist bool) *lineReader {
return highlighted
}
- rl.TabCompleter = func(line []rune, pos int, _ readline.DelayedTabContext) (string, []*readline.CompletionGroup) {
- term := rt.NewTerminationWith(l.MainThread().CurrentCont(), 2, false)
- compHandle := hshMod.Get(rt.StringValue("completion")).AsTable().Get(rt.StringValue("handler"))
- err := rt.Call(l.MainThread(), compHandle, []rt.Value{rt.StringValue(string(line)),
- rt.IntValue(int64(pos))}, term)
-
- var compGroups []*readline.CompletionGroup
- if err != nil {
- return "", compGroups
- }
-
- luaCompGroups := term.Get(0)
- luaPrefix := term.Get(1)
-
- if luaCompGroups.Type() != rt.TableType {
- return "", compGroups
- }
-
- groups := luaCompGroups.AsTable()
- // prefix is optional
- pfx, _ := luaPrefix.TryString()
-
- util.ForEach(groups, func(key rt.Value, val rt.Value) {
- if key.Type() != rt.IntType || val.Type() != rt.TableType {
- return
- }
-
- valTbl := val.AsTable()
- luaCompType := valTbl.Get(rt.StringValue("type"))
- luaCompItems := valTbl.Get(rt.StringValue("items"))
-
- if luaCompType.Type() != rt.StringType || luaCompItems.Type() != rt.TableType {
- return
- }
-
- items := []string{}
- itemDescriptions := make(map[string]string)
-
- util.ForEach(luaCompItems.AsTable(), func(lkey rt.Value, lval rt.Value) {
- if keytyp := lkey.Type(); keytyp == rt.StringType {
- // ['--flag'] = {'description', '--flag-alias'}
- itemName, ok := lkey.TryString()
- vlTbl, okk := lval.TryTable()
- if !ok && !okk {
- // TODO: error
- return
- }
-
- items = append(items, itemName)
- itemDescription, ok := vlTbl.Get(rt.IntValue(1)).TryString()
- if !ok {
- // TODO: error
- return
- }
- itemDescriptions[itemName] = itemDescription
- } else if keytyp == rt.IntType {
- vlStr, ok := lval.TryString()
- if !ok {
- // TODO: error
- return
- }
- items = append(items, vlStr)
- } else {
- // TODO: error
- return
- }
- })
-
- var dispType readline.TabDisplayType
- switch luaCompType.AsString() {
- case "grid": dispType = readline.TabDisplayGrid
- case "list": dispType = readline.TabDisplayList
- // need special cases, will implement later
- //case "map": dispType = readline.TabDisplayMap
- }
-
- compGroups = append(compGroups, &readline.CompletionGroup{
- DisplayType: dispType,
- Descriptions: itemDescriptions,
- Suggestions: items,
- TrimSlash: false,
- NoSpace: true,
- })
- })
-
- return pfx, compGroups
- }
+ setupTabCompleter(rl)
return lr
}
@@ -246,11 +159,13 @@ func (lr *lineReader) Resize() {
// method of saving history.
func (lr *lineReader) Loader(rtm *rt.Runtime) *rt.Table {
lrLua := map[string]util.LuaExport{
+ /*
"add": {lr.luaAddHistory, 1, false},
"all": {lr.luaAllHistory, 0, false},
"clear": {lr.luaClearHistory, 0, false},
"get": {lr.luaGetHistory, 1, false},
"size": {lr.luaSize, 0, false},
+ */
}
mod := rt.NewTable()
diff --git a/rl_midnight.go b/rl_midnight.go
new file mode 100644
index 0000000..25fdfda
--- /dev/null
+++ b/rl_midnight.go
@@ -0,0 +1,10 @@
+//go:build midnight
+package main
+
+import (
+ "github.com/maxlandon/readline"
+)
+
+func setupTabCompleter(rl *readline.Instance) {
+ // TODO
+}
diff --git a/rl_notmidnight.go b/rl_notmidnight.go
new file mode 100644
index 0000000..219439f
--- /dev/null
+++ b/rl_notmidnight.go
@@ -0,0 +1,99 @@
+//go:build !midnight
+package main
+
+import (
+ "hilbish/util"
+
+ rt "github.com/arnodel/golua/runtime"
+ "github.com/maxlandon/readline"
+)
+
+func setupTabCompleter(rl *readline.Instance) {
+ rl.TabCompleter = func(line []rune, pos int, _ readline.DelayedTabContext) (string, []*readline.CompletionGroup) {
+ term := rt.NewTerminationWith(l.UnderlyingRuntime().MainThread().CurrentCont(), 2, false)
+ compHandle := hshMod.Get(rt.StringValue("completion")).AsTable().Get(rt.StringValue("handler"))
+ err := rt.Call(l.UnderlyingRuntime().MainThread(), compHandle, []rt.Value{rt.StringValue(string(line)),
+ rt.IntValue(int64(pos))}, term)
+
+ var compGroups []*readline.CompletionGroup
+ if err != nil {
+ return "", compGroups
+ }
+
+ luaCompGroups := term.Get(0)
+ luaPrefix := term.Get(1)
+
+ if luaCompGroups.Type() != rt.TableType {
+ return "", compGroups
+ }
+
+ groups := luaCompGroups.AsTable()
+ // prefix is optional
+ pfx, _ := luaPrefix.TryString()
+
+ util.ForEach(groups, func(key rt.Value, val rt.Value) {
+ if key.Type() != rt.IntType || val.Type() != rt.TableType {
+ return
+ }
+
+ valTbl := val.AsTable()
+ luaCompType := valTbl.Get(rt.StringValue("type"))
+ luaCompItems := valTbl.Get(rt.StringValue("items"))
+
+ if luaCompType.Type() != rt.StringType || luaCompItems.Type() != rt.TableType {
+ return
+ }
+
+ items := []string{}
+ itemDescriptions := make(map[string]string)
+
+ util.ForEach(luaCompItems.AsTable(), func(lkey rt.Value, lval rt.Value) {
+ if keytyp := lkey.Type(); keytyp == rt.StringType {
+ // ['--flag'] = {'description', '--flag-alias'}
+ itemName, ok := lkey.TryString()
+ vlTbl, okk := lval.TryTable()
+ if !ok && !okk {
+ // TODO: error
+ return
+ }
+
+ items = append(items, itemName)
+ itemDescription, ok := vlTbl.Get(rt.IntValue(1)).TryString()
+ if !ok {
+ // TODO: error
+ return
+ }
+ itemDescriptions[itemName] = itemDescription
+ } else if keytyp == rt.IntType {
+ vlStr, ok := lval.TryString()
+ if !ok {
+ // TODO: error
+ return
+ }
+ items = append(items, vlStr)
+ } else {
+ // TODO: error
+ return
+ }
+ })
+
+ var dispType readline.TabDisplayType
+ switch luaCompType.AsString() {
+ case "grid": dispType = readline.TabDisplayGrid
+ case "list": dispType = readline.TabDisplayList
+ // need special cases, will implement later
+ //case "map": dispType = readline.TabDisplayMap
+ }
+
+ compGroups = append(compGroups, &readline.CompletionGroup{
+ DisplayType: dispType,
+ Descriptions: itemDescriptions,
+ Suggestions: items,
+ TrimSlash: false,
+ NoSpace: true,
+ })
+ })
+
+ return pfx, compGroups
+ }
+}
diff --git a/runnermode.go b/runnermode.go
index 55adfdc..269831d 100644
--- a/runnermode.go
+++ b/runnermode.go
@@ -1,9 +1,7 @@
package main
import (
- "hilbish/util"
-
- rt "github.com/arnodel/golua/runtime"
+ "hilbish/moonlight"
)
// #interface runner
@@ -49,15 +47,15 @@ hilbish.runnerMode(function(input)
end)
```
*/
-func runnerModeLoader(rtm *rt.Runtime) *rt.Table {
- exports := map[string]util.LuaExport{
+func runnerModeLoader(rtm *moonlight.Runtime) *moonlight.Table {
+ exports := map[string]moonlight.Export{
"sh": {shRunner, 1, false},
"lua": {luaRunner, 1, false},
"setMode": {hlrunnerMode, 1, false},
}
- mod := rt.NewTable()
- util.SetExports(rtm, mod, exports)
+ mod := moonlight.NewTable()
+ rtm.SetExports(mod, exports)
return mod
}
@@ -76,27 +74,27 @@ func _runnerMode() {}
// Runs a command in Hilbish's shell script interpreter.
// This is the equivalent of using `source`.
// #param cmd string
-func shRunner(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
- if err := c.Check1Arg(); err != nil {
+func shRunner(mlr *moonlight.Runtime, c *moonlight.GoCont) (moonlight.Cont, error) {
+ if err := mlr.Check1Arg(c); err != nil {
return nil, err
}
- cmd, err := c.StringArg(0)
+ cmd, err := mlr.StringArg(c, 0)
if err != nil {
return nil, err
}
_, exitCode, cont, err := execSh(aliases.Resolve(cmd))
- var luaErr rt.Value = rt.NilValue
+ var luaErr moonlight.Value = moonlight.NilValue
if err != nil {
- luaErr = rt.StringValue(err.Error())
+ luaErr = moonlight.StringValue(err.Error())
}
- runnerRet := rt.NewTable()
- runnerRet.Set(rt.StringValue("input"), rt.StringValue(cmd))
- runnerRet.Set(rt.StringValue("exitCode"), rt.IntValue(int64(exitCode)))
- runnerRet.Set(rt.StringValue("continue"), rt.BoolValue(cont))
- runnerRet.Set(rt.StringValue("err"), luaErr)
+ runnerRet := moonlight.NewTable()
+ runnerRet.SetField("input", moonlight.StringValue(cmd))
+ runnerRet.SetField("exitCode", moonlight.IntValue(int64(exitCode)))
+ runnerRet.SetField("continue", moonlight.BoolValue(cont))
+ runnerRet.SetField("err", luaErr)
- return c.PushingNext(t.Runtime, rt.TableValue(runnerRet)), nil
+ return mlr.PushNext1(c, moonlight.TableValue(runnerRet)), nil
}
// #interface runner
@@ -104,24 +102,25 @@ func shRunner(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
// Evaluates `cmd` as Lua input. This is the same as using `dofile`
// or `load`, but is appropriated for the runner interface.
// #param cmd string
-func luaRunner(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
- if err := c.Check1Arg(); err != nil {
+func luaRunner(mlr *moonlight.Runtime, c *moonlight.GoCont) (moonlight.Cont, error) {
+ if err := mlr.Check1Arg(c); err != nil {
return nil, err
}
- cmd, err := c.StringArg(0)
+ cmd, err := mlr.StringArg(c, 0)
if err != nil {
return nil, err
}
input, exitCode, err := handleLua(cmd)
- var luaErr rt.Value = rt.NilValue
+ var luaErr moonlight.Value = moonlight.NilValue
if err != nil {
- luaErr = rt.StringValue(err.Error())
+ luaErr = moonlight.StringValue(err.Error())
}
- runnerRet := rt.NewTable()
- runnerRet.Set(rt.StringValue("input"), rt.StringValue(input))
- runnerRet.Set(rt.StringValue("exitCode"), rt.IntValue(int64(exitCode)))
- runnerRet.Set(rt.StringValue("err"), luaErr)
+ runnerRet := moonlight.NewTable()
+ runnerRet.SetField("input", moonlight.StringValue(input))
+ runnerRet.SetField("exitCode", moonlight.IntValue(int64(exitCode)))
+ runnerRet.SetField("err", luaErr)
- return c.PushingNext(t.Runtime, rt.TableValue(runnerRet)), nil
+
+ return mlr.PushNext1(c, moonlight.TableValue(runnerRet)), nil
}
diff --git a/sink.go b/sink.go
index 3aa5507..ec52634 100644
--- a/sink.go
+++ b/sink.go
@@ -7,7 +7,8 @@ import (
"os"
"strings"
- "hilbish/util"
+ //"hilbish/util"
+ "hilbish/moonlight"
rt "github.com/arnodel/golua/runtime"
)
@@ -25,20 +26,22 @@ type sink struct{
autoFlush bool
}
-func setupSinkType(rtm *rt.Runtime) {
- sinkMeta := rt.NewTable()
+func setupSinkType() {
+ //sinkMeta := moonlight.NewTable()
- sinkMethods := rt.NewTable()
- sinkFuncs := map[string]util.LuaExport{
+ sinkMethods := moonlight.NewTable()
+ sinkFuncs := map[string]moonlight.Export{
+ /*
"flush": {luaSinkFlush, 1, false},
"read": {luaSinkRead, 1, false},
"readAll": {luaSinkReadAll, 1, false},
"autoFlush": {luaSinkAutoFlush, 2, false},
"write": {luaSinkWrite, 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) {
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)))
l.SetRegistry(sinkMetaKey, rt.TableValue(sinkMeta))
+*/
}
@@ -216,7 +220,7 @@ func newSinkInput(r io.Reader) *sink {
s := &sink{
reader: bufio.NewReader(r),
}
- s.ud = sinkUserData(s)
+ //s.ud = sinkUserData(s)
if f, ok := r.(*os.File); ok {
s.file = f
@@ -230,7 +234,7 @@ func newSinkOutput(w io.Writer) *sink {
writer: bufio.NewWriter(w),
autoFlush: true,
}
- s.ud = sinkUserData(s)
+ //s.ud = sinkUserData(s)
return s
}
@@ -254,7 +258,9 @@ func valueToSink(val rt.Value) (*sink, bool) {
return s, ok
}
+/*
func sinkUserData(s *sink) *rt.UserData {
- sinkMeta := l.Registry(sinkMetaKey)
+ sinkMeta := l.UnderlyingRuntime().Registry(sinkMetaKey)
return rt.NewUserData(s, sinkMeta.AsTable())
}
+*/
diff --git a/timer.go b/timer.go
index 5d536f5..68f85ed 100644
--- a/timer.go
+++ b/timer.go
@@ -2,10 +2,12 @@ package main
import (
"errors"
- "fmt"
- "os"
+// "fmt"
+// "os"
"time"
+// "hilbish/moonlight"
+
rt "github.com/arnodel/golua/runtime"
)
@@ -47,7 +49,8 @@ func (t *timer) start() error {
for {
select {
case <-t.ticker.C:
- _, err := rt.Call1(l.MainThread(), rt.FunctionValue(t.fun))
+ /*
+ _, err := l.Call1(moonlight.FunctionValue(t.fun))
if err != nil {
fmt.Fprintln(os.Stderr, "Error in function:\n", err)
t.stop()
@@ -56,6 +59,7 @@ func (t *timer) start() error {
if t.typ == timerTimeout {
t.stop()
}
+ */
case <-t.channel:
t.ticker.Stop()
return
diff --git a/timerhandler.go b/timerhandler.go
index 0a8e34f..0a981d3 100644
--- a/timerhandler.go
+++ b/timerhandler.go
@@ -5,7 +5,8 @@ import (
"sync"
"time"
- "hilbish/util"
+ "hilbish/moonlight"
+ //"hilbish/util"
rt "github.com/arnodel/golua/runtime"
)
@@ -47,7 +48,7 @@ func (th *timersModule) create(typ timerType, dur time.Duration, fun *rt.Closure
th: th,
id: th.latestID,
}
- t.ud = timerUserData(t)
+ //t.ud = timerUserData(t)
th.timers[th.latestID] = t
@@ -133,14 +134,17 @@ t:start()
print(t.running) // true
```
*/
-func (th *timersModule) loader(rtm *rt.Runtime) *rt.Table {
- timerMethods := rt.NewTable()
- timerFuncs := map[string]util.LuaExport{
+func (th *timersModule) loader() *moonlight.Table {
+ timerMethods := moonlight.NewTable()
+ timerFuncs := map[string]moonlight.Export{
+ /*
"start": {timerStart, 1, false},
"stop": {timerStop, 1, false},
+ */
}
- util.SetExports(rtm, timerMethods, timerFuncs)
+ l.SetExports(timerMethods, timerFuncs)
+/*
timerMeta := rt.NewTable()
timerIndex := func(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
ti, _ := timerArg(c, 0)
@@ -164,18 +168,21 @@ func (th *timersModule) loader(rtm *rt.Runtime) *rt.Table {
}
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},
"get": {th.luaGet, 1, false},
+ */
}
- luaTh := rt.NewTable()
- util.SetExports(rtm, luaTh, thExports)
+ luaTh := moonlight.NewTable()
+ l.SetExports(luaTh, thExports)
- util.SetField(rtm, luaTh, "INTERVAL", rt.IntValue(0))
- util.SetField(rtm, luaTh, "TIMEOUT", rt.IntValue(1))
+ luaTh.SetField("INTERVAL", moonlight.IntValue(0))
+ luaTh.SetField("TIMEOUT", moonlight.IntValue(1))
return luaTh
}
@@ -199,7 +206,9 @@ func valueToTimer(val rt.Value) (*timer, bool) {
return j, ok
}
+/*
func timerUserData(j *timer) *rt.UserData {
- timerMeta := l.Registry(timerMetaKey)
+ timerMeta := l.UnderlyingRuntime().Registry(timerMetaKey)
return rt.NewUserData(j, timerMeta.AsTable())
}
+*/
diff --git a/userdir.go b/userdir.go
index a6c4852..d4cbd39 100644
--- a/userdir.go
+++ b/userdir.go
@@ -1,9 +1,7 @@
package main
import (
- "hilbish/util"
-
- rt "github.com/arnodel/golua/runtime"
+ "hilbish/moonlight"
)
// #interface userDir
@@ -13,11 +11,11 @@ import (
// for configs and data.
// #field config The user's config directory
// #field data The user's directory for program data
-func userDirLoader(rtm *rt.Runtime) *rt.Table {
- mod := rt.NewTable()
+func userDirLoader() *moonlight.Table {
+ mod := moonlight.NewTable()
- util.SetField(rtm, mod, "config", rt.StringValue(confDir))
- util.SetField(rtm, mod, "data", rt.StringValue(userDataDir))
+ mod.SetField("config", moonlight.StringValue(confDir))
+ mod.SetField("data", moonlight.StringValue(userDataDir))
return mod
}
diff --git a/util/export.go b/util/export.go
index ee0b4a6..a4bd277 100644
--- a/util/export.go
+++ b/util/export.go
@@ -1,19 +1,23 @@
package util
import (
+ "hilbish/moonlight"
+
rt "github.com/arnodel/golua/runtime"
)
// LuaExport represents a Go function which can be exported to Lua.
type LuaExport struct {
- Function rt.GoFunctionFunc
+ Function moonlight.GoFunctionFunc
ArgNum int
Variadic bool
}
// SetExports puts the Lua function exports in the table.
func SetExports(rtm *rt.Runtime, tbl *rt.Table, exports map[string]LuaExport) {
+ /*
for name, export := range exports {
rtm.SetEnvGoFunc(tbl, name, export.Function, export.ArgNum, export.Variadic)
}
+ */
}
diff --git a/util/util.go b/util/util.go
index 0fcd4b0..46a6a2d 100644
--- a/util/util.go
+++ b/util/util.go
@@ -1,103 +1,31 @@
package util
import (
- "bufio"
- "io"
"strings"
- "os"
"os/user"
+ "hilbish/moonlight"
+
rt "github.com/arnodel/golua/runtime"
)
// 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.
-func SetField(rtm *rt.Runtime, module *rt.Table, field string, value rt.Value) {
- // TODO: ^ rtm isnt needed, i should remove it
+func SetField(module *rt.Table, field string, value rt.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("", []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
// a string and a closure.
-func HandleStrCallback(t *rt.Thread, c *rt.GoCont) (string, *rt.Closure, error) {
- if err := c.CheckNArgs(2); err != nil {
+func HandleStrCallback(mlr *moonlight.Runtime, c *moonlight.GoCont) (string, *moonlight.Closure, error) {
+ if err := mlr.CheckNArgs(c, 2); err != nil {
return "", nil, err
}
- name, err := c.StringArg(0)
+ name, err := mlr.StringArg(c, 0)
if err != nil {
return "", nil, err
}
- cb, err := c.ClosureArg(1)
+ cb, err := mlr.ClosureArg(c, 1)
if err != nil {
return "", nil, err
}