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