mirror of https://github.com/Hilbis/Hilbish
Compare commits
4 Commits
016a3a2ec7
...
26add67287
Author | SHA1 | Date |
---|---|---|
TorchedSammy | 26add67287 | |
TorchedSammy | 2086a1ec78 | |
TorchedSammy | d34aa09e8e | |
TorchedSammy | 9fc2247c20 |
|
@ -1,6 +1,6 @@
|
||||||
-- Default Hilbish config
|
-- Default Hilbish config
|
||||||
local lunacolors = require 'lunacolors'
|
local lunacolors = require 'lunacolors'
|
||||||
--local bait = require 'bait'
|
local bait = require 'bait'
|
||||||
local ansikit = require 'ansikit'
|
local ansikit = require 'ansikit'
|
||||||
|
|
||||||
local function doPrompt(fail)
|
local function doPrompt(fail)
|
||||||
|
@ -13,7 +13,6 @@ print(lunacolors.format(hilbish.greeting))
|
||||||
|
|
||||||
doPrompt()
|
doPrompt()
|
||||||
|
|
||||||
--[[
|
|
||||||
bait.catch('command.exit', function(code)
|
bait.catch('command.exit', function(code)
|
||||||
doPrompt(code ~= 0)
|
doPrompt(code ~= 0)
|
||||||
end)
|
end)
|
||||||
|
@ -25,4 +24,3 @@ bait.catch('hilbish.vimMode', function(mode)
|
||||||
ansikit.cursorStyle(ansikit.lineCursor)
|
ansikit.cursorStyle(ansikit.lineCursor)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
]]--
|
|
||||||
|
|
2
api.go
2
api.go
|
@ -271,7 +271,7 @@ func hlprompt(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
}
|
}
|
||||||
lr.SetPrompt(fmtPrompt(prompt))
|
lr.SetPrompt(fmtPrompt(prompt))
|
||||||
|
|
||||||
return nil, nil
|
return c.Next(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// multiprompt(str)
|
// multiprompt(str)
|
||||||
|
|
5
exec.go
5
exec.go
|
@ -114,8 +114,10 @@ func handleLua(cmdString string) (uint8, error) {
|
||||||
}
|
}
|
||||||
// And if there's no syntax errors and -n isnt provided, run
|
// And if there's no syntax errors and -n isnt provided, run
|
||||||
if !noexecute {
|
if !noexecute {
|
||||||
|
if chunk != nil {
|
||||||
_, err = rt.Call1(l.MainThread(), rt.FunctionValue(chunk))
|
_, err = rt.Call1(l.MainThread(), rt.FunctionValue(chunk))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
@ -445,5 +447,6 @@ func cmdFinish(code uint8, cmdstr string, private bool) {
|
||||||
handleHistory(cmdstr)
|
handleHistory(cmdstr)
|
||||||
}
|
}
|
||||||
// util.SetField(l, hshMod, "exitCode", lua.LNumber(code), "Exit code of last exected command")
|
// util.SetField(l, hshMod, "exitCode", lua.LNumber(code), "Exit code of last exected command")
|
||||||
hooks.Em.Emit("command.exit", code, cmdstr)
|
// using AsValue on an interface which is an int results in it being unknown .... ????
|
||||||
|
hooks.Em.Emit("command.exit", rt.IntValue(int64(code)), cmdstr)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,12 +5,13 @@ import (
|
||||||
"hilbish/util"
|
"hilbish/util"
|
||||||
|
|
||||||
"github.com/chuckpreslar/emission"
|
"github.com/chuckpreslar/emission"
|
||||||
"github.com/yuin/gopher-lua"
|
rt "github.com/arnodel/golua/runtime"
|
||||||
"layeh.com/gopher-luar"
|
"github.com/arnodel/golua/lib/packagelib"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Bait struct{
|
type Bait struct{
|
||||||
Em *emission.Emitter
|
Em *emission.Emitter
|
||||||
|
Loader packagelib.Loader
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() Bait {
|
func New() Bait {
|
||||||
|
@ -19,14 +20,27 @@ func New() Bait {
|
||||||
emitter.Off(hookname, hookfunc)
|
emitter.Off(hookname, hookfunc)
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
})
|
})
|
||||||
return Bait{
|
b := Bait{
|
||||||
Em: emitter,
|
Em: emitter,
|
||||||
}
|
}
|
||||||
|
b.Loader = packagelib.Loader{
|
||||||
|
Load: b.LoaderFunc,
|
||||||
|
Name: "bait",
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bait) Loader(L *lua.LState) int {
|
return b
|
||||||
mod := L.SetFuncs(L.NewTable(), map[string]lua.LGFunction{})
|
}
|
||||||
|
|
||||||
|
func (b *Bait) LoaderFunc(rtm *rt.Runtime) (rt.Value, func()) {
|
||||||
|
exports := map[string]util.LuaExport{
|
||||||
|
"catch": util.LuaExport{b.bcatch, 2, false},
|
||||||
|
"catchOnce": util.LuaExport{b.bcatchOnce, 2, false},
|
||||||
|
"throw": util.LuaExport{b.bthrow, 1, true},
|
||||||
|
}
|
||||||
|
mod := rt.NewTable()
|
||||||
|
util.SetExports(rtm, mod, exports)
|
||||||
|
|
||||||
|
/*
|
||||||
util.Document(L, mod,
|
util.Document(L, mod,
|
||||||
`Bait is the event emitter for Hilbish. Why name it bait?
|
`Bait is the event emitter for Hilbish. Why name it bait?
|
||||||
Because it throws hooks that you can catch (emits events
|
Because it throws hooks that you can catch (emits events
|
||||||
|
@ -35,36 +49,99 @@ is fun. This is what you will use if you want to listen
|
||||||
in on hooks to know when certain things have happened,
|
in on hooks to know when certain things have happened,
|
||||||
like when you've changed directory, a command has
|
like when you've changed directory, a command has
|
||||||
failed, etc. To find all available hooks, see doc hooks.`)
|
failed, etc. To find all available hooks, see doc hooks.`)
|
||||||
|
*/
|
||||||
|
|
||||||
L.SetField(mod, "throw", luar.New(L, b.bthrow))
|
return rt.TableValue(mod), nil
|
||||||
L.SetField(mod, "catch", luar.New(L, b.bcatch))
|
}
|
||||||
L.SetField(mod, "catchOnce", luar.New(L, b.bcatchOnce))
|
|
||||||
|
|
||||||
L.Push(mod)
|
func handleArgs(t *rt.Thread, c *rt.GoCont) (string, *rt.Closure, error) {
|
||||||
|
if err := c.CheckNArgs(2); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
name, err := c.StringArg(0)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
catcher, err := c.ClosureArg(1)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return 1
|
return name, catcher, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleHook(t *rt.Thread, c *rt.GoCont, name string, catcher *rt.Closure, args ...interface{}) {
|
||||||
|
funcVal := rt.FunctionValue(catcher)
|
||||||
|
var luaArgs []rt.Value
|
||||||
|
for _, arg := range args {
|
||||||
|
var luarg rt.Value
|
||||||
|
switch arg.(type) {
|
||||||
|
case rt.Value: luarg = arg.(rt.Value)
|
||||||
|
default: luarg = rt.AsValue(arg)
|
||||||
|
}
|
||||||
|
luaArgs = append(luaArgs, luarg)
|
||||||
|
}
|
||||||
|
_, err := rt.Call1(t, funcVal, luaArgs...)
|
||||||
|
if err != nil {
|
||||||
|
e := rt.NewError(rt.StringValue(err.Error()))
|
||||||
|
e = e.AddContext(c.Next(), 1)
|
||||||
|
// panicking here won't actually cause hilbish to panic and instead will
|
||||||
|
// print the error and remove the hook (look at emission recover from above)
|
||||||
|
panic(e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// throw(name, ...args)
|
// throw(name, ...args)
|
||||||
// Throws a hook with `name` with the provided `args`
|
// Throws a hook with `name` with the provided `args`
|
||||||
// --- @param name string
|
// --- @param name string
|
||||||
// --- @vararg any
|
// --- @vararg any
|
||||||
func (b *Bait) bthrow(name string, args ...interface{}) {
|
func (b *Bait) bthrow(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
b.Em.Emit(name, args...)
|
if err := c.Check1Arg(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
name, err := c.StringArg(0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ifaceSlice := make([]interface{}, len(c.Etc()))
|
||||||
|
for i, v := range c.Etc() {
|
||||||
|
ifaceSlice[i] = v
|
||||||
|
}
|
||||||
|
b.Em.Emit(name, ifaceSlice...)
|
||||||
|
|
||||||
|
return c.Next(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// catch(name, cb)
|
// catch(name, cb)
|
||||||
// Catches a hook with `name`. Runs the `cb` when it is thrown
|
// Catches a hook with `name`. Runs the `cb` when it is thrown
|
||||||
// --- @param name string
|
// --- @param name string
|
||||||
// --- @param cb function
|
// --- @param cb function
|
||||||
func (b *Bait) bcatch(name string, catcher func(...interface{})) {
|
func (b *Bait) bcatch(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
b.Em.On(name, catcher)
|
name, catcher, err := handleArgs(t, c)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
b.Em.On(name, func(args ...interface{}) {
|
||||||
|
handleHook(t, c, name, catcher, args...)
|
||||||
|
})
|
||||||
|
|
||||||
|
return c.Next(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// catchOnce(name, cb)
|
// catchOnce(name, cb)
|
||||||
// Same as catch, but only runs the `cb` once and then removes the hook
|
// Same as catch, but only runs the `cb` once and then removes the hook
|
||||||
// --- @param name string
|
// --- @param name string
|
||||||
// --- @param cb function
|
// --- @param cb function
|
||||||
func (b *Bait) bcatchOnce(name string, catcher func(...interface{})) {
|
func (b *Bait) bcatchOnce(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
b.Em.Once(name, catcher)
|
name, catcher, err := handleArgs(t, c)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
b.Em.Once(name, func(args ...interface{}) {
|
||||||
|
handleHook(t, c, name, catcher, args...)
|
||||||
|
})
|
||||||
|
|
||||||
|
return c.Next(), nil
|
||||||
}
|
}
|
||||||
|
|
13
lua.go
13
lua.go
|
@ -4,6 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"hilbish/util"
|
||||||
"hilbish/golibs/bait"
|
"hilbish/golibs/bait"
|
||||||
/*
|
/*
|
||||||
"hilbish/golibs/commander"
|
"hilbish/golibs/commander"
|
||||||
|
@ -42,7 +43,8 @@ func luaInit() {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
hooks = bait.New()
|
hooks = bait.New()
|
||||||
// l.PreloadModule("bait", hooks.Loader)
|
lib.LoadLibs(l, hooks.Loader)
|
||||||
|
|
||||||
// Add Ctrl-C handler
|
// Add Ctrl-C handler
|
||||||
hooks.Em.On("signal.sigint", func() {
|
hooks.Em.On("signal.sigint", func() {
|
||||||
if !interactive {
|
if !interactive {
|
||||||
|
@ -71,14 +73,9 @@ func runConfig(confpath string) {
|
||||||
if !interactive {
|
if !interactive {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
data, err := os.ReadFile(confpath)
|
err := util.DoFile(l, confpath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintln(os.Stderr, err, "\nAn error has occured while loading your config! Falling back to minimal default config.")
|
fmt.Fprintln(os.Stderr, err, "\nAn error has occured while loading your config! Falling back to minimal default config.")
|
||||||
chunk, _ := l.CompileAndLoadLuaChunk("", []byte(minimalconf), rt.TableValue(l.GlobalEnv()))
|
util.DoString(l, minimalconf)
|
||||||
_, err := rt.Call1(l.MainThread(), rt.FunctionValue(chunk))
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
}
|
||||||
chunk, _ := l.CompileAndLoadLuaChunk("", data, rt.TableValue(l.GlobalEnv()))
|
|
||||||
_, err = rt.Call1(l.MainThread(), rt.FunctionValue(chunk))
|
|
||||||
fmt.Println("config", err)
|
|
||||||
}
|
}
|
||||||
|
|
19
util/util.go
19
util/util.go
|
@ -1,6 +1,8 @@
|
||||||
package util
|
package util
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/yuin/gopher-lua"
|
"github.com/yuin/gopher-lua"
|
||||||
rt "github.com/arnodel/golua/runtime"
|
rt "github.com/arnodel/golua/runtime"
|
||||||
)
|
)
|
||||||
|
@ -36,3 +38,20 @@ func SetField(rtm *rt.Runtime, module *rt.Table, field string, value rt.Value, d
|
||||||
module.Set(rt.StringValue(field), value)
|
module.Set(rt.StringValue(field), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func DoString(rtm *rt.Runtime, code string) error {
|
||||||
|
chunk, err := rtm.CompileAndLoadLuaChunk("", []byte(code), rt.TableValue(rtm.GlobalEnv()))
|
||||||
|
if chunk != nil {
|
||||||
|
_, err = rt.Call1(rtm.MainThread(), rt.FunctionValue(chunk))
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func DoFile(rtm *rt.Runtime, filename string) error {
|
||||||
|
data, err := os.ReadFile(filename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return DoString(rtm, string(data))
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue