Compare commits

..

No commits in common. "14274a94322b4a5d53c3556655a54d660d182db5" and "0a5a2e727e713a726644d369c72feee79000f786" have entirely different histories.

2 changed files with 169 additions and 234 deletions

334
api.go
View File

@ -7,10 +7,10 @@ import (
"errors" "errors"
"fmt" "fmt"
"os" "os"
"os/exec" // "os/exec"
"runtime" "runtime"
"strings" "strings"
"syscall" // "syscall"
"time" "time"
"hilbish/util" "hilbish/util"
@ -19,28 +19,38 @@ import (
"github.com/arnodel/golua/lib/packagelib" "github.com/arnodel/golua/lib/packagelib"
"github.com/maxlandon/readline" "github.com/maxlandon/readline"
// "github.com/blackfireio/osinfo" // "github.com/blackfireio/osinfo"
"mvdan.cc/sh/v3/interp" // "mvdan.cc/sh/v3/interp"
) )
var exports = map[string]util.LuaExport{ var exports = map[string]util.LuaExport{
"alias": {hlalias, 2, false}, "alias": util.LuaExport{hlalias, 2, false},
"appendPath": {hlappendPath, 1, false}, /*
"complete": {hlcomplete, 2, false}, "appendPath": hlappendPath,
"cwd": {hlcwd, 0, false}, */
"exec": {hlexec, 1, false}, "complete": util.LuaExport{hlcomplete, 2, false},
"runnerMode": {hlrunnerMode, 1, false}, "cwd": util.LuaExport{hlcwd, 0, false},
"goro": {hlgoro, 1, true}, /*
"highlighter": {hlhighlighter, 1, false}, "exec": hlexec,
"hinter": {hlhinter, 1, false}, */
"multiprompt": {hlmultiprompt, 1, false}, "runnerMode": util.LuaExport{hlrunnerMode, 1, false},
"prependPath": {hlprependPath, 1, false}, /*
"prompt": {hlprompt, 1, false}, "goro": hlgoro,
"inputMode": {hlinputMode, 1, false}, */
"interval": {hlinterval, 2, false}, "highlighter": util.LuaExport{hlhighlighter, 1, false},
"read": {hlread, 1, false}, "hinter": util.LuaExport{hlhinter, 1, false},
"run": {hlrun, 1, false}, /*
"timeout": {hltimeout, 2, false}, "multiprompt": hlmlprompt,
"which": {hlwhich, 1, false}, "prependPath": hlprependPath,
*/
"prompt": util.LuaExport{hlprompt, 1, false},
"inputMode": util.LuaExport{hlinputMode, 1, false},
"interval": util.LuaExport{hlinterval, 2, false},
"read": util.LuaExport{hlread, 1, false},
/*
"run": hlrun,
"timeout": hltimeout,
"which": hlwhich,
*/
} }
var greeting string var greeting string
@ -104,23 +114,21 @@ Check out the {blue}{bold}guide{reset} command to get started.
//util.Document(L, aliasesModule, "Alias inferface for Hilbish.") //util.Document(L, aliasesModule, "Alias inferface for Hilbish.")
mod.Set(rt.StringValue("aliases"), rt.TableValue(aliasesModule)) mod.Set(rt.StringValue("aliases"), rt.TableValue(aliasesModule))
/*
// hilbish.history table // hilbish.history table
historyModule := lr.Loader(rtm) historyModule := lr.Loader(L)
//util.Document(L, historyModule, "History interface for Hilbish.") util.Document(L, historyModule, "History interface for Hilbish.")
mod.Set(rt.StringValue("history"), rt.TableValue(historyModule)) L.SetField(mod, "history", historyModule)
// hilbish.completion table // hilbish.completion table
hshcomp := rt.NewTable() hshcomp := L.NewTable()
util.SetField(rtm, hshcomp, "files", util.SetField(L, hshcomp, "files", L.NewFunction(luaFileComplete), "Completer for files")
rt.FunctionValue(rt.NewGoFunction(luaFileComplete, "files", 3, false)), util.SetField(L, hshcomp, "bins", L.NewFunction(luaBinaryComplete), "Completer for executables/binaries")
"Completer for files") util.Document(L, hshcomp, "Completions interface for Hilbish.")
util.SetField(rtm, hshcomp, "bins", L.SetField(mod, "completion", hshcomp)
rt.FunctionValue(rt.NewGoFunction(luaBinaryComplete, "bins", 3, false)),
"Completer for executables/binaries")
//util.Document(L, hshcomp, "Completions interface for Hilbish.")
mod.Set(rt.StringValue("completion"), rt.TableValue(hshcomp))
*/
// hilbish.runner table // hilbish.runner table
runnerModule := runnerModeLoader(rtm) runnerModule := runnerModeLoader(rtm)
//util.Document(L, runnerModule, "Runner/exec interface for Hilbish.") //util.Document(L, runnerModule, "Runner/exec interface for Hilbish.")
@ -143,75 +151,52 @@ func getenv(key, fallback string) string {
return value return value
} }
func luaFileComplete(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { /*
query, ctx, fds, err := getCompleteParams(t, c) func luaFileComplete(L *lua.LState) int {
if err != nil { query := L.CheckString(1)
return nil, err ctx := L.CheckString(2)
} fields := L.CheckTable(3)
completions := fileComplete(query, ctx, fds)
luaComps := rt.NewTable()
for i, comp := range completions {
luaComps.Set(rt.IntValue(int64(i + 1)), rt.StringValue(comp))
}
return c.PushingNext1(t.Runtime, rt.TableValue(luaComps)), nil
}
func luaBinaryComplete(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
query, ctx, fds, err := getCompleteParams(t, c)
if err != nil {
return nil, err
}
completions, _ := binaryComplete(query, ctx, fds)
luaComps := rt.NewTable()
for i, comp := range completions {
luaComps.Set(rt.IntValue(int64(i + 1)), rt.StringValue(comp))
}
return c.PushingNext1(t.Runtime, rt.TableValue(luaComps)), nil
}
func getCompleteParams(t *rt.Thread, c *rt.GoCont) (string, string, []string, error) {
if err := c.CheckNArgs(3); err != nil {
return "", "", []string{}, err
}
query, err := c.StringArg(0)
if err != nil {
return "", "", []string{}, err
}
ctx, err := c.StringArg(1)
if err != nil {
return "", "", []string{}, err
}
fields, err := c.TableArg(2)
if err != nil {
return "", "", []string{}, err
}
var fds []string var fds []string
nextVal := rt.NilValue fields.ForEach(func(k lua.LValue, v lua.LValue) {
for { fds = append(fds, v.String())
next, val, ok := fields.Next(nextVal) })
if next == rt.NilValue {
break
}
nextVal = next
valStr, ok := val.TryString() completions := fileComplete(query, ctx, fds)
if !ok { luaComps := L.NewTable()
continue
for _, comp := range completions {
luaComps.Append(lua.LString(comp))
} }
fds = append(fds, valStr) L.Push(luaComps)
}
return query, ctx, fds, err return 1
} }
func luaBinaryComplete(L *lua.LState) int {
query := L.CheckString(1)
ctx := L.CheckString(2)
fields := L.CheckTable(3)
var fds []string
fields.ForEach(func(k lua.LValue, v lua.LValue) {
fds = append(fds, v.String())
})
completions, _ := binaryComplete(query, ctx, fds)
luaComps := L.NewTable()
for _, comp := range completions {
luaComps.Append(lua.LString(comp))
}
L.Push(luaComps)
return 1
}
*/
func setVimMode(mode string) { func setVimMode(mode string) {
util.SetField(l, hshMod, "vimMode", rt.StringValue(mode), "Current Vim mode of Hilbish (nil if not in Vim mode)") util.SetField(l, hshMod, "vimMode", rt.StringValue(mode), "Current Vim mode of Hilbish (nil if not in Vim mode)")
hooks.Em.Emit("hilbish.vimMode", mode) hooks.Em.Emit("hilbish.vimMode", mode)
@ -221,19 +206,14 @@ func unsetVimMode() {
util.SetField(l, hshMod, "vimMode", rt.NilValue, "Current Vim mode of Hilbish (nil if not in Vim mode)") util.SetField(l, hshMod, "vimMode", rt.NilValue, "Current Vim mode of Hilbish (nil if not in Vim mode)")
} }
/*
// run(cmd) // run(cmd)
// Runs `cmd` in Hilbish's sh interpreter. // Runs `cmd` in Hilbish's sh interpreter.
// --- @param cmd string // --- @param cmd string
func hlrun(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { func hlrun(L *lua.LState) int {
if err := c.Check1Arg(); err != nil {
return nil, err
}
cmd, err := c.StringArg(0)
if err != nil {
return nil, err
}
var exitcode uint8 var exitcode uint8
err = execCommand(cmd) cmd := L.CheckString(1)
err := execCommand(cmd)
if code, ok := interp.IsExitStatus(err); ok { if code, ok := interp.IsExitStatus(err); ok {
exitcode = code exitcode = code
@ -241,8 +221,10 @@ func hlrun(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
exitcode = 1 exitcode = 1
} }
return c.PushingNext1(t.Runtime, rt.IntValue(int64(exitcode))), nil L.Push(lua.LNumber(exitcode))
return 1
} }
*/
// cwd() // cwd()
// Returns the current directory of the shell // Returns the current directory of the shell
@ -304,18 +286,13 @@ func hlprompt(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
// multiprompt(str) // multiprompt(str)
// Changes the continued line prompt to `str` // Changes the continued line prompt to `str`
// --- @param str string // --- @param str string
func hlmultiprompt(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { /*
if err := c.Check1Arg(); err != nil { func hlmlprompt(L *lua.LState) int {
return nil, err multilinePrompt = L.CheckString(1)
}
prompt, err := c.StringArg(0)
if err != nil {
return nil, err
}
multilinePrompt = prompt
return c.Next(), nil return 0
} }
*/
// alias(cmd, orig) // alias(cmd, orig)
// Sets an alias of `cmd` to `orig` // Sets an alias of `cmd` to `orig`
@ -339,39 +316,24 @@ func hlalias(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return c.Next(), nil return c.Next(), nil
} }
/*
// appendPath(dir) // appendPath(dir)
// Appends `dir` to $PATH // Appends `dir` to $PATH
// --- @param dir string|table // --- @param dir string|table
func hlappendPath(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { func hlappendPath(L *lua.LState) int {
if err := c.Check1Arg(); err != nil {
return nil, err
}
arg := c.Arg(0)
// check if dir is a table or a string // check if dir is a table or a string
if arg.Type() == rt.TableType { arg := L.Get(1)
nextVal := rt.NilValue if arg.Type() == lua.LTTable {
for { arg.(*lua.LTable).ForEach(func(k lua.LValue, v lua.LValue) {
next, val, ok := arg.AsTable().Next(nextVal) appendPath(v.String())
if next == rt.NilValue { })
break } else if arg.Type() == lua.LTString {
} appendPath(arg.String())
nextVal = next
valStr, ok := val.TryString()
if !ok {
continue
}
appendPath(valStr)
}
} else if arg.Type() == rt.StringType {
appendPath(arg.AsString())
} else { } else {
return nil, errors.New("bad argument to appendPath (expected string or table, got " + arg.TypeName() + ")") L.RaiseError("bad argument to appendPath (expected string or table, got %v)", L.Get(1).Type().String())
} }
return c.Next(), nil return 0
} }
func appendPath(dir string) { func appendPath(dir string) {
@ -387,14 +349,8 @@ func appendPath(dir string) {
// exec(cmd) // exec(cmd)
// Replaces running hilbish with `cmd` // Replaces running hilbish with `cmd`
// --- @param cmd string // --- @param cmd string
func hlexec(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { func hlexec(L *lua.LState) int {
if err := c.Check1Arg(); err != nil { cmd := L.CheckString(1)
return nil, err
}
cmd, err := c.StringArg(0)
if err != nil {
return nil, err
}
cmdArgs, _ := splitInput(cmd) cmdArgs, _ := splitInput(cmd)
if runtime.GOOS != "windows" { if runtime.GOOS != "windows" {
cmdPath, err := exec.LookPath(cmdArgs[0]) cmdPath, err := exec.LookPath(cmdArgs[0])
@ -416,59 +372,55 @@ func hlexec(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
os.Exit(0) os.Exit(0)
} }
return c.Next(), nil return 0
} }
// goro(fn) // goro(fn)
// Puts `fn` in a goroutine // Puts `fn` in a goroutine
// --- @param fn function // --- @param fn function
func hlgoro(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { func hlgoro(L *lua.LState) int {
if err := c.Check1Arg(); err != nil { fn := L.CheckFunction(1)
return nil, err argnum := L.GetTop()
} args := make([]lua.LValue, argnum)
fn, err := c.ClosureArg(0) for i := 1; i <= argnum; i++ {
if err != nil { args[i - 1] = L.Get(i)
return nil, err
} }
// call fn // call fn
go func() { go func() {
_, err := rt.Call1(l.MainThread(), rt.FunctionValue(fn), c.Etc()...) if err := L.CallByParam(lua.P{
if err != nil { Fn: fn,
NRet: 0,
Protect: true,
}, args...); err != nil {
fmt.Fprintln(os.Stderr, "Error in goro function:\n\n", err) fmt.Fprintln(os.Stderr, "Error in goro function:\n\n", err)
} }
}() }()
return c.Next(), nil return 0
} }
// timeout(cb, time) // timeout(cb, time)
// Runs the `cb` function after `time` in milliseconds // Runs the `cb` function after `time` in milliseconds
// --- @param cb function // --- @param cb function
// --- @param time number // --- @param time number
func hltimeout(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { func hltimeout(L *lua.LState) int {
if err := c.CheckNArgs(2); err != nil { cb := L.CheckFunction(1)
return nil, err ms := L.CheckInt(2)
}
cb, err := c.ClosureArg(0)
if err != nil {
return nil, err
}
ms, err := c.IntArg(1)
if err != nil {
return nil, err
}
timeout := time.Duration(ms) * time.Millisecond timeout := time.Duration(ms) * time.Millisecond
time.Sleep(timeout) time.Sleep(timeout)
_, err = rt.Call1(l.MainThread(), rt.FunctionValue(cb)) if err := L.CallByParam(lua.P{
if err != nil { Fn: cb,
return nil, err NRet: 0,
Protect: true,
}); err != nil {
fmt.Fprintln(os.Stderr, "Error in goro function:\n\n", err)
} }
return 0
return c.Next(), nil
} }
*/
// interval(cb, time) // interval(cb, time)
// Runs the `cb` function every `time` milliseconds // Runs the `cb` function every `time` milliseconds
@ -531,17 +483,12 @@ func hlcomplete(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return c.Next(), nil return c.Next(), nil
} }
/*
// prependPath(dir) // prependPath(dir)
// Prepends `dir` to $PATH // Prepends `dir` to $PATH
// --- @param dir string // --- @param dir string
func hlprependPath(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { func hlprependPath(L *lua.LState) int {
if err := c.Check1Arg(); err != nil { dir := L.CheckString(1)
return nil, err
}
dir, err := c.StringArg(0)
if err != nil {
return nil, err
}
dir = strings.Replace(dir, "~", curuser.HomeDir, 1) dir = strings.Replace(dir, "~", curuser.HomeDir, 1)
pathenv := os.Getenv("PATH") pathenv := os.Getenv("PATH")
@ -550,27 +497,24 @@ func hlprependPath(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
os.Setenv("PATH", dir + string(os.PathListSeparator) + pathenv) os.Setenv("PATH", dir + string(os.PathListSeparator) + pathenv)
} }
return c.Next(), nil return 0
} }
// which(binName) // which(binName)
// Searches for an executable called `binName` in the directories of $PATH // Searches for an executable called `binName` in the directories of $PATH
// --- @param binName string // --- @param binName string
func hlwhich(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { func hlwhich(L *lua.LState) int {
if err := c.Check1Arg(); err != nil { binName := L.CheckString(1)
return nil, err
}
binName, err := c.StringArg(0)
if err != nil {
return nil, err
}
path, err := exec.LookPath(binName) path, err := exec.LookPath(binName)
if err != nil { if err != nil {
return c.Next(), nil l.Push(lua.LNil)
return 1
} }
return c.PushingNext1(t.Runtime, rt.StringValue(path)), nil l.Push(lua.LString(path))
return 1
} }
*/
// inputMode(mode) // inputMode(mode)
// Sets the input mode for Hilbish's line reader. Accepts either emacs for vim // Sets the input mode for Hilbish's line reader. Accepts either emacs for vim

69
rl.go
View File

@ -5,8 +5,6 @@ import (
"io" "io"
"strings" "strings"
"hilbish/util"
"github.com/maxlandon/readline" "github.com/maxlandon/readline"
rt "github.com/arnodel/golua/runtime" rt "github.com/arnodel/golua/runtime"
) )
@ -294,65 +292,58 @@ func (lr *lineReader) Resize() {
} }
// lua module // lua module
func (lr *lineReader) Loader(rtm *rt.Runtime) *rt.Table { /*
lrLua := map[string]util.LuaExport{ func (lr *lineReader) Loader(L *lua.LState) *lua.LTable {
"add": {lr.luaAddHistory, 1, false}, lrLua := map[string]lua.LGFunction{
"all": {lr.luaAllHistory, 0, false}, "add": lr.luaAddHistory,
"clear": {lr.luaClearHistory, 0, false}, "all": lr.luaAllHistory,
"get": {lr.luaGetHistory, 1, false}, "clear": lr.luaClearHistory,
"size": {lr.luaSize, 0, false}, "get": lr.luaGetHistory,
"size": lr.luaSize,
} }
mod := rt.NewTable() mod := l.SetFuncs(l.NewTable(), lrLua)
util.SetExports(rtm, mod, lrLua)
return mod return mod
} }
func (lr *lineReader) luaAddHistory(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { func (lr *lineReader) luaAddHistory(l *lua.LState) int {
if err := c.Check1Arg(); err != nil { cmd := l.CheckString(1)
return nil, err
}
cmd, err := c.StringArg(0)
if err != nil {
return nil, err
}
lr.AddHistory(cmd) lr.AddHistory(cmd)
return c.Next(), nil return 0
} }
func (lr *lineReader) luaSize(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { func (lr *lineReader) luaSize(L *lua.LState) int {
return c.PushingNext1(t.Runtime, rt.IntValue(int64(fileHist.Len()))), nil L.Push(lua.LNumber(fileHist.Len()))
return 1
} }
func (lr *lineReader) luaGetHistory(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { func (lr *lineReader) luaGetHistory(L *lua.LState) int {
if err := c.Check1Arg(); err != nil { idx := L.CheckInt(1)
return nil, err cmd, _ := fileHist.GetLine(idx)
} L.Push(lua.LString(cmd))
idx, err := c.IntArg(0)
if err != nil {
return nil, err
}
cmd, _ := fileHist.GetLine(int(idx)) return 1
return c.PushingNext1(t.Runtime, rt.StringValue(cmd)), nil
} }
func (lr *lineReader) luaAllHistory(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { func (lr *lineReader) luaAllHistory(L *lua.LState) int {
tbl := rt.NewTable() tbl := L.NewTable()
size := fileHist.Len() size := fileHist.Len()
for i := 1; i < size; i++ { for i := 1; i < size; i++ {
cmd, _ := fileHist.GetLine(i) cmd, _ := fileHist.GetLine(i)
tbl.Set(rt.IntValue(int64(i)), rt.StringValue(cmd)) tbl.Append(lua.LString(cmd))
} }
return c.PushingNext1(t.Runtime, rt.TableValue(tbl)), nil L.Push(tbl)
return 1
} }
func (lr *lineReader) luaClearHistory(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { func (lr *lineReader) luaClearHistory(l *lua.LState) int {
fileHist.clear() fileHist.clear()
return c.Next(), nil return 0
} }
*/