Compare commits

..

No commits in common. "dce02e53106c40fb6ea855daaebc29f3d892b16b" and "26add6728750b5f793aaf74a59a7ae3cbb76bff1" have entirely different histories.

11 changed files with 136 additions and 184 deletions

47
api.go
View File

@ -22,32 +22,24 @@ import (
)
var exports = map[string]util.LuaExport{
/*
"alias": hlalias,
/*"alias": hlalias,
"appendPath": hlappendPath,
"complete": hlcomplete,
*/
"cwd": util.LuaExport{hlcwd, 0, false},
/*
"cwd": hlcwd,
"exec": hlexec,
"runnerMode": hlrunnerMode,
"goro": hlgoro,
"highlighter": hlhighlighter,
"hinter": hlhinter,
"multiprompt": hlmlprompt,
"prependPath": hlprependPath,
*/
"prependPath": hlprependPath,*/
"prompt": util.LuaExport{hlprompt, 1, false},
/*
"inputMode": hlinputMode,
/*"inputMode": hlinputMode,
"interval": hlinterval,
*/
"read": util.LuaExport{hlprompt, 1, false},
/*
"read": hlread,
"run": hlrun,
"timeout": hltimeout,
"which": hlwhich,
*/
"which": hlwhich,*/
}
var greeting string
@ -77,8 +69,8 @@ Check out the {blue}{bold}guide{reset} command to get started.
util.SetField(L, mod, "ver", lua.LString(version), "Hilbish version")
util.SetField(L, mod, "user", lua.LString(username), "Username of user")
util.SetField(L, mod, "host", lua.LString(host), "Host name of the machine")
util.SetField(L, mod, "home", lua.LString(curuser.HomeDir), "Home directory of the user")
*/
util.SetField(rtm, mod, "home", rt.StringValue(curuser.HomeDir), "Home directory of the user")
util.SetField(rtm, mod, "dataDir", rt.StringValue(dataDir), "Directory for Hilbish's data files")
/*
util.SetField(L, mod, "interactive", lua.LBool(interactive), "If this is an interactive shell")
@ -226,40 +218,37 @@ func hlrun(L *lua.LState) int {
L.Push(lua.LNumber(exitcode))
return 1
}
*/
// cwd()
// Returns the current directory of the shell
func hlcwd(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
func hlcwd(L *lua.LState) int {
cwd, _ := os.Getwd()
return c.PushingNext1(t.Runtime, rt.StringValue(cwd)), nil
}
L.Push(lua.LString(cwd))
return 1
}
// read(prompt) -> input?
// Read input from the user, using Hilbish's line editor/input reader.
// This is a separate instance from the one Hilbish actually uses.
// Returns `input`, will be nil if ctrl + d is pressed, or an error occurs (which shouldn't happen)
// --- @param prompt string
func hlread(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.Check1Arg(); err != nil {
return nil, err
}
luaprompt, err := c.StringArg(0)
if err != nil {
return nil, err
}
func hlread(L *lua.LState) int {
luaprompt := L.CheckString(1)
lualr := newLineReader("", true)
lualr.SetPrompt(luaprompt)
input, err := lualr.Read()
if err != nil {
return c.Next(), nil
L.Push(lua.LNil)
return 1
}
return c.PushingNext1(t.Runtime, rt.StringValue(input)), nil
L.Push(lua.LString(input))
return 1
}
*/
/*
prompt(str)

26
exec.go
View File

@ -183,27 +183,37 @@ func execCommand(cmd string) error {
}
// If command is defined in Lua then run it
luacmdArgs := rt.NewTable()
for i, str := range args[1:] {
luacmdArgs.Set(rt.IntValue(int64(i + 1)), rt.StringValue(str))
/*
luacmdArgs := l.NewTable()
for _, str := range args[1:] {
luacmdArgs.Append(lua.LString(str))
}
if commands[args[0]] != nil {
luaexitcode, err := rt.Call1(l.MainThread(), rt.FunctionValue(commands[args[0]]), rt.TableValue(luacmdArgs))
err := l.CallByParam(lua.P{
Fn: commands[args[0]],
NRet: 1,
Protect: true,
}, luacmdArgs)
if err != nil {
fmt.Fprintln(os.Stderr,
"Error in command:\n\n" + err.Error())
return interp.NewExitStatus(1)
}
luaexitcode := l.Get(-1)
var exitcode uint8
if code, ok := luaexitcode.TryInt(); ok {
l.Pop(1)
if code, ok := luaexitcode.(lua.LNumber); luaexitcode != lua.LNil && ok {
exitcode = uint8(code)
} // TODO: deregister commander if return isnt number
}
return interp.NewExitStatus(exitcode)
}
*/
err := lookpath(args[0])
if err == errNotExec {
@ -437,8 +447,6 @@ func cmdFinish(code uint8, cmdstr string, private bool) {
handleHistory(cmdstr)
}
// util.SetField(l, hshMod, "exitCode", lua.LNumber(code), "Exit code of last exected command")
// 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
// using AsValue on an interface which is an int results in it being unknown .... ????
hooks.Em.Emit("command.exit", rt.IntValue(int64(code)), cmdstr)
}

2
go.mod
View File

@ -20,5 +20,3 @@ replace mvdan.cc/sh/v3 => github.com/Rosettea/sh/v3 v3.4.0-0.dev.0.2022030614040
replace github.com/maxlandon/readline => ./readline
replace layeh.com/gopher-luar => github.com/layeh/gopher-luar v1.0.10
replace github.com/arnodel/golua => github.com/Rosettea/golua v0.0.0-20220329005655-c29b74de7d20

2
go.sum
View File

@ -1,5 +1,3 @@
github.com/Rosettea/golua v0.0.0-20220329005655-c29b74de7d20 h1:i4XwNhWKlHP9+oHfpNandGsjj9XQG+uah+SdAjLknbc=
github.com/Rosettea/golua v0.0.0-20220329005655-c29b74de7d20/go.mod h1:9jzpYPiU2is0HVGCiuIOBSXdergHUW44IEjmuN1UrIE=
github.com/Rosettea/readline-1 v0.0.0-20220302012429-9ce5d23760f7 h1:LoY+kBKqMQqBcilRpVvifBTVve84asa3btpx3D/+IvM=
github.com/Rosettea/readline-1 v0.0.0-20220302012429-9ce5d23760f7/go.mod h1:QiUAvbhg8PzCA4hlafCUl0bKD/0VmcocM4AjqtszAJs=
github.com/Rosettea/readline-1 v0.0.0-20220305004552-071c22768119 h1:rGsc30WTD5hk+oiXrAKsAIwZn5qBeTAdr29y3HhJh9E=

View File

@ -4,9 +4,9 @@ import (
"fmt"
"hilbish/util"
"github.com/chuckpreslar/emission"
rt "github.com/arnodel/golua/runtime"
"github.com/arnodel/golua/lib/packagelib"
"github.com/chuckpreslar/emission"
)
type Bait struct{
@ -54,6 +54,22 @@ failed, etc. To find all available hooks, see doc hooks.`)
return rt.TableValue(mod), nil
}
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 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
@ -101,7 +117,7 @@ func (b *Bait) bthrow(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
// --- @param name string
// --- @param cb function
func (b *Bait) bcatch(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
name, catcher, err := util.HandleStrCallback(t, c)
name, catcher, err := handleArgs(t, c)
if err != nil {
return nil, err
}
@ -118,7 +134,7 @@ func (b *Bait) bcatch(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
// --- @param name string
// --- @param cb function
func (b *Bait) bcatchOnce(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
name, catcher, err := util.HandleStrCallback(t, c)
name, catcher, err := handleArgs(t, c)
if err != nil {
return nil, err
}

View File

@ -3,68 +3,52 @@ package commander
import (
"hilbish/util"
rt "github.com/arnodel/golua/runtime"
"github.com/arnodel/golua/lib/packagelib"
"github.com/chuckpreslar/emission"
"github.com/yuin/gopher-lua"
)
type Commander struct{
Events *emission.Emitter
Loader packagelib.Loader
}
func New() Commander {
c := Commander{
return Commander{
Events: emission.NewEmitter(),
}
c.Loader = packagelib.Loader{
Load: c.LoaderFunc,
Name: "commander",
}
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},
func (c *Commander) Loader(L *lua.LState) int {
exports := map[string]lua.LGFunction{
"register": c.cregister,
"deregister": c.cderegister,
}
mod := rt.NewTable()
util.SetExports(rtm, mod, exports)
// util.Document(L, mod, "Commander is Hilbish's custom command library, a way to write commands in Lua.")
mod := L.SetFuncs(L.NewTable(), exports)
util.Document(L, mod, "Commander is Hilbish's custom command library, a way to write commands in Lua.")
L.Push(mod)
return rt.TableValue(mod), nil
return 1
}
// register(name, cb)
// Register a command with `name` that runs `cb` when ran
// --- @param name string
// --- @param cb function
func (c *Commander) cregister(t *rt.Thread, ct *rt.GoCont) (rt.Cont, error) {
cmdName, cmd, err := util.HandleStrCallback(t, ct)
if err != nil {
return nil, err
}
func (c *Commander) cregister(L *lua.LState) int {
cmdName := L.CheckString(1)
cmd := L.CheckFunction(2)
c.Events.Emit("commandRegister", cmdName, cmd)
return ct.Next(), err
return 0
}
// deregister(name)
// Deregisters any command registered with `name`
// --- @param name string
func (c *Commander) cderegister(t *rt.Thread, ct *rt.GoCont) (rt.Cont, error) {
if err := ct.Check1Arg(); err != nil {
return nil, err
}
cmdName, err := ct.StringArg(0)
if err != nil {
return nil, err
}
func (c *Commander) cderegister(L *lua.LState) int {
cmdName := L.CheckString(1)
c.Events.Emit("commandDeregister", cmdName)
return ct.Next(), err
return 0
}

View File

@ -8,71 +8,51 @@ import (
"strings"
"hilbish/util"
rt "github.com/arnodel/golua/runtime"
"github.com/arnodel/golua/lib/packagelib"
"github.com/yuin/gopher-lua"
)
var Loader = packagelib.Loader{
Load: LoaderFunc,
Name: "fs",
}
func Loader(L *lua.LState) int {
mod := L.SetFuncs(L.NewTable(), exports)
func LoaderFunc(rtm *rt.Runtime) (rt.Value, func()) {
exports := map[string]util.LuaExport{
"cd": util.LuaExport{fcd, 1, false},
"mkdir": util.LuaExport{fmkdir, 2, false},
"stat": util.LuaExport{fstat, 1, false},
"readdir": util.LuaExport{freaddir, 1, false},
}
mod := rt.NewTable()
util.SetExports(rtm, mod, exports)
/*
util.Document(L, mod, `The fs module provides easy and simple access to
filesystem functions and other things, and acts an
addition to the Lua standard library's I/O and fs functions.`)
*/
return rt.TableValue(mod), nil
L.Push(mod)
return 1
}
var exports = map[string]lua.LGFunction{
"cd": fcd,
"mkdir": fmkdir,
"stat": fstat,
"readdir": freaddir,
}
// cd(dir)
// Changes directory to `dir`
// --- @param dir string
func fcd(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.Check1Arg(); err != nil {
return nil, err
}
path, err := c.StringArg(0)
func fcd(L *lua.LState) int {
path := L.CheckString(1)
err := os.Chdir(strings.TrimSpace(path))
if err != nil {
return nil, err
e := err.(*os.PathError).Err.Error()
L.RaiseError(e + ": " + path)
}
err = os.Chdir(strings.TrimSpace(path))
if err != nil {
return nil, err
}
return c.Next(), err
return 0
}
// mkdir(name, recursive)
// Makes a directory called `name`. If `recursive` is true, it will create its parent directories.
// --- @param name string
// --- @param recursive boolean
func fmkdir(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.CheckNArgs(2); err != nil {
return nil, err
}
dirname, err := c.StringArg(0)
if err != nil {
return nil, err
}
recursive, err := c.BoolArg(1)
if err != nil {
return nil, err
}
func fmkdir(L *lua.LState) int {
dirname := L.CheckString(1)
recursive := L.ToBool(2)
path := strings.TrimSpace(dirname)
var err error
if recursive {
err = os.MkdirAll(path, 0744)
@ -80,58 +60,51 @@ func fmkdir(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
err = os.Mkdir(path, 0744)
}
if err != nil {
return nil, err
L.RaiseError(err.Error() + ": " + path)
}
return c.Next(), err
return 0
}
// stat(path)
// Returns info about `path`
// --- @param path string
func fstat(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.Check1Arg(); err != nil {
return nil, err
}
path, err := c.StringArg(0)
if err != nil {
return nil, err
}
func fstat(L *lua.LState) int {
path := L.CheckString(1)
pathinfo, err := os.Stat(path)
if err != nil {
return nil, err
L.RaiseError(err.Error() + ": " + path)
return 0
}
statTbl := rt.NewTable()
statTbl.Set(rt.StringValue("name"), rt.StringValue(pathinfo.Name()))
statTbl.Set(rt.StringValue("size"), rt.IntValue(pathinfo.Size()))
statTbl.Set(rt.StringValue("mode"), rt.StringValue("0" + strconv.FormatInt(int64(pathinfo.Mode().Perm()), 8)))
statTbl.Set(rt.StringValue("isDir"), rt.BoolValue(pathinfo.IsDir()))
statTbl := L.NewTable()
L.SetField(statTbl, "name", lua.LString(pathinfo.Name()))
L.SetField(statTbl, "size", lua.LNumber(pathinfo.Size()))
L.SetField(statTbl, "mode", lua.LString("0" + strconv.FormatInt(int64(pathinfo.Mode().Perm()), 8)))
L.SetField(statTbl, "isDir", lua.LBool(pathinfo.IsDir()))
L.Push(statTbl)
return c.PushingNext1(t.Runtime, rt.TableValue(statTbl)), nil
return 1
}
// readdir(dir)
// Returns a table of files in `dir`
// --- @param dir string
// --- @return table
func freaddir(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.Check1Arg(); err != nil {
return nil, err
}
dir, err := c.StringArg(0)
if err != nil {
return nil, err
}
names := rt.NewTable()
func freaddir(L *lua.LState) int {
dir := L.CheckString(1)
names := L.NewTable()
dirEntries, err := os.ReadDir(dir)
if err != nil {
return nil, err
L.RaiseError(err.Error() + ": " + dir)
return 0
}
for i, entry := range dirEntries {
names.Set(rt.IntValue(int64(i + 1)), rt.StringValue(entry.Name()))
for _, entry := range dirEntries {
names.Append(lua.LString(entry.Name()))
}
return c.PushingNext1(t.Runtime, rt.TableValue(names)), nil
L.Push(names)
return 1
}

30
lua.go
View File

@ -6,9 +6,9 @@ import (
"hilbish/util"
"hilbish/golibs/bait"
/*
"hilbish/golibs/commander"
"hilbish/golibs/fs"
/*
"hilbish/golibs/terminal"
*/
rt "github.com/arnodel/golua/runtime"
@ -23,23 +23,24 @@ func luaInit() {
lib.LoadLibs(l, hilbishLoader)
// yes this is stupid, i know
util.DoString(l, "hilbish = require 'hilbish'")
chunk, _ := l.CompileAndLoadLuaChunk("", []byte("hilbish = require 'hilbish'"), rt.TableValue(l.GlobalEnv()))
_, err := rt.Call1(l.MainThread(), rt.FunctionValue(chunk))
fmt.Println("hsh load", err)
// Add fs and terminal module module to Lua
lib.LoadLibs(l, fs.Loader)
/*
/* l.PreloadModule("fs", fs.Loader)
l.PreloadModule("terminal", terminal.Loader)
*/
cmds := commander.New()
// When a command from Lua is added, register it for use
cmds.Events.On("commandRegister", func(cmdName string, cmd *rt.Closure) {
cmds.Events.On("commandRegister", func(cmdName string, cmd *lua.LFunction) {
commands[cmdName] = cmd
})
cmds.Events.On("commandDeregister", func(cmdName string) {
delete(commands, cmdName)
})
lib.LoadLibs(l, cmds.Loader)
l.PreloadModule("commander", cmds.Loader)
*/
hooks = bait.New()
lib.LoadLibs(l, hooks.Loader)
@ -52,19 +53,20 @@ func luaInit() {
})
// Add more paths that Lua can require from
err := util.DoString(l, "package.path = package.path .. " + requirePaths)
if err != nil {
fmt.Fprintln(os.Stderr, "Could not add preload paths! Libraries will be missing. This shouldn't happen.")
}
chunk, _ = l.CompileAndLoadLuaChunk("", []byte("package.path = package.path .. " + requirePaths), rt.TableValue(l.GlobalEnv()))
_, err = rt.Call1(l.MainThread(), rt.FunctionValue(chunk))
fmt.Println("package path", err)
err = util.DoFile(l, "prelude/init.lua")
data, err := os.ReadFile("prelude/init.lua")
if err != nil {
err = util.DoFile(l, preloadPath)
data, err = os.ReadFile(preloadPath)
if err != nil {
fmt.Fprintln(os.Stderr, "Missing preload file, builtins may be missing.")
}
}
fmt.Println(err)
chunk, _ = l.CompileAndLoadLuaChunk("", data, rt.TableValue(l.GlobalEnv()))
_, err = rt.Call1(l.MainThread(), rt.FunctionValue(chunk))
fmt.Println("prelude", err)
}
func runConfig(confpath string) {

View File

@ -23,7 +23,7 @@ var (
l *rt.Runtime
lr *lineReader
commands = map[string]*rt.Closure{}
commands = map[string]*lua.LFunction{}
luaCompletions = map[string]*lua.LFunction{}
confDir string

View File

@ -8,7 +8,7 @@ local _ = require 'succulent' -- Function additions
local oldDir = hilbish.cwd()
local shlvl = tonumber(os.getenv 'SHLVL')
if shlvl ~= nil then os.setenv('SHLVL', tostring(shlvl + 1)) else os.setenv('SHLVL', '0') end
if shlvl ~= nil then os.setenv('SHLVL', shlvl + 1) else os.setenv('SHLVL', 0) end
-- Builtins
local recentDirs = {}

View File

@ -55,19 +55,3 @@ func DoFile(rtm *rt.Runtime, filename string) error {
return DoString(rtm, string(data))
}
func HandleStrCallback(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
}
cb, err := c.ClosureArg(1)
if err != nil {
return "", nil, err
}
return name, cb, err
}