fix!: add complete input to history, including continued input

this introduces a breaking change to runner functions.
they are now required to return 3 values, the first
being the user's input, and the 2 others that it was
before. the `hilbish.runner` functions respectively
have been updated, so if you just return from those
there will be no difference
pull/143/head
TorchedSammy 2022-04-13 10:11:38 -04:00
parent ce625aca0c
commit 626b036b4b
Signed by: sammyette
GPG Key ID: 904FC49417B44DCD
3 changed files with 36 additions and 27 deletions

View File

@ -20,7 +20,7 @@ An example:
hilbish.runnerMode(function(input)
local ok = pcall(fennel.eval, input)
if ok then
return 0, nil
return input, 0, nil
end
return hilbish.runner.sh(input)
@ -28,7 +28,9 @@ end)
The `hilbish.runner` interface is an alternative to using `hilbish.runnerMode`
and also provides the sh and Lua runner functions that Hilbish itself uses.
A runner function is expected to return 2 values: the exit code, and an error.
A runner function is expected to return 3 values: the input, exit code, and an error.
The input return is there incase you need to prompt for more input.
If you don't, just return the input passed to the runner function.
The exit code has to be a number, it will be 0 otherwise and the error can be
`nil` to indicate no error.
@ -36,5 +38,5 @@ The exit code has to be a number, it will be 0 otherwise and the error can be
These are the functions for the `hilbish.runner` interface
+ setMode(mode) > The same as `hilbish.runnerMode`
+ sh(input) -> code, err > Runs `input` in Hilbish's sh interpreter
+ lua(input) -> code, err > Evals `input` as Lua code
+ sh(input) -> input, code, err > Runs `input` in Hilbish's sh interpreter
+ lua(input) -> input, code, err > Evals `input` as Lua code

45
exec.go
View File

@ -32,38 +32,40 @@ func runInput(input string, priv bool) {
cmdString := aliases.Resolve(input)
hooks.Em.Emit("command.preexec", input, cmdString)
var exitCode uint8
var err error
if runnerMode.Type() == rt.StringType {
switch runnerMode.AsString() {
case "hybrid":
_, err := handleLua(cmdString)
_, _, err = handleLua(cmdString)
if err == nil {
cmdFinish(0, input, priv)
return
}
exitCode, err := handleSh(cmdString)
input, exitCode, err = handleSh(cmdString)
if err != nil {
fmt.Fprintln(os.Stderr, err)
}
cmdFinish(exitCode, input, priv)
case "hybridRev":
_, err := handleSh(cmdString)
_, _, err = handleSh(cmdString)
if err == nil {
cmdFinish(0, input, priv)
return
}
exitCode, err := handleLua(cmdString)
input, exitCode, err = handleLua(cmdString)
if err != nil {
fmt.Fprintln(os.Stderr, err)
}
cmdFinish(exitCode, input, priv)
case "lua":
exitCode, err := handleLua(cmdString)
input, exitCode, err = handleLua(cmdString)
if err != nil {
fmt.Fprintln(os.Stderr, err)
}
cmdFinish(exitCode, input, priv)
case "sh":
exitCode, err := handleSh(cmdString)
input, exitCode, err = handleSh(cmdString)
if err != nil {
fmt.Fprintln(os.Stderr, err)
}
@ -79,14 +81,19 @@ func runInput(input string, priv bool) {
return
}
luaexitcode := term.Get(0) // first return value (makes sense right i love stacks)
luaexitcode := term.Get(0)
runErr := term.Get(1)
luaInput := term.Get(1)
var exitCode uint8
if code, ok := luaexitcode.TryInt(); ok {
exitCode = uint8(code)
}
if inp, ok := luaInput.TryString(); ok {
input = inp
}
if runErr != rt.NilValue {
fmt.Fprintln(os.Stderr, runErr)
}
@ -94,7 +101,7 @@ func runInput(input string, priv bool) {
}
}
func handleLua(cmdString string) (uint8, error) {
func handleLua(cmdString string) (string, uint8, error) {
// First try to load input, essentially compiling to bytecode
chunk, err := l.CompileAndLoadLuaChunk("", []byte(cmdString), rt.TableValue(l.GlobalEnv()))
if err != nil && noexecute {
@ -105,7 +112,7 @@ func handleLua(cmdString string) (uint8, error) {
}
}
*/
return 125, err
return cmdString, 125, err
}
// And if there's no syntax errors and -n isnt provided, run
if !noexecute {
@ -114,19 +121,19 @@ func handleLua(cmdString string) (uint8, error) {
}
}
if err == nil {
return 0, nil
return cmdString, 0, nil
}
return 125, err
return cmdString, 125, err
}
func handleSh(cmdString string) (uint8, error) {
func handleSh(cmdString string) (string, uint8, error) {
_, _, err := execCommand(cmdString, true)
if err != nil {
// If input is incomplete, start multiline prompting
if syntax.IsIncomplete(err) {
if !interactive {
return 126, err
return cmdString, 126, err
}
for {
cmdString, err = continuePrompt(strings.TrimSuffix(cmdString, "\\"))
@ -137,23 +144,23 @@ func handleSh(cmdString string) (uint8, error) {
if syntax.IsIncomplete(err) || strings.HasSuffix(cmdString, "\\") {
continue
} else if code, ok := interp.IsExitStatus(err); ok {
return code, nil
return cmdString, code, nil
} else if err != nil {
return 126, err
return cmdString, 126, err
} else {
return 0, nil
return cmdString, 0, nil
}
}
} else {
if code, ok := interp.IsExitStatus(err); ok {
return code, nil
return cmdString, code, nil
} else {
return 126, err
return cmdString, 126, err
}
}
}
return 0, nil
return cmdString, 0, nil
}
// Run command in sh interpreter

View File

@ -28,13 +28,13 @@ func shRunner(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return nil, err
}
exitCode, err := handleSh(cmd)
input, exitCode, err := handleSh(cmd)
var luaErr rt.Value = rt.NilValue
if err != nil {
luaErr = rt.StringValue(err.Error())
}
return c.PushingNext(t.Runtime, rt.IntValue(int64(exitCode)), luaErr), nil
return c.PushingNext(t.Runtime, rt.StringValue(input), rt.IntValue(int64(exitCode)), luaErr), nil
}
func luaRunner(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
@ -46,11 +46,11 @@ func luaRunner(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return nil, err
}
exitCode, err := handleLua(cmd)
input, exitCode, err := handleLua(cmd)
var luaErr rt.Value = rt.NilValue
if err != nil {
luaErr = rt.StringValue(err.Error())
}
return c.PushingNext(t.Runtime, rt.IntValue(int64(exitCode)), luaErr), nil
return c.PushingNext(t.Runtime, rt.StringValue(input), rt.IntValue(int64(exitCode)), luaErr), nil
}