Compare commits

..

2 Commits

Author SHA1 Message Date
TorchedSammy 0379e302ac docs: [ci] generate new docs 2023-03-25 21:42:46 +00:00
sammyette d577b3c958
feat: sink enhancements (#241)
* feat: add read method to sinks

* feat: add manual flush method for sinks

* fix: add flush as sink method and fix arg amount for read

* feat: add pipe property to sinks to see if stdin sink is a pipe

* feat: add method autoFlush to toggle/change automatic flushing

* chore: update changelog
2023-03-25 17:42:25 -04:00
4 changed files with 130 additions and 4 deletions

View File

@ -1,6 +1,12 @@
# 🎀 Changelog # 🎀 Changelog
## Unreleased ## Unreleased
### Added
- Made a few additions to the sink type:
- `read()` method for retrieving input (so now the `in` sink of commanders is useful)
- `flush()` and `autoFlush()` related to flushing outputs
- `pipe` property to check if a sink with input is a pipe (like stdin)
### Fixed ### Fixed
- Replaced `sed` in-place editing with `grep` and `mv` for compatibility with BSD utils - Replaced `sed` in-place editing with `grep` and `mv` for compatibility with BSD utils

View File

@ -109,6 +109,16 @@ A sink is a structure that has input and/or output to/from
a desination. a desination.
### Methods ### Methods
#### autoFlush(auto)
Sets/toggles the option of automatically flushing output.
A call with no argument will toggle the value.
#### flush()
Flush writes all buffered input to the sink.
#### read() -> string
Reads input from the sink.
#### write(str) #### write(str)
Writes data to a sink. Writes data to a sink.

View File

@ -180,6 +180,18 @@ function hilbish.jobs:foreground() end
--- @param cmd string --- @param cmd string
function hilbish.runner.lua(cmd) end function hilbish.runner.lua(cmd) end
--- Sets/toggles the option of automatically flushing output.
--- A call with no argument will toggle the value.
--- @param auto boolean|nil
function hilbish:autoFlush(auto) end
--- Flush writes all buffered input to the sink.
function hilbish:flush() end
--- Reads input from the sink.
--- @returns string
function hilbish:read() end
--- Writes data to a sink. --- Writes data to a sink.
function hilbish:write(str) end function hilbish:write(str) end

106
sink.go
View File

@ -1,8 +1,10 @@
package main package main
import ( import (
"bufio"
"fmt" "fmt"
"io" "io"
"os"
"hilbish/util" "hilbish/util"
@ -15,9 +17,11 @@ var sinkMetaKey = rt.StringValue("hshsink")
// A sink is a structure that has input and/or output to/from // A sink is a structure that has input and/or output to/from
// a desination. // a desination.
type sink struct{ type sink struct{
writer io.Writer writer *bufio.Writer
reader io.Reader reader *bufio.Reader
file *os.File
ud *rt.UserData ud *rt.UserData
autoFlush bool
} }
func setupSinkType(rtm *rt.Runtime) { func setupSinkType(rtm *rt.Runtime) {
@ -25,15 +29,35 @@ func setupSinkType(rtm *rt.Runtime) {
sinkMethods := rt.NewTable() sinkMethods := rt.NewTable()
sinkFuncs := map[string]util.LuaExport{ sinkFuncs := map[string]util.LuaExport{
"flush": {luaSinkFlush, 1, false},
"read": {luaSinkRead, 1, false},
"autoFlush": {luaSinkAutoFlush, 2, false},
"write": {luaSinkWrite, 2, false}, "write": {luaSinkWrite, 2, false},
"writeln": {luaSinkWriteln, 2, false}, "writeln": {luaSinkWriteln, 2, false},
} }
util.SetExports(l, sinkMethods, sinkFuncs) util.SetExports(l, sinkMethods, sinkFuncs)
sinkIndex := func(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { sinkIndex := func(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
s, _ := sinkArg(c, 0)
arg := c.Arg(1) arg := c.Arg(1)
val := sinkMethods.Get(arg) val := sinkMethods.Get(arg)
if val != rt.NilValue {
return c.PushingNext1(t.Runtime, val), nil
}
keyStr, _ := arg.TryString()
switch keyStr {
case "pipe":
val = rt.BoolValue(false)
if s.file != nil {
fileInfo, _ := s.file.Stat();
val = rt.BoolValue(fileInfo.Mode() & os.ModeCharDevice == 0)
}
}
return c.PushingNext1(t.Runtime, val), nil return c.PushingNext1(t.Runtime, val), nil
} }
@ -41,6 +65,25 @@ func setupSinkType(rtm *rt.Runtime) {
l.SetRegistry(sinkMetaKey, rt.TableValue(sinkMeta)) l.SetRegistry(sinkMetaKey, rt.TableValue(sinkMeta))
} }
// #member
// read() -> string
// --- @returns string
// Reads input from the sink.
func luaSinkRead(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.Check1Arg(); err != nil {
return nil, err
}
s, err := sinkArg(c, 0)
if err != nil {
return nil, err
}
str, _ := s.reader.ReadString('\n')
return c.PushingNext1(t.Runtime, rt.StringValue(str)), nil
}
// #member // #member
// write(str) // write(str)
// Writes data to a sink. // Writes data to a sink.
@ -59,6 +102,9 @@ func luaSinkWrite(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
} }
s.writer.Write([]byte(data)) s.writer.Write([]byte(data))
if s.autoFlush {
s.writer.Flush()
}
return c.Next(), nil return c.Next(), nil
} }
@ -81,22 +127,74 @@ func luaSinkWriteln(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
} }
s.writer.Write([]byte(data + "\n")) s.writer.Write([]byte(data + "\n"))
if s.autoFlush {
s.writer.Flush()
}
return c.Next(), nil
}
// #member
// flush()
// Flush writes all buffered input to the sink.
func luaSinkFlush(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.Check1Arg(); err != nil {
return nil, err
}
s, err := sinkArg(c, 0)
if err != nil {
return nil, err
}
s.writer.Flush()
return c.Next(), nil
}
// #member
// autoFlush(auto)
// Sets/toggles the option of automatically flushing output.
// A call with no argument will toggle the value.
// --- @param auto boolean|nil
func luaSinkAutoFlush(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
s, err := sinkArg(c, 0)
if err != nil {
return nil, err
}
v := c.Arg(1)
if v.Type() != rt.BoolType && v.Type() != rt.NilType {
return nil, fmt.Errorf("#1 must be a boolean")
}
value := !s.autoFlush
if v.Type() == rt.BoolType {
value = v.AsBool()
}
s.autoFlush = value
return c.Next(), nil return c.Next(), nil
} }
func newSinkInput(r io.Reader) *sink { func newSinkInput(r io.Reader) *sink {
s := &sink{ s := &sink{
reader: r, reader: bufio.NewReader(r),
} }
s.ud = sinkUserData(s) s.ud = sinkUserData(s)
if f, ok := r.(*os.File); ok {
s.file = f
}
return s return s
} }
func newSinkOutput(w io.Writer) *sink { func newSinkOutput(w io.Writer) *sink {
s := &sink{ s := &sink{
writer: w, writer: bufio.NewWriter(w),
autoFlush: true,
} }
s.ud = sinkUserData(s) s.ud = sinkUserData(s)