refactor: use foreach function to loop over lua tables

insensitive-tab^2
TorchedSammy 2022-04-21 14:01:59 -04:00
parent 86aa40af64
commit bd35e3b871
Signed by: sammyette
GPG Key ID: 904FC49417B44DCD
4 changed files with 147 additions and 127 deletions

87
api.go
View File

@ -148,75 +148,6 @@ 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)
if err != nil {
return nil, err
}
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
nextVal := rt.NilValue
for {
next, val, ok := fields.Next(nextVal)
if next == rt.NilValue {
break
}
nextVal = next
valStr, ok := val.TryString()
if !ok {
continue
}
fds = append(fds, valStr)
}
return query, ctx, fds, err
}
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)
@ -395,21 +326,11 @@ func hlappendPath(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
// check if dir is a table or a string // check if dir is a table or a string
if arg.Type() == rt.TableType { if arg.Type() == rt.TableType {
nextVal := rt.NilValue util.ForEach(arg.AsTable(), func(k rt.Value, v rt.Value) {
for { if v.Type() == rt.StringType {
next, val, ok := arg.AsTable().Next(nextVal) appendPath(v.AsString())
if next == rt.NilValue {
break
}
nextVal = next
valStr, ok := val.TryString()
if !ok {
continue
}
appendPath(valStr)
} }
})
} else if arg.Type() == rt.StringType { } else if arg.Type() == rt.StringType {
appendPath(arg.AsString()) appendPath(arg.AsString())
} else { } else {

View File

@ -1,9 +1,14 @@
package main package main
import ( import (
"errors"
"path/filepath" "path/filepath"
"strings" "strings"
"os" "os"
"hilbish/util"
rt "github.com/arnodel/golua/runtime"
) )
func fileComplete(query, ctx string, fields []string) ([]string, string) { func fileComplete(query, ctx string, fields []string) ([]string, string) {
@ -111,3 +116,101 @@ func escapeFilename(fname string) string {
r := strings.NewReplacer(args...) r := strings.NewReplacer(args...)
return r.Replace(fname) return r.Replace(fname)
} }
func callLuaCompleter(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.CheckNArgs(4); err != nil {
return nil, err
}
completer, err := c.StringArg(0)
if err != nil {
return nil, err
}
query, err := c.StringArg(1)
if err != nil {
return nil, err
}
ctx, err := c.StringArg(2)
if err != nil {
return nil, err
}
fields, err := c.TableArg(3)
if err != nil {
return nil, err
}
var completecb *rt.Closure
var ok bool
if completecb, ok = luaCompletions[completer]; !ok {
return nil, errors.New("completer " + completer + " does not exist")
}
// we must keep the holy 80 cols
completerReturn, err := rt.Call1(l.MainThread(),
rt.FunctionValue(completecb), rt.StringValue(query),
rt.StringValue(ctx), rt.TableValue(fields))
if err != nil {
return nil, err
}
return c.PushingNext1(t.Runtime, completerReturn), nil
}
func luaFileComplete(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
query, ctx, fds, err := getCompleteParams(t, c)
if err != nil {
return nil, err
}
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
util.ForEach(fields, func(k rt.Value, v rt.Value) {
if v.Type() == rt.StringType {
fds = append(fds, v.AsString())
}
})
return query, ctx, fds, err
}

70
rl.go
View File

@ -34,8 +34,7 @@ func newLineReader(prompt string, noHist bool) *lineReader {
case readline.VimKeys: modeStr = "normal" case readline.VimKeys: modeStr = "normal"
case readline.VimInsert: modeStr = "insert" case readline.VimInsert: modeStr = "insert"
case readline.VimDelete: modeStr = "delete" case readline.VimDelete: modeStr = "delete"
case readline.VimReplaceOnce: case readline.VimReplaceOnce, readline.VimReplaceMany: modeStr = "replace"
case readline.VimReplaceMany: modeStr = "replace"
} }
setVimMode(modeStr) setVimMode(modeStr)
} }
@ -153,71 +152,54 @@ func newLineReader(prompt string, noHist bool) *lineReader {
to work on subcommands and subcompletions to work on subcommands and subcompletions
*/ */
if cmpTbl, ok := luacompleteTable.TryTable(); ok { if cmpTbl, ok := luacompleteTable.TryTable(); ok {
nextVal := rt.NilValue util.ForEach(cmpTbl, func(key rt.Value, val rt.Value) {
for { if key.Type() != rt.IntType && val.Type() != rt.TableType {
next, val, ok := cmpTbl.Next(nextVal) return
if next == rt.NilValue {
break
}
nextVal = next
_, ok = next.TryInt()
valTbl, okk := val.TryTable()
if !ok || !okk {
// TODO: error?
break
} }
valTbl := val.AsTable()
luaCompType := valTbl.Get(rt.StringValue("type")) luaCompType := valTbl.Get(rt.StringValue("type"))
luaCompItems := valTbl.Get(rt.StringValue("items")) luaCompItems := valTbl.Get(rt.StringValue("items"))
compType, ok := luaCompType.TryString() if luaCompType.Type() != rt.StringType && luaCompItems.Type() != rt.TableType {
compItems, okk := luaCompItems.TryTable() return
if !ok || !okk {
// TODO: error
break
} }
var items []string items := []string{}
itemDescriptions := make(map[string]string) itemDescriptions := make(map[string]string)
nxVal := rt.NilValue
for {
nx, vl, _ := compItems.Next(nxVal)
if nx == rt.NilValue {
break
}
nxVal = nx
if tstr := nx.Type(); tstr == rt.StringType { util.ForEach(luaCompItems.AsTable(), func(lkey rt.Value, lval rt.Value) {
if keytyp := lkey.Type(); keytyp == rt.StringType {
// ['--flag'] = {'description', '--flag-alias'} // ['--flag'] = {'description', '--flag-alias'}
nxStr, ok := nx.TryString() itemName, ok := lkey.TryString()
vlTbl, okk := vl.TryTable() vlTbl, okk := lval.TryTable()
if !ok || !okk { if !ok && !okk {
// TODO: error // TODO: error
continue return
} }
items = append(items, nxStr)
items = append(items, itemName)
itemDescription, ok := vlTbl.Get(rt.IntValue(1)).TryString() itemDescription, ok := vlTbl.Get(rt.IntValue(1)).TryString()
if !ok { if !ok {
// TODO: error // TODO: error
continue return
} }
itemDescriptions[nxStr] = itemDescription itemDescriptions[itemName] = itemDescription
} else if tstr == rt.IntType { } else if keytyp == rt.IntType {
vlStr, okk := vl.TryString() vlStr, ok := lval.TryString()
if !okk { if !ok {
// TODO: error // TODO: error
continue return
} }
items = append(items, vlStr) items = append(items, vlStr)
} else { } else {
// TODO: error // TODO: error
continue return
}
} }
})
var dispType readline.TabDisplayType var dispType readline.TabDisplayType
switch compType { switch luaCompType.AsString() {
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
@ -231,7 +213,7 @@ func newLineReader(prompt string, noHist bool) *lineReader {
TrimSlash: false, TrimSlash: false,
NoSpace: true, NoSpace: true,
}) })
} })
} }
} }

View File

@ -118,3 +118,17 @@ func HandleStrCallback(t *rt.Thread, c *rt.GoCont) (string, *rt.Closure, error)
return name, cb, err return name, cb, err
} }
// ForEach loops through a Lua table.
func ForEach(tbl *rt.Table, cb func(key rt.Value, val rt.Value)) {
nextVal := rt.NilValue
for {
key, val, _ := tbl.Next(nextVal)
if key == rt.NilValue {
break
}
nextVal = key
cb(key, val)
}
}