mirror of https://github.com/Hilbis/Hilbish
Compare commits
12 Commits
86afa0c3e2
...
af14dc20a4
Author | SHA1 | Date |
---|---|---|
sammyette | af14dc20a4 | |
sammyette | ff6e08902f | |
sammyette | bbd5637e9b | |
TorchedSammy | d46c079afb | |
sammyette | 42ab856e45 | |
TorchedSammy | 478e3020b1 | |
sammyette | a20123fc24 | |
sammyette | fb9d30520a | |
sammyette | 521298733e | |
sammyette | f8a391e24f | |
James Dugan | aa376f9b14 | |
sammyette | 16b39fe157 |
|
@ -1,8 +1,12 @@
|
||||||
name: Build
|
name: Build
|
||||||
|
|
||||||
on:
|
on:
|
||||||
- push
|
push:
|
||||||
- pull_request
|
branches:
|
||||||
|
- master
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
@ -19,18 +23,18 @@ jobs:
|
||||||
goos: windows
|
goos: windows
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: '1.18.8'
|
go-version: '1.18.8'
|
||||||
- name: Download Task
|
- name: Download Task
|
||||||
run: 'sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d'
|
run: 'sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d'
|
||||||
- name: Build
|
- name: Build
|
||||||
run: GOOS=${{ matrix.goos }} GOARCH=${{ matrix.goarch }} ./bin/task
|
run: GOOS=${{ matrix.goos }} GOARCH=${{ matrix.goarch }} ./bin/task
|
||||||
- uses: actions/upload-artifact@v2
|
- uses: actions/upload-artifact@v4
|
||||||
if: matrix.goos == 'windows'
|
if: matrix.goos == 'windows'
|
||||||
with:
|
with:
|
||||||
name: hilbish-${{ matrix.goos }}-${{ matrix.goarch }}
|
name: hilbish-${{ matrix.goos }}-${{ matrix.goarch }}
|
||||||
|
@ -44,7 +48,7 @@ jobs:
|
||||||
libs
|
libs
|
||||||
docs
|
docs
|
||||||
emmyLuaDocs
|
emmyLuaDocs
|
||||||
- uses: actions/upload-artifact@v2
|
- uses: actions/upload-artifact@v4
|
||||||
if: matrix.goos != 'windows'
|
if: matrix.goos != 'windows'
|
||||||
with:
|
with:
|
||||||
name: hilbish-${{ matrix.goos }}-${{ matrix.goarch }}
|
name: hilbish-${{ matrix.goos }}-${{ matrix.goarch }}
|
||||||
|
|
|
@ -26,7 +26,7 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
|
|
|
@ -9,8 +9,8 @@ jobs:
|
||||||
gen:
|
gen:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/setup-go@v2
|
- uses: actions/setup-go@v5
|
||||||
- name: Run docgen
|
- name: Run docgen
|
||||||
run: go run cmd/docgen/docgen.go
|
run: go run cmd/docgen/docgen.go
|
||||||
- name: Commit new docs
|
- name: Commit new docs
|
||||||
|
|
|
@ -9,7 +9,7 @@ jobs:
|
||||||
create-release:
|
create-release:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- uses: taiki-e/create-gh-release-action@v1
|
- uses: taiki-e/create-gh-release-action@v1
|
||||||
with:
|
with:
|
||||||
title: Hilbish $tag
|
title: Hilbish $tag
|
||||||
|
@ -30,7 +30,7 @@ jobs:
|
||||||
- goarch: arm64
|
- goarch: arm64
|
||||||
goos: windows
|
goos: windows
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
|
@ -1,22 +1,26 @@
|
||||||
name: Build website
|
name: Build website
|
||||||
|
|
||||||
on:
|
on:
|
||||||
- push
|
push:
|
||||||
- pull_request
|
branches:
|
||||||
|
- master
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
deploy:
|
deploy:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Setup Hugo
|
- name: Setup Hugo
|
||||||
uses: peaceiris/actions-hugo@v2
|
uses: peaceiris/actions-hugo@v3
|
||||||
with:
|
with:
|
||||||
hugo-version: 'latest'
|
hugo-version: '0.111.3'
|
||||||
extended: true
|
extended: true
|
||||||
|
|
||||||
- name: Set branch name
|
- name: Set branch name
|
||||||
|
@ -32,14 +36,14 @@ jobs:
|
||||||
|
|
||||||
- name: Deploy
|
- name: Deploy
|
||||||
if: env.BRANCH_NAME == 'master' && github.repository_owner == 'Rosettea'
|
if: env.BRANCH_NAME == 'master' && github.repository_owner == 'Rosettea'
|
||||||
uses: peaceiris/actions-gh-pages@v3
|
uses: peaceiris/actions-gh-pages@v4
|
||||||
with:
|
with:
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
publish_dir: ./website/public
|
publish_dir: ./website/public
|
||||||
keep_files: true
|
keep_files: true
|
||||||
- name: Deploy
|
- name: Deploy
|
||||||
if: env.BRANCH_NAME != 'master' && github.repository_owner == 'Rosettea'
|
if: env.BRANCH_NAME != 'master' && github.repository_owner == 'Rosettea'
|
||||||
uses: peaceiris/actions-gh-pages@v3
|
uses: peaceiris/actions-gh-pages@v4
|
||||||
with:
|
with:
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
publish_dir: ./website/public
|
publish_dir: ./website/public
|
||||||
|
|
40
CHANGELOG.md
40
CHANGELOG.md
|
@ -1,5 +1,44 @@
|
||||||
# 🎀 Changelog
|
# 🎀 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
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Fix ansi attributes causing issues with text when cut off in greenhouse
|
||||||
|
|
||||||
|
## [2.2.3] - 2024-04-27
|
||||||
|
### Fixed
|
||||||
|
- Highligher and hinter work now, since it was regressed from the previous minor release.
|
||||||
|
- `cat` command no longer prints extra newline at end of each file
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- `cat` command now reads files in chunks, allowing for reading large files
|
||||||
|
|
||||||
## [2.2.2] - 2024-04-16
|
## [2.2.2] - 2024-04-16
|
||||||
### Fixed
|
### Fixed
|
||||||
- Line refresh fixes (less flicker)
|
- Line refresh fixes (less flicker)
|
||||||
|
@ -708,6 +747,7 @@ This input for example will prompt for more input to complete:
|
||||||
|
|
||||||
First "stable" release of Hilbish.
|
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.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.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
|
[2.2.0]: https://github.com/Rosettea/Hilbish/compare/v2.1.0...v2.2.0
|
||||||
|
|
129
api.go
129
api.go
|
@ -16,6 +16,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
@ -27,6 +28,7 @@ import (
|
||||||
|
|
||||||
rt "github.com/arnodel/golua/runtime"
|
rt "github.com/arnodel/golua/runtime"
|
||||||
"github.com/arnodel/golua/lib/packagelib"
|
"github.com/arnodel/golua/lib/packagelib"
|
||||||
|
"github.com/arnodel/golua/lib/iolib"
|
||||||
"github.com/maxlandon/readline"
|
"github.com/maxlandon/readline"
|
||||||
"mvdan.cc/sh/v3/interp"
|
"mvdan.cc/sh/v3/interp"
|
||||||
)
|
)
|
||||||
|
@ -152,12 +154,64 @@ func unsetVimMode() {
|
||||||
util.SetField(l, hshMod, "vimMode", rt.NilValue)
|
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.
|
// 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 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
|
// #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) {
|
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 {
|
if err := c.Check1Arg(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -166,20 +220,57 @@ func hlrun(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
strms := &streams{}
|
||||||
var terminalOut bool
|
var terminalOut bool
|
||||||
if len(c.Etc()) != 0 {
|
if len(c.Etc()) != 0 {
|
||||||
tout := c.Etc()[0]
|
tout := c.Etc()[0]
|
||||||
termOut, ok := tout.TryBool()
|
|
||||||
terminalOut = termOut
|
var ok bool
|
||||||
|
terminalOut, ok = tout.TryBool()
|
||||||
if !ok {
|
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 {
|
} else {
|
||||||
terminalOut = true
|
if !terminalOut {
|
||||||
|
strms = &streams{
|
||||||
|
stdout: new(bytes.Buffer),
|
||||||
|
stderr: new(bytes.Buffer),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var exitcode uint8
|
var exitcode uint8
|
||||||
stdout, stderr, err := execCommand(cmd, terminalOut)
|
stdout, stderr, err := execCommand(cmd, strms)
|
||||||
|
|
||||||
if code, ok := interp.IsExitStatus(err); ok {
|
if code, ok := interp.IsExitStatus(err); ok {
|
||||||
exitcode = code
|
exitcode = code
|
||||||
|
@ -187,11 +278,12 @@ func hlrun(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
exitcode = 1
|
exitcode = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
stdoutStr := ""
|
var stdoutStr, stderrStr string
|
||||||
stderrStr := ""
|
if stdoutBuf, ok := stdout.(*bytes.Buffer); ok {
|
||||||
if !terminalOut {
|
stdoutStr = stdoutBuf.String()
|
||||||
stdoutStr = stdout.(*bytes.Buffer).String()
|
}
|
||||||
stderrStr = stderr.(*bytes.Buffer).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
|
return c.PushingNext(t.Runtime, rt.IntValue(int64(exitcode)), rt.StringValue(stdoutStr), rt.StringValue(stderrStr)), nil
|
||||||
|
@ -609,7 +701,7 @@ func hlwhich(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
cmd := strings.Split(alias, " ")[0]
|
cmd := strings.Split(alias, " ")[0]
|
||||||
|
|
||||||
// check for commander
|
// check for commander
|
||||||
if commands[cmd] != nil {
|
if cmds.Commands[cmd] != nil {
|
||||||
// they dont resolve to a path, so just send the cmd
|
// they dont resolve to a path, so just send the cmd
|
||||||
return c.PushingNext1(t.Runtime, rt.StringValue(cmd)), nil
|
return c.PushingNext1(t.Runtime, rt.StringValue(cmd)), nil
|
||||||
}
|
}
|
||||||
|
@ -712,5 +804,14 @@ func hlhinter(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
// #example
|
// #example
|
||||||
// #param line string
|
// #param line string
|
||||||
func hlhighlighter(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func hlhighlighter(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
return c.Next(), nil
|
if err := c.Check1Arg(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
line, err := c.StringArg(0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.PushingNext1(t.Runtime, rt.StringValue(line)), nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -488,8 +488,12 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
mdTable.SetContent(i - diff, 0, fmt.Sprintf(`<a href="#%s">%s</a>`, dps.FuncName, dps.FuncSig))
|
mdTable.SetContent(i - diff, 0, fmt.Sprintf(`<a href="#%s">%s</a>`, dps.FuncName, dps.FuncSig))
|
||||||
|
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])
|
mdTable.SetContent(i - diff, 1, dps.Doc[0])
|
||||||
}
|
}
|
||||||
|
}
|
||||||
f.WriteString(mdTable.String())
|
f.WriteString(mdTable.String())
|
||||||
f.WriteString("\n")
|
f.WriteString("\n")
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,7 +128,7 @@ func binaryComplete(query, ctx string, fields []string) ([]string, string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// add lua registered commands to completions
|
// add lua registered commands to completions
|
||||||
for cmdName := range commands {
|
for cmdName := range cmds.Commands {
|
||||||
if strings.HasPrefix(cmdName, query) {
|
if strings.HasPrefix(cmdName, query) {
|
||||||
completions = append(completions, cmdName)
|
completions = append(completions, cmdName)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
that will print `Hello world!` to output. One question you may
|
||||||
have is: What is the `sinks` parameter?
|
have is: What is the `sinks` parameter?
|
||||||
|
|
||||||
The `sinks` parameter is a table with 3 keys: `in`, `out`,
|
The `sinks` parameter is a table with 3 keys: `input`, `out`, and `err`.
|
||||||
and `err`. All of them are a <a href="/Hilbish/docs/api/hilbish/#sink" style="text-decoration: none;">Sink</a>.
|
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 <a href="/Hilbish/docs/api/hilbish/#sink" style="text-decoration: none;">Sink</a>.
|
||||||
|
In the future, `sinks.in` will be removed.
|
||||||
|
|
||||||
- `in` is the standard input.
|
- `in` is the standard input.
|
||||||
You may use the read functions on this sink to get input from the user.
|
You may use the read functions on this sink to get input from the user.
|
||||||
|
@ -41,6 +44,7 @@ This sink is for writing errors, as the name would suggest.
|
||||||
|----|----|
|
|----|----|
|
||||||
|<a href="#deregister">deregister(name)</a>|Removes the named command. Note that this will only remove Commander-registered commands.|
|
|<a href="#deregister">deregister(name)</a>|Removes the named command. Note that this will only remove Commander-registered commands.|
|
||||||
|<a href="#register">register(name, cb)</a>|Adds a new command with the given `name`. When Hilbish has to run a command with a name,|
|
|<a href="#register">register(name, cb)</a>|Adds a new command with the given `name`. When Hilbish has to run a command with a name,|
|
||||||
|
|<a href="#registry">registry() -> table</a>|Returns all registered commanders. Returns a list of tables with the following keys:|
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
<div id='deregister'>
|
<div id='deregister'>
|
||||||
|
@ -91,3 +95,19 @@ end)
|
||||||
```
|
```
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<div id='registry'>
|
||||||
|
<h4 class='heading'>
|
||||||
|
commander.registry() -> table
|
||||||
|
<a href="#registry" class='heading-link'>
|
||||||
|
<i class="fas fa-paperclip"></i>
|
||||||
|
</a>
|
||||||
|
</h4>
|
||||||
|
|
||||||
|
Returns all registered commanders. Returns a list of tables with the following keys:
|
||||||
|
- `exec`: The function used to run the commander. Commanders require args and sinks to be passed.
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
This function has no parameters.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ library offers more functions and will work on any operating system Hilbish does
|
||||||
|<a href="#glob">glob(pattern) -> matches (table)</a>|Match all files based on the provided `pattern`.|
|
|<a href="#glob">glob(pattern) -> matches (table)</a>|Match all files based on the provided `pattern`.|
|
||||||
|<a href="#join">join(...path) -> string</a>|Takes any list of paths and joins them based on the operating system's path separator.|
|
|<a href="#join">join(...path) -> string</a>|Takes any list of paths and joins them based on the operating system's path separator.|
|
||||||
|<a href="#mkdir">mkdir(name, recursive)</a>|Creates a new directory with the provided `name`.|
|
|<a href="#mkdir">mkdir(name, recursive)</a>|Creates a new directory with the provided `name`.|
|
||||||
|
|<a href="#pipe">fpipe() -> File, File</a>|Returns a pair of connected files, also known as a pipe.|
|
||||||
|<a href="#readdir">readdir(path) -> table[string]</a>|Returns a list of all files and directories in the provided path.|
|
|<a href="#readdir">readdir(path) -> table[string]</a>|Returns a list of all files and directories in the provided path.|
|
||||||
|<a href="#stat">stat(path) -> {}</a>|Returns the information about a given `path`.|
|
|<a href="#stat">stat(path) -> {}</a>|Returns the information about a given `path`.|
|
||||||
|
|
||||||
|
@ -183,6 +184,22 @@ fs.mkdir('./foo/bar', true)
|
||||||
```
|
```
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<div id='pipe'>
|
||||||
|
<h4 class='heading'>
|
||||||
|
fs.fpipe() -> File, File
|
||||||
|
<a href="#pipe" class='heading-link'>
|
||||||
|
<i class="fas fa-paperclip"></i>
|
||||||
|
</a>
|
||||||
|
</h4>
|
||||||
|
|
||||||
|
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.
|
||||||
|
</div>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
<div id='readdir'>
|
<div id='readdir'>
|
||||||
<h4 class='heading'>
|
<h4 class='heading'>
|
||||||
|
|
|
@ -28,7 +28,7 @@ interfaces and functions which directly relate to shell functionality.
|
||||||
|<a href="#prependPath">prependPath(dir)</a>|Prepends `dir` to $PATH.|
|
|<a href="#prependPath">prependPath(dir)</a>|Prepends `dir` to $PATH.|
|
||||||
|<a href="#prompt">prompt(str, typ)</a>|Changes the shell prompt to the provided string.|
|
|<a href="#prompt">prompt(str, typ)</a>|Changes the shell prompt to the provided string.|
|
||||||
|<a href="#read">read(prompt) -> input (string)</a>|Read input from the user, using Hilbish's line editor/input reader.|
|
|<a href="#read">read(prompt) -> input (string)</a>|Read input from the user, using Hilbish's line editor/input reader.|
|
||||||
|<a href="#run">run(cmd, returnOut) -> exitCode (number), stdout (string), stderr (string)</a>|Runs `cmd` in Hilbish's shell script interpreter.|
|
|<a href="#run">run(cmd, streams) -> exitCode (number), stdout (string), stderr (string)</a>|Runs `cmd` in Hilbish's shell script interpreter.|
|
||||||
|<a href="#runnerMode">runnerMode(mode)</a>|Sets the execution/runner mode for interactive Hilbish.|
|
|<a href="#runnerMode">runnerMode(mode)</a>|Sets the execution/runner mode for interactive Hilbish.|
|
||||||
|<a href="#timeout">timeout(cb, time) -> @Timer</a>|Executed the `cb` function after a period of `time`.|
|
|<a href="#timeout">timeout(cb, time) -> @Timer</a>|Executed the `cb` function after a period of `time`.|
|
||||||
|<a href="#which">which(name) -> string</a>|Checks if `name` is a valid command.|
|
|<a href="#which">which(name) -> string</a>|Checks if `name` is a valid command.|
|
||||||
|
@ -413,21 +413,44 @@ Text to print before input, can be empty.
|
||||||
<hr>
|
<hr>
|
||||||
<div id='run'>
|
<div id='run'>
|
||||||
<h4 class='heading'>
|
<h4 class='heading'>
|
||||||
hilbish.run(cmd, returnOut) -> exitCode (number), stdout (string), stderr (string)
|
hilbish.run(cmd, streams) -> exitCode (number), stdout (string), stderr (string)
|
||||||
<a href="#run" class='heading-link'>
|
<a href="#run" class='heading-link'>
|
||||||
<i class="fas fa-paperclip"></i>
|
<i class="fas fa-paperclip"></i>
|
||||||
</a>
|
</a>
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
Runs `cmd` in Hilbish's shell script interpreter.
|
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.
|
||||||
|
|
||||||
#### Parameters
|
#### Parameters
|
||||||
`string` **`cmd`**
|
`string` **`cmd`**
|
||||||
|
|
||||||
|
|
||||||
`boolean` **`returnOut`**
|
`table|boolean` **`streams`**
|
||||||
If this is true, the function will return the standard output and error of the command instead of printing it.
|
|
||||||
|
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
```lua
|
||||||
|
|
||||||
|
// 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
|
||||||
|
})
|
||||||
|
|
||||||
|
```
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
|
@ -11,4 +11,8 @@ function commander.deregister(name) end
|
||||||
---
|
---
|
||||||
function commander.register(name, cb) end
|
function commander.register(name, cb) end
|
||||||
|
|
||||||
|
--- Returns all registered commanders. Returns a list of tables with the following keys:
|
||||||
|
--- - `exec`: The function used to run the commander. Commanders require args and sinks to be passed.
|
||||||
|
function commander.registry() end
|
||||||
|
|
||||||
return commander
|
return commander
|
||||||
|
|
|
@ -34,6 +34,10 @@ function fs.join(...path) end
|
||||||
---
|
---
|
||||||
function fs.mkdir(name, recursive) 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.
|
--- Returns a list of all files and directories in the provided path.
|
||||||
function fs.readdir(path) end
|
function fs.readdir(path) end
|
||||||
|
|
||||||
|
|
|
@ -132,7 +132,13 @@ function hilbish.prompt(str, typ) end
|
||||||
function hilbish.read(prompt) end
|
function hilbish.read(prompt) end
|
||||||
|
|
||||||
--- Runs `cmd` in Hilbish's shell script interpreter.
|
--- Runs `cmd` in Hilbish's shell script interpreter.
|
||||||
function hilbish.run(cmd, returnOut) end
|
--- 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.
|
||||||
|
---
|
||||||
|
function hilbish.run(cmd, streams) end
|
||||||
|
|
||||||
--- Sets the execution/runner mode for interactive Hilbish.
|
--- Sets the execution/runner mode for interactive Hilbish.
|
||||||
--- This determines whether Hilbish wll try to run input as Lua
|
--- This determines whether Hilbish wll try to run input as Lua
|
||||||
|
|
46
exec.go
46
exec.go
|
@ -28,6 +28,12 @@ var errNotExec = errors.New("not executable")
|
||||||
var errNotFound = errors.New("not found")
|
var errNotFound = errors.New("not found")
|
||||||
var runnerMode rt.Value = rt.StringValue("hybrid")
|
var runnerMode rt.Value = rt.StringValue("hybrid")
|
||||||
|
|
||||||
|
type streams struct {
|
||||||
|
stdout io.Writer
|
||||||
|
stderr io.Writer
|
||||||
|
stdin io.Reader
|
||||||
|
}
|
||||||
|
|
||||||
type execError struct{
|
type execError struct{
|
||||||
typ string
|
typ string
|
||||||
cmd 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) {
|
func execSh(cmdString string) (string, uint8, bool, error) {
|
||||||
_, _, err := execCommand(cmdString, true)
|
_, _, err := execCommand(cmdString, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// If input is incomplete, start multiline prompting
|
// If input is incomplete, start multiline prompting
|
||||||
if syntax.IsIncomplete(err) {
|
if syntax.IsIncomplete(err) {
|
||||||
|
@ -257,7 +263,7 @@ func execSh(cmdString string) (string, uint8, bool, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run command in sh interpreter
|
// 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), "")
|
file, err := syntax.NewParser().Parse(strings.NewReader(cmd), "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
@ -265,15 +271,24 @@ func execCommand(cmd string, terminalOut bool) (io.Writer, io.Writer, error) {
|
||||||
|
|
||||||
runner, _ := interp.New()
|
runner, _ := interp.New()
|
||||||
|
|
||||||
var stdout io.Writer
|
if strms == nil {
|
||||||
var stderr io.Writer
|
strms = &streams{}
|
||||||
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.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)
|
buf := new(bytes.Buffer)
|
||||||
printer := syntax.NewPrinter()
|
printer := syntax.NewPrinter()
|
||||||
|
|
||||||
|
@ -292,11 +307,11 @@ func execCommand(cmd string, terminalOut bool) (io.Writer, io.Writer, error) {
|
||||||
interp.ExecHandler(execHandle(bg))(runner)
|
interp.ExecHandler(execHandle(bg))(runner)
|
||||||
err = runner.Run(context.TODO(), stmt)
|
err = runner.Run(context.TODO(), stmt)
|
||||||
if err != nil {
|
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 {
|
func execHandle(bg bool) interp.ExecHandlerFunc {
|
||||||
|
@ -327,17 +342,18 @@ func execHandle(bg bool) interp.ExecHandlerFunc {
|
||||||
}
|
}
|
||||||
|
|
||||||
hc := interp.HandlerCtx(ctx)
|
hc := interp.HandlerCtx(ctx)
|
||||||
if commands[args[0]] != nil {
|
if cmd := cmds.Commands[args[0]]; cmd != nil {
|
||||||
stdin := newSinkInput(hc.Stdin)
|
stdin := newSinkInput(hc.Stdin)
|
||||||
stdout := newSinkOutput(hc.Stdout)
|
stdout := newSinkOutput(hc.Stdout)
|
||||||
stderr := newSinkOutput(hc.Stderr)
|
stderr := newSinkOutput(hc.Stderr)
|
||||||
|
|
||||||
sinks := rt.NewTable()
|
sinks := rt.NewTable()
|
||||||
sinks.Set(rt.StringValue("in"), rt.UserDataValue(stdin.ud))
|
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("out"), rt.UserDataValue(stdout.ud))
|
||||||
sinks.Set(rt.StringValue("err"), rt.UserDataValue(stderr.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))
|
luaexitcode, err := rt.Call1(l.MainThread(), rt.FunctionValue(cmd), 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)
|
||||||
|
@ -349,7 +365,7 @@ func execHandle(bg bool) interp.ExecHandlerFunc {
|
||||||
exitcode = uint8(code)
|
exitcode = uint8(code)
|
||||||
} else if luaexitcode != rt.NilValue {
|
} else if luaexitcode != rt.NilValue {
|
||||||
// deregister commander
|
// deregister commander
|
||||||
delete(commands, args[0])
|
delete(cmds.Commands, args[0])
|
||||||
fmt.Fprintf(os.Stderr, "Commander did not return number for exit code. %s, you're fired.\n", args[0])
|
fmt.Fprintf(os.Stderr, "Commander did not return number for exit code. %s, you're fired.\n", args[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
24
go.mod
24
go.mod
|
@ -3,26 +3,26 @@ module hilbish
|
||||||
go 1.18
|
go 1.18
|
||||||
|
|
||||||
require (
|
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/atsushinee/go-markdown-generator v0.0.0-20191121114853-83f9e1f68504
|
||||||
github.com/blackfireio/osinfo v1.0.3
|
github.com/blackfireio/osinfo v1.0.5
|
||||||
github.com/maxlandon/readline v0.1.0-beta.0.20211027085530-2b76cabb8036
|
github.com/maxlandon/readline v1.0.14
|
||||||
github.com/pborman/getopt v1.1.0
|
github.com/pborman/getopt v1.1.0
|
||||||
github.com/sahilm/fuzzy v0.1.0
|
github.com/sahilm/fuzzy v0.1.1
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a
|
golang.org/x/sys v0.19.0
|
||||||
golang.org/x/term v0.0.0-20220411215600-e5f449aeb171
|
golang.org/x/term v0.19.0
|
||||||
mvdan.cc/sh/v3 v3.5.1
|
mvdan.cc/sh/v3 v3.8.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect
|
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect
|
||||||
github.com/arnodel/strftime v0.1.6 // 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/kylelemons/godebug v1.1.0 // indirect
|
||||||
github.com/olekukonko/ts v0.0.0-20171002115256-78ecb04241c0 // indirect
|
github.com/olekukonko/ts v0.0.0-20171002115256-78ecb04241c0 // indirect
|
||||||
github.com/rivo/uniseg v0.2.0 // indirect
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
golang.org/x/sync v0.0.0-20220513210516-0976fa681c29 // indirect
|
golang.org/x/sync v0.7.0 // indirect
|
||||||
golang.org/x/text v0.3.7 // 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
|
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 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
|
||||||
|
|
51
go.sum
51
go.sum
|
@ -1,26 +1,21 @@
|
||||||
github.com/Rosettea/golua v0.0.0-20221213193027-cbf6d4e4d345 h1:QNYjYDogUSiNUkffbhFSrSCtpZhofeiVYGFN2FI4wSs=
|
github.com/Rosettea/golua v0.0.0-20240427174124-d239074c1749 h1:jIFnWBTsYw8s7RX7H2AOXjDVhWP3ol7OzUVaPN2KnGI=
|
||||||
github.com/Rosettea/golua v0.0.0-20221213193027-cbf6d4e4d345/go.mod h1:9jzpYPiU2is0HVGCiuIOBSXdergHUW44IEjmuN1UrIE=
|
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 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/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 h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
|
||||||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=
|
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 h1:0hc0pUvk8KhEMXE+htyaOUV42zNcf/csIbjzEFCJqsw=
|
||||||
github.com/arnodel/strftime v0.1.6/go.mod h1:5NbK5XqYK8QpRZpqKNt4OlxLtIB8cotkLk4KTKzJfWs=
|
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 h1:R1/AOzdMbopSliUTTEHvHbyNmnZ3YxY5GvdhTkpPsSY=
|
||||||
github.com/atsushinee/go-markdown-generator v0.0.0-20191121114853-83f9e1f68504/go.mod h1:kHBCvAXJIatTX1pw6tLiOspjGc3MhUDRlog9yrCUS+k=
|
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.5 h1:6hlaWzfcpb87gRmznVf7wSdhysGqLRz9V/xuSdCEXrA=
|
||||||
github.com/blackfireio/osinfo v1.0.3/go.mod h1:Pd987poVNmd5Wsx6PRPw4+w7kLlf9iJxoRKPtPAjOrA=
|
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.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/creack/pty v1.1.15 h1:cKRCLMj3Ddm54bKSpemfQ8AtYFBhAI2MPmdys22fBdc=
|
github.com/creack/pty v1.1.15 h1:cKRCLMj3Ddm54bKSpemfQ8AtYFBhAI2MPmdys22fBdc=
|
||||||
github.com/creack/pty v1.1.15/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
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.11.0 h1:B5w6uuS6ki6iDG+aH/RFeoMb8ijQh/pGabewqp2UeJ0=
|
||||||
github.com/evilsocket/islazy v1.10.6/go.mod h1:OrwQGYg3DuZvXUfmH+KIZDjwTCbrjy48T24TUpGqVVw=
|
github.com/evilsocket/islazy v1.11.0/go.mod h1:muYH4x5MB5YRdkxnrOtrXLIBX6LySj1uFIqys94LKdo=
|
||||||
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/google/renameio v1.0.1/go.mod h1:t/HQoYBZSsWSNK35C6CO/TpPLDVWvxOHboWUAweKUpk=
|
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.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
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/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 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
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 h1:LiZB1h0GIcudcDci2bxbqI6DXV8bF8POAnArqvRrIyw=
|
||||||
github.com/olekukonko/ts v0.0.0-20171002115256-78ecb04241c0/go.mod h1:F/7q8/HZz+TXjlsoZQQKVYvXTZaFH4QRa3y+j1p7MS0=
|
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 h1:eJ3aFZroQqq0bWmraivjQNt6Dmm5M0h2JcDW38/Azb0=
|
||||||
github.com/pborman/getopt v1.1.0/go.mod h1:FxXoW1Re00sQG/+KIkuSqRL/LwQgSkv7uyac+STFsbk=
|
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/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.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
|
||||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
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 h1:d1PiN4RxzIFXCJTvRkvSkKqwtRAl5ZV4lATKtQI0B7I=
|
||||||
github.com/rogpeppe/go-internal v1.8.1-0.20210923151022-86f73c517451/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
|
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.1 h1:ceu5RHF8DGgoi+/dR5PsECjCDH1BE3Fnmpo7aVXOdRA=
|
||||||
github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
|
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-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.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||||
golang.org/x/sync v0.0.0-20220513210516-0976fa681c29/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
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/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
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-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.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
|
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
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/term v0.0.0-20210916214954-140adaaadfaf/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
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.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=
|
||||||
golang.org/x/term v0.0.0-20220411215600-e5f449aeb171/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
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=
|
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
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=
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
mvdan.cc/editorconfig v0.2.0/go.mod h1:lvnnD3BNdBYkhq+B4uBuFFKatfp02eB6HixDvEz91C0=
|
mvdan.cc/editorconfig v0.2.0/go.mod h1:lvnnD3BNdBYkhq+B4uBuFFKatfp02eB6HixDvEz91C0=
|
||||||
|
|
|
@ -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
|
that will print `Hello world!` to output. One question you may
|
||||||
have is: What is the `sinks` parameter?
|
have is: What is the `sinks` parameter?
|
||||||
|
|
||||||
The `sinks` parameter is a table with 3 keys: `in`, `out`,
|
The `sinks` parameter is a table with 3 keys: `input`, `out`, and `err`.
|
||||||
and `err`. All of them are a @Sink.
|
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.
|
- `in` is the standard input.
|
||||||
You may use the read functions on this sink to get input from the user.
|
You may use the read functions on this sink to get input from the user.
|
||||||
|
@ -40,11 +43,13 @@ import (
|
||||||
type Commander struct{
|
type Commander struct{
|
||||||
Events *bait.Bait
|
Events *bait.Bait
|
||||||
Loader packagelib.Loader
|
Loader packagelib.Loader
|
||||||
|
Commands map[string]*rt.Closure
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(rtm *rt.Runtime) Commander {
|
func New(rtm *rt.Runtime) *Commander {
|
||||||
c := Commander{
|
c := &Commander{
|
||||||
Events: bait.New(rtm),
|
Events: bait.New(rtm),
|
||||||
|
Commands: make(map[string]*rt.Closure),
|
||||||
}
|
}
|
||||||
c.Loader = packagelib.Loader{
|
c.Loader = packagelib.Loader{
|
||||||
Load: c.loaderFunc,
|
Load: c.loaderFunc,
|
||||||
|
@ -58,6 +63,7 @@ func (c *Commander) loaderFunc(rtm *rt.Runtime) (rt.Value, func()) {
|
||||||
exports := map[string]util.LuaExport{
|
exports := map[string]util.LuaExport{
|
||||||
"register": util.LuaExport{c.cregister, 2, false},
|
"register": util.LuaExport{c.cregister, 2, false},
|
||||||
"deregister": util.LuaExport{c.cderegister, 1, false},
|
"deregister": util.LuaExport{c.cderegister, 1, false},
|
||||||
|
"registry": util.LuaExport{c.cregistry, 0, false},
|
||||||
}
|
}
|
||||||
mod := rt.NewTable()
|
mod := rt.NewTable()
|
||||||
util.SetExports(rtm, mod, exports)
|
util.SetExports(rtm, mod, exports)
|
||||||
|
@ -88,7 +94,7 @@ func (c *Commander) cregister(t *rt.Thread, ct *rt.GoCont) (rt.Cont, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Events.Emit("commandRegister", cmdName, cmd)
|
c.Commands[cmdName] = cmd
|
||||||
|
|
||||||
return ct.Next(), err
|
return ct.Next(), err
|
||||||
}
|
}
|
||||||
|
@ -105,7 +111,23 @@ func (c *Commander) cderegister(t *rt.Thread, ct *rt.GoCont) (rt.Cont, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Events.Emit("commandDeregister", cmdName)
|
delete(c.Commands, cmdName)
|
||||||
|
|
||||||
return ct.Next(), err
|
return ct.Next(), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// registry() -> table
|
||||||
|
// Returns all registered commanders. Returns a list of tables with the following keys:
|
||||||
|
// - `exec`: The function used to run the commander. Commanders require args and sinks to be passed.
|
||||||
|
// #returns table
|
||||||
|
func (c *Commander) cregistry(t *rt.Thread, ct *rt.GoCont) (rt.Cont, error) {
|
||||||
|
registryLua := rt.NewTable()
|
||||||
|
for cmdName, cmd := range c.Commands {
|
||||||
|
cmdTbl := rt.NewTable()
|
||||||
|
cmdTbl.Set(rt.StringValue("exec"), rt.FunctionValue(cmd))
|
||||||
|
|
||||||
|
registryLua.Set(rt.StringValue(cmdName), rt.TableValue(cmdTbl))
|
||||||
|
}
|
||||||
|
|
||||||
|
return ct.PushingNext1(t.Runtime, rt.TableValue(registryLua)), nil
|
||||||
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
|
|
||||||
rt "github.com/arnodel/golua/runtime"
|
rt "github.com/arnodel/golua/runtime"
|
||||||
"github.com/arnodel/golua/lib/packagelib"
|
"github.com/arnodel/golua/lib/packagelib"
|
||||||
|
"github.com/arnodel/golua/lib/iolib"
|
||||||
)
|
)
|
||||||
|
|
||||||
var Loader = packagelib.Loader{
|
var Loader = packagelib.Loader{
|
||||||
|
@ -36,6 +37,7 @@ func loaderFunc(rtm *rt.Runtime) (rt.Value, func()) {
|
||||||
"dir": util.LuaExport{fdir, 1, false},
|
"dir": util.LuaExport{fdir, 1, false},
|
||||||
"glob": util.LuaExport{fglob, 1, false},
|
"glob": util.LuaExport{fglob, 1, false},
|
||||||
"join": util.LuaExport{fjoin, 0, true},
|
"join": util.LuaExport{fjoin, 0, true},
|
||||||
|
"pipe": util.LuaExport{fpipe, 0, false},
|
||||||
}
|
}
|
||||||
mod := rt.NewTable()
|
mod := rt.NewTable()
|
||||||
util.SetExports(rtm, mod, exports)
|
util.SetExports(rtm, mod, exports)
|
||||||
|
@ -226,6 +228,22 @@ func fmkdir(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
return c.Next(), err
|
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]
|
// readdir(path) -> table[string]
|
||||||
// Returns a list of all files and directories in the provided path.
|
// Returns a list of all files and directories in the provided path.
|
||||||
// #param dir string
|
// #param dir string
|
||||||
|
|
14
lua.go
14
lua.go
|
@ -33,19 +33,7 @@ func luaInit() {
|
||||||
lib.LoadLibs(l, fs.Loader)
|
lib.LoadLibs(l, fs.Loader)
|
||||||
lib.LoadLibs(l, terminal.Loader)
|
lib.LoadLibs(l, terminal.Loader)
|
||||||
|
|
||||||
cmds := commander.New(l)
|
cmds = commander.New(l)
|
||||||
// When a command from Lua is added, register it for use
|
|
||||||
cmds.Events.On("commandRegister", func(args ...interface{}) {
|
|
||||||
cmdName := args[0].(string)
|
|
||||||
cmd := args[1].(*rt.Closure)
|
|
||||||
|
|
||||||
commands[cmdName] = cmd
|
|
||||||
})
|
|
||||||
cmds.Events.On("commandDeregister", func(args ...interface{}) {
|
|
||||||
cmdName := args[0].(string)
|
|
||||||
|
|
||||||
delete(commands, cmdName)
|
|
||||||
})
|
|
||||||
lib.LoadLibs(l, cmds.Loader)
|
lib.LoadLibs(l, cmds.Loader)
|
||||||
|
|
||||||
hooks = bait.New(l)
|
hooks = bait.New(l)
|
||||||
|
|
3
main.go
3
main.go
|
@ -14,6 +14,7 @@ import (
|
||||||
|
|
||||||
"hilbish/util"
|
"hilbish/util"
|
||||||
"hilbish/golibs/bait"
|
"hilbish/golibs/bait"
|
||||||
|
"hilbish/golibs/commander"
|
||||||
|
|
||||||
rt "github.com/arnodel/golua/runtime"
|
rt "github.com/arnodel/golua/runtime"
|
||||||
"github.com/pborman/getopt"
|
"github.com/pborman/getopt"
|
||||||
|
@ -25,7 +26,6 @@ var (
|
||||||
l *rt.Runtime
|
l *rt.Runtime
|
||||||
lr *lineReader
|
lr *lineReader
|
||||||
|
|
||||||
commands = map[string]*rt.Closure{}
|
|
||||||
luaCompletions = map[string]*rt.Closure{}
|
luaCompletions = map[string]*rt.Closure{}
|
||||||
|
|
||||||
confDir string
|
confDir string
|
||||||
|
@ -33,6 +33,7 @@ var (
|
||||||
curuser *user.User
|
curuser *user.User
|
||||||
|
|
||||||
hooks *bait.Bait
|
hooks *bait.Bait
|
||||||
|
cmds *commander.Commander
|
||||||
defaultConfPath string
|
defaultConfPath string
|
||||||
defaultHistPath string
|
defaultHistPath string
|
||||||
)
|
)
|
||||||
|
|
|
@ -9,6 +9,8 @@ commander.register('cat', function(args, sinks)
|
||||||
usage: cat [file]...]]
|
usage: cat [file]...]]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local chunkSize = 2^13 -- 8K buffer size
|
||||||
|
|
||||||
for _, fName in ipairs(args) do
|
for _, fName in ipairs(args) do
|
||||||
local f = io.open(fName)
|
local f = io.open(fName)
|
||||||
if f == nil then
|
if f == nil then
|
||||||
|
@ -17,7 +19,11 @@ usage: cat [file]...]]
|
||||||
goto continue
|
goto continue
|
||||||
end
|
end
|
||||||
|
|
||||||
sinks.out:writeln(f:read '*a')
|
while true do
|
||||||
|
local block = f:read(chunkSize)
|
||||||
|
if not block then break end
|
||||||
|
sinks.out:write(block)
|
||||||
|
end
|
||||||
::continue::
|
::continue::
|
||||||
end
|
end
|
||||||
io.flush()
|
io.flush()
|
||||||
|
|
|
@ -17,8 +17,8 @@ function M.renderCodeBlock(text)
|
||||||
end
|
end
|
||||||
|
|
||||||
for i, line in ipairs(lines) do
|
for i, line in ipairs(lines) do
|
||||||
lines[i] = ' ' .. M.highlight(line:sub(0, longest))
|
lines[i] = lunacolors.format('{greyBg}' .. ' ' .. M.highlight(line:sub(0, longest))
|
||||||
.. string.rep(' ', longest - line:len()) .. ' '
|
.. string.rep(' ', longest - line:len()) .. ' ')
|
||||||
end
|
end
|
||||||
|
|
||||||
return '\n' .. lunacolors.format('{greyBg}' .. table.concat(lines, '\n')) .. '\n'
|
return '\n' .. lunacolors.format('{greyBg}' .. table.concat(lines, '\n')) .. '\n'
|
||||||
|
|
|
@ -61,17 +61,24 @@ function Greenhouse:updateCurrentPage(text)
|
||||||
page:setText(text)
|
page:setText(text)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local ansiPatters = {
|
||||||
|
'\x1b%[%d+;%d+;%d+;%d+;%d+%w',
|
||||||
|
'\x1b%[%d+;%d+;%d+;%d+%w',
|
||||||
|
'\x1b%[%d+;%d+;%d+%w',
|
||||||
|
'\x1b%[%d+;%d+%w',
|
||||||
|
'\x1b%[%d+%w'
|
||||||
|
}
|
||||||
|
|
||||||
function Greenhouse:sub(str, offset, limit)
|
function Greenhouse:sub(str, offset, limit)
|
||||||
local overhead = 0
|
local overhead = 0
|
||||||
local function addOverhead(s)
|
local function addOverhead(s)
|
||||||
overhead = overhead + string.len(s)
|
overhead = overhead + string.len(s)
|
||||||
end
|
end
|
||||||
|
|
||||||
local s = str:gsub('\x1b%[%d+;%d+;%d+;%d+;%d+%w', addOverhead)
|
local s = str
|
||||||
:gsub('\x1b%[%d+;%d+;%d+;%d+%w', addOverhead)
|
for _, pat in ipairs(ansiPatters) do
|
||||||
:gsub('\x1b%[%d+;%d+;%d+%w',addOverhead)
|
s = s:gsub(pat, addOverhead)
|
||||||
:gsub('\x1b%[%d+;%d+%w', addOverhead)
|
end
|
||||||
:gsub('\x1b%[%d+%w', addOverhead)
|
|
||||||
|
|
||||||
return s:sub(offset, utf8.offset(str, limit + overhead) or limit + overhead)
|
return s:sub(offset, utf8.offset(str, limit + overhead) or limit + overhead)
|
||||||
--return s:sub(offset, limit + overhead)
|
--return s:sub(offset, limit + overhead)
|
||||||
|
@ -94,14 +101,40 @@ function Greenhouse:draw()
|
||||||
self.sink:write(ansikit.getCSI(2, 'J'))
|
self.sink:write(ansikit.getCSI(2, 'J'))
|
||||||
|
|
||||||
local writer = self.sink.writeln
|
local writer = self.sink.writeln
|
||||||
|
self.attributes = {}
|
||||||
for i = offset, offset + self.region.height - 1 do
|
for i = offset, offset + self.region.height - 1 do
|
||||||
|
local resetEnd = false
|
||||||
if i > #lines then break end
|
if i > #lines then break end
|
||||||
|
|
||||||
if i == offset + self.region.height - 1 then writer = self.sink.write end
|
if i == offset + self.region.height - 1 then writer = self.sink.write end
|
||||||
|
|
||||||
self.sink:write(ansikit.getCSI(self.start + i - offset .. ';1', 'H'))
|
self.sink:write(ansikit.getCSI(self.start + i - offset .. ';1', 'H'))
|
||||||
local line = lines[i]:gsub('{separator}', function() return self.separator:rep(self.region.width - 1) end)
|
local line = lines[i]:gsub('{separator}', function() return self.separator:rep(self.region.width - 1) end)
|
||||||
writer(self.sink, self:sub(line:gsub('\t', ' '), self.horizOffset, self.region.width))
|
for _, pat in ipairs(ansiPatters) do
|
||||||
|
line:gsub(pat, function(s)
|
||||||
|
if s == lunacolors.formatColors.reset then
|
||||||
|
self.attributes = {}
|
||||||
|
resetEnd = true
|
||||||
|
else
|
||||||
|
--resetEnd = false
|
||||||
|
--table.insert(self.attributes, s)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
--[[
|
||||||
|
if #self.attributes ~= 0 then
|
||||||
|
for _, attr in ipairs(self.attributes) do
|
||||||
|
--writer(self.sink, attr)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
]]--
|
||||||
|
|
||||||
|
self.sink:write(lunacolors.formatColors.reset)
|
||||||
|
writer(self.sink, self:sub(line:gsub('\t', ' '), self.horizOffset, self.region.width + self.horizOffset))
|
||||||
|
if resetEnd then
|
||||||
|
self.sink:write(lunacolors.formatColors.reset)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
writer(self.sink, '\27[0m')
|
writer(self.sink, '\27[0m')
|
||||||
self:render()
|
self:render()
|
||||||
|
@ -271,6 +304,15 @@ end
|
||||||
function Greenhouse:input(char)
|
function Greenhouse:input(char)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function read()
|
||||||
|
terminal.saveState()
|
||||||
|
terminal.setRaw()
|
||||||
|
local c = hilbish.editor.readChar()
|
||||||
|
|
||||||
|
terminal.restoreState()
|
||||||
|
return c
|
||||||
|
end
|
||||||
|
|
||||||
function Greenhouse:initUi()
|
function Greenhouse:initUi()
|
||||||
local ansikit = require 'ansikit'
|
local ansikit = require 'ansikit'
|
||||||
local bait = require 'bait'
|
local bait = require 'bait'
|
||||||
|
@ -280,14 +322,17 @@ function Greenhouse:initUi()
|
||||||
local Page = require 'nature.greenhouse.page'
|
local Page = require 'nature.greenhouse.page'
|
||||||
local done = false
|
local done = false
|
||||||
|
|
||||||
bait.catch('signal.sigint', function()
|
local function sigint()
|
||||||
ansikit.clear()
|
ansikit.clear()
|
||||||
done = true
|
done = true
|
||||||
end)
|
end
|
||||||
|
|
||||||
bait.catch('signal.resize', function()
|
local function resize()
|
||||||
self:update()
|
self:update()
|
||||||
end)
|
end
|
||||||
|
bait.catch('signal.sigint', sigint)
|
||||||
|
|
||||||
|
bait.catch('signal.resize', resize)
|
||||||
|
|
||||||
ansikit.screenAlt()
|
ansikit.screenAlt()
|
||||||
ansikit.clear(true)
|
ansikit.clear(true)
|
||||||
|
@ -311,15 +356,10 @@ function Greenhouse:initUi()
|
||||||
|
|
||||||
ansikit.showCursor()
|
ansikit.showCursor()
|
||||||
ansikit.screenMain()
|
ansikit.screenMain()
|
||||||
end
|
|
||||||
|
|
||||||
function read()
|
self = nil
|
||||||
terminal.saveState()
|
bait.release('signal.sigint', sigint)
|
||||||
terminal.setRaw()
|
bait.release('signal.resize', resize)
|
||||||
local c = hilbish.editor.readChar()
|
|
||||||
|
|
||||||
terminal.restoreState()
|
|
||||||
return c
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return Greenhouse
|
return Greenhouse
|
||||||
|
|
13
rl.go
13
rl.go
|
@ -70,11 +70,8 @@ func newLineReader(prompt string, noHist bool) *lineReader {
|
||||||
hooks.Emit("hilbish.vimAction", actionStr, args)
|
hooks.Emit("hilbish.vimAction", actionStr, args)
|
||||||
}
|
}
|
||||||
rl.HintText = func(line []rune, pos int) []rune {
|
rl.HintText = func(line []rune, pos int) []rune {
|
||||||
if hinter == nil {
|
hinter := hshMod.Get(rt.StringValue("hinter"))
|
||||||
return []rune{}
|
retVal, err := rt.Call1(l.MainThread(), hinter,
|
||||||
}
|
|
||||||
|
|
||||||
retVal, err := rt.Call1(l.MainThread(), rt.FunctionValue(hinter),
|
|
||||||
rt.StringValue(string(line)), rt.IntValue(int64(pos)))
|
rt.StringValue(string(line)), rt.IntValue(int64(pos)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
|
@ -89,10 +86,8 @@ func newLineReader(prompt string, noHist bool) *lineReader {
|
||||||
return []rune(hintText)
|
return []rune(hintText)
|
||||||
}
|
}
|
||||||
rl.SyntaxHighlighter = func(line []rune) string {
|
rl.SyntaxHighlighter = func(line []rune) string {
|
||||||
if highlighter == nil {
|
highlighter := hshMod.Get(rt.StringValue("highlighter"))
|
||||||
return string(line)
|
retVal, err := rt.Call1(l.MainThread(), highlighter,
|
||||||
}
|
|
||||||
retVal, err := rt.Call1(l.MainThread(), rt.FunctionValue(highlighter),
|
|
||||||
rt.StringValue(string(line)))
|
rt.StringValue(string(line)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
|
|
Loading…
Reference in New Issue