mirror of https://github.com/Hilbis/Hilbish
feat: add interface docs
parent
23d18ef11c
commit
0b1024de19
|
@ -66,8 +66,9 @@ func (a *aliasModule) Resolve(cmdstr string) string {
|
|||
|
||||
// lua section
|
||||
|
||||
// #interface
|
||||
// ALIAS LOADER TEST
|
||||
// #interface aliases
|
||||
// command aliasing
|
||||
// The alias interface deals with all command aliases in Hilbish.
|
||||
func (a *aliasModule) Loader(rtm *rt.Runtime) *rt.Table {
|
||||
// create a lua module with our functions
|
||||
hshaliasesLua := map[string]util.LuaExport{
|
||||
|
@ -83,6 +84,9 @@ func (a *aliasModule) Loader(rtm *rt.Runtime) *rt.Table {
|
|||
return mod
|
||||
}
|
||||
|
||||
// #interface aliases
|
||||
// list()
|
||||
// Get a table of all aliases.
|
||||
func (a *aliasModule) luaList(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||
aliasesList := rt.NewTable()
|
||||
for k, v := range a.All() {
|
||||
|
|
9
api.go
9
api.go
|
@ -250,11 +250,12 @@ func hlcwd(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
|||
}
|
||||
|
||||
|
||||
// read(prompt?) -> input?
|
||||
// read(prompt) -> input
|
||||
// Read input from the user, using Hilbish's line editor/input reader.
|
||||
// This is a separate instance from the one Hilbish actually uses.
|
||||
// Returns `input`, will be nil if ctrl + d is pressed, or an error occurs (which shouldn't happen)
|
||||
// --- @param prompt string
|
||||
// --- @param prompt string|nil
|
||||
// --- @returns string|nil
|
||||
func hlread(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||
luaprompt := c.Arg(0)
|
||||
if typ := luaprompt.Type(); typ != rt.StringType && typ != rt.NilType {
|
||||
|
@ -281,7 +282,7 @@ func hlread(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
|||
}
|
||||
|
||||
/*
|
||||
prompt(str, typ?)
|
||||
prompt(str, typ)
|
||||
Changes the shell prompt to `str`
|
||||
There are a few verbs that can be used in the prompt text.
|
||||
These will be formatted and replaced with the appropriate values.
|
||||
|
@ -289,7 +290,7 @@ These will be formatted and replaced with the appropriate values.
|
|||
`%u` - Name of current user
|
||||
`%h` - Hostname of device
|
||||
--- @param str string
|
||||
--- @param typ string Type of prompt, being left or right. Left by default.
|
||||
--- @param typ string|nil Type of prompt, being left or right. Left by default.
|
||||
*/
|
||||
func hlprompt(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||
err := c.Check1Arg()
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
)
|
||||
|
||||
var header = `---
|
||||
name: Module %s
|
||||
name: %s %s
|
||||
description: %s
|
||||
layout: apidoc
|
||||
---
|
||||
|
@ -21,24 +21,33 @@ layout: apidoc
|
|||
`
|
||||
|
||||
type emmyPiece struct {
|
||||
FuncName string
|
||||
Docs []string
|
||||
DocPiece *docPiece
|
||||
Annotations []string
|
||||
Params []string // we only need to know param name to put in function
|
||||
FuncName string
|
||||
}
|
||||
|
||||
type module struct {
|
||||
Docs []docPiece
|
||||
ShortDescription string
|
||||
Description string
|
||||
Interface bool
|
||||
ParentModule string
|
||||
HasInterfaces bool
|
||||
}
|
||||
|
||||
type docPiece struct {
|
||||
Doc []string
|
||||
FuncSig string
|
||||
FuncName string
|
||||
Interfacing string
|
||||
ParentModule string
|
||||
GoFuncName string
|
||||
IsInterface bool
|
||||
IsMember bool
|
||||
}
|
||||
|
||||
var docs = make(map[string]module)
|
||||
var interfaceDocs = make(map[string]module)
|
||||
var emmyDocs = make(map[string][]emmyPiece)
|
||||
var prefix = map[string]string{
|
||||
"main": "hl",
|
||||
|
@ -50,17 +59,36 @@ var prefix = map[string]string{
|
|||
}
|
||||
|
||||
func setupDoc(mod string, fun *doc.Func) *docPiece {
|
||||
if !strings.HasPrefix(fun.Name, "hl") && mod == "main" {
|
||||
docs := strings.TrimSpace(fun.Doc)
|
||||
inInterface := strings.HasPrefix(docs, "#interface")
|
||||
if (!strings.HasPrefix(fun.Name, prefix[mod]) && !inInterface) || (strings.ToLower(fun.Name) == "loader" && !inInterface) {
|
||||
return nil
|
||||
}
|
||||
if !strings.HasPrefix(fun.Name, prefix[mod]) || fun.Name == "Loader" {
|
||||
return nil
|
||||
|
||||
pts := strings.Split(docs, "\n")
|
||||
parts := []string{}
|
||||
tags := make(map[string][]string)
|
||||
for _, part := range pts {
|
||||
if strings.HasPrefix(part, "#") {
|
||||
tagParts := strings.Split(strings.TrimPrefix(part, "#"), " ")
|
||||
tags[tagParts[0]] = tagParts[1:]
|
||||
} else {
|
||||
parts = append(parts, part)
|
||||
}
|
||||
parts := strings.Split(strings.TrimSpace(fun.Doc), "\n")
|
||||
}
|
||||
|
||||
var interfaces string
|
||||
funcsig := parts[0]
|
||||
doc := parts[1:]
|
||||
funcName := strings.TrimPrefix(fun.Name, prefix[mod])
|
||||
funcdoc := []string{}
|
||||
em := emmyPiece{FuncName: strings.TrimPrefix(fun.Name, prefix[mod])}
|
||||
|
||||
if inInterface {
|
||||
interfaces = tags["interface"][0]
|
||||
funcName = interfaces + "." + strings.Split(funcsig, "(")[0]
|
||||
}
|
||||
em := emmyPiece{FuncName: funcName}
|
||||
|
||||
for _, d := range doc {
|
||||
if strings.HasPrefix(d, "---") {
|
||||
emmyLine := strings.TrimSpace(strings.TrimPrefix(d, "---"))
|
||||
|
@ -72,24 +100,39 @@ func setupDoc(mod string, fun *doc.Func) *docPiece {
|
|||
if emmyType == "@vararg" {
|
||||
em.Params = append(em.Params, "...") // add vararg
|
||||
}
|
||||
em.Docs = append(em.Docs, d)
|
||||
em.Annotations = append(em.Annotations, d)
|
||||
} else {
|
||||
funcdoc = append(funcdoc, d)
|
||||
}
|
||||
}
|
||||
|
||||
dps := docPiece{
|
||||
var isMember bool
|
||||
if tags["member"] != nil {
|
||||
isMember = true
|
||||
}
|
||||
var parentMod string
|
||||
if inInterface {
|
||||
parentMod = mod
|
||||
}
|
||||
dps := &docPiece{
|
||||
Doc: funcdoc,
|
||||
FuncSig: funcsig,
|
||||
FuncName: strings.TrimPrefix(fun.Name, prefix[mod]),
|
||||
FuncName: funcName,
|
||||
Interfacing: interfaces,
|
||||
GoFuncName: strings.ToLower(fun.Name),
|
||||
IsInterface: inInterface,
|
||||
IsMember: isMember,
|
||||
ParentModule: parentMod,
|
||||
}
|
||||
if strings.HasSuffix(dps.GoFuncName, strings.ToLower("loader")) {
|
||||
dps.Doc = parts
|
||||
}
|
||||
em.DocPiece = dps
|
||||
|
||||
emmyDocs[mod] = append(emmyDocs[mod], em)
|
||||
return &dps
|
||||
return dps
|
||||
}
|
||||
|
||||
// feel free to clean this up
|
||||
// it works, dont really care about the code
|
||||
func main() {
|
||||
fset := token.NewFileSet()
|
||||
os.Mkdir("docs", 0777)
|
||||
|
@ -117,21 +160,36 @@ func main() {
|
|||
}
|
||||
}
|
||||
|
||||
interfaceModules := make(map[string]*module)
|
||||
for l, f := range pkgs {
|
||||
p := doc.New(f, "./", doc.AllDecls)
|
||||
pieces := []docPiece{}
|
||||
mod := l
|
||||
if mod == "main" {
|
||||
mod = "hilbish"
|
||||
}
|
||||
var hasInterfaces bool
|
||||
for _, t := range p.Funcs {
|
||||
piece := setupDoc(mod, t)
|
||||
if piece != nil {
|
||||
if piece == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
pieces = append(pieces, *piece)
|
||||
if piece.IsInterface {
|
||||
hasInterfaces = true
|
||||
}
|
||||
}
|
||||
for _, t := range p.Types {
|
||||
for _, m := range t.Methods {
|
||||
piece := setupDoc(mod, m)
|
||||
if piece != nil {
|
||||
if piece == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
pieces = append(pieces, *piece)
|
||||
if piece.IsInterface {
|
||||
hasInterfaces = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -139,27 +197,65 @@ func main() {
|
|||
descParts := strings.Split(strings.TrimSpace(p.Doc), "\n")
|
||||
shortDesc := descParts[0]
|
||||
desc := descParts[1:]
|
||||
filteredPieces := []docPiece{}
|
||||
for _, piece := range pieces {
|
||||
if !piece.IsInterface {
|
||||
filteredPieces = append(filteredPieces, piece)
|
||||
continue
|
||||
}
|
||||
|
||||
modname := piece.ParentModule + "." + piece.Interfacing
|
||||
if interfaceModules[modname] == nil {
|
||||
interfaceModules[modname] = &module{
|
||||
ParentModule: piece.ParentModule,
|
||||
}
|
||||
}
|
||||
|
||||
if strings.HasSuffix(piece.GoFuncName, strings.ToLower("loader")) {
|
||||
shortDesc := piece.Doc[0]
|
||||
desc := piece.Doc[1:]
|
||||
interfaceModules[modname].ShortDescription = shortDesc
|
||||
interfaceModules[modname].Description = strings.Join(desc, "\n")
|
||||
continue
|
||||
}
|
||||
interfaceModules[modname].Docs = append(interfaceModules[modname].Docs, piece)
|
||||
}
|
||||
|
||||
docs[mod] = module{
|
||||
Docs: pieces,
|
||||
Docs: filteredPieces,
|
||||
ShortDescription: shortDesc,
|
||||
Description: strings.Join(desc, "\n"),
|
||||
HasInterfaces: hasInterfaces,
|
||||
}
|
||||
}
|
||||
|
||||
for key, mod := range interfaceModules {
|
||||
docs[key] = *mod
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(len(docs) * 2)
|
||||
|
||||
for mod, v := range docs {
|
||||
modN := mod
|
||||
if mod == "main" {
|
||||
modN = "hilbish"
|
||||
docPath := "docs/api/" + mod + ".md"
|
||||
if v.HasInterfaces {
|
||||
os.Mkdir("docs/api/" + mod, 0777)
|
||||
os.Remove(docPath) // remove old doc path if it exists
|
||||
docPath = "docs/api/" + mod + "/_index.md"
|
||||
}
|
||||
if v.ParentModule != "" {
|
||||
docPath = "docs/api/" + v.ParentModule + "/" + mod + ".md"
|
||||
}
|
||||
|
||||
go func(modName string, modu module) {
|
||||
go func(modname, docPath string, modu module) {
|
||||
defer wg.Done()
|
||||
modOrIface := "Module"
|
||||
if modu.ParentModule != "" {
|
||||
modOrIface = "Interface"
|
||||
}
|
||||
|
||||
f, _ := os.Create("docs/api/" + modName + ".md")
|
||||
f.WriteString(fmt.Sprintf(header, modName, modu.ShortDescription))
|
||||
f, _ := os.Create(docPath)
|
||||
f.WriteString(fmt.Sprintf(header, modOrIface, modname, modu.ShortDescription))
|
||||
f.WriteString(fmt.Sprintf("## Introduction\n%s\n\n## Functions\n", modu.Description))
|
||||
for _, dps := range modu.Docs {
|
||||
f.WriteString(fmt.Sprintf("### %s\n", dps.FuncSig))
|
||||
|
@ -170,28 +266,41 @@ func main() {
|
|||
}
|
||||
f.WriteString("\n")
|
||||
}
|
||||
}(modN, v)
|
||||
}(mod, docPath, v)
|
||||
|
||||
go func(md, modName string) {
|
||||
go func(md, modname string, modu module) {
|
||||
defer wg.Done()
|
||||
|
||||
ff, _ := os.Create("emmyLuaDocs/" + modName + ".lua")
|
||||
ff.WriteString("--- @meta\n\nlocal " + modName + " = {}\n\n")
|
||||
for _, em := range emmyDocs[md] {
|
||||
funcdocs := []string{}
|
||||
for _, dps := range docs[md].Docs {
|
||||
if dps.FuncName == em.FuncName {
|
||||
funcdocs = dps.Doc
|
||||
if modu.ParentModule != "" {
|
||||
return
|
||||
}
|
||||
|
||||
ff, _ := os.Create("emmyLuaDocs/" + modname + ".lua")
|
||||
ff.WriteString("--- @meta\n\nlocal " + modname + " = {}\n\n")
|
||||
for _, em := range emmyDocs[modname] {
|
||||
if strings.HasSuffix(em.DocPiece.GoFuncName, strings.ToLower("loader")) {
|
||||
continue
|
||||
}
|
||||
|
||||
dps := em.DocPiece
|
||||
funcdocs := dps.Doc
|
||||
ff.WriteString("--- " + strings.Join(funcdocs, "\n--- ") + "\n")
|
||||
if len(em.Docs) != 0 {
|
||||
ff.WriteString(strings.Join(em.Docs, "\n") + "\n")
|
||||
if len(em.Annotations) != 0 {
|
||||
ff.WriteString(strings.Join(em.Annotations, "\n") + "\n")
|
||||
}
|
||||
ff.WriteString("function " + modName + "." + em.FuncName + "(" + strings.Join(em.Params, ", ") + ") end\n\n")
|
||||
accessor := "."
|
||||
if dps.IsMember {
|
||||
accessor = ":"
|
||||
}
|
||||
ff.WriteString("return " + modName + "\n")
|
||||
}(mod, modN)
|
||||
signature := strings.Split(dps.FuncSig, " ->")[0]
|
||||
var intrface string
|
||||
if dps.IsInterface {
|
||||
intrface = "." + dps.Interfacing
|
||||
}
|
||||
ff.WriteString("function " + modname + intrface + accessor + signature + " end\n\n")
|
||||
}
|
||||
ff.WriteString("return " + modname + "\n")
|
||||
}(mod, mod, v)
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
|
|
@ -172,6 +172,9 @@ func escapeFilename(fname string) string {
|
|||
return escapeReplaer.Replace(fname)
|
||||
}
|
||||
|
||||
// #interface completions
|
||||
// tab completions
|
||||
// The completions interface deals with tab completions.
|
||||
func completionLoader(rtm *rt.Runtime) *rt.Table {
|
||||
exports := map[string]util.LuaExport{
|
||||
"files": {luaFileComplete, 3, false},
|
||||
|
|
|
@ -1,91 +0,0 @@
|
|||
---
|
||||
name: Module hilbish
|
||||
description: the core Hilbish API
|
||||
layout: apidoc
|
||||
---
|
||||
|
||||
## Introduction
|
||||
The Hilbish module includes the core API, containing
|
||||
interfaces and functions which directly relate to shell functionality.
|
||||
|
||||
## Functions
|
||||
### alias(cmd, orig)
|
||||
Sets an alias of `cmd` to `orig`
|
||||
|
||||
### appendPath(dir)
|
||||
Appends `dir` to $PATH
|
||||
|
||||
### complete(scope, cb)
|
||||
Registers a completion handler for `scope`.
|
||||
A `scope` is currently only expected to be `command.<cmd>`,
|
||||
replacing <cmd> with the name of the command (for example `command.git`).
|
||||
`cb` must be a function that returns a table of "completion groups."
|
||||
Check `doc completions` for more information.
|
||||
|
||||
### cwd()
|
||||
Returns the current directory of the shell
|
||||
|
||||
### exec(cmd)
|
||||
Replaces running hilbish with `cmd`
|
||||
|
||||
### goro(fn)
|
||||
Puts `fn` in a goroutine
|
||||
|
||||
### highlighter(line)
|
||||
Line highlighter handler. This is mainly for syntax highlighting, but in
|
||||
reality could set the input of the prompt to *display* anything. The
|
||||
callback is passed the current line and is expected to return a line that
|
||||
will be used as the input display.
|
||||
|
||||
### hinter(line, pos)
|
||||
The command line hint handler. It gets called on every key insert to
|
||||
determine what text to use as an inline hint. It is passed the current
|
||||
line and cursor position. It is expected to return a string which is used
|
||||
as the text for the hint. This is by default a shim. To set hints,
|
||||
override this function with your custom handler.
|
||||
|
||||
### inputMode(mode)
|
||||
Sets the input mode for Hilbish's line reader. Accepts either emacs or vim
|
||||
|
||||
### interval(cb, time)
|
||||
Runs the `cb` function every `time` milliseconds.
|
||||
Returns a `timer` object (see `doc timers`).
|
||||
|
||||
### multiprompt(str)
|
||||
Changes the continued line prompt to `str`
|
||||
|
||||
### prependPath(dir)
|
||||
Prepends `dir` to $PATH
|
||||
|
||||
### prompt(str, typ?)
|
||||
Changes the shell prompt to `str`
|
||||
There are a few verbs that can be used in the prompt text.
|
||||
These will be formatted and replaced with the appropriate values.
|
||||
`%d` - Current working directory
|
||||
`%u` - Name of current user
|
||||
`%h` - Hostname of device
|
||||
|
||||
### read(prompt?) -> input?
|
||||
Read input from the user, using Hilbish's line editor/input reader.
|
||||
This is a separate instance from the one Hilbish actually uses.
|
||||
Returns `input`, will be nil if ctrl + d is pressed, or an error occurs (which shouldn't happen)
|
||||
|
||||
### run(cmd, returnOut) -> exitCode, stdout, stderr
|
||||
Runs `cmd` in Hilbish's sh interpreter.
|
||||
If returnOut is true, the outputs of `cmd` will be returned as the 2nd and
|
||||
3rd values instead of being outputted to the terminal.
|
||||
|
||||
### runnerMode(mode)
|
||||
Sets the execution/runner mode for interactive Hilbish. This determines whether
|
||||
Hilbish wll try to run input as Lua and/or sh or only do one of either.
|
||||
Accepted values for mode are hybrid (the default), hybridRev (sh first then Lua),
|
||||
sh, and lua. It also accepts a function, to which if it is passed one
|
||||
will call it to execute user input instead.
|
||||
|
||||
### timeout(cb, time)
|
||||
Runs the `cb` function after `time` in milliseconds
|
||||
Returns a `timer` object (see `doc timers`).
|
||||
|
||||
### which(name)
|
||||
Checks if `name` is a valid command
|
||||
|
|
@ -27,6 +27,6 @@ function bait.release(name, catcher) end
|
|||
--- Throws a hook with `name` with the provided `args`
|
||||
--- @param name string
|
||||
--- @vararg any
|
||||
function bait.throw(name, ...) end
|
||||
function bait.throw(name, ...args) end
|
||||
|
||||
return bait
|
||||
|
|
|
@ -8,7 +8,7 @@ function fs.abs(path) end
|
|||
|
||||
--- Gives the basename of `path`. For the rules,
|
||||
--- see Go's filepath.Base
|
||||
function fs.basename() end
|
||||
function fs.basename(path) end
|
||||
|
||||
--- Changes directory to `dir`
|
||||
--- @param dir string
|
||||
|
@ -16,15 +16,15 @@ function fs.cd(dir) end
|
|||
|
||||
--- Returns the directory part of `path`. For the rules, see Go's
|
||||
--- filepath.Dir
|
||||
function fs.dir() end
|
||||
function fs.dir(path) end
|
||||
|
||||
--- Glob all files and directories that match the pattern.
|
||||
--- For the rules, see Go's filepath.Glob
|
||||
function fs.glob() end
|
||||
function fs.glob(pattern) end
|
||||
|
||||
--- Takes paths and joins them together with the OS's
|
||||
--- directory separator (forward or backward slash).
|
||||
function fs.join() end
|
||||
function fs.join(paths...) end
|
||||
|
||||
--- Makes a directory called `name`. If `recursive` is true, it will create its parent directories.
|
||||
--- @param name string
|
||||
|
|
|
@ -73,20 +73,21 @@ function hilbish.prependPath(dir) end
|
|||
--- `%u` - Name of current user
|
||||
--- `%h` - Hostname of device
|
||||
--- @param str string
|
||||
--- @param typ string Type of prompt, being left or right. Left by default.
|
||||
--- @param typ string|nil Type of prompt, being left or right. Left by default.
|
||||
function hilbish.prompt(str, typ) end
|
||||
|
||||
--- Read input from the user, using Hilbish's line editor/input reader.
|
||||
--- This is a separate instance from the one Hilbish actually uses.
|
||||
--- Returns `input`, will be nil if ctrl + d is pressed, or an error occurs (which shouldn't happen)
|
||||
--- @param prompt string
|
||||
--- @param prompt string|nil
|
||||
--- @returns string|nil
|
||||
function hilbish.read(prompt) end
|
||||
|
||||
--- Runs `cmd` in Hilbish's sh interpreter.
|
||||
--- If returnOut is true, the outputs of `cmd` will be returned as the 2nd and
|
||||
--- 3rd values instead of being outputted to the terminal.
|
||||
--- @param cmd string
|
||||
function hilbish.run(cmd) end
|
||||
function hilbish.run(cmd, returnOut) end
|
||||
|
||||
--- Sets the execution/runner mode for interactive Hilbish. This determines whether
|
||||
--- Hilbish wll try to run input as Lua and/or sh or only do one of either.
|
||||
|
@ -105,6 +106,12 @@ function hilbish.timeout(cb, time) end
|
|||
|
||||
--- Checks if `name` is a valid command
|
||||
--- @param binName string
|
||||
function hilbish.which(binName) end
|
||||
function hilbish.which(name) end
|
||||
|
||||
--- Stops a timer.
|
||||
function hilbish.timers:stop() end
|
||||
|
||||
--- Get a table of all aliases.
|
||||
function hilbish.aliases.list() end
|
||||
|
||||
return hilbish
|
||||
|
|
6
rl.go
6
rl.go
|
@ -225,7 +225,11 @@ func (lr *lineReader) Resize() {
|
|||
return
|
||||
}
|
||||
|
||||
// lua module
|
||||
// #interface history
|
||||
// command history
|
||||
// The history interface deals with command history.
|
||||
// This includes the ability to override functions to change the main
|
||||
// method of saving history.
|
||||
func (lr *lineReader) Loader(rtm *rt.Runtime) *rt.Table {
|
||||
lrLua := map[string]util.LuaExport{
|
||||
"add": {lr.luaAddHistory, 1, false},
|
||||
|
|
4
timer.go
4
timer.go
|
@ -91,6 +91,10 @@ func timerStart(thr *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
|||
return c.Next(), nil
|
||||
}
|
||||
|
||||
// #interface timers
|
||||
// #member
|
||||
// stop()
|
||||
// Stops a timer.
|
||||
func timerStop(thr *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||
if err := c.Check1Arg(); err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -100,6 +100,11 @@ func (th *timersModule) luaGet(thr *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
|||
return c.Next(), nil
|
||||
}
|
||||
|
||||
// #interface timers
|
||||
// timeout and interval API
|
||||
// The timers interface si one to easily set timeouts and intervals
|
||||
// to run functions after a certain time or repeatedly without using
|
||||
// odd tricks.
|
||||
func (th *timersModule) loader(rtm *rt.Runtime) *rt.Table {
|
||||
timerMethods := rt.NewTable()
|
||||
timerFuncs := map[string]util.LuaExport{
|
||||
|
|
Loading…
Reference in New Issue