Hilbish/lua.go

193 lines
4.0 KiB
Go
Raw Normal View History

2021-03-19 23:03:11 +00:00
package main
import (
2021-03-31 02:37:08 +00:00
"fmt"
"os"
"os/exec"
"strings"
"syscall"
"time"
"hilbish/golibs/bait"
"hilbish/golibs/commander"
"hilbish/golibs/fs"
2021-03-31 02:37:08 +00:00
"github.com/yuin/gopher-lua"
"layeh.com/gopher-luar"
2021-03-19 23:03:11 +00:00
)
var minimalconf = `
lunacolors = require 'lunacolors'
prompt(lunacolors.format(
'{blue}%u {cyan}%d {green}{reset} '
))
`
func LuaInit() {
2021-03-31 02:37:08 +00:00
l = lua.NewState()
l.OpenLibs()
l.SetGlobal("prompt", l.NewFunction(hshprompt))
l.SetGlobal("multiprompt", l.NewFunction(hshmlprompt))
2021-03-31 02:37:08 +00:00
l.SetGlobal("alias", l.NewFunction(hshalias))
l.SetGlobal("appendPath", l.NewFunction(hshappendPath))
l.SetGlobal("exec", l.NewFunction(hshexec))
l.SetGlobal("goro", luar.New(l, hshgoroutine))
l.SetGlobal("timeout", luar.New(l, hshtimeout))
l.SetGlobal("interval", l.NewFunction(hshinterval))
2021-03-31 02:37:08 +00:00
// yes this is stupid, i know
l.PreloadModule("hilbish", HilbishLoader)
l.DoString("hilbish = require 'hilbish'")
2021-03-31 02:37:08 +00:00
// Add fs module to Lua
l.PreloadModule("fs", fs.Loader)
2021-03-31 02:37:08 +00:00
cmds := commander.New()
2021-03-31 02:37:08 +00:00
// When a command from Lua is added, register it for use
2021-06-10 00:43:01 +00:00
// TODO: maybe dont add command code to a lua table? insstead use a map
cmds.Events.On("commandRegister",
2021-04-19 02:09:27 +00:00
func(cmdName string, cmd *lua.LFunction) {
commands[cmdName] = true
l.SetField(
l.GetTable(l.GetGlobal("commanding"),
lua.LString("__commands")),
cmdName,
cmd)
})
2021-03-31 02:37:08 +00:00
l.PreloadModule("commander", cmds.Loader)
2021-03-31 02:37:08 +00:00
hooks = bait.New()
l.PreloadModule("bait", hooks.Loader)
2021-03-31 02:37:08 +00:00
// Add more paths that Lua can require from
l.DoString("package.path = package.path .. " + requirePaths)
2021-03-31 02:37:08 +00:00
err := l.DoFile("preload.lua")
2021-03-31 02:37:08 +00:00
if err != nil {
err = l.DoFile(preloadPath)
2021-03-31 02:37:08 +00:00
if err != nil {
fmt.Fprintln(os.Stderr,
2021-04-19 02:09:27 +00:00
"Missing preload file, builtins may be missing.")
2021-03-31 02:37:08 +00:00
}
}
}
func RunConfig(confpath string) {
2021-04-28 11:26:23 +00:00
if !interactive {
return
}
err := l.DoFile(confpath)
2021-03-31 02:37:08 +00:00
if err != nil {
fmt.Fprintln(os.Stderr, err,
"\nAn error has occured while loading your config! Falling back to minimal default config.")
l.DoString(minimalconf)
2021-03-31 02:37:08 +00:00
}
}
func RunLogin() {
if _, err := os.Stat(homedir + "/.hprofile.lua"); os.IsNotExist(err) {
return
}
if !login {
return
}
err := l.DoFile(homedir + "/.hprofile.lua")
if err != nil {
fmt.Fprintln(os.Stderr, err,
"\nAn error has occured while loading your login config!n")
}
}
2021-03-19 23:03:11 +00:00
func hshprompt(L *lua.LState) int {
prompt = L.CheckString(1)
2021-03-19 23:03:11 +00:00
return 0
}
func hshmlprompt(L *lua.LState) int {
multilinePrompt = L.CheckString(1)
return 0
}
2021-03-21 21:19:51 +00:00
func hshalias(L *lua.LState) int {
alias := L.CheckString(1)
source := L.CheckString(2)
2021-03-21 21:19:51 +00:00
aliases[alias] = source
return 1
}
2021-04-28 22:09:10 +00:00
func hshappendPath(L *lua.LState) int {
dir := L.CheckString(1)
dir = strings.Replace(dir, "~", curuser.HomeDir, 1)
pathenv := os.Getenv("PATH")
2021-04-28 22:09:10 +00:00
// if dir isnt already in $PATH, add it
if !strings.Contains(pathenv, dir) {
os.Setenv("PATH", pathenv + ":" + dir)
}
2021-04-28 22:09:10 +00:00
return 0
}
func hshexec(L *lua.LState) int {
cmd := L.CheckString(1)
cmdArgs, _ := splitInput(cmd)
cmdPath, err := exec.LookPath(cmdArgs[0])
if err != nil {
fmt.Println(err)
// if we get here, cmdPath will be nothing
// therefore nothing will run
}
// syscall.Exec requires an absolute path to a binary
// path, args, string slice of environments
// TODO: alternative for windows
syscall.Exec(cmdPath, cmdArgs, os.Environ())
return 0 // random thought: does this ever return?
}
func hshgoroutine(gofunc func()) {
go gofunc()
}
func hshtimeout(timeoutfunc func(), ms int) {
timeout := time.Duration(ms) * time.Millisecond
time.AfterFunc(timeout, timeoutfunc)
}
func hshinterval(L *lua.LState) int {
intervalfunc := L.CheckFunction(1)
ms := L.CheckInt(2)
interval := time.Duration(ms) * time.Millisecond
ticker := time.NewTicker(interval)
stop := make(chan lua.LValue)
go func() {
for {
select {
case <-ticker.C:
if err := L.CallByParam(lua.P{
Fn: intervalfunc,
NRet: 0,
Protect: true,
}); err != nil {
panic(err)
}
case <-stop:
ticker.Stop()
return
}
}
}()
L.Push(lua.LChannel(stop))
return 1
}