2022-03-20 19:15:44 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2022-04-04 10:40:02 +00:00
|
|
|
"hilbish/util"
|
|
|
|
|
|
|
|
rt "github.com/arnodel/golua/runtime"
|
2022-03-20 19:15:44 +00:00
|
|
|
)
|
|
|
|
|
2022-12-15 04:00:54 +00:00
|
|
|
// #interface runner
|
|
|
|
// interactive command runner customization
|
2023-12-26 03:08:29 +00:00
|
|
|
/* The runner interface contains functions that allow the user to change
|
|
|
|
how Hilbish interprets interactive input.
|
|
|
|
Users can add and change the default runner for interactive input to any
|
|
|
|
language or script of their choosing. A good example is using it to
|
|
|
|
write command in Fennel.
|
|
|
|
|
|
|
|
Runners are functions that evaluate user input. The default runners in
|
|
|
|
Hilbish can run shell script and Lua code.
|
|
|
|
|
|
|
|
A runner is passed the input and has to return a table with these values.
|
|
|
|
All are not required, only the useful ones the runner needs to return.
|
|
|
|
(So if there isn't an error, just omit `err`.)
|
|
|
|
|
2024-08-16 19:15:10 +00:00
|
|
|
- `exitCode` (number): Exit code of the command
|
|
|
|
- `input` (string): The text input of the user. This is used by Hilbish to append extra input, in case
|
|
|
|
more is requested.
|
|
|
|
- `err` (string): A string that represents an error from the runner.
|
|
|
|
This should only be set when, for example, there is a syntax error.
|
|
|
|
It can be set to a few special values for Hilbish to throw the right
|
|
|
|
hooks and have a better looking message.
|
|
|
|
- `<command>: not-found` will throw a `command.not-found` hook
|
|
|
|
based on what `<command>` is.
|
|
|
|
- `<command>: not-executable` will throw a `command.not-executable` hook.
|
|
|
|
- `continue` (boolean): Whether Hilbish should prompt the user for no input
|
|
|
|
- `newline` (boolean): Whether a newline should be added at the end of `input`.
|
2023-12-26 03:08:29 +00:00
|
|
|
|
|
|
|
Here is a simple example of a fennel runner. It falls back to
|
|
|
|
shell script if fennel eval has an error.
|
|
|
|
```lua
|
|
|
|
local fennel = require 'fennel'
|
|
|
|
|
|
|
|
hilbish.runnerMode(function(input)
|
|
|
|
local ok = pcall(fennel.eval, input)
|
|
|
|
if ok then
|
|
|
|
return {
|
|
|
|
input = input
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
return hilbish.runner.sh(input)
|
|
|
|
end)
|
|
|
|
```
|
|
|
|
*/
|
2022-04-04 10:40:02 +00:00
|
|
|
func runnerModeLoader(rtm *rt.Runtime) *rt.Table {
|
|
|
|
exports := map[string]util.LuaExport{
|
|
|
|
"sh": {shRunner, 1, false},
|
|
|
|
"lua": {luaRunner, 1, false},
|
|
|
|
"setMode": {hlrunnerMode, 1, false},
|
2022-03-20 19:15:44 +00:00
|
|
|
}
|
|
|
|
|
2022-04-04 10:40:02 +00:00
|
|
|
mod := rt.NewTable()
|
|
|
|
util.SetExports(rtm, mod, exports)
|
2022-03-20 19:15:44 +00:00
|
|
|
|
|
|
|
return mod
|
|
|
|
}
|
|
|
|
|
2022-12-15 04:00:54 +00:00
|
|
|
// #interface runner
|
|
|
|
// setMode(cb)
|
2023-12-26 03:08:29 +00:00
|
|
|
// This is the same as the `hilbish.runnerMode` function.
|
|
|
|
// It takes a callback, which will be used to execute all interactive input.
|
2022-12-15 04:00:54 +00:00
|
|
|
// In normal cases, neither callbacks should be overrided by the user,
|
|
|
|
// as the higher level functions listed below this will handle it.
|
2023-12-26 03:08:29 +00:00
|
|
|
// #param cb function
|
2022-12-15 04:00:54 +00:00
|
|
|
func _runnerMode() {}
|
|
|
|
|
|
|
|
// #interface runner
|
|
|
|
// sh(cmd)
|
|
|
|
// Runs a command in Hilbish's shell script interpreter.
|
|
|
|
// This is the equivalent of using `source`.
|
2023-12-26 03:08:29 +00:00
|
|
|
// #param cmd string
|
2022-04-04 10:40:02 +00:00
|
|
|
func shRunner(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
|
|
|
if err := c.Check1Arg(); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
cmd, err := c.StringArg(0)
|
2022-03-20 19:15:44 +00:00
|
|
|
if err != nil {
|
2022-04-04 10:40:02 +00:00
|
|
|
return nil, err
|
2022-03-20 19:15:44 +00:00
|
|
|
}
|
|
|
|
|
2024-08-16 17:50:34 +00:00
|
|
|
_, exitCode, cont, newline, err := execSh(aliases.Resolve(cmd))
|
2022-04-04 10:40:02 +00:00
|
|
|
var luaErr rt.Value = rt.NilValue
|
|
|
|
if err != nil {
|
|
|
|
luaErr = rt.StringValue(err.Error())
|
|
|
|
}
|
2022-06-03 02:33:30 +00:00
|
|
|
runnerRet := rt.NewTable()
|
2022-09-18 01:00:28 +00:00
|
|
|
runnerRet.Set(rt.StringValue("input"), rt.StringValue(cmd))
|
2022-06-03 02:33:30 +00:00
|
|
|
runnerRet.Set(rt.StringValue("exitCode"), rt.IntValue(int64(exitCode)))
|
|
|
|
runnerRet.Set(rt.StringValue("continue"), rt.BoolValue(cont))
|
2024-08-16 17:50:34 +00:00
|
|
|
runnerRet.Set(rt.StringValue("newline"), rt.BoolValue(newline))
|
2022-06-03 02:33:30 +00:00
|
|
|
runnerRet.Set(rt.StringValue("err"), luaErr)
|
2022-03-20 19:15:44 +00:00
|
|
|
|
2022-06-03 02:33:30 +00:00
|
|
|
return c.PushingNext(t.Runtime, rt.TableValue(runnerRet)), nil
|
2022-03-20 19:15:44 +00:00
|
|
|
}
|
|
|
|
|
2022-12-15 04:00:54 +00:00
|
|
|
// #interface runner
|
|
|
|
// lua(cmd)
|
|
|
|
// Evaluates `cmd` as Lua input. This is the same as using `dofile`
|
|
|
|
// or `load`, but is appropriated for the runner interface.
|
2023-12-26 03:08:29 +00:00
|
|
|
// #param cmd string
|
2022-04-04 10:40:02 +00:00
|
|
|
func luaRunner(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
|
|
|
if err := c.Check1Arg(); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
cmd, err := c.StringArg(0)
|
2022-03-20 19:15:44 +00:00
|
|
|
if err != nil {
|
2022-04-04 10:40:02 +00:00
|
|
|
return nil, err
|
2022-03-20 19:15:44 +00:00
|
|
|
}
|
|
|
|
|
2022-04-13 14:11:38 +00:00
|
|
|
input, exitCode, err := handleLua(cmd)
|
2022-04-04 10:40:02 +00:00
|
|
|
var luaErr rt.Value = rt.NilValue
|
|
|
|
if err != nil {
|
|
|
|
luaErr = rt.StringValue(err.Error())
|
|
|
|
}
|
2022-06-03 02:33:30 +00:00
|
|
|
runnerRet := rt.NewTable()
|
|
|
|
runnerRet.Set(rt.StringValue("input"), rt.StringValue(input))
|
|
|
|
runnerRet.Set(rt.StringValue("exitCode"), rt.IntValue(int64(exitCode)))
|
|
|
|
runnerRet.Set(rt.StringValue("err"), luaErr)
|
2022-03-20 19:15:44 +00:00
|
|
|
|
2022-06-03 02:33:30 +00:00
|
|
|
return c.PushingNext(t.Runtime, rt.TableValue(runnerRet)), nil
|
2022-03-20 19:15:44 +00:00
|
|
|
}
|