mirror of https://github.com/Hilbis/Hilbish
Compare commits
No commits in common. "10f6db20d4252895e0c06a229e9e9122bd9dc1fd" and "dce02e53106c40fb6ea855daaebc29f3d892b16b" have entirely different histories.
10f6db20d4
...
dce02e5310
19
api.go
19
api.go
|
@ -25,8 +25,8 @@ var exports = map[string]util.LuaExport{
|
||||||
/*
|
/*
|
||||||
"alias": hlalias,
|
"alias": hlalias,
|
||||||
"appendPath": hlappendPath,
|
"appendPath": hlappendPath,
|
||||||
*/
|
"complete": hlcomplete,
|
||||||
"complete": util.LuaExport{hlcomplete, 2, false},
|
*/
|
||||||
"cwd": util.LuaExport{hlcwd, 0, false},
|
"cwd": util.LuaExport{hlcwd, 0, false},
|
||||||
/*
|
/*
|
||||||
"exec": hlexec,
|
"exec": hlexec,
|
||||||
|
@ -121,7 +121,7 @@ Check out the {blue}{bold}guide{reset} command to get started.
|
||||||
util.Document(L, historyModule, "History interface for Hilbish.")
|
util.Document(L, historyModule, "History interface for Hilbish.")
|
||||||
L.SetField(mod, "history", historyModule)
|
L.SetField(mod, "history", historyModule)
|
||||||
|
|
||||||
// hilbish.completion table
|
// hilbish.completions table
|
||||||
hshcomp := L.NewTable()
|
hshcomp := L.NewTable()
|
||||||
|
|
||||||
util.SetField(L, hshcomp, "files", L.NewFunction(luaFileComplete), "Completer for files")
|
util.SetField(L, hshcomp, "files", L.NewFunction(luaFileComplete), "Completer for files")
|
||||||
|
@ -446,7 +446,6 @@ func hlinterval(L *lua.LState) int {
|
||||||
L.Push(lua.LChannel(stop))
|
L.Push(lua.LChannel(stop))
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
// complete(scope, cb)
|
// complete(scope, cb)
|
||||||
// Registers a completion handler for `scope`.
|
// Registers a completion handler for `scope`.
|
||||||
|
@ -458,17 +457,15 @@ func hlinterval(L *lua.LState) int {
|
||||||
// `grid` (the normal file completion display) or `list` (with a description)
|
// `grid` (the normal file completion display) or `list` (with a description)
|
||||||
// --- @param scope string
|
// --- @param scope string
|
||||||
// --- @param cb function
|
// --- @param cb function
|
||||||
func hlcomplete(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func hlcomplete(L *lua.LState) int {
|
||||||
scope, cb, err := util.HandleStrCallback(t, c)
|
scope := L.CheckString(1)
|
||||||
if err != nil {
|
cb := L.CheckFunction(2)
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
luaCompletions[scope] = cb
|
luaCompletions[scope] = cb
|
||||||
|
|
||||||
return c.Next(), nil
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
// prependPath(dir)
|
// prependPath(dir)
|
||||||
// Prepends `dir` to $PATH
|
// Prepends `dir` to $PATH
|
||||||
// --- @param dir string
|
// --- @param dir string
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// The fs module provides easy and simple access to filesystem functions and other
|
||||||
|
// things, and acts an addition to the Lua standard library's I/O and fs functions.
|
||||||
package fs
|
package fs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -6,7 +8,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"hilbish/util"
|
"hilbish/util"
|
||||||
|
|
||||||
rt "github.com/arnodel/golua/runtime"
|
rt "github.com/arnodel/golua/runtime"
|
||||||
"github.com/arnodel/golua/lib/packagelib"
|
"github.com/arnodel/golua/lib/packagelib"
|
||||||
)
|
)
|
||||||
|
|
|
@ -5,78 +5,76 @@ import (
|
||||||
|
|
||||||
"hilbish/util"
|
"hilbish/util"
|
||||||
|
|
||||||
rt "github.com/arnodel/golua/runtime"
|
|
||||||
"github.com/arnodel/golua/lib/packagelib"
|
|
||||||
"golang.org/x/term"
|
"golang.org/x/term"
|
||||||
|
"github.com/yuin/gopher-lua"
|
||||||
)
|
)
|
||||||
|
|
||||||
var termState *term.State
|
var termState *term.State
|
||||||
var Loader = packagelib.Loader{
|
|
||||||
Load: loaderFunc,
|
func Loader(L *lua.LState) int {
|
||||||
Name: "terminal",
|
mod := L.SetFuncs(L.NewTable(), exports)
|
||||||
|
util.Document(L, mod, "The terminal library is a simple and lower level library for certain terminal interactions.")
|
||||||
|
|
||||||
|
L.Push(mod)
|
||||||
|
|
||||||
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func loaderFunc(rtm *rt.Runtime) (rt.Value, func()) {
|
var exports = map[string]lua.LGFunction{
|
||||||
exports := map[string]util.LuaExport{
|
"setRaw": termraw,
|
||||||
"setRaw": util.LuaExport{termsetRaw, 0, false},
|
"restoreState": termrestoreState,
|
||||||
"restoreState": util.LuaExport{termrestoreState, 0, false},
|
"size": termsize,
|
||||||
"size": util.LuaExport{termsize, 0, false},
|
"saveState": termsaveState,
|
||||||
"saveState": util.LuaExport{termsaveState, 0, false},
|
|
||||||
}
|
|
||||||
|
|
||||||
mod := rt.NewTable()
|
|
||||||
util.SetExports(rtm, mod, exports)
|
|
||||||
//util.Document(L, mod, "The terminal library is a simple and lower level library for certain terminal interactions.")
|
|
||||||
|
|
||||||
return rt.TableValue(mod), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// size()
|
// size()
|
||||||
// Gets the dimensions of the terminal. Returns a table with `width` and `height`
|
// Gets the dimensions of the terminal. Returns a table with `width` and `height`
|
||||||
// Note: this is not the size in relation to the dimensions of the display
|
// Note: this is not the size in relation to the dimensions of the display
|
||||||
func termsize(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func termsize(L *lua.LState) int {
|
||||||
w, h, err := term.GetSize(int(os.Stdin.Fd()))
|
w, h, err := term.GetSize(int(os.Stdin.Fd()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
L.RaiseError(err.Error())
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
dimensions := L.NewTable()
|
||||||
|
L.SetField(dimensions, "width", lua.LNumber(w))
|
||||||
|
L.SetField(dimensions, "height", lua.LNumber(h))
|
||||||
|
|
||||||
dimensions := rt.NewTable()
|
L.Push(dimensions)
|
||||||
dimensions.Set(rt.StringValue("width"), rt.IntValue(int64(w)))
|
return 1
|
||||||
dimensions.Set(rt.StringValue("height"), rt.IntValue(int64(h)))
|
|
||||||
|
|
||||||
return c.PushingNext1(t.Runtime, rt.TableValue(dimensions)), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// saveState()
|
// saveState()
|
||||||
// Saves the current state of the terminal
|
// Saves the current state of the terminal
|
||||||
func termsaveState(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func termsaveState(L *lua.LState) int {
|
||||||
state, err := term.GetState(int(os.Stdin.Fd()))
|
state, err := term.GetState(int(os.Stdin.Fd()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
L.RaiseError(err.Error())
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
termState = state
|
termState = state
|
||||||
return c.Next(), nil
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// restoreState()
|
// restoreState()
|
||||||
// Restores the last saved state of the terminal
|
// Restores the last saved state of the terminal
|
||||||
func termrestoreState(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func termrestoreState(L *lua.LState) int {
|
||||||
err := term.Restore(int(os.Stdin.Fd()), termState)
|
err := term.Restore(int(os.Stdin.Fd()), termState)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
L.RaiseError(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.Next(), nil
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// setRaw()
|
// setRaw()
|
||||||
// Puts the terminal in raw mode
|
// Puts the terminal in raw mode
|
||||||
func termsetRaw(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func termraw(L *lua.LState) int {
|
||||||
_, err := term.MakeRaw(int(os.Stdin.Fd()))
|
_, err := term.MakeRaw(int(os.Stdin.Fd()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
L.RaiseError(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.Next(), nil
|
return 0
|
||||||
}
|
}
|
||||||
|
|
7
lua.go
7
lua.go
|
@ -8,8 +8,9 @@ import (
|
||||||
"hilbish/golibs/bait"
|
"hilbish/golibs/bait"
|
||||||
"hilbish/golibs/commander"
|
"hilbish/golibs/commander"
|
||||||
"hilbish/golibs/fs"
|
"hilbish/golibs/fs"
|
||||||
|
/*
|
||||||
"hilbish/golibs/terminal"
|
"hilbish/golibs/terminal"
|
||||||
|
*/
|
||||||
rt "github.com/arnodel/golua/runtime"
|
rt "github.com/arnodel/golua/runtime"
|
||||||
"github.com/arnodel/golua/lib"
|
"github.com/arnodel/golua/lib"
|
||||||
)
|
)
|
||||||
|
@ -26,7 +27,9 @@ func luaInit() {
|
||||||
|
|
||||||
// Add fs and terminal module module to Lua
|
// Add fs and terminal module module to Lua
|
||||||
lib.LoadLibs(l, fs.Loader)
|
lib.LoadLibs(l, fs.Loader)
|
||||||
lib.LoadLibs(l, terminal.Loader)
|
/*
|
||||||
|
l.PreloadModule("terminal", terminal.Loader)
|
||||||
|
*/
|
||||||
|
|
||||||
cmds := commander.New()
|
cmds := commander.New()
|
||||||
// When a command from Lua is added, register it for use
|
// When a command from Lua is added, register it for use
|
||||||
|
|
3
main.go
3
main.go
|
@ -14,6 +14,7 @@ import (
|
||||||
|
|
||||||
rt "github.com/arnodel/golua/runtime"
|
rt "github.com/arnodel/golua/runtime"
|
||||||
"github.com/pborman/getopt"
|
"github.com/pborman/getopt"
|
||||||
|
"github.com/yuin/gopher-lua"
|
||||||
"github.com/maxlandon/readline"
|
"github.com/maxlandon/readline"
|
||||||
"golang.org/x/term"
|
"golang.org/x/term"
|
||||||
)
|
)
|
||||||
|
@ -23,7 +24,7 @@ var (
|
||||||
lr *lineReader
|
lr *lineReader
|
||||||
|
|
||||||
commands = map[string]*rt.Closure{}
|
commands = map[string]*rt.Closure{}
|
||||||
luaCompletions = map[string]*rt.Closure{}
|
luaCompletions = map[string]*lua.LFunction{}
|
||||||
|
|
||||||
confDir string
|
confDir string
|
||||||
userDataDir string
|
userDataDir string
|
||||||
|
|
105
rl.go
105
rl.go
|
@ -6,7 +6,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/maxlandon/readline"
|
"github.com/maxlandon/readline"
|
||||||
rt "github.com/arnodel/golua/runtime"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type lineReader struct {
|
type lineReader struct {
|
||||||
|
@ -18,6 +17,7 @@ var hinter lua.LValue = lua.LNil
|
||||||
var highlighter lua.LValue = lua.LNil
|
var highlighter lua.LValue = lua.LNil
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// other gophers might hate this naming but this is local, shut up
|
||||||
func newLineReader(prompt string, noHist bool) *lineReader {
|
func newLineReader(prompt string, noHist bool) *lineReader {
|
||||||
rl := readline.NewInstance()
|
rl := readline.NewInstance()
|
||||||
// we don't mind hilbish.read rl instances having completion,
|
// we don't mind hilbish.read rl instances having completion,
|
||||||
|
@ -93,7 +93,6 @@ func newLineReader(prompt string, noHist bool) *lineReader {
|
||||||
|
|
||||||
return highlighted
|
return highlighted
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
rl.TabCompleter = func(line []rune, pos int, _ readline.DelayedTabContext) (string, []*readline.CompletionGroup) {
|
rl.TabCompleter = func(line []rune, pos int, _ readline.DelayedTabContext) (string, []*readline.CompletionGroup) {
|
||||||
ctx := string(line)
|
ctx := string(line)
|
||||||
var completions []string
|
var completions []string
|
||||||
|
@ -125,20 +124,23 @@ func newLineReader(prompt string, noHist bool) *lineReader {
|
||||||
return prefix, compGroup
|
return prefix, compGroup
|
||||||
} else {
|
} else {
|
||||||
if completecb, ok := luaCompletions["command." + fields[0]]; ok {
|
if completecb, ok := luaCompletions["command." + fields[0]]; ok {
|
||||||
luaFields := rt.NewTable()
|
luaFields := l.NewTable()
|
||||||
for i, f := range fields {
|
for _, f := range fields {
|
||||||
luaFields.Set(rt.IntValue(int64(i + 1)), rt.StringValue(f))
|
luaFields.Append(lua.LString(f))
|
||||||
}
|
}
|
||||||
|
err := l.CallByParam(lua.P{
|
||||||
// we must keep the holy 80 cols
|
Fn: completecb,
|
||||||
luacompleteTable, err := rt.Call1(l.MainThread(),
|
NRet: 1,
|
||||||
rt.FunctionValue(completecb), rt.StringValue(query),
|
Protect: true,
|
||||||
rt.StringValue(ctx), rt.TableValue(luaFields))
|
}, lua.LString(query), lua.LString(ctx), luaFields)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", compGroup
|
return "", compGroup
|
||||||
}
|
}
|
||||||
|
|
||||||
|
luacompleteTable := l.Get(-1)
|
||||||
|
l.Pop(1)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
as an example with git,
|
as an example with git,
|
||||||
completion table should be structured like:
|
completion table should be structured like:
|
||||||
|
@ -163,78 +165,41 @@ func newLineReader(prompt string, noHist bool) *lineReader {
|
||||||
it is the responsibility of the completer
|
it is the responsibility of the completer
|
||||||
to work on subcommands and subcompletions
|
to work on subcommands and subcompletions
|
||||||
*/
|
*/
|
||||||
if cmpTbl, ok := luacompleteTable.TryTable(); ok {
|
/*
|
||||||
nextVal := rt.NilValue
|
if cmpTbl, ok := luacompleteTable.(*lua.LTable); ok {
|
||||||
for {
|
cmpTbl.ForEach(func(key lua.LValue, value lua.LValue) {
|
||||||
next, val, ok := cmpTbl.Next(nextVal)
|
if key.Type() == lua.LTNumber {
|
||||||
if next == rt.NilValue {
|
// completion group
|
||||||
break
|
if value.Type() == lua.LTTable {
|
||||||
|
luaCmpGroup := value.(*lua.LTable)
|
||||||
|
compType := luaCmpGroup.RawGet(lua.LString("type"))
|
||||||
|
compItems := luaCmpGroup.RawGet(lua.LString("items"))
|
||||||
|
if compType.Type() != lua.LTString {
|
||||||
|
l.RaiseError("bad type name for completion (expected string, got %v)", compType.Type().String())
|
||||||
}
|
}
|
||||||
nextVal = next
|
if compItems.Type() != lua.LTTable {
|
||||||
|
l.RaiseError("bad items for completion (expected table, got %v)", compItems.Type().String())
|
||||||
_, ok = next.TryInt()
|
|
||||||
valTbl, okk := val.TryTable()
|
|
||||||
if !ok || !okk {
|
|
||||||
// TODO: error?
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
luaCompType := valTbl.Get(rt.StringValue("type"))
|
|
||||||
luaCompItems := valTbl.Get(rt.StringValue("items"))
|
|
||||||
|
|
||||||
compType, ok := luaCompType.TryString()
|
|
||||||
compItems, okk := luaCompItems.TryTable()
|
|
||||||
if !ok || !okk {
|
|
||||||
// TODO: error
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
var items []string
|
var items []string
|
||||||
itemDescriptions := make(map[string]string)
|
itemDescriptions := make(map[string]string)
|
||||||
nxVal := rt.NilValue
|
compItems.(*lua.LTable).ForEach(func(k lua.LValue, v lua.LValue) {
|
||||||
for {
|
if k.Type() == lua.LTString {
|
||||||
nx, vl, _ := compItems.Next(nxVal)
|
|
||||||
if nx == rt.NilValue {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
nxVal = nx
|
|
||||||
|
|
||||||
if tstr := nx.Type(); tstr == rt.StringType {
|
|
||||||
// ['--flag'] = {'description', '--flag-alias'}
|
// ['--flag'] = {'description', '--flag-alias'}
|
||||||
nxStr, ok := nx.TryString()
|
itm := v.(*lua.LTable)
|
||||||
vlTbl, okk := vl.TryTable()
|
items = append(items, k.String())
|
||||||
if !ok || !okk {
|
itemDescriptions[k.String()] = itm.RawGet(lua.LNumber(1)).String()
|
||||||
// TODO: error
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
items = append(items, nxStr)
|
|
||||||
itemDescription, ok := vlTbl.Get(rt.IntValue(1)).TryString()
|
|
||||||
if !ok {
|
|
||||||
// TODO: error
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
itemDescriptions[nxStr] = itemDescription
|
|
||||||
} else if tstr == rt.IntType {
|
|
||||||
vlStr, okk := vl.TryString()
|
|
||||||
if !okk {
|
|
||||||
// TODO: error
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
items = append(items, vlStr)
|
|
||||||
} else {
|
} else {
|
||||||
// TODO: error
|
items = append(items, v.String())
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
|
||||||
var dispType readline.TabDisplayType
|
var dispType readline.TabDisplayType
|
||||||
switch compType {
|
switch compType.String() {
|
||||||
case "grid": dispType = readline.TabDisplayGrid
|
case "grid": dispType = readline.TabDisplayGrid
|
||||||
case "list": dispType = readline.TabDisplayList
|
case "list": dispType = readline.TabDisplayList
|
||||||
// need special cases, will implement later
|
// need special cases, will implement later
|
||||||
//case "map": dispType = readline.TabDisplayMap
|
//case "map": dispType = readline.TabDisplayMap
|
||||||
}
|
}
|
||||||
|
|
||||||
compGroup = append(compGroup, &readline.CompletionGroup{
|
compGroup = append(compGroup, &readline.CompletionGroup{
|
||||||
DisplayType: dispType,
|
DisplayType: dispType,
|
||||||
Descriptions: itemDescriptions,
|
Descriptions: itemDescriptions,
|
||||||
|
@ -244,6 +209,8 @@ func newLineReader(prompt string, noHist bool) *lineReader {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(compGroup) == 0 {
|
if len(compGroup) == 0 {
|
||||||
|
@ -256,7 +223,7 @@ func newLineReader(prompt string, noHist bool) *lineReader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "", compGroup
|
return "", compGroup
|
||||||
}
|
}*/
|
||||||
|
|
||||||
return &lineReader{
|
return &lineReader{
|
||||||
rl,
|
rl,
|
||||||
|
|
Loading…
Reference in New Issue