mirror of https://github.com/Hilbis/Hilbish
Compare commits
3 Commits
dce02e5310
...
10f6db20d4
Author | SHA1 | Date |
---|---|---|
TorchedSammy | 10f6db20d4 | |
TorchedSammy | e1d4258e07 | |
TorchedSammy | ead72f0a5c |
17
api.go
17
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.completions table
|
// hilbish.completion 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,6 +446,7 @@ 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`.
|
||||||
|
@ -457,15 +458,17 @@ 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(L *lua.LState) int {
|
func hlcomplete(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
scope := L.CheckString(1)
|
scope, cb, err := util.HandleStrCallback(t, c)
|
||||||
cb := L.CheckFunction(2)
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
luaCompletions[scope] = cb
|
luaCompletions[scope] = cb
|
||||||
|
|
||||||
return 0
|
return c.Next(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
// prependPath(dir)
|
// prependPath(dir)
|
||||||
// Prepends `dir` to $PATH
|
// Prepends `dir` to $PATH
|
||||||
// --- @param dir string
|
// --- @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
|
package fs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -8,6 +6,7 @@ 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,76 +5,78 @@ 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{
|
||||||
func Loader(L *lua.LState) int {
|
Load: loaderFunc,
|
||||||
mod := L.SetFuncs(L.NewTable(), exports)
|
Name: "terminal",
|
||||||
util.Document(L, mod, "The terminal library is a simple and lower level library for certain terminal interactions.")
|
|
||||||
|
|
||||||
L.Push(mod)
|
|
||||||
|
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var exports = map[string]lua.LGFunction{
|
func loaderFunc(rtm *rt.Runtime) (rt.Value, func()) {
|
||||||
"setRaw": termraw,
|
exports := map[string]util.LuaExport{
|
||||||
"restoreState": termrestoreState,
|
"setRaw": util.LuaExport{termsetRaw, 0, false},
|
||||||
"size": termsize,
|
"restoreState": util.LuaExport{termrestoreState, 0, false},
|
||||||
"saveState": termsaveState,
|
"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()
|
// 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(L *lua.LState) int {
|
func termsize(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
w, h, err := term.GetSize(int(os.Stdin.Fd()))
|
w, h, err := term.GetSize(int(os.Stdin.Fd()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
L.RaiseError(err.Error())
|
return nil, err
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
dimensions := L.NewTable()
|
|
||||||
L.SetField(dimensions, "width", lua.LNumber(w))
|
|
||||||
L.SetField(dimensions, "height", lua.LNumber(h))
|
|
||||||
|
|
||||||
L.Push(dimensions)
|
dimensions := rt.NewTable()
|
||||||
return 1
|
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()
|
// saveState()
|
||||||
// Saves the current state of the terminal
|
// 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()))
|
state, err := term.GetState(int(os.Stdin.Fd()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
L.RaiseError(err.Error())
|
return nil, err
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
termState = state
|
termState = state
|
||||||
return 0
|
return c.Next(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// restoreState()
|
// restoreState()
|
||||||
// Restores the last saved state of the terminal
|
// 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)
|
err := term.Restore(int(os.Stdin.Fd()), termState)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
L.RaiseError(err.Error())
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0
|
return c.Next(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// setRaw()
|
// setRaw()
|
||||||
// Puts the terminal in raw mode
|
// 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()))
|
_, err := term.MakeRaw(int(os.Stdin.Fd()))
|
||||||
if err != nil {
|
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/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"
|
||||||
)
|
)
|
||||||
|
@ -27,9 +26,7 @@ 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,7 +14,6 @@ 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"
|
||||||
)
|
)
|
||||||
|
@ -24,7 +23,7 @@ var (
|
||||||
lr *lineReader
|
lr *lineReader
|
||||||
|
|
||||||
commands = map[string]*rt.Closure{}
|
commands = map[string]*rt.Closure{}
|
||||||
luaCompletions = map[string]*lua.LFunction{}
|
luaCompletions = map[string]*rt.Closure{}
|
||||||
|
|
||||||
confDir string
|
confDir string
|
||||||
userDataDir string
|
userDataDir string
|
||||||
|
|
109
rl.go
109
rl.go
|
@ -6,6 +6,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/maxlandon/readline"
|
"github.com/maxlandon/readline"
|
||||||
|
rt "github.com/arnodel/golua/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
type lineReader struct {
|
type lineReader struct {
|
||||||
|
@ -17,7 +18,6 @@ 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,6 +93,7 @@ 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
|
||||||
|
@ -124,23 +125,20 @@ 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 := l.NewTable()
|
luaFields := rt.NewTable()
|
||||||
for _, f := range fields {
|
for i, f := range fields {
|
||||||
luaFields.Append(lua.LString(f))
|
luaFields.Set(rt.IntValue(int64(i + 1)), rt.StringValue(f))
|
||||||
}
|
}
|
||||||
err := l.CallByParam(lua.P{
|
|
||||||
Fn: completecb,
|
// we must keep the holy 80 cols
|
||||||
NRet: 1,
|
luacompleteTable, err := rt.Call1(l.MainThread(),
|
||||||
Protect: true,
|
rt.FunctionValue(completecb), rt.StringValue(query),
|
||||||
}, lua.LString(query), lua.LString(ctx), luaFields)
|
rt.StringValue(ctx), rt.TableValue(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:
|
||||||
|
@ -165,41 +163,78 @@ 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 {
|
||||||
if cmpTbl, ok := luacompleteTable.(*lua.LTable); ok {
|
nextVal := rt.NilValue
|
||||||
cmpTbl.ForEach(func(key lua.LValue, value lua.LValue) {
|
for {
|
||||||
if key.Type() == lua.LTNumber {
|
next, val, ok := cmpTbl.Next(nextVal)
|
||||||
// completion group
|
if next == rt.NilValue {
|
||||||
if value.Type() == lua.LTTable {
|
break
|
||||||
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 compItems.Type() != lua.LTTable {
|
nextVal = next
|
||||||
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)
|
||||||
compItems.(*lua.LTable).ForEach(func(k lua.LValue, v lua.LValue) {
|
nxVal := rt.NilValue
|
||||||
if k.Type() == lua.LTString {
|
for {
|
||||||
// ['--flag'] = {'description', '--flag-alias'}
|
nx, vl, _ := compItems.Next(nxVal)
|
||||||
itm := v.(*lua.LTable)
|
if nx == rt.NilValue {
|
||||||
items = append(items, k.String())
|
break
|
||||||
itemDescriptions[k.String()] = itm.RawGet(lua.LNumber(1)).String()
|
}
|
||||||
} else {
|
nxVal = nx
|
||||||
items = append(items, v.String())
|
|
||||||
|
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
|
var dispType readline.TabDisplayType
|
||||||
switch compType.String() {
|
switch compType {
|
||||||
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,
|
||||||
|
@ -209,8 +244,6 @@ func newLineReader(prompt string, noHist bool) *lineReader {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(compGroup) == 0 {
|
if len(compGroup) == 0 {
|
||||||
|
@ -223,7 +256,7 @@ func newLineReader(prompt string, noHist bool) *lineReader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "", compGroup
|
return "", compGroup
|
||||||
}*/
|
}
|
||||||
|
|
||||||
return &lineReader{
|
return &lineReader{
|
||||||
rl,
|
rl,
|
||||||
|
|
Loading…
Reference in New Issue