diff --git a/CHANGELOG.md b/CHANGELOG.md
index 22535496..021edf74 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,33 @@
# 🎀 Changelog
+## Unreleased
+### Added
+- `fs.pipe` function to get a pair of connected files (a pipe).
+- Added an alternative 2nd parameter to `hilbish.run`, which is `streams`.
+`streams` is a table of input and output streams to run the command with.
+It uses these 3 keys:
+ - `input` as standard input for the command
+ - `out` as standard output
+ - `err` as standard error
+
+Here is a minimal example of the new usage which allows users to now pipe commands
+directly via Lua functions:
+
+```lua
+local fs = require 'fs'
+local pr, pw = fs.pipe()
+hilbish.run('ls -l', {
+ stdout = pw,
+ stderr = pw,
+})
+
+pw:close()
+
+hilbish.run('wc -l', {
+ stdin = pr
+})
+```
+
## [2.2.3] - 2024-04-27
### Fixed
- Highligher and hinter work now, since it was regressed from the previous minor release.
@@ -716,6 +744,7 @@ This input for example will prompt for more input to complete:
First "stable" release of Hilbish.
+[2.2.3]: https://github.com/Rosettea/Hilbish/compare/v2.2.2...v2.2.3
[2.2.2]: https://github.com/Rosettea/Hilbish/compare/v2.2.1...v2.2.2
[2.2.1]: https://github.com/Rosettea/Hilbish/compare/v2.2.0...v2.2.1
[2.2.0]: https://github.com/Rosettea/Hilbish/compare/v2.1.0...v2.2.0
diff --git a/api.go b/api.go
index b8e62b31..6f8f5176 100644
--- a/api.go
+++ b/api.go
@@ -16,6 +16,7 @@ import (
"bytes"
"errors"
"fmt"
+ "io"
"os"
"os/exec"
"runtime"
@@ -27,6 +28,7 @@ import (
rt "github.com/arnodel/golua/runtime"
"github.com/arnodel/golua/lib/packagelib"
+ "github.com/arnodel/golua/lib/iolib"
"github.com/maxlandon/readline"
"mvdan.cc/sh/v3/interp"
)
@@ -152,12 +154,64 @@ func unsetVimMode() {
util.SetField(l, hshMod, "vimMode", rt.NilValue)
}
-// run(cmd, returnOut) -> exitCode (number), stdout (string), stderr (string)
+func handleStream(v rt.Value, strms *streams, errStream bool) error {
+ ud, ok := v.TryUserData()
+ if !ok {
+ return errors.New("expected metatable argument")
+ }
+
+ val := ud.Value()
+ var varstrm io.Writer
+ if f, ok := val.(*iolib.File); ok {
+ varstrm = f.Handle()
+ }
+
+ if f, ok := val.(*sink); ok {
+ varstrm = f.writer
+ }
+
+ if varstrm == nil {
+ return errors.New("expected either a sink or file")
+ }
+
+ if errStream {
+ strms.stderr = varstrm
+ } else {
+ strms.stdout = varstrm
+ }
+
+ return nil
+}
+
+// run(cmd, streams) -> exitCode (number), stdout (string), stderr (string)
// Runs `cmd` in Hilbish's shell script interpreter.
+// The `streams` parameter specifies the output and input streams the command should use.
+// For example, to write command output to a sink.
+// As a table, the caller can directly specify the standard output, error, and input
+// streams of the command with the table keys `out`, `err`, and `input` respectively.
+// As a boolean, it specifies whether the command should use standard output or return its output streams.
// #param cmd string
-// #param returnOut boolean If this is true, the function will return the standard output and error of the command instead of printing it.
+// #param streams table|boolean
// #returns number, string, string
+// #example
+/*
+// This code is the same as `ls -l | wc -l`
+local fs = require 'fs'
+local pr, pw = fs.pipe()
+hilbish.run('ls -l', {
+ stdout = pw,
+ stderr = pw,
+})
+
+pw:close()
+
+hilbish.run('wc -l', {
+ stdin = pr
+})
+*/
+// #example
func hlrun(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
+ // TODO: ON BREAKING RELEASE, DO NOT ACCEPT `streams` AS A BOOLEAN.
if err := c.Check1Arg(); err != nil {
return nil, err
}
@@ -166,20 +220,57 @@ func hlrun(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return nil, err
}
+ strms := &streams{}
var terminalOut bool
if len(c.Etc()) != 0 {
tout := c.Etc()[0]
- termOut, ok := tout.TryBool()
- terminalOut = termOut
+
+ var ok bool
+ terminalOut, ok = tout.TryBool()
if !ok {
- return nil, errors.New("bad argument to run (expected boolean, got " + tout.TypeName() + ")")
+ luastreams, ok := tout.TryTable()
+ if !ok {
+ return nil, errors.New("bad argument to run (expected boolean or table, got " + tout.TypeName() + ")")
+ }
+
+ handleStream(luastreams.Get(rt.StringValue("out")), strms, false)
+ handleStream(luastreams.Get(rt.StringValue("err")), strms, true)
+
+ stdinstrm := luastreams.Get(rt.StringValue("input"))
+ if !stdinstrm.IsNil() {
+ ud, ok := stdinstrm.TryUserData()
+ if !ok {
+ return nil, errors.New("bad type as run stdin stream (expected userdata as either sink or file, got " + stdinstrm.TypeName() + ")")
+ }
+
+ val := ud.Value()
+ var varstrm io.Reader
+ if f, ok := val.(*iolib.File); ok {
+ varstrm = f.Handle()
+ }
+
+ if f, ok := val.(*sink); ok {
+ varstrm = f.reader
+ }
+
+ if varstrm == nil {
+ return nil, errors.New("bad type as run stdin stream (expected userdata as either sink or file)")
+ }
+
+ strms.stdin = varstrm
+ }
+ } else {
+ if !terminalOut {
+ strms = &streams{
+ stdout: new(bytes.Buffer),
+ stderr: new(bytes.Buffer),
+ }
+ }
}
- } else {
- terminalOut = true
}
var exitcode uint8
- stdout, stderr, err := execCommand(cmd, terminalOut)
+ stdout, stderr, err := execCommand(cmd, strms)
if code, ok := interp.IsExitStatus(err); ok {
exitcode = code
@@ -187,11 +278,12 @@ func hlrun(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
exitcode = 1
}
- stdoutStr := ""
- stderrStr := ""
- if !terminalOut {
- stdoutStr = stdout.(*bytes.Buffer).String()
- stderrStr = stderr.(*bytes.Buffer).String()
+ var stdoutStr, stderrStr string
+ if stdoutBuf, ok := stdout.(*bytes.Buffer); ok {
+ stdoutStr = stdoutBuf.String()
+ }
+ if stderrBuf, ok := stderr.(*bytes.Buffer); ok {
+ stderrStr = stderrBuf.String()
}
return c.PushingNext(t.Runtime, rt.IntValue(int64(exitcode)), rt.StringValue(stdoutStr), rt.StringValue(stderrStr)), nil
diff --git a/cmd/docgen/docgen.go b/cmd/docgen/docgen.go
index 86a622ac..bf8fd1bd 100644
--- a/cmd/docgen/docgen.go
+++ b/cmd/docgen/docgen.go
@@ -488,7 +488,11 @@ func main() {
}
mdTable.SetContent(i - diff, 0, fmt.Sprintf(`%s`, dps.FuncName, dps.FuncSig))
- mdTable.SetContent(i - diff, 1, dps.Doc[0])
+ if len(dps.Doc) == 0 {
+ fmt.Printf("WARNING! Function %s on module %s has no documentation!\n", dps.FuncName, modname)
+ } else {
+ mdTable.SetContent(i - diff, 1, dps.Doc[0])
+ }
}
f.WriteString(mdTable.String())
f.WriteString("\n")
diff --git a/docs/api/commander.md b/docs/api/commander.md
index 03ece547..c26445a8 100644
--- a/docs/api/commander.md
+++ b/docs/api/commander.md
@@ -26,8 +26,11 @@ 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?
-The `sinks` parameter is a table with 3 keys: `in`, `out`,
-and `err`. All of them are a Sink.
+The `sinks` parameter is a table with 3 keys: `input`, `out`, and `err`.
+There is an `in` alias to `input`, but it requires using the string accessor syntax (`sinks['in']`)
+as `in` is also a Lua keyword, so `input` is preferred for use.
+All of them are a Sink.
+In the future, `sinks.in` will be removed.
- `in` is the standard input.
You may use the read functions on this sink to get input from the user.
diff --git a/docs/api/fs.md b/docs/api/fs.md
index bc14055f..7b733ef2 100644
--- a/docs/api/fs.md
+++ b/docs/api/fs.md
@@ -23,6 +23,7 @@ library offers more functions and will work on any operating system Hilbish does
|glob(pattern) -> matches (table)|Match all files based on the provided `pattern`.|
|join(...path) -> string|Takes any list of paths and joins them based on the operating system's path separator.|
|mkdir(name, recursive)|Creates a new directory with the provided `name`.|
+|fpipe() -> File, File|Returns a pair of connected files, also known as a pipe.|
|readdir(path) -> table[string]|Returns a list of all files and directories in the provided path.|
|stat(path) -> {}|Returns the information about a given `path`.|
@@ -183,6 +184,22 @@ fs.mkdir('./foo/bar', true)
```
+
+
+
+fs.fpipe() -> File, File
+
+
+
+
+
+Returns a pair of connected files, also known as a pipe.
+The type returned is a Lua file, same as returned from `io` functions.
+
+#### Parameters
+This function has no parameters.
+
+
diff --git a/docs/api/hilbish/_index.md b/docs/api/hilbish/_index.md
index b79dcde3..1407e69e 100644
--- a/docs/api/hilbish/_index.md
+++ b/docs/api/hilbish/_index.md
@@ -28,7 +28,7 @@ interfaces and functions which directly relate to shell functionality.
|prependPath(dir)|Prepends `dir` to $PATH.|
|prompt(str, typ)|Changes the shell prompt to the provided string.|
|read(prompt) -> input (string)|Read input from the user, using Hilbish's line editor/input reader.|
-|run(cmd, returnOut) -> exitCode (number), stdout (string), stderr (string)|Runs `cmd` in Hilbish's shell script interpreter.|
+|run(cmd, streams) -> exitCode (number), stdout (string), stderr (string)|Runs `cmd` in Hilbish's shell script interpreter.|
|runnerMode(mode)|Sets the execution/runner mode for interactive Hilbish.|
|timeout(cb, time) -> @Timer|Executed the `cb` function after a period of `time`.|
|which(name) -> string|Checks if `name` is a valid command.|
@@ -413,20 +413,25 @@ Text to print before input, can be empty.
-hilbish.run(cmd, returnOut) -> exitCode (number), stdout (string), stderr (string)
+hilbish.run(cmd, streams) -> exitCode (number), stdout (string), stderr (string)
Runs `cmd` in Hilbish's shell script interpreter.
+Specifies the output and input streams the command should use.
+For example, to write command output to a sink.
+As a table, the caller can directly specify the standard output, error, and input
+streams of the command with the table keys `out`, `err`, and `input` respectively.
+As a boolean, it specifies whether the command should use standard output or return its output streams.
#### Parameters
`string` **`cmd`**
-`boolean` **`returnOut`**
-If this is true, the function will return the standard output and error of the command instead of printing it.
+`table|boolean` **`streams`**
+
diff --git a/emmyLuaDocs/fs.lua b/emmyLuaDocs/fs.lua
index 89a418bb..ef80eba9 100644
--- a/emmyLuaDocs/fs.lua
+++ b/emmyLuaDocs/fs.lua
@@ -34,6 +34,10 @@ function fs.join(...path) end
---
function fs.mkdir(name, recursive) end
+--- Returns a pair of connected files, also known as a pipe.
+--- The type returned is a Lua file, same as returned from `io` functions.
+function fs.fpipe() end
+
--- Returns a list of all files and directories in the provided path.
function fs.readdir(path) end
diff --git a/emmyLuaDocs/hilbish.lua b/emmyLuaDocs/hilbish.lua
index 7cca3552..d931918e 100644
--- a/emmyLuaDocs/hilbish.lua
+++ b/emmyLuaDocs/hilbish.lua
@@ -132,7 +132,12 @@ function hilbish.prompt(str, typ) end
function hilbish.read(prompt) end
--- Runs `cmd` in Hilbish's shell script interpreter.
-function hilbish.run(cmd, returnOut) end
+--- Specifies the output and input streams the command should use.
+--- For example, to write command output to a sink.
+--- As a table, the caller can directly specify the standard output, error, and input
+--- streams of the command with the table keys `out`, `err`, and `input` respectively.
+--- As a boolean, it specifies whether the command should use standard output or return its output streams.
+function hilbish.run(cmd, streams) end
--- Sets the execution/runner mode for interactive Hilbish.
--- This determines whether Hilbish wll try to run input as Lua
diff --git a/exec.go b/exec.go
index cf84231f..355fa3d1 100644
--- a/exec.go
+++ b/exec.go
@@ -28,6 +28,12 @@ var errNotExec = errors.New("not executable")
var errNotFound = errors.New("not found")
var runnerMode rt.Value = rt.StringValue("hybrid")
+type streams struct {
+ stdout io.Writer
+ stderr io.Writer
+ stdin io.Reader
+}
+
type execError struct{
typ string
cmd string
@@ -236,7 +242,7 @@ func handleSh(cmdString string) (input string, exitCode uint8, cont bool, runErr
}
func execSh(cmdString string) (string, uint8, bool, error) {
- _, _, err := execCommand(cmdString, true)
+ _, _, err := execCommand(cmdString, nil)
if err != nil {
// If input is incomplete, start multiline prompting
if syntax.IsIncomplete(err) {
@@ -257,7 +263,7 @@ func execSh(cmdString string) (string, uint8, bool, error) {
}
// Run command in sh interpreter
-func execCommand(cmd string, terminalOut bool) (io.Writer, io.Writer, error) {
+func execCommand(cmd string, strms *streams) (io.Writer, io.Writer, error) {
file, err := syntax.NewParser().Parse(strings.NewReader(cmd), "")
if err != nil {
return nil, nil, err
@@ -265,15 +271,24 @@ func execCommand(cmd string, terminalOut bool) (io.Writer, io.Writer, error) {
runner, _ := interp.New()
- var stdout io.Writer
- var stderr io.Writer
- if terminalOut {
- interp.StdIO(os.Stdin, os.Stdout, os.Stderr)(runner)
- } else {
- stdout = new(bytes.Buffer)
- stderr = new(bytes.Buffer)
- interp.StdIO(os.Stdin, stdout, stderr)(runner)
+ if strms == nil {
+ strms = &streams{}
}
+
+ if strms.stdout == nil {
+ strms.stdout = os.Stdout
+ }
+
+ if strms.stderr == nil {
+ strms.stderr = os.Stderr
+ }
+
+ if strms.stdin == nil {
+ strms.stdin = os.Stdin
+ }
+
+ interp.StdIO(strms.stdin, strms.stdout, strms.stderr)(runner)
+
buf := new(bytes.Buffer)
printer := syntax.NewPrinter()
@@ -292,11 +307,11 @@ func execCommand(cmd string, terminalOut bool) (io.Writer, io.Writer, error) {
interp.ExecHandler(execHandle(bg))(runner)
err = runner.Run(context.TODO(), stmt)
if err != nil {
- return stdout, stderr, err
+ return strms.stdout, strms.stderr, err
}
}
- return stdout, stderr, nil
+ return strms.stdout, strms.stderr, nil
}
func execHandle(bg bool) interp.ExecHandlerFunc {
@@ -334,6 +349,7 @@ func execHandle(bg bool) interp.ExecHandlerFunc {
sinks := rt.NewTable()
sinks.Set(rt.StringValue("in"), rt.UserDataValue(stdin.ud))
+ sinks.Set(rt.StringValue("input"), rt.UserDataValue(stdin.ud))
sinks.Set(rt.StringValue("out"), rt.UserDataValue(stdout.ud))
sinks.Set(rt.StringValue("err"), rt.UserDataValue(stderr.ud))
diff --git a/go.mod b/go.mod
index 6753a171..a7975b7f 100644
--- a/go.mod
+++ b/go.mod
@@ -3,26 +3,26 @@ module hilbish
go 1.18
require (
- github.com/arnodel/golua v0.0.0-20220221163911-dfcf252b6f86
+ github.com/arnodel/golua v0.0.0-20230215163904-e0b5347eaaa1
github.com/atsushinee/go-markdown-generator v0.0.0-20191121114853-83f9e1f68504
- github.com/blackfireio/osinfo v1.0.3
- github.com/maxlandon/readline v0.1.0-beta.0.20211027085530-2b76cabb8036
+ github.com/blackfireio/osinfo v1.0.5
+ github.com/maxlandon/readline v1.0.14
github.com/pborman/getopt v1.1.0
- github.com/sahilm/fuzzy v0.1.0
- golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a
- golang.org/x/term v0.0.0-20220411215600-e5f449aeb171
- mvdan.cc/sh/v3 v3.5.1
+ github.com/sahilm/fuzzy v0.1.1
+ golang.org/x/sys v0.19.0
+ golang.org/x/term v0.19.0
+ mvdan.cc/sh/v3 v3.8.0
)
require (
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect
github.com/arnodel/strftime v0.1.6 // indirect
- github.com/evilsocket/islazy v1.10.6 // indirect
+ github.com/evilsocket/islazy v1.11.0 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/olekukonko/ts v0.0.0-20171002115256-78ecb04241c0 // indirect
- github.com/rivo/uniseg v0.2.0 // indirect
- golang.org/x/sync v0.0.0-20220513210516-0976fa681c29 // indirect
- golang.org/x/text v0.3.7 // indirect
+ github.com/rivo/uniseg v0.4.7 // indirect
+ golang.org/x/sync v0.7.0 // indirect
+ golang.org/x/text v0.14.0 // indirect
)
replace mvdan.cc/sh/v3 => github.com/Rosettea/sh/v3 v3.4.0-0.dev.0.20220524215627-dfd9a4fa219b
@@ -31,4 +31,4 @@ replace github.com/maxlandon/readline => ./readline
replace layeh.com/gopher-luar => github.com/layeh/gopher-luar v1.0.10
-replace github.com/arnodel/golua => github.com/Rosettea/golua v0.0.0-20221213193027-cbf6d4e4d345
+replace github.com/arnodel/golua => github.com/Rosettea/golua v0.0.0-20240427174124-d239074c1749
diff --git a/go.sum b/go.sum
index f82ef01f..193f17e0 100644
--- a/go.sum
+++ b/go.sum
@@ -1,26 +1,21 @@
-github.com/Rosettea/golua v0.0.0-20221213193027-cbf6d4e4d345 h1:QNYjYDogUSiNUkffbhFSrSCtpZhofeiVYGFN2FI4wSs=
-github.com/Rosettea/golua v0.0.0-20221213193027-cbf6d4e4d345/go.mod h1:9jzpYPiU2is0HVGCiuIOBSXdergHUW44IEjmuN1UrIE=
+github.com/Rosettea/golua v0.0.0-20240427174124-d239074c1749 h1:jIFnWBTsYw8s7RX7H2AOXjDVhWP3ol7OzUVaPN2KnGI=
+github.com/Rosettea/golua v0.0.0-20240427174124-d239074c1749/go.mod h1:9jzpYPiU2is0HVGCiuIOBSXdergHUW44IEjmuN1UrIE=
github.com/Rosettea/sh/v3 v3.4.0-0.dev.0.20220524215627-dfd9a4fa219b h1:s5eDMhBk6H1BgipgLub/gv9qeyBaTuiHM0k3h2/9TSE=
github.com/Rosettea/sh/v3 v3.4.0-0.dev.0.20220524215627-dfd9a4fa219b/go.mod h1:R09vh/04ILvP2Gj8/Z9Jd0Dh0ZIvaucowMEs6abQpWs=
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=
-github.com/arnodel/edit v0.0.0-20220202110212-dfc8d7a13890/go.mod h1:AcpttpuZBaL9xl8/CX+Em4fBTUbwIkJ66RiAsJlNrBk=
github.com/arnodel/strftime v0.1.6 h1:0hc0pUvk8KhEMXE+htyaOUV42zNcf/csIbjzEFCJqsw=
github.com/arnodel/strftime v0.1.6/go.mod h1:5NbK5XqYK8QpRZpqKNt4OlxLtIB8cotkLk4KTKzJfWs=
-github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
github.com/atsushinee/go-markdown-generator v0.0.0-20191121114853-83f9e1f68504 h1:R1/AOzdMbopSliUTTEHvHbyNmnZ3YxY5GvdhTkpPsSY=
github.com/atsushinee/go-markdown-generator v0.0.0-20191121114853-83f9e1f68504/go.mod h1:kHBCvAXJIatTX1pw6tLiOspjGc3MhUDRlog9yrCUS+k=
-github.com/blackfireio/osinfo v1.0.3 h1:Yk2t2GTPjBcESv6nDSWZKO87bGMQgO+Hi9OoXPpxX8c=
-github.com/blackfireio/osinfo v1.0.3/go.mod h1:Pd987poVNmd5Wsx6PRPw4+w7kLlf9iJxoRKPtPAjOrA=
+github.com/blackfireio/osinfo v1.0.5 h1:6hlaWzfcpb87gRmznVf7wSdhysGqLRz9V/xuSdCEXrA=
+github.com/blackfireio/osinfo v1.0.5/go.mod h1:Pd987poVNmd5Wsx6PRPw4+w7kLlf9iJxoRKPtPAjOrA=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.15 h1:cKRCLMj3Ddm54bKSpemfQ8AtYFBhAI2MPmdys22fBdc=
github.com/creack/pty v1.1.15/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
-github.com/evilsocket/islazy v1.10.6 h1:MFq000a1ByoumoJWlytqg0qon0KlBeUfPsDjY0hK0bo=
-github.com/evilsocket/islazy v1.10.6/go.mod h1:OrwQGYg3DuZvXUfmH+KIZDjwTCbrjy48T24TUpGqVVw=
-github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
-github.com/gdamore/tcell/v2 v2.4.0/go.mod h1:cTTuF84Dlj/RqmaCIV5p4w8uG1zWdk0SF6oBpwHp4fU=
+github.com/evilsocket/islazy v1.11.0 h1:B5w6uuS6ki6iDG+aH/RFeoMb8ijQh/pGabewqp2UeJ0=
+github.com/evilsocket/islazy v1.11.0/go.mod h1:muYH4x5MB5YRdkxnrOtrXLIBX6LySj1uFIqys94LKdo=
github.com/google/renameio v1.0.1/go.mod h1:t/HQoYBZSsWSNK35C6CO/TpPLDVWvxOHboWUAweKUpk=
-github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
@@ -30,40 +25,30 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
-github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
-github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/olekukonko/ts v0.0.0-20171002115256-78ecb04241c0 h1:LiZB1h0GIcudcDci2bxbqI6DXV8bF8POAnArqvRrIyw=
github.com/olekukonko/ts v0.0.0-20171002115256-78ecb04241c0/go.mod h1:F/7q8/HZz+TXjlsoZQQKVYvXTZaFH4QRa3y+j1p7MS0=
github.com/pborman/getopt v1.1.0 h1:eJ3aFZroQqq0bWmraivjQNt6Dmm5M0h2JcDW38/Azb0=
github.com/pborman/getopt v1.1.0/go.mod h1:FxXoW1Re00sQG/+KIkuSqRL/LwQgSkv7uyac+STFsbk=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
-github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
-github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
-github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
+github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
+github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.1-0.20210923151022-86f73c517451 h1:d1PiN4RxzIFXCJTvRkvSkKqwtRAl5ZV4lATKtQI0B7I=
github.com/rogpeppe/go-internal v1.8.1-0.20210923151022-86f73c517451/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
-github.com/sahilm/fuzzy v0.1.0 h1:FzWGaw2Opqyu+794ZQ9SYifWv2EIXpwP4q8dY1kDAwI=
-github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
+github.com/sahilm/fuzzy v0.1.1 h1:ceu5RHF8DGgoi+/dR5PsECjCDH1BE3Fnmpo7aVXOdRA=
+github.com/sahilm/fuzzy v0.1.1/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20220513210516-0976fa681c29 h1:w8s32wxx3sY+OjLlv9qltkLU5yvJzxjjgiHWLjdIcw4=
-golang.org/x/sync v0.0.0-20220513210516-0976fa681c29/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
+golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210925032602-92d5a993a665/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
-golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
+golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20210916214954-140adaaadfaf/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/term v0.0.0-20220411215600-e5f449aeb171 h1:EH1Deb8WZJ0xc0WK//leUHXcX9aLE5SymusoTmMZye8=
-golang.org/x/term v0.0.0-20220411215600-e5f449aeb171/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
-golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=
+golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
+golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
+golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
mvdan.cc/editorconfig v0.2.0/go.mod h1:lvnnD3BNdBYkhq+B4uBuFFKatfp02eB6HixDvEz91C0=
diff --git a/golibs/commander/commander.go b/golibs/commander/commander.go
index ea2da7a9..f4d588d8 100644
--- a/golibs/commander/commander.go
+++ b/golibs/commander/commander.go
@@ -17,8 +17,11 @@ 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?
-The `sinks` parameter is a table with 3 keys: `in`, `out`,
-and `err`. All of them are a @Sink.
+The `sinks` parameter is a table with 3 keys: `input`, `out`, and `err`.
+There is an `in` alias to `input`, but it requires using the string accessor syntax (`sinks['in']`)
+as `in` is also a Lua keyword, so `input` is preferred for use.
+All of them are a @Sink.
+In the future, `sinks.in` will be removed.
- `in` is the standard input.
You may use the read functions on this sink to get input from the user.
diff --git a/golibs/fs/fs.go b/golibs/fs/fs.go
index 5bd22c6c..9e03325a 100644
--- a/golibs/fs/fs.go
+++ b/golibs/fs/fs.go
@@ -18,6 +18,7 @@ import (
rt "github.com/arnodel/golua/runtime"
"github.com/arnodel/golua/lib/packagelib"
+ "github.com/arnodel/golua/lib/iolib"
)
var Loader = packagelib.Loader{
@@ -36,6 +37,7 @@ func loaderFunc(rtm *rt.Runtime) (rt.Value, func()) {
"dir": util.LuaExport{fdir, 1, false},
"glob": util.LuaExport{fglob, 1, false},
"join": util.LuaExport{fjoin, 0, true},
+ "pipe": util.LuaExport{fpipe, 0, false},
}
mod := rt.NewTable()
util.SetExports(rtm, mod, exports)
@@ -226,6 +228,22 @@ func fmkdir(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return c.Next(), err
}
+// fpipe() -> File, File
+// Returns a pair of connected files, also known as a pipe.
+// The type returned is a Lua file, same as returned from `io` functions.
+// #returns File
+// #returns File
+func fpipe(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
+ rf, wf, err := os.Pipe()
+ if err != nil {
+ return nil, err
+ }
+
+ rfLua := iolib.NewFile(rf, 0)
+ wfLua := iolib.NewFile(wf, 0)
+
+ return c.PushingNext(t.Runtime, rfLua.Value(t.Runtime), wfLua.Value(t.Runtime)), nil
+}
// readdir(path) -> table[string]
// Returns a list of all files and directories in the provided path.
// #param dir string