mirror of
https://github.com/Hilbis/Hilbish
synced 2025-07-01 00:32: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("completions"), rt.TableValue(hshcomp))
|
||||
|
||||
// hilbish.runner table
|
||||
runnerModule := runnerModeLoader(rtm)
|
||||
mod.Set(rt.StringValue("runner"), rt.TableValue(runnerModule))
|
||||
|
||||
// hilbish.jobs table
|
||||
jobs = newJobHandler()
|
||||
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) {
|
||||
// end my suffering
|
||||
// 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 {
|
||||
all := make(map[string]bool)
|
||||
newSlice := []string{}
|
||||
|
@ -1,10 +1,53 @@
|
||||
-- @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 currentRunner = 'hybrid'
|
||||
local runners = {}
|
||||
|
||||
-- lsp shut up
|
||||
hilbish = hilbish
|
||||
hilbish.runner = {}
|
||||
|
||||
--- Get a runner by name.
|
||||
--- @param name string Name of the runner to retrieve.
|
||||
@ -167,6 +210,35 @@ function hilbish.runner.sh(input)
|
||||
return hilbish.snail:run(input)
|
||||
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)
|
||||
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