mirror of
https://github.com/Hilbis/Hilbish
synced 2025-07-01 16:52:03 +00:00
feat: add yarn library
This commit is contained in:
parent
1bb433dc64
commit
002282f186
20
api.go
20
api.go
@ -25,8 +25,9 @@ import (
|
|||||||
|
|
||||||
"hilbish/util"
|
"hilbish/util"
|
||||||
|
|
||||||
rt "github.com/arnodel/golua/runtime"
|
|
||||||
"github.com/arnodel/golua/lib/packagelib"
|
"github.com/arnodel/golua/lib/packagelib"
|
||||||
|
rt "github.com/arnodel/golua/runtime"
|
||||||
|
|
||||||
//"github.com/arnodel/golua/lib/iolib"
|
//"github.com/arnodel/golua/lib/iolib"
|
||||||
"github.com/maxlandon/readline"
|
"github.com/maxlandon/readline"
|
||||||
//"mvdan.cc/sh/v3/interp"
|
//"mvdan.cc/sh/v3/interp"
|
||||||
@ -61,7 +62,9 @@ func hilbishLoad(rtm *rt.Runtime) (rt.Value, func()) {
|
|||||||
mod := rt.NewTable()
|
mod := rt.NewTable()
|
||||||
|
|
||||||
util.SetExports(rtm, mod, exports)
|
util.SetExports(rtm, mod, exports)
|
||||||
|
if hshMod == nil {
|
||||||
hshMod = mod
|
hshMod = mod
|
||||||
|
}
|
||||||
|
|
||||||
host, _ := os.Hostname()
|
host, _ := os.Hostname()
|
||||||
username := curuser.Username
|
username := curuser.Username
|
||||||
@ -131,7 +134,7 @@ func hilbishLoad(rtm *rt.Runtime) (rt.Value, func()) {
|
|||||||
pluginModule := moduleLoader(rtm)
|
pluginModule := moduleLoader(rtm)
|
||||||
mod.Set(rt.StringValue("module"), rt.TableValue(pluginModule))
|
mod.Set(rt.StringValue("module"), rt.TableValue(pluginModule))
|
||||||
|
|
||||||
sinkModule := util.SinkLoader(l)
|
sinkModule := util.SinkLoader(rtm)
|
||||||
mod.Set(rt.StringValue("sink"), rt.TableValue(sinkModule))
|
mod.Set(rt.StringValue("sink"), rt.TableValue(sinkModule))
|
||||||
|
|
||||||
return rt.TableValue(mod), nil
|
return rt.TableValue(mod), nil
|
||||||
@ -194,7 +197,6 @@ func hlcwd(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
|||||||
return c.PushingNext1(t.Runtime, rt.StringValue(cwd)), nil
|
return c.PushingNext1(t.Runtime, rt.StringValue(cwd)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// read(prompt) -> input (string)
|
// read(prompt) -> input (string)
|
||||||
// Read input from the user, using Hilbish's line editor/input reader.
|
// Read input from the user, using Hilbish's line editor/input reader.
|
||||||
// This is a separate instance from the one Hilbish actually uses.
|
// This is a separate instance from the one Hilbish actually uses.
|
||||||
@ -268,8 +270,10 @@ func hlprompt(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
|||||||
case "left":
|
case "left":
|
||||||
prompt = p
|
prompt = p
|
||||||
lr.SetPrompt(fmtPrompt(prompt))
|
lr.SetPrompt(fmtPrompt(prompt))
|
||||||
case "right": lr.SetRightPrompt(fmtPrompt(p))
|
case "right":
|
||||||
default: return nil, errors.New("expected prompt type to be right or left, got " + typ)
|
lr.SetRightPrompt(fmtPrompt(p))
|
||||||
|
default:
|
||||||
|
return nil, errors.New("expected prompt type to be right or left, got " + typ)
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.Next(), nil
|
return c.Next(), nil
|
||||||
@ -386,7 +390,7 @@ func appendPath(dir string) {
|
|||||||
|
|
||||||
// if dir isnt already in $PATH, add it
|
// if dir isnt already in $PATH, add it
|
||||||
if !strings.Contains(pathenv, dir) {
|
if !strings.Contains(pathenv, dir) {
|
||||||
os.Setenv("PATH", pathenv + string(os.PathListSeparator) + dir)
|
os.Setenv("PATH", pathenv+string(os.PathListSeparator)+dir)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -571,7 +575,7 @@ func hlprependPath(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
|||||||
|
|
||||||
// if dir isnt already in $PATH, add in
|
// if dir isnt already in $PATH, add in
|
||||||
if !strings.Contains(pathenv, dir) {
|
if !strings.Contains(pathenv, dir) {
|
||||||
os.Setenv("PATH", dir + string(os.PathListSeparator) + pathenv)
|
os.Setenv("PATH", dir+string(os.PathListSeparator)+pathenv)
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.Next(), nil
|
return c.Next(), nil
|
||||||
@ -667,7 +671,9 @@ func hlhinter(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
|||||||
// #example
|
// #example
|
||||||
// --This code will highlight all double quoted strings in green.
|
// --This code will highlight all double quoted strings in green.
|
||||||
// function hilbish.highlighter(line)
|
// function hilbish.highlighter(line)
|
||||||
|
//
|
||||||
// return line:gsub('"%w+"', function(c) return lunacolors.green(c) end)
|
// return line:gsub('"%w+"', function(c) return lunacolors.green(c) end)
|
||||||
|
//
|
||||||
// end
|
// end
|
||||||
// #example
|
// #example
|
||||||
// #param line string
|
// #param line string
|
||||||
|
130
golibs/yarn/yarn.go
Normal file
130
golibs/yarn/yarn.go
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
package yarn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"hilbish/util"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/arnodel/golua/lib/packagelib"
|
||||||
|
rt "github.com/arnodel/golua/runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
var yarnMetaKey = rt.StringValue("hshyarn")
|
||||||
|
var globalSpool *Yarn
|
||||||
|
|
||||||
|
type Yarn struct {
|
||||||
|
initializer func(*rt.Runtime)
|
||||||
|
Loader packagelib.Loader
|
||||||
|
}
|
||||||
|
|
||||||
|
type Thread struct {
|
||||||
|
rtm *rt.Runtime
|
||||||
|
f rt.Callable
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(init func(*rt.Runtime)) *Yarn {
|
||||||
|
yrn := &Yarn{
|
||||||
|
initializer: init,
|
||||||
|
}
|
||||||
|
yrn.Loader = packagelib.Loader{
|
||||||
|
Load: yrn.loaderFunc,
|
||||||
|
Name: "yarn",
|
||||||
|
}
|
||||||
|
|
||||||
|
globalSpool = yrn
|
||||||
|
|
||||||
|
return yrn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (y *Yarn) loaderFunc(rtm *rt.Runtime) (rt.Value, func()) {
|
||||||
|
yarnMeta := rt.NewTable()
|
||||||
|
yarnMeta.Set(rt.StringValue("__call"), rt.FunctionValue(rt.NewGoFunction(yarnrun, "__call", 1, true)))
|
||||||
|
rtm.SetRegistry(yarnMetaKey, rt.TableValue(yarnMeta))
|
||||||
|
|
||||||
|
exports := map[string]util.LuaExport{
|
||||||
|
"thread": {
|
||||||
|
Function: yarncreate,
|
||||||
|
ArgNum: 1,
|
||||||
|
Variadic: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
mod := rt.NewTable()
|
||||||
|
util.SetExports(rtm, mod, exports)
|
||||||
|
|
||||||
|
return rt.TableValue(mod), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (y *Yarn) init(th *Thread) {
|
||||||
|
y.initializer(th.rtm)
|
||||||
|
}
|
||||||
|
|
||||||
|
// create(fun)
|
||||||
|
// Creates a new, fresh Yarn thread.
|
||||||
|
func yarncreate(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
|
if err := c.Check1Arg(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
fun, err := c.CallableArg(0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
yrn := &Thread{
|
||||||
|
rtm: rt.New(os.Stdout),
|
||||||
|
f: fun,
|
||||||
|
}
|
||||||
|
globalSpool.init(yrn)
|
||||||
|
|
||||||
|
return c.PushingNext(t.Runtime, rt.UserDataValue(yarnUserData(t.Runtime, yrn))), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func yarnrun(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
|
if err := c.Check1Arg(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
yrn, err := yarnArg(c, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
yrn.Run(c.Etc())
|
||||||
|
|
||||||
|
return c.Next(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (y *Thread) Run(args []rt.Value) {
|
||||||
|
go func() {
|
||||||
|
term := rt.NewTerminationWith(y.rtm.MainThread().CurrentCont(), 0, true)
|
||||||
|
err := rt.Call(y.rtm.MainThread(), rt.FunctionValue(y.f), args, term)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func yarnArg(c *rt.GoCont, arg int) (*Thread, error) {
|
||||||
|
j, ok := valueToYarn(c.Arg(arg))
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("#%d must be a yarn thread", arg+1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return j, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func valueToYarn(val rt.Value) (*Thread, bool) {
|
||||||
|
u, ok := val.TryUserData()
|
||||||
|
if !ok {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
j, ok := u.Value().(*Thread)
|
||||||
|
return j, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func yarnUserData(rtm *rt.Runtime, t *Thread) *rt.UserData {
|
||||||
|
yarnMeta := rtm.Registry(yarnMetaKey)
|
||||||
|
return rt.NewUserData(t, yarnMeta.AsTable())
|
||||||
|
}
|
89
lua.go
89
lua.go
@ -5,60 +5,31 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"hilbish/util"
|
|
||||||
"hilbish/golibs/bait"
|
"hilbish/golibs/bait"
|
||||||
"hilbish/golibs/commander"
|
"hilbish/golibs/commander"
|
||||||
"hilbish/golibs/fs"
|
"hilbish/golibs/fs"
|
||||||
"hilbish/golibs/snail"
|
"hilbish/golibs/snail"
|
||||||
"hilbish/golibs/terminal"
|
"hilbish/golibs/terminal"
|
||||||
|
"hilbish/golibs/yarn"
|
||||||
|
"hilbish/util"
|
||||||
|
|
||||||
rt "github.com/arnodel/golua/runtime"
|
|
||||||
"github.com/arnodel/golua/lib"
|
"github.com/arnodel/golua/lib"
|
||||||
"github.com/arnodel/golua/lib/debuglib"
|
"github.com/arnodel/golua/lib/debuglib"
|
||||||
|
rt "github.com/arnodel/golua/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
var minimalconf = `hilbish.prompt '& '`
|
var minimalconf = `hilbish.prompt '& '`
|
||||||
|
|
||||||
func luaInit() {
|
func luaInit() {
|
||||||
l = rt.New(os.Stdout)
|
l = rt.New(os.Stdout)
|
||||||
l.PushContext(rt.RuntimeContextDef{
|
|
||||||
MessageHandler: debuglib.Traceback,
|
|
||||||
})
|
|
||||||
lib.LoadAll(l)
|
|
||||||
|
|
||||||
lib.LoadLibs(l, hilbishLoader)
|
loadLibs(l)
|
||||||
// yes this is stupid, i know
|
|
||||||
util.DoString(l, "hilbish = require 'hilbish'")
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
// Add Ctrl-C handler
|
|
||||||
hooks.On("signal.sigint", func(...interface{}) rt.Value {
|
|
||||||
if !interactive {
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
return rt.NilValue
|
|
||||||
})
|
|
||||||
|
|
||||||
lr.rl.RawInputCallback = func(r []rune) {
|
|
||||||
hooks.Emit("hilbish.rawInput", string(r))
|
|
||||||
}
|
|
||||||
|
|
||||||
lib.LoadLibs(l, fs.Loader)
|
|
||||||
lib.LoadLibs(l, terminal.Loader)
|
|
||||||
lib.LoadLibs(l, snail.Loader)
|
|
||||||
|
|
||||||
cmds = commander.New(l)
|
|
||||||
lib.LoadLibs(l, cmds.Loader)
|
|
||||||
|
|
||||||
|
yarnPool := yarn.New(yarnloadLibs)
|
||||||
|
lib.LoadLibs(l, yarnPool.Loader)
|
||||||
|
|
||||||
// Add more paths that Lua can require from
|
// Add more paths that Lua can require from
|
||||||
_, err := util.DoString(l, "package.path = package.path .. " + requirePaths)
|
_, err := util.DoString(l, "package.path = package.path .. "+requirePaths)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintln(os.Stderr, "Could not add Hilbish require paths! Libraries will be missing. This shouldn't happen.")
|
fmt.Fprintln(os.Stderr, "Could not add Hilbish require paths! Libraries will be missing. This shouldn't happen.")
|
||||||
}
|
}
|
||||||
@ -74,6 +45,52 @@ func luaInit() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func loadLibs(r *rt.Runtime) {
|
||||||
|
r.PushContext(rt.RuntimeContextDef{
|
||||||
|
MessageHandler: debuglib.Traceback,
|
||||||
|
})
|
||||||
|
lib.LoadAll(r)
|
||||||
|
|
||||||
|
lib.LoadLibs(r, hilbishLoader)
|
||||||
|
// yes this is stupid, i know
|
||||||
|
util.DoString(r, "hilbish = require 'hilbish'")
|
||||||
|
|
||||||
|
hooks = bait.New(r)
|
||||||
|
hooks.SetRecoverer(func(event string, handler *bait.Listener, err interface{}) {
|
||||||
|
fmt.Println("Error in `error` hook handler:", err)
|
||||||
|
hooks.Off(event, handler)
|
||||||
|
})
|
||||||
|
lib.LoadLibs(r, hooks.Loader)
|
||||||
|
|
||||||
|
// Add Ctrl-C handler
|
||||||
|
hooks.On("signal.sigint", func(...interface{}) rt.Value {
|
||||||
|
if !interactive {
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
return rt.NilValue
|
||||||
|
})
|
||||||
|
|
||||||
|
lr.rl.RawInputCallback = func(rn []rune) {
|
||||||
|
hooks.Emit("hilbish.rawInput", string(rn))
|
||||||
|
}
|
||||||
|
|
||||||
|
lib.LoadLibs(r, fs.Loader)
|
||||||
|
lib.LoadLibs(r, terminal.Loader)
|
||||||
|
lib.LoadLibs(r, snail.Loader)
|
||||||
|
|
||||||
|
cmds = commander.New(r)
|
||||||
|
lib.LoadLibs(r, cmds.Loader)
|
||||||
|
}
|
||||||
|
|
||||||
|
func yarnloadLibs(r *rt.Runtime) {
|
||||||
|
r.PushContext(rt.RuntimeContextDef{
|
||||||
|
MessageHandler: debuglib.Traceback,
|
||||||
|
})
|
||||||
|
lib.LoadAll(r)
|
||||||
|
|
||||||
|
lib.LoadLibs(r, hilbishLoader)
|
||||||
|
}
|
||||||
|
|
||||||
func runConfig(confpath string) {
|
func runConfig(confpath string) {
|
||||||
if !interactive {
|
if !interactive {
|
||||||
return
|
return
|
||||||
|
Loading…
x
Reference in New Issue
Block a user