mirror of https://github.com/Hilbis/Hilbish
Compare commits
No commits in common. "1339dc4a2f2e1ecfca4289f799631ab2cd337769" and "e3c25586e42f770f85401440cb32cc6752fdfd39" have entirely different histories.
1339dc4a2f
...
e3c25586e4
|
@ -27,7 +27,7 @@ jobs:
|
||||||
with:
|
with:
|
||||||
go-version: '1.17.7'
|
go-version: '1.17.7'
|
||||||
- name: Build
|
- name: Build
|
||||||
run: GOOS=${{ matrix.goos }} GOARCH=${{ matrix.goarch }} make
|
run: GOOS=${{ matrix.goos }} GOARCH=${{ matrix.goarch }} go build
|
||||||
- uses: actions/upload-artifact@v2
|
- uses: actions/upload-artifact@v2
|
||||||
if: matrix.goos == 'windows'
|
if: matrix.goos == 'windows'
|
||||||
with:
|
with:
|
||||||
|
|
|
@ -46,8 +46,6 @@ includes git commit, branch, and (new!!) release name.
|
||||||
- Added `fg` and `bg` builtins
|
- Added `fg` and `bg` builtins
|
||||||
- `job.foreground()` and `job.background()`, when `job` is a job object,
|
- `job.foreground()` and `job.background()`, when `job` is a job object,
|
||||||
foreground and backgrounds a job respectively.
|
foreground and backgrounds a job respectively.
|
||||||
- Friendlier functions to the `hilbish.runner` interface, which also allow
|
|
||||||
having and using multiple runners.
|
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- **Breaking Change:** Upgraded to Lua 5.4.
|
- **Breaking Change:** Upgraded to Lua 5.4.
|
||||||
|
@ -58,9 +56,6 @@ This is probably one of (if not the) biggest things in this release.
|
||||||
user input, exit code, and error. User input has been added to the return to
|
user input, exit code, and error. User input has been added to the return to
|
||||||
account for runners wanting to prompt for continued input, and to add it
|
account for runners wanting to prompt for continued input, and to add it
|
||||||
properly to history.
|
properly to history.
|
||||||
- **Breaking Change:** Job objects and timers are now Lua userdata instead
|
|
||||||
of a table, so their functions require you to call them with a colon instead
|
|
||||||
of a dot. (ie. `job.stop()` -> `job:stop()`)
|
|
||||||
- All `fs` module functions which take paths now implicitly expand ~ to home.
|
- All `fs` module functions which take paths now implicitly expand ~ to home.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
4
api.go
4
api.go
|
@ -476,7 +476,7 @@ func hltimeout(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
timer := timers.create(timerTimeout, interval, cb)
|
timer := timers.create(timerTimeout, interval, cb)
|
||||||
timer.start()
|
timer.start()
|
||||||
|
|
||||||
return c.PushingNext1(t.Runtime, rt.UserDataValue(timer.ud)), nil
|
return c.PushingNext1(t.Runtime, timer.lua()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// interval(cb, time)
|
// interval(cb, time)
|
||||||
|
@ -502,7 +502,7 @@ func hlinterval(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
timer := timers.create(timerInterval, interval, cb)
|
timer := timers.create(timerInterval, interval, cb)
|
||||||
timer.start()
|
timer.start()
|
||||||
|
|
||||||
return c.PushingNext1(t.Runtime, rt.UserDataValue(timer.ud)), nil
|
return c.PushingNext1(t.Runtime, timer.lua()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// complete(scope, cb)
|
// complete(scope, cb)
|
||||||
|
|
|
@ -20,11 +20,8 @@ and `execPath` is an absolute path for the command executable.
|
||||||
- `disown(id)`: Removes a job by ID from the job table.
|
- `disown(id)`: Removes a job by ID from the job table.
|
||||||
|
|
||||||
# Job Object
|
# Job Object
|
||||||
A job object is a piece of `userdata`. All the functions of a job require
|
A job object on the Lua side is a table with some functions.
|
||||||
you to call them with a colon, since they are *methods* for the job object.
|
On the under side it represents a job in the job table.
|
||||||
Example: hilbish.jobs.last():foreground()
|
|
||||||
Which will foreground the last job.
|
|
||||||
|
|
||||||
You can still have a job object for a disowned job,
|
You can still have a job object for a disowned job,
|
||||||
it just won't be *working* anywhere. :^)
|
it just won't be *working* anywhere. :^)
|
||||||
|
|
||||||
|
|
|
@ -35,21 +35,8 @@ The exit code has to be a number, it will be 0 otherwise and the error can be
|
||||||
`nil` to indicate no error.
|
`nil` to indicate no error.
|
||||||
|
|
||||||
## Functions
|
## Functions
|
||||||
These are the "low level" functions for the `hilbish.runner` interface.
|
These are the functions for the `hilbish.runner` interface
|
||||||
|
|
||||||
+ setMode(mode) > The same as `hilbish.runnerMode`
|
+ setMode(mode) > The same as `hilbish.runnerMode`
|
||||||
+ sh(input) -> input, code, err > Runs `input` in Hilbish's sh interpreter
|
+ sh(input) -> input, code, err > Runs `input` in Hilbish's sh interpreter
|
||||||
+ lua(input) -> input, code, err > Evals `input` as Lua code
|
+ lua(input) -> input, code, err > Evals `input` as Lua code
|
||||||
|
|
||||||
The others here are defined in Lua and have EmmyLua documentation.
|
|
||||||
These functions should be preferred over the previous ones.
|
|
||||||
+ setCurrent(mode) > The same as `setMode`, but works with runners managed
|
|
||||||
via the functions below.
|
|
||||||
+ add(name, runner) > Adds a runner to a table of available runners. The `runner`
|
|
||||||
argument is either a function or a table with a run callback.
|
|
||||||
+ set(name, runner) > The same as `add` but requires passing a table and
|
|
||||||
overwrites if the `name`d runner already exists.
|
|
||||||
+ get(name) > runner > Gets a runner by name. It is a table with at least a
|
|
||||||
run function, to run input.
|
|
||||||
+ exec(cmd, runnerName) > Runs `cmd` with a runner. If `runnerName` isn't passed,
|
|
||||||
the current runner mode is used.
|
|
||||||
|
|
|
@ -16,17 +16,9 @@ a timer via ID.
|
||||||
when the timer is triggered.
|
when the timer is triggered.
|
||||||
|
|
||||||
# Timer Object
|
# Timer Object
|
||||||
All those previously mentioned functions return a `timer` object, to which
|
Those previously mentioned functions return a `timer` object, to which you can
|
||||||
you can stop and start a timer again.
|
stop and start a timer again. The functions of the timers interface also
|
||||||
|
return a timer object.
|
||||||
An example of usage:
|
|
||||||
local t = hilbish.timers.create(1, 5000, function()
|
|
||||||
print 'hello!'
|
|
||||||
end)
|
|
||||||
|
|
||||||
t:stop()
|
|
||||||
print(t.running, t.duration, t.type)
|
|
||||||
t:start()
|
|
||||||
|
|
||||||
## Properties
|
## Properties
|
||||||
- `duration`: amount of time the timer runs for in milliseconds
|
- `duration`: amount of time the timer runs for in milliseconds
|
||||||
|
|
146
job.go
146
job.go
|
@ -3,7 +3,6 @@ package main
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
@ -16,7 +15,6 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var jobs *jobHandler
|
var jobs *jobHandler
|
||||||
var jobMetaKey = rt.StringValue("hshjob")
|
|
||||||
|
|
||||||
type job struct {
|
type job struct {
|
||||||
cmd string
|
cmd string
|
||||||
|
@ -34,7 +32,6 @@ type job struct {
|
||||||
cmderr io.Writer
|
cmderr io.Writer
|
||||||
stdout *bytes.Buffer
|
stdout *bytes.Buffer
|
||||||
stderr *bytes.Buffer
|
stderr *bytes.Buffer
|
||||||
ud *rt.UserData
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *job) start() error {
|
func (j *job) start() error {
|
||||||
|
@ -67,7 +64,7 @@ func (j *job) start() error {
|
||||||
j.pid = proc.Pid
|
j.pid = proc.Pid
|
||||||
j.running = true
|
j.running = true
|
||||||
|
|
||||||
hooks.Em.Emit("job.start", rt.UserDataValue(j.ud))
|
hooks.Em.Emit("job.start", j.lua())
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -82,7 +79,7 @@ func (j *job) stop() {
|
||||||
|
|
||||||
func (j *job) finish() {
|
func (j *job) finish() {
|
||||||
j.running = false
|
j.running = false
|
||||||
hooks.Em.Emit("job.done", rt.UserDataValue(j.ud))
|
hooks.Em.Emit("job.done", j.lua())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *job) wait() {
|
func (j *job) wait() {
|
||||||
|
@ -110,16 +107,28 @@ func (j *job) getProc() *os.Process {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func luaStartJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func (j *job) lua() rt.Value {
|
||||||
if err := c.Check1Arg(); err != nil {
|
jobFuncs := map[string]util.LuaExport{
|
||||||
return nil, err
|
"stop": {j.luaStop, 0, false},
|
||||||
}
|
"start": {j.luaStart, 0, false},
|
||||||
|
"foreground": {j.luaForeground, 0, false},
|
||||||
j, err := jobArg(c, 0)
|
"background": {j.luaBackground, 0, false},
|
||||||
if err != nil {
|
}
|
||||||
return nil, err
|
luaJob := rt.NewTable()
|
||||||
|
util.SetExports(l, luaJob, jobFuncs)
|
||||||
|
|
||||||
|
luaJob.Set(rt.StringValue("cmd"), rt.StringValue(j.cmd))
|
||||||
|
luaJob.Set(rt.StringValue("running"), rt.BoolValue(j.running))
|
||||||
|
luaJob.Set(rt.StringValue("id"), rt.IntValue(int64(j.id)))
|
||||||
|
luaJob.Set(rt.StringValue("pid"), rt.IntValue(int64(j.pid)))
|
||||||
|
luaJob.Set(rt.StringValue("exitCode"), rt.IntValue(int64(j.exitCode)))
|
||||||
|
luaJob.Set(rt.StringValue("stdout"), rt.StringValue(string(j.stdout.Bytes())))
|
||||||
|
luaJob.Set(rt.StringValue("stderr"), rt.StringValue(string(j.stderr.Bytes())))
|
||||||
|
|
||||||
|
return rt.TableValue(luaJob)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (j *job) luaStart(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if !j.running {
|
if !j.running {
|
||||||
err := j.start()
|
err := j.start()
|
||||||
exit := handleExecErr(err)
|
exit := handleExecErr(err)
|
||||||
|
@ -130,16 +139,7 @@ func luaStartJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
return c.Next(), nil
|
return c.Next(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func luaStopJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func (j *job) luaStop(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if err := c.Check1Arg(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
j, err := jobArg(c, 0)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if j.running {
|
if j.running {
|
||||||
j.stop()
|
j.stop()
|
||||||
j.finish()
|
j.finish()
|
||||||
|
@ -148,16 +148,7 @@ func luaStopJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
return c.Next(), nil
|
return c.Next(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func luaForegroundJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func (j *job) luaForeground(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if err := c.Check1Arg(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
j, err := jobArg(c, 0)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if !j.running {
|
if !j.running {
|
||||||
return nil, errors.New("job not running")
|
return nil, errors.New("job not running")
|
||||||
}
|
}
|
||||||
|
@ -166,7 +157,7 @@ func luaForegroundJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
jobs.foreground = true
|
jobs.foreground = true
|
||||||
// this is kinda funny
|
// this is kinda funny
|
||||||
// background continues the process incase it got suspended
|
// background continues the process incase it got suspended
|
||||||
err = j.background()
|
err := j.background()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -180,21 +171,12 @@ func luaForegroundJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
return c.Next(), nil
|
return c.Next(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func luaBackgroundJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func (j *job) luaBackground(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if err := c.Check1Arg(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
j, err := jobArg(c, 0)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if !j.running {
|
if !j.running {
|
||||||
return nil, errors.New("job not running")
|
return nil, errors.New("job not running")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = j.background()
|
err := j.background()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -233,10 +215,8 @@ func (j *jobHandler) add(cmd string, args []string, path string) *job {
|
||||||
stdout: &bytes.Buffer{},
|
stdout: &bytes.Buffer{},
|
||||||
stderr: &bytes.Buffer{},
|
stderr: &bytes.Buffer{},
|
||||||
}
|
}
|
||||||
jb.ud = jobUserData(jb)
|
|
||||||
|
|
||||||
j.jobs[j.latestID] = jb
|
j.jobs[j.latestID] = jb
|
||||||
hooks.Em.Emit("job.add", rt.UserDataValue(jb.ud))
|
hooks.Em.Emit("job.add", jb.lua())
|
||||||
|
|
||||||
return jb
|
return jb
|
||||||
}
|
}
|
||||||
|
@ -277,44 +257,6 @@ func (j *jobHandler) stopAll() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *jobHandler) loader(rtm *rt.Runtime) *rt.Table {
|
func (j *jobHandler) loader(rtm *rt.Runtime) *rt.Table {
|
||||||
jobMethods := rt.NewTable()
|
|
||||||
jFuncs := map[string]util.LuaExport{
|
|
||||||
"stop": {luaStopJob, 1, false},
|
|
||||||
"start": {luaStartJob, 1, false},
|
|
||||||
"foreground": {luaForegroundJob, 1, false},
|
|
||||||
"background": {luaBackgroundJob, 1, false},
|
|
||||||
}
|
|
||||||
util.SetExports(l, jobMethods, jFuncs)
|
|
||||||
|
|
||||||
jobMeta := rt.NewTable()
|
|
||||||
jobIndex := func(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
|
||||||
j, _ := jobArg(c, 0)
|
|
||||||
|
|
||||||
arg := c.Arg(1)
|
|
||||||
val := jobMethods.Get(arg)
|
|
||||||
|
|
||||||
if val != rt.NilValue {
|
|
||||||
return c.PushingNext1(t.Runtime, val), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
keyStr, _ := arg.TryString()
|
|
||||||
|
|
||||||
switch keyStr {
|
|
||||||
case "cmd": val = rt.StringValue(j.cmd)
|
|
||||||
case "running": val = rt.BoolValue(j.running)
|
|
||||||
case "id": val = rt.IntValue(int64(j.id))
|
|
||||||
case "pid": val = rt.IntValue(int64(j.pid))
|
|
||||||
case "exitCode": val = rt.IntValue(int64(j.exitCode))
|
|
||||||
case "stdout": val = rt.StringValue(string(j.stdout.Bytes()))
|
|
||||||
case "stderr": val = rt.StringValue(string(j.stderr.Bytes()))
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.PushingNext1(t.Runtime, val), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
jobMeta.Set(rt.StringValue("__index"), rt.FunctionValue(rt.NewGoFunction(jobIndex, "__index", 2, false)))
|
|
||||||
l.SetRegistry(jobMetaKey, rt.TableValue(jobMeta))
|
|
||||||
|
|
||||||
jobFuncs := map[string]util.LuaExport{
|
jobFuncs := map[string]util.LuaExport{
|
||||||
"all": {j.luaAllJobs, 0, false},
|
"all": {j.luaAllJobs, 0, false},
|
||||||
"last": {j.luaLastJob, 0, false},
|
"last": {j.luaLastJob, 0, false},
|
||||||
|
@ -329,30 +271,6 @@ func (j *jobHandler) loader(rtm *rt.Runtime) *rt.Table {
|
||||||
return luaJob
|
return luaJob
|
||||||
}
|
}
|
||||||
|
|
||||||
func jobArg(c *rt.GoCont, arg int) (*job, error) {
|
|
||||||
j, ok := valueToJob(c.Arg(arg))
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("#%d must be a job", arg + 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return j, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func valueToJob(val rt.Value) (*job, bool) {
|
|
||||||
u, ok := val.TryUserData()
|
|
||||||
if !ok {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
j, ok := u.Value().(*job)
|
|
||||||
return j, ok
|
|
||||||
}
|
|
||||||
|
|
||||||
func jobUserData(j *job) *rt.UserData {
|
|
||||||
jobMeta := l.Registry(jobMetaKey)
|
|
||||||
return rt.NewUserData(j, jobMeta.AsTable())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (j *jobHandler) luaGetJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func (j *jobHandler) luaGetJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
j.mu.RLock()
|
j.mu.RLock()
|
||||||
defer j.mu.RUnlock()
|
defer j.mu.RUnlock()
|
||||||
|
@ -370,7 +288,7 @@ func (j *jobHandler) luaGetJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
return c.Next(), nil
|
return c.Next(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.PushingNext(t.Runtime, rt.UserDataValue(job.ud)), nil
|
return c.PushingNext1(t.Runtime, job.lua()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *jobHandler) luaAddJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func (j *jobHandler) luaAddJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
|
@ -399,7 +317,7 @@ func (j *jobHandler) luaAddJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
|
|
||||||
jb := j.add(cmd, args, execPath)
|
jb := j.add(cmd, args, execPath)
|
||||||
|
|
||||||
return c.PushingNext1(t.Runtime, rt.UserDataValue(jb.ud)), nil
|
return c.PushingNext1(t.Runtime, jb.lua()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *jobHandler) luaAllJobs(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func (j *jobHandler) luaAllJobs(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
|
@ -408,7 +326,7 @@ func (j *jobHandler) luaAllJobs(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
|
|
||||||
jobTbl := rt.NewTable()
|
jobTbl := rt.NewTable()
|
||||||
for id, job := range j.jobs {
|
for id, job := range j.jobs {
|
||||||
jobTbl.Set(rt.IntValue(int64(id)), rt.UserDataValue(job.ud))
|
jobTbl.Set(rt.IntValue(int64(id)), job.lua())
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.PushingNext1(t.Runtime, rt.TableValue(jobTbl)), nil
|
return c.PushingNext1(t.Runtime, rt.TableValue(jobTbl)), nil
|
||||||
|
@ -440,5 +358,5 @@ func (j *jobHandler) luaLastJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
return c.Next(), nil
|
return c.Next(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.PushingNext1(t.Runtime, rt.UserDataValue(job.ud)), nil
|
return c.PushingNext1(t.Runtime, job.lua()), nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ require 'nature.commands'
|
||||||
require 'nature.completions'
|
require 'nature.completions'
|
||||||
require 'nature.opts'
|
require 'nature.opts'
|
||||||
require 'nature.vim'
|
require 'nature.vim'
|
||||||
require 'nature.runner'
|
|
||||||
|
|
||||||
local shlvl = tonumber(os.getenv 'SHLVL')
|
local shlvl = tonumber(os.getenv 'SHLVL')
|
||||||
if shlvl ~= nil then
|
if shlvl ~= nil then
|
||||||
|
|
|
@ -1,106 +0,0 @@
|
||||||
local currentRunner = 'hybrid'
|
|
||||||
local runners = {}
|
|
||||||
|
|
||||||
-- lsp shut up
|
|
||||||
hilbish = hilbish
|
|
||||||
|
|
||||||
--- Get a runner by name.
|
|
||||||
--- @param name string
|
|
||||||
--- @return table
|
|
||||||
function hilbish.runner.get(name)
|
|
||||||
local r = runners[name]
|
|
||||||
|
|
||||||
if not r then
|
|
||||||
error(string.format('runner %s does not exist', name))
|
|
||||||
end
|
|
||||||
|
|
||||||
return r
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Adds a runner to the table of available runners. If runner is a table,
|
|
||||||
--- it must have the run function in it.
|
|
||||||
--- @param name string
|
|
||||||
--- @param runner function | table
|
|
||||||
function hilbish.runner.add(name, runner)
|
|
||||||
if type(name) ~= 'string' then
|
|
||||||
error 'expected runner name to be a table'
|
|
||||||
end
|
|
||||||
|
|
||||||
if type(runner) == 'function' then
|
|
||||||
runner = {run = runner} -- this probably looks confusing
|
|
||||||
end
|
|
||||||
|
|
||||||
if type(runner) ~= 'table' then
|
|
||||||
error 'expected runner to be a table or function'
|
|
||||||
end
|
|
||||||
|
|
||||||
if runners[name] then
|
|
||||||
error(string.format('runner %s already exists', name))
|
|
||||||
end
|
|
||||||
|
|
||||||
hilbish.runner.set(name, runner)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Sets a runner by name. The runner table must have the run function in it.
|
|
||||||
--- @param name string
|
|
||||||
--- @param runner table
|
|
||||||
function hilbish.runner.set(name, runner)
|
|
||||||
if not runner.run or type(runner.run) ~= 'function' then
|
|
||||||
error 'run function in runner missing'
|
|
||||||
end
|
|
||||||
|
|
||||||
runners[name] = runner
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Executes cmd with a runner. If runnerName isn't passed, it uses
|
|
||||||
--- the user's current runner.
|
|
||||||
--- @param cmd string
|
|
||||||
--- @param runnerName string?
|
|
||||||
--- @return string, number, string
|
|
||||||
function hilbish.runner.exec(cmd, runnerName)
|
|
||||||
if not runnerName then runnerName = currentRunner end
|
|
||||||
|
|
||||||
local r = hilbish.runner.get(runnerName)
|
|
||||||
|
|
||||||
return r.run(cmd)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Sets the current interactive/command line runner mode.
|
|
||||||
--- @param name string
|
|
||||||
function hilbish.runner.setCurrent(name)
|
|
||||||
local r = hilbish.runner.get(name)
|
|
||||||
currentRunner = name
|
|
||||||
|
|
||||||
hilbish.runner.setMode(r.run)
|
|
||||||
end
|
|
||||||
|
|
||||||
hilbish.runner.add('hybrid', function(input)
|
|
||||||
local cmdStr = hilbish.aliases.resolve(input)
|
|
||||||
|
|
||||||
local _, _, err = hilbish.runner.lua(cmdStr)
|
|
||||||
if not err then
|
|
||||||
return input, 0, nil
|
|
||||||
end
|
|
||||||
|
|
||||||
return hilbish.runner.sh(input)
|
|
||||||
end)
|
|
||||||
|
|
||||||
hilbish.runner.add('hybridRev', function(input)
|
|
||||||
local _, _, err = hilbish.runner.sh(input)
|
|
||||||
if not err then
|
|
||||||
return input, 0, nil
|
|
||||||
end
|
|
||||||
|
|
||||||
local cmdStr = hilbish.aliases.resolve(input)
|
|
||||||
return hilbish.runner.lua(cmdStr)
|
|
||||||
end)
|
|
||||||
|
|
||||||
hilbish.runner.add('lua', function(input)
|
|
||||||
local cmdStr = hilbish.aliases.resolve(input)
|
|
||||||
return hilbish.runner.lua(cmdStr)
|
|
||||||
end)
|
|
||||||
|
|
||||||
hilbish.runner.add('sh', function(input)
|
|
||||||
return hilbish.runner.sh(input)
|
|
||||||
end)
|
|
||||||
|
|
|
@ -73,7 +73,6 @@ func (g *CompletionGroup) updateTabFind(rl *Instance) {
|
||||||
|
|
||||||
// We perform filter right here, so we create a new completion group, and populate it with our results.
|
// We perform filter right here, so we create a new completion group, and populate it with our results.
|
||||||
for i := range g.Suggestions {
|
for i := range g.Suggestions {
|
||||||
if rl.regexSearch == nil { continue }
|
|
||||||
if rl.regexSearch.MatchString(g.Suggestions[i]) {
|
if rl.regexSearch.MatchString(g.Suggestions[i]) {
|
||||||
suggs = append(suggs, g.Suggestions[i])
|
suggs = append(suggs, g.Suggestions[i])
|
||||||
} else if g.DisplayType == TabDisplayList && rl.regexSearch.MatchString(g.Descriptions[g.Suggestions[i]]) {
|
} else if g.DisplayType == TabDisplayList && rl.regexSearch.MatchString(g.Descriptions[g.Suggestions[i]]) {
|
||||||
|
|
|
@ -45,7 +45,6 @@ func (rl *Instance) echo() {
|
||||||
print(seqClearScreenBelow)
|
print(seqClearScreenBelow)
|
||||||
|
|
||||||
// Print the prompt
|
// Print the prompt
|
||||||
rl.promptInPlace("")
|
|
||||||
print(string(rl.realPrompt))
|
print(string(rl.realPrompt))
|
||||||
|
|
||||||
// Assemble the line, taking virtual completions into account
|
// Assemble the line, taking virtual completions into account
|
||||||
|
|
|
@ -73,7 +73,8 @@ func (rl *Instance) RefreshPromptLog(log string) (err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) promptInPlace(prompt string) {
|
// RefreshPromptInPlace - Refreshes the prompt in the very same place he is.
|
||||||
|
func (rl *Instance) RefreshPromptInPlace(prompt string) (err error) {
|
||||||
// We adjust cursor movement, depending on which mode we're currently in.
|
// We adjust cursor movement, depending on which mode we're currently in.
|
||||||
// Prompt data intependent
|
// Prompt data intependent
|
||||||
if !rl.modeTabCompletion {
|
if !rl.modeTabCompletion {
|
||||||
|
@ -90,11 +91,15 @@ func (rl *Instance) promptInPlace(prompt string) {
|
||||||
rl.SetPrompt(prompt)
|
rl.SetPrompt(prompt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if rl.Multiline {
|
||||||
|
rl.tcUsedY += 1
|
||||||
|
}
|
||||||
|
|
||||||
// Clear the input line and everything below
|
// Clear the input line and everything below
|
||||||
print(seqClearLine)
|
print(seqClearLine)
|
||||||
moveCursorUp(rl.infoY + rl.tcUsedY)
|
moveCursorUp(rl.infoY + rl.tcUsedY)
|
||||||
moveCursorBackwards(GetTermWidth())
|
moveCursorBackwards(GetTermWidth())
|
||||||
print("\r" + seqClearScreenBelow)
|
print("\r\n" + seqClearScreenBelow)
|
||||||
|
|
||||||
// Add a new line if needed
|
// Add a new line if needed
|
||||||
if rl.Multiline {
|
if rl.Multiline {
|
||||||
|
@ -103,11 +108,8 @@ func (rl *Instance) promptInPlace(prompt string) {
|
||||||
} else {
|
} else {
|
||||||
fmt.Print(rl.mainPrompt)
|
fmt.Print(rl.mainPrompt)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// RefreshPromptInPlace - Refreshes the prompt in the very same place he is.
|
// Refresh the line
|
||||||
func (rl *Instance) RefreshPromptInPlace(prompt string) (err error) {
|
|
||||||
rl.promptInPlace(prompt)
|
|
||||||
rl.updateHelpers()
|
rl.updateHelpers()
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
|
@ -33,7 +33,6 @@ func (rl *Instance) updateTabFind(r []rune) {
|
||||||
var err error
|
var err error
|
||||||
rl.regexSearch, err = regexp.Compile("(?i)" + string(rl.tfLine))
|
rl.regexSearch, err = regexp.Compile("(?i)" + string(rl.tfLine))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rl.RefreshPromptLog(err.Error())
|
|
||||||
rl.infoText = []rune(Red("Failed to match search regexp"))
|
rl.infoText = []rune(Red("Failed to match search regexp"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
44
timer.go
44
timer.go
|
@ -6,6 +6,8 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"hilbish/util"
|
||||||
|
|
||||||
rt "github.com/arnodel/golua/runtime"
|
rt "github.com/arnodel/golua/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -23,7 +25,6 @@ type timer struct{
|
||||||
fun *rt.Closure
|
fun *rt.Closure
|
||||||
th *timerHandler
|
th *timerHandler
|
||||||
ticker *time.Ticker
|
ticker *time.Ticker
|
||||||
ud *rt.UserData
|
|
||||||
channel chan struct{}
|
channel chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,17 +74,8 @@ func (t *timer) stop() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func timerStart(thr *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func (t *timer) luaStart(thr *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if err := c.Check1Arg(); err != nil {
|
err := t.start()
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
t, err := timerArg(c, 0)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = t.start()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -91,20 +83,26 @@ func timerStart(thr *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
return c.Next(), nil
|
return c.Next(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func timerStop(thr *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func (t *timer) luaStop(thr *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if err := c.Check1Arg(); err != nil {
|
err := t.stop()
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
t, err := timerArg(c, 0)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = t.stop()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.Next(), nil
|
return c.Next(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *timer) lua() rt.Value {
|
||||||
|
tExports := map[string]util.LuaExport{
|
||||||
|
"start": {t.luaStart, 0, false},
|
||||||
|
"stop": {t.luaStop, 0, false},
|
||||||
|
}
|
||||||
|
luaTimer := rt.NewTable()
|
||||||
|
util.SetExports(l, luaTimer, tExports)
|
||||||
|
|
||||||
|
luaTimer.Set(rt.StringValue("type"), rt.IntValue(int64(t.typ)))
|
||||||
|
luaTimer.Set(rt.StringValue("running"), rt.BoolValue(t.running))
|
||||||
|
luaTimer.Set(rt.StringValue("duration"), rt.IntValue(int64(t.dur / time.Millisecond)))
|
||||||
|
|
||||||
|
return rt.TableValue(luaTimer)
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -11,8 +10,6 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var timers *timerHandler
|
var timers *timerHandler
|
||||||
var timerMetaKey = rt.StringValue("hshtimer")
|
|
||||||
|
|
||||||
type timerHandler struct {
|
type timerHandler struct {
|
||||||
mu *sync.RWMutex
|
mu *sync.RWMutex
|
||||||
wg *sync.WaitGroup
|
wg *sync.WaitGroup
|
||||||
|
@ -47,8 +44,6 @@ func (th *timerHandler) create(typ timerType, dur time.Duration, fun *rt.Closure
|
||||||
th: th,
|
th: th,
|
||||||
id: th.latestID,
|
id: th.latestID,
|
||||||
}
|
}
|
||||||
t.ud = timerUserData(t)
|
|
||||||
|
|
||||||
th.timers[th.latestID] = t
|
th.timers[th.latestID] = t
|
||||||
|
|
||||||
return t
|
return t
|
||||||
|
@ -80,7 +75,7 @@ func (th *timerHandler) luaCreate(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
|
|
||||||
timerTyp := timerType(timerTypInt)
|
timerTyp := timerType(timerTypInt)
|
||||||
tmr := th.create(timerTyp, time.Duration(ms) * time.Millisecond, cb)
|
tmr := th.create(timerTyp, time.Duration(ms) * time.Millisecond, cb)
|
||||||
return c.PushingNext1(t.Runtime, rt.UserDataValue(tmr.ud)), nil
|
return c.PushingNext1(t.Runtime, tmr.lua()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (th *timerHandler) luaGet(thr *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func (th *timerHandler) luaGet(thr *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
|
@ -94,45 +89,13 @@ func (th *timerHandler) luaGet(thr *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
|
|
||||||
t := th.get(int(id))
|
t := th.get(int(id))
|
||||||
if t != nil {
|
if t != nil {
|
||||||
return c.PushingNext1(thr.Runtime, rt.UserDataValue(t.ud)), nil
|
return c.PushingNext1(thr.Runtime, t.lua()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.Next(), nil
|
return c.Next(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (th *timerHandler) loader(rtm *rt.Runtime) *rt.Table {
|
func (th *timerHandler) loader(rtm *rt.Runtime) *rt.Table {
|
||||||
timerMethods := rt.NewTable()
|
|
||||||
timerFuncs := map[string]util.LuaExport{
|
|
||||||
"start": {timerStart, 1, false},
|
|
||||||
"stop": {timerStop, 1, false},
|
|
||||||
}
|
|
||||||
util.SetExports(rtm, timerMethods, timerFuncs)
|
|
||||||
|
|
||||||
timerMeta := rt.NewTable()
|
|
||||||
timerIndex := func(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
|
||||||
ti, _ := timerArg(c, 0)
|
|
||||||
|
|
||||||
arg := c.Arg(1)
|
|
||||||
val := timerMethods.Get(arg)
|
|
||||||
|
|
||||||
if val != rt.NilValue {
|
|
||||||
return c.PushingNext1(t.Runtime, val), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
keyStr, _ := arg.TryString()
|
|
||||||
|
|
||||||
switch keyStr {
|
|
||||||
case "type": val = rt.IntValue(int64(ti.typ))
|
|
||||||
case "running": val = rt.BoolValue(ti.running)
|
|
||||||
case "duration": val = rt.IntValue(int64(ti.dur / time.Millisecond))
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.PushingNext1(t.Runtime, val), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
timerMeta.Set(rt.StringValue("__index"), rt.FunctionValue(rt.NewGoFunction(timerIndex, "__index", 2, false)))
|
|
||||||
l.SetRegistry(timerMetaKey, rt.TableValue(timerMeta))
|
|
||||||
|
|
||||||
thExports := map[string]util.LuaExport{
|
thExports := map[string]util.LuaExport{
|
||||||
"create": {th.luaCreate, 3, false},
|
"create": {th.luaCreate, 3, false},
|
||||||
"get": {th.luaGet, 1, false},
|
"get": {th.luaGet, 1, false},
|
||||||
|
@ -143,27 +106,3 @@ func (th *timerHandler) loader(rtm *rt.Runtime) *rt.Table {
|
||||||
|
|
||||||
return luaTh
|
return luaTh
|
||||||
}
|
}
|
||||||
|
|
||||||
func timerArg(c *rt.GoCont, arg int) (*timer, error) {
|
|
||||||
j, ok := valueToTimer(c.Arg(arg))
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("#%d must be a timer", arg + 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return j, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func valueToTimer(val rt.Value) (*timer, bool) {
|
|
||||||
u, ok := val.TryUserData()
|
|
||||||
if !ok {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
j, ok := u.Value().(*timer)
|
|
||||||
return j, ok
|
|
||||||
}
|
|
||||||
|
|
||||||
func timerUserData(j *timer) *rt.UserData {
|
|
||||||
timerMeta := l.Registry(timerMetaKey)
|
|
||||||
return rt.NewUserData(j, timerMeta.AsTable())
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue