mirror of https://github.com/Hilbis/Hilbish
Compare commits
3 Commits
c87fbe2b99
...
f97a04179d
Author | SHA1 | Date |
---|---|---|
sammyette | f97a04179d | |
sammyette | 2f6ab5fd92 | |
sammyette | 088e326bd1 |
|
@ -4,9 +4,11 @@
|
||||||
### Added
|
### Added
|
||||||
- Documented custom userdata types (Job and Timer Objects)
|
- Documented custom userdata types (Job and Timer Objects)
|
||||||
- Coming with fix is also adding the return types for some functions that were missing it
|
- Coming with fix is also adding the return types for some functions that were missing it
|
||||||
|
- Added a dedicated input and dedicated outputs for commanders.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- `hilbish.which` not working correctly with aliases
|
- `hilbish.which` not working correctly with aliases
|
||||||
|
- Commanders not being able to pipe with commands or any related operator.
|
||||||
|
|
||||||
## [2.0.1] - 2022-12-28
|
## [2.0.1] - 2022-12-28
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2022 Rosettea
|
Copyright (c) 2021-2023 Rosettea
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
@ -414,7 +414,14 @@ func main() {
|
||||||
|
|
||||||
f, _ := os.Create(docPath)
|
f, _ := os.Create(docPath)
|
||||||
f.WriteString(fmt.Sprintf(header, modOrIface, modname, modu.ShortDescription))
|
f.WriteString(fmt.Sprintf(header, modOrIface, modname, modu.ShortDescription))
|
||||||
f.WriteString(fmt.Sprintf("## Introduction\n%s\n\n", modu.Description))
|
typeTag, _ := regexp.Compile(`@\w+`)
|
||||||
|
modDescription := typeTag.ReplaceAllStringFunc(strings.Replace(modu.Description, "<", `\<`, -1), func(typ string) string {
|
||||||
|
typName := typ[1:]
|
||||||
|
typLookup := typeTable[strings.ToLower(typName)]
|
||||||
|
linkedTyp := fmt.Sprintf("/Hilbish/docs/api/%s/%s/#%s", typLookup[0], typLookup[0] + "." + typLookup[1], strings.ToLower(typName))
|
||||||
|
return fmt.Sprintf(`<a href="%s" style="text-decoration: none;">%s</a>`, linkedTyp, typName)
|
||||||
|
})
|
||||||
|
f.WriteString(fmt.Sprintf("## Introduction\n%s\n\n", modDescription))
|
||||||
if len(modu.Fields) != 0 {
|
if len(modu.Fields) != 0 {
|
||||||
f.WriteString("## Interface fields\n")
|
f.WriteString("## Interface fields\n")
|
||||||
for _, dps := range modu.Fields {
|
for _, dps := range modu.Fields {
|
||||||
|
@ -435,7 +442,6 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(modu.Docs) != 0 {
|
if len(modu.Docs) != 0 {
|
||||||
typeTag, _ := regexp.Compile(`@\w+`)
|
|
||||||
f.WriteString("## Functions\n")
|
f.WriteString("## Functions\n")
|
||||||
for _, dps := range modu.Docs {
|
for _, dps := range modu.Docs {
|
||||||
if dps.IsMember {
|
if dps.IsMember {
|
||||||
|
@ -475,8 +481,6 @@ func main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f.WriteString("\n")
|
f.WriteString("\n")
|
||||||
typeTag, _ := regexp.Compile(`@\w+`)
|
|
||||||
|
|
||||||
f.WriteString("### Methods\n")
|
f.WriteString("### Methods\n")
|
||||||
for _, dps := range modu.Docs {
|
for _, dps := range modu.Docs {
|
||||||
if !dps.IsMember {
|
if !dps.IsMember {
|
||||||
|
|
|
@ -8,7 +8,41 @@ menu:
|
||||||
---
|
---
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
Commander is a library for writing custom commands in Lua.
|
Commander is a library for writing custom commands in Lua.
|
||||||
|
In order to make it easier to write commands for Hilbish,
|
||||||
|
not require separate scripts and to be able to use in a config,
|
||||||
|
the Commander library exists. This is like a very simple wrapper
|
||||||
|
that works with Hilbish for writing commands. Example:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
local commander = require 'commander'
|
||||||
|
|
||||||
|
commander.register('hello', function(args, sinks)
|
||||||
|
sinks.out:writeln 'Hello world!'
|
||||||
|
end)
|
||||||
|
```
|
||||||
|
|
||||||
|
In this example, a command with the name of `hello` is created
|
||||||
|
that will print `Hello world!` to output. One question you may
|
||||||
|
have is: What is the `sinks` parameter?
|
||||||
|
|
||||||
|
A sink is a writable/readable pipe, or you can imagine a Lua
|
||||||
|
file. It's used in this case to write to the proper output,
|
||||||
|
incase a user either pipes to another command or redirects somewhere else.
|
||||||
|
|
||||||
|
So, the `sinks` parameter is a table containing 3 sinks:
|
||||||
|
`in`, `out`, and `err`.
|
||||||
|
- `in` is the standard input. You can read from this sink
|
||||||
|
to get user input. (**This is currently unimplemented.**)
|
||||||
|
- `out` is standard output. This is usually where text meant for
|
||||||
|
output should go.
|
||||||
|
- `err` is standard error. This sink is for writing errors, as the
|
||||||
|
name would suggest.
|
||||||
|
|
||||||
|
A sink has 2 methods:
|
||||||
|
- `write(str)` will write to the sink.
|
||||||
|
- `writeln(str)` will write to the sink with a newline at the end.
|
||||||
|
|
||||||
## Functions
|
## Functions
|
||||||
### deregister(name)
|
### deregister(name)
|
||||||
|
|
13
exec.go
13
exec.go
|
@ -323,8 +323,18 @@ func execHandle(bg bool) interp.ExecHandlerFunc {
|
||||||
luacmdArgs.Set(rt.IntValue(int64(i + 1)), rt.StringValue(str))
|
luacmdArgs.Set(rt.IntValue(int64(i + 1)), rt.StringValue(str))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hc := interp.HandlerCtx(ctx)
|
||||||
if commands[args[0]] != nil {
|
if commands[args[0]] != nil {
|
||||||
luaexitcode, err := rt.Call1(l.MainThread(), rt.FunctionValue(commands[args[0]]), rt.TableValue(luacmdArgs))
|
stdin := newSinkInput(hc.Stdin)
|
||||||
|
stdout := newSinkOutput(hc.Stdout)
|
||||||
|
stderr := newSinkOutput(hc.Stderr)
|
||||||
|
|
||||||
|
sinks := rt.NewTable()
|
||||||
|
sinks.Set(rt.StringValue("in"), rt.UserDataValue(stdin.ud))
|
||||||
|
sinks.Set(rt.StringValue("out"), rt.UserDataValue(stdout.ud))
|
||||||
|
sinks.Set(rt.StringValue("err"), rt.UserDataValue(stderr.ud))
|
||||||
|
|
||||||
|
luaexitcode, err := rt.Call1(l.MainThread(), rt.FunctionValue(commands[args[0]]), rt.TableValue(luacmdArgs), rt.TableValue(sinks))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintln(os.Stderr, "Error in command:\n" + err.Error())
|
fmt.Fprintln(os.Stderr, "Error in command:\n" + err.Error())
|
||||||
return interp.NewExitStatus(1)
|
return interp.NewExitStatus(1)
|
||||||
|
@ -364,7 +374,6 @@ func execHandle(bg bool) interp.ExecHandlerFunc {
|
||||||
killTimeout := 2 * time.Second
|
killTimeout := 2 * time.Second
|
||||||
// from here is basically copy-paste of the default exec handler from
|
// from here is basically copy-paste of the default exec handler from
|
||||||
// sh/interp but with our job handling
|
// sh/interp but with our job handling
|
||||||
hc := interp.HandlerCtx(ctx)
|
|
||||||
path, err := interp.LookPathDir(hc.Dir, hc.Env, args[0])
|
path, err := interp.LookPathDir(hc.Dir, hc.Env, args[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintln(hc.Stderr, err)
|
fmt.Fprintln(hc.Stderr, err)
|
||||||
|
|
|
@ -1,5 +1,40 @@
|
||||||
// library for custom commands
|
// library for custom commands
|
||||||
// Commander is a library for writing custom commands in Lua.
|
/*
|
||||||
|
Commander is a library for writing custom commands in Lua.
|
||||||
|
In order to make it easier to write commands for Hilbish,
|
||||||
|
not require separate scripts and to be able to use in a config,
|
||||||
|
the Commander library exists. This is like a very simple wrapper
|
||||||
|
that works with Hilbish for writing commands. Example:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
local commander = require 'commander'
|
||||||
|
|
||||||
|
commander.register('hello', function(args, sinks)
|
||||||
|
sinks.out:writeln 'Hello world!'
|
||||||
|
end)
|
||||||
|
```
|
||||||
|
|
||||||
|
In this example, a command with the name of `hello` is created
|
||||||
|
that will print `Hello world!` to output. One question you may
|
||||||
|
have is: What is the `sinks` parameter?
|
||||||
|
|
||||||
|
A sink is a writable/readable pipe, or you can imagine a Lua
|
||||||
|
file. It's used in this case to write to the proper output,
|
||||||
|
incase a user either pipes to another command or redirects somewhere else.
|
||||||
|
|
||||||
|
So, the `sinks` parameter is a table containing 3 sinks:
|
||||||
|
`in`, `out`, and `err`.
|
||||||
|
- `in` is the standard input. You can read from this sink
|
||||||
|
to get user input. (**This is currently unimplemented.**)
|
||||||
|
- `out` is standard output. This is usually where text meant for
|
||||||
|
output should go.
|
||||||
|
- `err` is standard error. This sink is for writing errors, as the
|
||||||
|
name would suggest.
|
||||||
|
|
||||||
|
A sink has 2 methods:
|
||||||
|
- `write(str)` will write to the sink.
|
||||||
|
- `writeln(str)` will write to the sink with a newline at the end.
|
||||||
|
*/
|
||||||
package commander
|
package commander
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
1
lua.go
1
lua.go
|
@ -23,6 +23,7 @@ func luaInit() {
|
||||||
MessageHandler: debuglib.Traceback,
|
MessageHandler: debuglib.Traceback,
|
||||||
})
|
})
|
||||||
lib.LoadAll(l)
|
lib.LoadAll(l)
|
||||||
|
setupSinkType(l)
|
||||||
|
|
||||||
lib.LoadLibs(l, hilbishLoader)
|
lib.LoadLibs(l, hilbishLoader)
|
||||||
// yes this is stupid, i know
|
// yes this is stupid, i know
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
local commander = require 'commander'
|
local commander = require 'commander'
|
||||||
|
|
||||||
commander.register('bg', function()
|
commander.register('bg', function(_, sinks)
|
||||||
local job = hilbish.jobs.last()
|
local job = hilbish.jobs.last()
|
||||||
if not job then
|
if not job then
|
||||||
print 'bg: no last job'
|
sinks.out:writeln 'bg: no last job'
|
||||||
return 1
|
return 1
|
||||||
end
|
end
|
||||||
|
|
||||||
local err = job.background()
|
local err = job.background()
|
||||||
if err then
|
if err then
|
||||||
print('bg: ' .. err)
|
sinks.out:writeln('bg: ' .. err)
|
||||||
return 2
|
return 2
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
local commander = require 'commander'
|
local commander = require 'commander'
|
||||||
local fs = require 'fs'
|
local fs = require 'fs'
|
||||||
|
|
||||||
commander.register('cat', function(args)
|
commander.register('cat', function(args, sinks)
|
||||||
local exit = 0
|
local exit = 0
|
||||||
|
|
||||||
if #args == 0 then
|
if #args == 0 then
|
||||||
print [[
|
sinks.out:writeln [[
|
||||||
usage: cat [file]...]]
|
usage: cat [file]...]]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -13,11 +13,11 @@ usage: cat [file]...]]
|
||||||
local f = io.open(fName)
|
local f = io.open(fName)
|
||||||
if f == nil then
|
if f == nil then
|
||||||
exit = 1
|
exit = 1
|
||||||
print(string.format('cat: %s: no such file or directory', fName))
|
sinks.out:writeln(string.format('cat: %s: no such file or directory', fName))
|
||||||
goto continue
|
goto continue
|
||||||
end
|
end
|
||||||
|
|
||||||
io.write(f:read '*a')
|
sinks.out:writeln(f:read '*a')
|
||||||
::continue::
|
::continue::
|
||||||
end
|
end
|
||||||
io.flush()
|
io.flush()
|
||||||
|
|
|
@ -4,16 +4,16 @@ local fs = require 'fs'
|
||||||
local dirs = require 'nature.dirs'
|
local dirs = require 'nature.dirs'
|
||||||
|
|
||||||
dirs.old = hilbish.cwd()
|
dirs.old = hilbish.cwd()
|
||||||
commander.register('cd', function (args)
|
commander.register('cd', function (args, sinks)
|
||||||
if #args > 1 then
|
if #args > 1 then
|
||||||
print("cd: too many arguments")
|
sinks.out:writeln("cd: too many arguments")
|
||||||
return 1
|
return 1
|
||||||
end
|
end
|
||||||
|
|
||||||
local path = args[1] and args[1] or hilbish.home
|
local path = args[1] and args[1] or hilbish.home
|
||||||
if path == '-' then
|
if path == '-' then
|
||||||
path = dirs.old
|
path = dirs.old
|
||||||
print(path)
|
sinks.out:writeln(path)
|
||||||
end
|
end
|
||||||
|
|
||||||
dirs.setOld(hilbish.cwd())
|
dirs.setOld(hilbish.cwd())
|
||||||
|
@ -21,7 +21,7 @@ commander.register('cd', function (args)
|
||||||
|
|
||||||
local ok, err = pcall(function() fs.cd(path) end)
|
local ok, err = pcall(function() fs.cd(path) end)
|
||||||
if not ok then
|
if not ok then
|
||||||
print(err)
|
sinks.out:writeln(err)
|
||||||
return 1
|
return 1
|
||||||
end
|
end
|
||||||
bait.throw('cd', path)
|
bait.throw('cd', path)
|
||||||
|
|
|
@ -3,9 +3,9 @@ local fs = require 'fs'
|
||||||
local lunacolors = require 'lunacolors'
|
local lunacolors = require 'lunacolors'
|
||||||
local dirs = require 'nature.dirs'
|
local dirs = require 'nature.dirs'
|
||||||
|
|
||||||
commander.register('cdr', function(args)
|
commander.register('cdr', function(args, sinks)
|
||||||
if not args[1] then
|
if not args[1] then
|
||||||
print(lunacolors.format [[
|
sinks.out:writeln(lunacolors.format [[
|
||||||
cdr: change directory to one which has been recently visied
|
cdr: change directory to one which has been recently visied
|
||||||
|
|
||||||
usage: cdr <index>
|
usage: cdr <index>
|
||||||
|
@ -17,21 +17,21 @@ to get a list of recent directories, use {green}{underline}cdr list{reset}]])
|
||||||
if args[1] == 'list' then
|
if args[1] == 'list' then
|
||||||
local recentDirs = dirs.recentDirs
|
local recentDirs = dirs.recentDirs
|
||||||
if #recentDirs == 0 then
|
if #recentDirs == 0 then
|
||||||
print 'No directories have been visited.'
|
sinks.out:writeln 'No directories have been visited.'
|
||||||
return 1
|
return 1
|
||||||
end
|
end
|
||||||
print(table.concat(recentDirs, '\n'))
|
sinks.out:writeln(table.concat(recentDirs, '\n'))
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local index = tonumber(args[1])
|
local index = tonumber(args[1])
|
||||||
if not index then
|
if not index then
|
||||||
print(string.format('Received %s as index, which isn\'t a number.', index))
|
sinks.out:writeln(string.format('Received %s as index, which isn\'t a number.', index))
|
||||||
return 1
|
return 1
|
||||||
end
|
end
|
||||||
|
|
||||||
if not dirs.recent(index) then
|
if not dirs.recent(index) then
|
||||||
print(string.format('No recent directory found at index %s.', index))
|
sinks.out:writeln(string.format('No recent directory found at index %s.', index))
|
||||||
return 1
|
return 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
local commander = require 'commander'
|
local commander = require 'commander'
|
||||||
|
|
||||||
commander.register('disown', function(args)
|
commander.register('disown', function(args, sinks)
|
||||||
if #hilbish.jobs.all() == 0 then
|
if #hilbish.jobs.all() == 0 then
|
||||||
print 'disown: no current job'
|
sinks.out:writeln 'disown: no current job'
|
||||||
return 1
|
return 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ commander.register('disown', function(args)
|
||||||
if #args < 0 then
|
if #args < 0 then
|
||||||
id = tonumber(args[1])
|
id = tonumber(args[1])
|
||||||
if not id then
|
if not id then
|
||||||
print 'disown: invalid id for job'
|
sinks.out:writeln 'disown: invalid id for job'
|
||||||
return 1
|
return 1
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
@ -19,7 +19,7 @@ commander.register('disown', function(args)
|
||||||
|
|
||||||
local ok = pcall(hilbish.jobs.disown, id)
|
local ok = pcall(hilbish.jobs.disown, id)
|
||||||
if not ok then
|
if not ok then
|
||||||
print 'disown: job does not exist'
|
sinks.out:writeln 'disown: job does not exist'
|
||||||
return 2
|
return 2
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
|
@ -2,7 +2,7 @@ local commander = require 'commander'
|
||||||
local fs = require 'fs'
|
local fs = require 'fs'
|
||||||
local lunacolors = require 'lunacolors'
|
local lunacolors = require 'lunacolors'
|
||||||
|
|
||||||
commander.register('doc', function(args)
|
commander.register('doc', function(args, sinks)
|
||||||
local moddocPath = hilbish.dataDir .. '/docs/'
|
local moddocPath = hilbish.dataDir .. '/docs/'
|
||||||
local stat = fs.stat '.git/refs/heads/extended-job-api'
|
local stat = fs.stat '.git/refs/heads/extended-job-api'
|
||||||
if stat then
|
if stat then
|
||||||
|
@ -48,16 +48,16 @@ Available sections: ]] .. table.concat(modules, ', ')
|
||||||
f = io.open(moddocPath .. subdocName .. '.md', 'rb')
|
f = io.open(moddocPath .. subdocName .. '.md', 'rb')
|
||||||
end
|
end
|
||||||
if not f then
|
if not f then
|
||||||
print('No documentation found for ' .. mod .. '.')
|
sinks.out:writeln('No documentation found for ' .. mod .. '.')
|
||||||
return 1
|
return 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
funcdocs = f:read '*a':gsub('-([%d]+)', '%1')
|
funcdocs = f:read '*a':gsub('-([%d]+)', '%1')
|
||||||
local moddocs = table.filter(fs.readdir(moddocPath), function(f) return f ~= '_index.md' or f ~= 'index.md' end)
|
local moddocs = table.filter(fs.readdir(moddocPath), function(f) return f ~= '_index.md' and f ~= 'index.md' end)
|
||||||
local subdocs = table.map(moddocs, function(fname)
|
local subdocs = table.map(moddocs, function(fname)
|
||||||
return lunacolors.underline(lunacolors.blue(string.gsub(fname, '.md', '')))
|
return lunacolors.underline(lunacolors.blue(string.gsub(fname, '.md', '')))
|
||||||
end)
|
end)
|
||||||
if subdocName == '_index' then
|
if #moddocs ~= 0 then
|
||||||
funcdocs = funcdocs .. '\nSubdocs: ' .. table.concat(subdocs, ', ')
|
funcdocs = funcdocs .. '\nSubdocs: ' .. table.concat(subdocs, ', ')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ Available sections: ]] .. table.concat(modules, ', ')
|
||||||
end
|
end
|
||||||
|
|
||||||
local backtickOccurence = 0
|
local backtickOccurence = 0
|
||||||
print(lunacolors.format(doc:gsub('`', function()
|
sinks.out:writeln(lunacolors.format(doc:gsub('`', function()
|
||||||
backtickOccurence = backtickOccurence + 1
|
backtickOccurence = backtickOccurence + 1
|
||||||
if backtickOccurence % 2 == 0 then
|
if backtickOccurence % 2 == 0 then
|
||||||
return '{reset}'
|
return '{reset}'
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
local commander = require 'commander'
|
local commander = require 'commander'
|
||||||
|
|
||||||
commander.register('fg', function()
|
commander.register('fg', function(_, sinks)
|
||||||
local job = hilbish.jobs.last()
|
local job = hilbish.jobs.last()
|
||||||
if not job then
|
if not job then
|
||||||
print 'fg: no last job'
|
sinks.out:writeln 'fg: no last job'
|
||||||
return 1
|
return 1
|
||||||
end
|
end
|
||||||
|
|
||||||
local err = job.foreground() -- waits for job; blocks
|
local err = job.foreground() -- waits for job; blocks
|
||||||
if err then
|
if err then
|
||||||
print('fg: ' .. err)
|
sinks.out:writeln('fg: ' .. err)
|
||||||
return 2
|
return 2
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
|
@ -0,0 +1,121 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"hilbish/util"
|
||||||
|
|
||||||
|
rt "github.com/arnodel/golua/runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
var sinkMetaKey = rt.StringValue("hshsink")
|
||||||
|
|
||||||
|
// a sink is a structure that has input and/or output
|
||||||
|
// it is like a lua file when used in popen, but specific to hilbish
|
||||||
|
type sink struct{
|
||||||
|
writer io.Writer
|
||||||
|
reader io.Reader
|
||||||
|
ud *rt.UserData
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupSinkType(rtm *rt.Runtime) {
|
||||||
|
sinkMeta := rt.NewTable()
|
||||||
|
|
||||||
|
sinkMethods := rt.NewTable()
|
||||||
|
sinkFuncs := map[string]util.LuaExport{
|
||||||
|
"write": {luaSinkWrite, 2, false},
|
||||||
|
"writeln": {luaSinkWriteln, 2, false},
|
||||||
|
}
|
||||||
|
util.SetExports(l, sinkMethods, sinkFuncs)
|
||||||
|
|
||||||
|
sinkIndex := func(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
|
arg := c.Arg(1)
|
||||||
|
val := sinkMethods.Get(arg)
|
||||||
|
|
||||||
|
return c.PushingNext1(t.Runtime, val), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
sinkMeta.Set(rt.StringValue("__index"), rt.FunctionValue(rt.NewGoFunction(sinkIndex, "__index", 2, false)))
|
||||||
|
l.SetRegistry(sinkMetaKey, rt.TableValue(sinkMeta))
|
||||||
|
}
|
||||||
|
|
||||||
|
func luaSinkWrite(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
|
if err := c.CheckNArgs(2); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
s, err := sinkArg(c, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
data, err := c.StringArg(1)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
s.writer.Write([]byte(data))
|
||||||
|
|
||||||
|
return c.Next(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func luaSinkWriteln(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
|
if err := c.CheckNArgs(2); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
s, err := sinkArg(c, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
data, err := c.StringArg(1)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
s.writer.Write([]byte(data + "\n"))
|
||||||
|
|
||||||
|
return c.Next(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func newSinkInput(r io.Reader) *sink {
|
||||||
|
s := &sink{
|
||||||
|
reader: r,
|
||||||
|
}
|
||||||
|
s.ud = sinkUserData(s)
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func newSinkOutput(w io.Writer) *sink {
|
||||||
|
s := &sink{
|
||||||
|
writer: w,
|
||||||
|
}
|
||||||
|
s.ud = sinkUserData(s)
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func sinkArg(c *rt.GoCont, arg int) (*sink, error) {
|
||||||
|
s, ok := valueToSink(c.Arg(arg))
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("#%d must be a sink", arg + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func valueToSink(val rt.Value) (*sink, bool) {
|
||||||
|
u, ok := val.TryUserData()
|
||||||
|
if !ok {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
s, ok := u.Value().(*sink)
|
||||||
|
return s, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func sinkUserData(s *sink) *rt.UserData {
|
||||||
|
sinkMeta := l.Registry(sinkMetaKey)
|
||||||
|
return rt.NewUserData(s, sinkMeta.AsTable())
|
||||||
|
}
|
Loading…
Reference in New Issue