mirror of
https://github.com/Hilbis/Hilbish
synced 2025-07-01 16:52:03 +00:00
refactor: fully implement hilbish.runner in lua
This commit is contained in:
parent
91d7acf093
commit
7d503750c0
4
api.go
4
api.go
@ -110,10 +110,6 @@ func hilbishLoad(rtm *rt.Runtime) (rt.Value, func()) {
|
|||||||
mod.Set(rt.StringValue("completion"), rt.TableValue(hshcomp))
|
mod.Set(rt.StringValue("completion"), rt.TableValue(hshcomp))
|
||||||
mod.Set(rt.StringValue("completions"), rt.TableValue(hshcomp))
|
mod.Set(rt.StringValue("completions"), rt.TableValue(hshcomp))
|
||||||
|
|
||||||
// hilbish.runner table
|
|
||||||
runnerModule := runnerModeLoader(rtm)
|
|
||||||
mod.Set(rt.StringValue("runner"), rt.TableValue(runnerModule))
|
|
||||||
|
|
||||||
// hilbish.jobs table
|
// hilbish.jobs table
|
||||||
jobs = newJobHandler()
|
jobs = newJobHandler()
|
||||||
jobModule := jobs.loader(rtm)
|
jobModule := jobs.loader(rtm)
|
||||||
|
27
exec.go
27
exec.go
@ -18,33 +18,6 @@ func runInput(input string, priv bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleLua(input string) (string, uint8, error) {
|
|
||||||
cmdString := aliases.Resolve(input)
|
|
||||||
// First try to load input, essentially compiling to bytecode
|
|
||||||
chunk, err := l.CompileAndLoadLuaChunk("", []byte(cmdString), rt.TableValue(l.GlobalEnv()))
|
|
||||||
if err != nil && noexecute {
|
|
||||||
fmt.Println(err)
|
|
||||||
/* if lerr, ok := err.(*lua.ApiError); ok {
|
|
||||||
if perr, ok := lerr.Cause.(*parse.Error); ok {
|
|
||||||
print(perr.Pos.Line == parse.EOF)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
return cmdString, 125, err
|
|
||||||
}
|
|
||||||
// And if there's no syntax errors and -n isnt provided, run
|
|
||||||
if !noexecute {
|
|
||||||
if chunk != nil {
|
|
||||||
_, err = rt.Call1(l.MainThread(), rt.FunctionValue(chunk))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err == nil {
|
|
||||||
return cmdString, 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return cmdString, 125, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func splitInput(input string) ([]string, string) {
|
func splitInput(input string) ([]string, string) {
|
||||||
// end my suffering
|
// end my suffering
|
||||||
// TODO: refactor this garbage
|
// TODO: refactor this garbage
|
||||||
|
31
main.go
31
main.go
@ -251,37 +251,6 @@ func continuePrompt(prev string, newline bool) (string, error) {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// This semi cursed function formats our prompt (obviously)
|
|
||||||
func fmtPrompt(prompt string) string {
|
|
||||||
host, _ := os.Hostname()
|
|
||||||
cwd, _ := os.Getwd()
|
|
||||||
|
|
||||||
cwd = util.AbbrevHome(cwd)
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
args := []string{
|
|
||||||
"d", cwd,
|
|
||||||
"D", filepath.Base(cwd),
|
|
||||||
"h", host,
|
|
||||||
"u", username,
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, v := range args {
|
|
||||||
if i%2 == 0 {
|
|
||||||
args[i] = "%" + v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r := strings.NewReplacer(args...)
|
|
||||||
nprompt := r.Replace(prompt)
|
|
||||||
|
|
||||||
return nprompt
|
|
||||||
}
|
|
||||||
|
|
||||||
func removeDupes(slice []string) []string {
|
func removeDupes(slice []string) []string {
|
||||||
all := make(map[string]bool)
|
all := make(map[string]bool)
|
||||||
newSlice := []string{}
|
newSlice := []string{}
|
||||||
|
@ -1,10 +1,53 @@
|
|||||||
-- @module hilbish.runner
|
-- @module hilbish.runner
|
||||||
|
--- interactive command runner customization
|
||||||
|
--- 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`.)
|
||||||
|
---
|
||||||
|
--- - `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`.
|
||||||
|
---
|
||||||
|
--- 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)
|
||||||
|
--- ```
|
||||||
local snail = require 'snail'
|
local snail = require 'snail'
|
||||||
local currentRunner = 'hybrid'
|
local currentRunner = 'hybrid'
|
||||||
local runners = {}
|
local runners = {}
|
||||||
|
|
||||||
-- lsp shut up
|
-- lsp shut up
|
||||||
hilbish = hilbish
|
hilbish.runner = {}
|
||||||
|
|
||||||
--- Get a runner by name.
|
--- Get a runner by name.
|
||||||
--- @param name string Name of the runner to retrieve.
|
--- @param name string Name of the runner to retrieve.
|
||||||
@ -167,6 +210,35 @@ function hilbish.runner.sh(input)
|
|||||||
return hilbish.snail:run(input)
|
return hilbish.snail:run(input)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- lua(cmd)
|
||||||
|
--- Evaluates `cmd` as Lua input. This is the same as using `dofile`
|
||||||
|
--- or `load`, but is appropriated for the runner interface.
|
||||||
|
-- @param cmd string
|
||||||
|
function hilbish.runner.lua(input)
|
||||||
|
local fun, err = load(input)
|
||||||
|
if err then
|
||||||
|
return {
|
||||||
|
input = input,
|
||||||
|
exitCode = 125,
|
||||||
|
err = err
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
local ok = pcall(fun)
|
||||||
|
if not ok then
|
||||||
|
return {
|
||||||
|
input = input,
|
||||||
|
exitCode = 126,
|
||||||
|
err = err
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
return {
|
||||||
|
input = input,
|
||||||
|
exitCode = 0,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
hilbish.runner.add('hybrid', function(input)
|
hilbish.runner.add('hybrid', function(input)
|
||||||
local cmdStr = hilbish.aliases.resolve(input)
|
local cmdStr = hilbish.aliases.resolve(input)
|
||||||
|
|
||||||
|
@ -1,90 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"hilbish/util"
|
|
||||||
|
|
||||||
rt "github.com/arnodel/golua/runtime"
|
|
||||||
)
|
|
||||||
|
|
||||||
// #interface runner
|
|
||||||
// interactive command runner customization
|
|
||||||
/* 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`.)
|
|
||||||
|
|
||||||
- `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`.
|
|
||||||
|
|
||||||
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)
|
|
||||||
```
|
|
||||||
*/
|
|
||||||
func runnerModeLoader(rtm *rt.Runtime) *rt.Table {
|
|
||||||
exports := map[string]util.LuaExport{
|
|
||||||
"lua": {luaRunner, 1, false},
|
|
||||||
}
|
|
||||||
|
|
||||||
mod := rt.NewTable()
|
|
||||||
util.SetExports(rtm, mod, exports)
|
|
||||||
|
|
||||||
return mod
|
|
||||||
}
|
|
||||||
|
|
||||||
// #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.
|
|
||||||
// #param cmd string
|
|
||||||
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)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
input, exitCode, err := handleLua(cmd)
|
|
||||||
var luaErr rt.Value = rt.NilValue
|
|
||||||
if err != nil {
|
|
||||||
luaErr = rt.StringValue(err.Error())
|
|
||||||
}
|
|
||||||
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)
|
|
||||||
|
|
||||||
return c.PushingNext(t.Runtime, rt.TableValue(runnerRet)), nil
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user