2021-05-16 19:53:21 +00:00
|
|
|
// Here is the core api for the hilbi shell itself
|
|
|
|
// Basically, stuff about the shell itself and other functions
|
|
|
|
// go here.
|
|
|
|
package main
|
|
|
|
|
2021-05-16 21:13:28 +00:00
|
|
|
import (
|
|
|
|
"os"
|
2021-09-26 01:39:06 +00:00
|
|
|
"runtime"
|
2021-07-08 10:44:57 +00:00
|
|
|
"strings"
|
2021-05-16 21:13:28 +00:00
|
|
|
|
2021-10-16 19:40:08 +00:00
|
|
|
"hilbish/util"
|
|
|
|
|
2021-05-16 22:10:46 +00:00
|
|
|
"github.com/pborman/getopt"
|
2021-05-16 21:13:28 +00:00
|
|
|
"github.com/yuin/gopher-lua"
|
|
|
|
"mvdan.cc/sh/v3/interp"
|
|
|
|
)
|
|
|
|
|
|
|
|
var exports = map[string]lua.LGFunction {
|
2021-10-16 16:40:53 +00:00
|
|
|
"run": hlrun,
|
|
|
|
"flag": hlflag,
|
|
|
|
"cwd": hlcwd,
|
2021-10-30 23:53:42 +00:00
|
|
|
"read": hlread,
|
2021-05-16 21:13:28 +00:00
|
|
|
}
|
|
|
|
|
2021-12-06 21:21:31 +00:00
|
|
|
func hilbishLoader(L *lua.LState) int {
|
2021-05-16 21:13:28 +00:00
|
|
|
mod := L.SetFuncs(L.NewTable(), exports)
|
|
|
|
|
|
|
|
host, _ := os.Hostname()
|
2021-09-26 01:39:06 +00:00
|
|
|
username := curuser.Username
|
|
|
|
// this will be baked into binary since GOOS is a constant
|
|
|
|
if runtime.GOOS == "windows" {
|
|
|
|
username = strings.Split(username, "\\")[1] // for some reason Username includes the hostname on windows
|
|
|
|
}
|
2021-05-16 21:13:28 +00:00
|
|
|
|
2021-11-22 23:59:28 +00:00
|
|
|
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")
|
2021-12-01 22:31:04 +00:00
|
|
|
util.SetField(L, mod, "home", lua.LString(curuser.HomeDir), "Home directory of the user")
|
2021-11-22 23:59:28 +00:00
|
|
|
util.SetField(L, mod, "dataDir", lua.LString(dataDir), "Directory for Hilbish's data files")
|
|
|
|
util.SetField(L, mod, "interactive", lua.LBool(interactive), "If this is an interactive shell")
|
|
|
|
util.SetField(L, mod, "login", lua.LBool(interactive), "Whether this is a login shell")
|
2021-05-16 21:13:28 +00:00
|
|
|
|
2021-10-08 00:58:07 +00:00
|
|
|
xdg := L.NewTable()
|
2021-11-26 03:24:35 +00:00
|
|
|
util.SetField(L, xdg, "config", lua.LString(confDir), "XDG config directory")
|
2021-12-01 22:31:04 +00:00
|
|
|
util.SetField(L, xdg, "data", lua.LString(getenv("XDG_DATA_HOME", curuser.HomeDir + "/.local/share")), "XDG data directory")
|
2021-10-16 19:40:08 +00:00
|
|
|
L.SetField(mod, "xdg", xdg)
|
2021-10-08 00:58:07 +00:00
|
|
|
|
2021-11-26 03:24:35 +00:00
|
|
|
util.Document(L, xdg, "Variables for the XDG base directory spec.")
|
2021-12-13 21:32:55 +00:00
|
|
|
util.Document(L, mod, "Hilbish's core API, containing submodules and functions which relate to the shell itself.")
|
2021-05-16 21:13:28 +00:00
|
|
|
L.Push(mod)
|
|
|
|
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
2021-10-16 16:40:53 +00:00
|
|
|
// run(cmd)
|
|
|
|
// Runs `cmd` in Hilbish's sh interpreter
|
|
|
|
func hlrun(L *lua.LState) int {
|
2021-12-07 21:27:07 +00:00
|
|
|
var exitcode uint8
|
2021-05-16 21:13:28 +00:00
|
|
|
cmd := L.CheckString(1)
|
|
|
|
err := execCommand(cmd)
|
|
|
|
|
|
|
|
if code, ok := interp.IsExitStatus(err); ok {
|
|
|
|
exitcode = code
|
|
|
|
} else if err != nil {
|
|
|
|
exitcode = 1
|
|
|
|
}
|
|
|
|
|
|
|
|
L.Push(lua.LNumber(exitcode))
|
|
|
|
return 1
|
2021-05-16 19:53:21 +00:00
|
|
|
}
|
|
|
|
|
2021-10-16 16:40:53 +00:00
|
|
|
// flag(f)
|
|
|
|
// Checks if the `f` flag has been passed to Hilbish.
|
|
|
|
func hlflag(L *lua.LState) int {
|
2021-05-16 22:10:46 +00:00
|
|
|
flagchar := L.CheckString(1)
|
|
|
|
|
|
|
|
L.Push(lua.LBool(getopt.Lookup([]rune(flagchar)[0]).Seen()))
|
|
|
|
|
|
|
|
return 1
|
|
|
|
}
|
2021-05-27 23:06:17 +00:00
|
|
|
|
2021-10-16 16:40:53 +00:00
|
|
|
// cwd()
|
|
|
|
// Returns the current directory of the shell
|
|
|
|
func hlcwd(L *lua.LState) int {
|
2021-05-27 23:06:17 +00:00
|
|
|
cwd, _ := os.Getwd()
|
|
|
|
|
|
|
|
L.Push(lua.LString(cwd))
|
|
|
|
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
2021-10-08 00:58:07 +00:00
|
|
|
func getenv(key, fallback string) string {
|
|
|
|
value := os.Getenv(key)
|
|
|
|
if len(value) == 0 {
|
|
|
|
return fallback
|
|
|
|
}
|
|
|
|
return value
|
|
|
|
}
|
2021-10-30 23:53:42 +00:00
|
|
|
|
|
|
|
// 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)
|
|
|
|
func hlread(L *lua.LState) int {
|
|
|
|
luaprompt := L.CheckString(1)
|
2021-12-06 21:21:31 +00:00
|
|
|
lualr := newLineReader(luaprompt)
|
2021-10-30 23:53:42 +00:00
|
|
|
|
|
|
|
input, err := lualr.Read()
|
|
|
|
if err != nil {
|
|
|
|
L.Push(lua.LNil)
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
|
|
|
L.Push(lua.LString(input))
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|