chore: merge from master

hinter-autocomplete
sammyette 2024-12-22 12:07:42 -04:00
commit dbd8cb169a
Signed by: sammyette
GPG Key ID: 904FC49417B44DCD
12 changed files with 110 additions and 76 deletions

View File

@ -1,5 +1,16 @@
# 🎀 Changelog
## Unreleased
### Fixed
- Skip over file and prevent panic if info cannot be retrieved during file completion (due to permission error or anything else)
## [2.3.3] - 2024-11-04
### Fixed
- Heredocs having issues
### Added
- Adding `\` at the end of input will add a newline and prompt for more input.
## [2.3.2] - 2024-07-30
### Fixed
- Command path searching due to 2.3 changes to the shell interpreter
@ -773,7 +784,8 @@ This input for example will prompt for more input to complete:
First "stable" release of Hilbish.
[2.3.1]: https://github.com/Rosettea/Hilbish/compare/v2.3.1...v2.3.2
[2.3.3]: https://github.com/Rosettea/Hilbish/compare/v2.3.2...v2.3.3
[2.3.2]: https://github.com/Rosettea/Hilbish/compare/v2.3.1...v2.3.2
[2.3.1]: https://github.com/Rosettea/Hilbish/compare/v2.3.0...v2.3.1
[2.3.0]: https://github.com/Rosettea/Hilbish/compare/v2.2.3...v2.3.0
[2.2.3]: https://github.com/Rosettea/Hilbish/compare/v2.2.2...v2.2.3

View File

@ -13,19 +13,23 @@
<br>
Hilbish is an extensible shell designed to be highly customizable.
It is configured in Lua and provides a good range of features.
It aims to be easy to use for anyone but powerful enough for
those who need it.
It is configured in Lua, and provides a good range of features.
It aims to be easy to use for anyone, and powerful enough for
those who need more.
The motivation for choosing Lua was that its simpler and better to use
than old shell script. It's fine for basic interactive shell uses,
but that's the only place Hilbish has shell script; everything else is Lua
and aims to be infinitely configurable. If something isn't, open an issue!
than old shell scripts. It's fine for basic interactive shell uses,
and supports [both Lua and Sh interactively](https://rosettea.github.io/Hilbish/docs/features/runner-mode/).
That's the only place Hilbish can use traditional shell syntax though;
everything else is Lua and aims to be infinitely configurable.
If something isn't, open an issue!
# Screenshots
<div align="center">
<img src="gallery/tab.png">
<img src="gallery/pillprompt.png">
</div>
# Getting Hilbish

View File

@ -157,9 +157,12 @@ func matchPath(query string) ([]string, string) {
files, _ := os.ReadDir(path)
for _, entry := range files {
// should we handle errors here?
file, err := entry.Info()
if err == nil && file.Mode() & os.ModeSymlink != 0 {
if err != nil {
continue
}
if file.Mode() & os.ModeSymlink != 0 {
path, err := filepath.EvalSymlinks(filepath.Join(path, file.Name()))
if err == nil {
file, err = os.Lstat(path)

View File

@ -21,16 +21,18 @@ 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): A numerical code to indicate the exit result.
- `input` (string): The user input. This will be used to add
to the history.
- `err` (string): A string to indicate an interal error for the runner.
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 to prompt the user for more input.
- `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.

View File

@ -33,19 +33,6 @@ needs to run interactive input. For more detail, see the [API documentation](../
The `hilbish.runner` interface is an alternative to using `hilbish.runnerMode`
and also provides the shell script and Lua runner functions that Hilbish itself uses.
A runner function is expected to return a table with the following values:
- `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
## Functions
These are the "low level" functions for the `hilbish.runner` interface.

56
exec.go
View File

@ -98,6 +98,7 @@ func runInput(input string, priv bool) {
var exitCode uint8
var err error
var cont bool
var newline bool
// save incase it changes while prompting (For some reason)
currentRunner := runnerMode
if currentRunner.Type() == rt.StringType {
@ -108,9 +109,9 @@ func runInput(input string, priv bool) {
cmdFinish(0, input, priv)
return
}
input, exitCode, cont, err = handleSh(input)
input, exitCode, cont, newline, err = handleSh(input)
case "hybridRev":
_, _, _, err = handleSh(input)
_, _, _, _, err = handleSh(input)
if err == nil {
cmdFinish(0, input, priv)
return
@ -119,12 +120,12 @@ func runInput(input string, priv bool) {
case "lua":
input, exitCode, err = handleLua(input)
case "sh":
input, exitCode, cont, err = handleSh(input)
input, exitCode, cont, newline, err = handleSh(input)
}
} else {
// can only be a string or function so
var runnerErr error
input, exitCode, cont, runnerErr, err = runLuaRunner(currentRunner, input)
input, exitCode, cont, newline, runnerErr, err = runLuaRunner(currentRunner, input)
if err != nil {
fmt.Fprintln(os.Stderr, err)
cmdFinish(124, input, priv)
@ -137,15 +138,15 @@ func runInput(input string, priv bool) {
}
if cont {
input, err = reprompt(input)
input, err = continuePrompt(input, newline)
if err == nil {
goto rerun
} else if err == io.EOF {
return
lr.SetPrompt(fmtPrompt(prompt))
}
}
if err != nil {
if err != nil && err != io.EOF {
if exErr, ok := isExecError(err); ok {
hooks.Emit("command." + exErr.typ, exErr.cmd)
} else {
@ -155,26 +156,28 @@ func runInput(input string, priv bool) {
cmdFinish(exitCode, input, priv)
}
func reprompt(input string) (string, error) {
func reprompt(input string, newline bool) (string, error) {
for {
in, err := continuePrompt(strings.TrimSuffix(input, "\\"))
/*
if strings.HasSuffix(input, "\\") {
input = strings.TrimSuffix(input, "\\") + "\n"
}
*/
in, err := continuePrompt(input, newline)
if err != nil {
lr.SetPrompt(fmtPrompt(prompt))
return input, err
}
if strings.HasSuffix(in, "\\") {
continue
}
return in, nil
}
}
func runLuaRunner(runr rt.Value, userInput string) (input string, exitCode uint8, continued bool, runnerErr, err error) {
func runLuaRunner(runr rt.Value, userInput string) (input string, exitCode uint8, continued bool, newline bool, runnerErr, err error) {
term := rt.NewTerminationWith(l.MainThread().CurrentCont(), 3, false)
err = rt.Call(l.MainThread(), runr, []rt.Value{rt.StringValue(userInput)}, term)
if err != nil {
return "", 124, false, nil, err
return "", 124, false, false, nil, err
}
var runner *rt.Table
@ -202,6 +205,10 @@ func runLuaRunner(runr rt.Value, userInput string) (input string, exitCode uint8
if c, ok := runner.Get(rt.StringValue("continue")).TryBool(); ok {
continued = c
}
if nl, ok := runner.Get(rt.StringValue("newline")).TryBool(); ok {
newline = nl
}
return
}
@ -232,35 +239,40 @@ func handleLua(input string) (string, uint8, error) {
return cmdString, 125, err
}
func handleSh(cmdString string) (input string, exitCode uint8, cont bool, runErr error) {
func handleSh(cmdString string) (input string, exitCode uint8, cont bool, newline bool, runErr error) {
shRunner := hshMod.Get(rt.StringValue("runner")).AsTable().Get(rt.StringValue("sh"))
var err error
input, exitCode, cont, runErr, err = runLuaRunner(shRunner, cmdString)
input, exitCode, cont, newline, runErr, err = runLuaRunner(shRunner, cmdString)
if err != nil {
runErr = err
}
return
}
func execSh(cmdString string) (string, uint8, bool, error) {
func execSh(cmdString string) (input string, exitcode uint8, cont bool, newline bool, e error) {
_, _, err := execCommand(cmdString, nil)
if err != nil {
// If input is incomplete, start multiline prompting
if syntax.IsIncomplete(err) {
if !interactive {
return cmdString, 126, false, err
return cmdString, 126, false, false, err
}
return cmdString, 126, true, err
newline := false
if strings.Contains(err.Error(), "unclosed here-document") {
newline = true
}
return cmdString, 126, true, newline, err
} else {
if code, ok := interp.IsExitStatus(err); ok {
return cmdString, code, false, nil
return cmdString, code, false, false, nil
} else {
return cmdString, 126, false, err
return cmdString, 126, false, false, err
}
}
}
return cmdString, 0, false, nil
return cmdString, 0, false, false, nil
}
// Run command in sh interpreter

2
go.mod
View File

@ -34,4 +34,4 @@ replace github.com/maxlandon/readline => ./readline
replace layeh.com/gopher-luar => github.com/layeh/gopher-luar v1.0.10
replace github.com/arnodel/golua => github.com/Rosettea/golua v0.0.0-20240427174124-d239074c1749
replace github.com/arnodel/golua => github.com/Rosettea/golua v0.0.0-20241104031959-5551ea280f23

4
go.sum
View File

@ -1,5 +1,5 @@
github.com/Rosettea/golua v0.0.0-20240427174124-d239074c1749 h1:jIFnWBTsYw8s7RX7H2AOXjDVhWP3ol7OzUVaPN2KnGI=
github.com/Rosettea/golua v0.0.0-20240427174124-d239074c1749/go.mod h1:9jzpYPiU2is0HVGCiuIOBSXdergHUW44IEjmuN1UrIE=
github.com/Rosettea/golua v0.0.0-20241104031959-5551ea280f23 h1:mUZnT0gmDEmTkqXsbnDbuJ3CNil7DCOMiCQYgjbKIdI=
github.com/Rosettea/golua v0.0.0-20241104031959-5551ea280f23/go.mod h1:9jzpYPiU2is0HVGCiuIOBSXdergHUW44IEjmuN1UrIE=
github.com/Rosettea/sh/v3 v3.4.0-0.dev.0.20240815163633-562273e09b73 h1:zTTUJqNnrF2qf4LgygN8Oae5Uxn6ewH0hA8jyTCHfXw=
github.com/Rosettea/sh/v3 v3.4.0-0.dev.0.20240815163633-562273e09b73/go.mod h1:YZalN5H7WNQw3DGij6IvHsEhn5YMW7M2FCwG6gnfKy4=
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=

17
main.go
View File

@ -223,8 +223,9 @@ input:
}
if strings.HasSuffix(input, "\\") {
print("\n")
for {
input, err = continuePrompt(input)
input, err = continuePrompt(strings.TrimSuffix(input, "\\") + "\n", false)
if err != nil {
running = true
lr.SetPrompt(fmtPrompt(prompt))
@ -248,16 +249,24 @@ input:
exit(0)
}
func continuePrompt(prev string) (string, error) {
func continuePrompt(prev string, newline bool) (string, error) {
hooks.Emit("multiline", nil)
lr.SetPrompt(multilinePrompt)
cont, err := lr.Read()
if err != nil {
return "", err
}
cont = strings.TrimSpace(cont)
return prev + strings.TrimSuffix(cont, "\n"), nil
if newline {
cont = "\n" + cont
}
if strings.HasSuffix(cont, "\\") {
cont = strings.TrimSuffix(cont, "\\") + "\n"
}
return prev + cont, nil
}
// This semi cursed function formats our prompt (obviously)

View File

@ -2,7 +2,9 @@ local bait = require 'bait'
local lunacolors = require 'lunacolors'
hilbish.motd = [[
{magenta}Hilbish{reset} blooms in the {blue}midnight.{reset}
Wait ... {magenta}2.3{reset} is basically the same as {red}2.2?{reset}
Erm.. {blue}Ctrl-C works for Commanders,{reset} {cyan}and the sh runner has some fixes.{reset}
Just trust me bro, this is an important bug fix release. {red}- 🌺 sammyette{reset}
]]
bait.catch('hilbish.init', function()

View File

@ -21,16 +21,18 @@ 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): A numerical code to indicate the exit result.
- `input` (string): The user input. This will be used to add
to the history.
- `err` (string): A string to indicate an interal error for the runner.
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 to prompt the user for more input.
- `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.
@ -85,7 +87,7 @@ func shRunner(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return nil, err
}
_, exitCode, cont, err := execSh(aliases.Resolve(cmd))
_, exitCode, cont, newline, err := execSh(aliases.Resolve(cmd))
var luaErr rt.Value = rt.NilValue
if err != nil {
luaErr = rt.StringValue(err.Error())
@ -94,6 +96,7 @@ func shRunner(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
runnerRet.Set(rt.StringValue("input"), rt.StringValue(cmd))
runnerRet.Set(rt.StringValue("exitCode"), rt.IntValue(int64(exitCode)))
runnerRet.Set(rt.StringValue("continue"), rt.BoolValue(cont))
runnerRet.Set(rt.StringValue("newline"), rt.BoolValue(newline))
runnerRet.Set(rt.StringValue("err"), luaErr)
return c.PushingNext(t.Runtime, rt.TableValue(runnerRet)), nil

View File

@ -11,8 +11,8 @@ var (
// Version info
var (
ver = "v2.4.0"
releaseName = "Moonflower"
ver = "v2.3.3"
releaseName = "Alyssum"
gitCommit string
gitBranch string