mirror of https://github.com/Hilbis/Hilbish
Compare commits
No commits in common. "1fd99a78cca2ff3d5f40413621df2b90c62c0eb2" and "8fdde4aa58b176d32e0e92d09bcb4bd1b6cbf978" have entirely different histories.
1fd99a78cc
...
8fdde4aa58
13
CHANGELOG.md
13
CHANGELOG.md
|
@ -23,17 +23,6 @@ is for everything/anything as opposed to just adding a single command completion
|
||||||
[#122](https://github.com/Rosettea/Hilbish/issues/122)
|
[#122](https://github.com/Rosettea/Hilbish/issues/122)
|
||||||
- `fs.abs(path)` to get absolute path.
|
- `fs.abs(path)` to get absolute path.
|
||||||
- Nature module (`doc nature`)
|
- Nature module (`doc nature`)
|
||||||
- `hilbish.jobs.add(cmdstr, args, execPath)` to add a job to the job table.
|
|
||||||
`cmdstr` would be user input, `args` is the args for the command (includes arg0)
|
|
||||||
and `execPath` is absolute path to command executable
|
|
||||||
- `job.add` hook is thrown when a job is added. acts as a unique hook for
|
|
||||||
jobs
|
|
||||||
- `hilbish.jobs.disown(id)` and `disown` builtin to disown a job. `disown`
|
|
||||||
without arguments will disown the last job.
|
|
||||||
- `hilbish.jobs.last()` returns the last added job.
|
|
||||||
- Job output (stdout/stderr) can now be obtained via the `stdout` and `stderr`
|
|
||||||
fields on a job object.
|
|
||||||
- Documentation for jobs is now available via `doc jobs`.
|
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- **Breaking Change:** Upgraded to Lua 5.4.
|
- **Breaking Change:** Upgraded to Lua 5.4.
|
||||||
|
@ -68,8 +57,6 @@ certain color rules.
|
||||||
- Cursor position with CJK characters. ([#145](https://github.com/Rosettea/Hilbish/pull/145))
|
- Cursor position with CJK characters. ([#145](https://github.com/Rosettea/Hilbish/pull/145))
|
||||||
- Files with same name as parent folder in completions getting cut off [#136](https://github.com/Rosettea/Hilbish/issues/136))
|
- Files with same name as parent folder in completions getting cut off [#136](https://github.com/Rosettea/Hilbish/issues/136))
|
||||||
- `hilbish.which` now works with commanders and aliases.
|
- `hilbish.which` now works with commanders and aliases.
|
||||||
- Background jobs no longer take stdin so they do not interfere with shell
|
|
||||||
input.
|
|
||||||
|
|
||||||
## [1.2.0] - 2022-03-17
|
## [1.2.0] - 2022-03-17
|
||||||
### Added
|
### Added
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
Note: `job` refers to a job object. YOu can check `doc jobs` for more
|
Note: A `job` is a table with the following keys:
|
||||||
detail.
|
- cmd: command string
|
||||||
|
- running: boolean whether the job is running
|
||||||
|
- id: unique id for the job
|
||||||
|
- pid: process id for the job
|
||||||
|
- exitCode: exit code of the job
|
||||||
|
In ordinary cases you'd prefer to use the id instead of pid. The id is unique to
|
||||||
|
Hilbish and is how you get jobs with the `hilbish.jobs` interface.
|
||||||
|
|
||||||
+ `job.start` -> job > Thrown when a new background job starts.
|
+ `job.start` -> job > Thrown when a new background job starts.
|
||||||
|
|
||||||
|
|
|
@ -1,40 +0,0 @@
|
||||||
Hilbish has pretty standard job control. It's missing one or two things,
|
|
||||||
but works well. One thing which is different from other shells
|
|
||||||
(besides Hilbish) itself is the API for jobs, and of course it's in Lua.
|
|
||||||
You can add jobs, stop and delete (disown) them and even get output.
|
|
||||||
|
|
||||||
# Job Interface
|
|
||||||
The job interface refers to `hilbish.jobs`.
|
|
||||||
## Functions
|
|
||||||
(Note that in the list here, they're called from `hilbish.jobs`, so
|
|
||||||
a listing of `foo` would mean `hilbish.jobs.foo`)
|
|
||||||
|
|
||||||
- `all()` -> {jobs}: Returns a table of all jobs.
|
|
||||||
- `last()` -> job: Returns the last added job.
|
|
||||||
- `get(id)` -> job: Get a job by its ID.
|
|
||||||
- `add(cmdstr, args, execPath)` -> job: Adds a new job to the job table.
|
|
||||||
Note that this does not run the command; You have to start it manually.
|
|
||||||
`cmdstr` is the user's input for the job, `args` is a table of arguments
|
|
||||||
for the command. It includes arg0 (don't set it as entry 0 in the table)
|
|
||||||
and `execPath` is an absolute path for the command executable.
|
|
||||||
- `disown(id)`: Removes a job by ID from the job table.
|
|
||||||
|
|
||||||
# Job Object
|
|
||||||
A job object on the Lua side is a table with some functions.
|
|
||||||
On the under side it represents a job in the job table.
|
|
||||||
You can still have a job object for a disowned job,
|
|
||||||
it just won't be *working* anywhere. :^)
|
|
||||||
|
|
||||||
## Properties
|
|
||||||
- `cmd`: command string
|
|
||||||
- `running`: boolean whether the job is running
|
|
||||||
- `id`: unique id for the job
|
|
||||||
- `pid`: process id for the job
|
|
||||||
- `exitCode`: exit code of the job
|
|
||||||
In ordinary cases you'd prefer to use the `id` instead of `pid`.
|
|
||||||
The `id` is unique to Hilbish and is how you get jobs with the
|
|
||||||
`hilbish.jobs` interface. It may also not describe the job entirely.
|
|
||||||
|
|
||||||
## Functions
|
|
||||||
- `stop()`: Stops the job.
|
|
||||||
- `start()`: Starts the job.
|
|
51
job.go
51
job.go
|
@ -1,7 +1,6 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
@ -28,10 +27,9 @@ type job struct {
|
||||||
// would just be so itll be the same binary command always (path changes)
|
// would just be so itll be the same binary command always (path changes)
|
||||||
path string
|
path string
|
||||||
handle *exec.Cmd
|
handle *exec.Cmd
|
||||||
cmdout io.Writer
|
stdin io.Reader
|
||||||
cmderr io.Writer
|
stdout io.Writer
|
||||||
stdout *bytes.Buffer
|
stderr io.Writer
|
||||||
stderr *bytes.Buffer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *job) start() error {
|
func (j *job) start() error {
|
||||||
|
@ -40,19 +38,13 @@ func (j *job) start() error {
|
||||||
cmd := exec.Cmd{
|
cmd := exec.Cmd{
|
||||||
Path: j.path,
|
Path: j.path,
|
||||||
Args: j.args,
|
Args: j.args,
|
||||||
|
Stdin: j.stdin,
|
||||||
|
Stdout: j.stdout,
|
||||||
|
Stderr: j.stderr,
|
||||||
}
|
}
|
||||||
j.setHandle(&cmd)
|
j.setHandle(&cmd)
|
||||||
}
|
}
|
||||||
// bgProcAttr is defined in execfile_<os>.go, it holds a procattr struct
|
|
||||||
// in a simple explanation, it makes signals from hilbish (sigint)
|
|
||||||
// not go to it (child process)
|
|
||||||
j.handle.SysProcAttr = bgProcAttr
|
j.handle.SysProcAttr = bgProcAttr
|
||||||
// reset output buffers
|
|
||||||
j.stdout.Reset()
|
|
||||||
j.stderr.Reset()
|
|
||||||
// make cmd write to both standard output and output buffers for lua access
|
|
||||||
j.handle.Stdout = io.MultiWriter(j.cmdout, j.stdout)
|
|
||||||
j.handle.Stderr = io.MultiWriter(j.cmderr, j.stderr)
|
|
||||||
|
|
||||||
if !j.once {
|
if !j.once {
|
||||||
j.once = true
|
j.once = true
|
||||||
|
@ -90,12 +82,9 @@ func (j *job) setHandle(handle *exec.Cmd) {
|
||||||
j.handle = handle
|
j.handle = handle
|
||||||
j.args = handle.Args
|
j.args = handle.Args
|
||||||
j.path = handle.Path
|
j.path = handle.Path
|
||||||
if handle.Stdout != nil {
|
j.stdin = handle.Stdin
|
||||||
j.cmdout = handle.Stdout
|
j.stdout = handle.Stdout
|
||||||
}
|
j.stderr = handle.Stderr
|
||||||
if handle.Stderr != nil {
|
|
||||||
j.cmderr = handle.Stderr
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *job) getProc() *os.Process {
|
func (j *job) getProc() *os.Process {
|
||||||
|
@ -120,8 +109,6 @@ func (j *job) lua() rt.Value {
|
||||||
luaJob.Set(rt.StringValue("id"), rt.IntValue(int64(j.id)))
|
luaJob.Set(rt.StringValue("id"), rt.IntValue(int64(j.id)))
|
||||||
luaJob.Set(rt.StringValue("pid"), rt.IntValue(int64(j.pid)))
|
luaJob.Set(rt.StringValue("pid"), rt.IntValue(int64(j.pid)))
|
||||||
luaJob.Set(rt.StringValue("exitCode"), rt.IntValue(int64(j.exitCode)))
|
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)
|
return rt.TableValue(luaJob)
|
||||||
}
|
}
|
||||||
|
@ -171,10 +158,9 @@ func (j *jobHandler) add(cmd string, args []string, path string) *job {
|
||||||
id: j.latestID,
|
id: j.latestID,
|
||||||
args: args,
|
args: args,
|
||||||
path: path,
|
path: path,
|
||||||
cmdout: os.Stdout,
|
stdin: os.Stdin,
|
||||||
cmderr: os.Stderr,
|
stdout: os.Stdout,
|
||||||
stdout: &bytes.Buffer{},
|
stderr: os.Stderr,
|
||||||
stderr: &bytes.Buffer{},
|
|
||||||
}
|
}
|
||||||
j.jobs[j.latestID] = jb
|
j.jobs[j.latestID] = jb
|
||||||
hooks.Em.Emit("job.add", jb.lua())
|
hooks.Em.Emit("job.add", jb.lua())
|
||||||
|
@ -222,7 +208,7 @@ func (j *jobHandler) loader(rtm *rt.Runtime) *rt.Table {
|
||||||
"all": {j.luaAllJobs, 0, false},
|
"all": {j.luaAllJobs, 0, false},
|
||||||
"last": {j.luaLastJob, 0, false},
|
"last": {j.luaLastJob, 0, false},
|
||||||
"get": {j.luaGetJob, 1, false},
|
"get": {j.luaGetJob, 1, false},
|
||||||
"add": {j.luaAddJob, 3, false},
|
"add": {j.luaAddJob, 2, false},
|
||||||
"disown": {j.luaDisownJob, 1, false},
|
"disown": {j.luaDisownJob, 1, false},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,7 +239,7 @@ func (j *jobHandler) luaGetJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
if err := c.CheckNArgs(3); err != nil {
|
if err := c.CheckNArgs(2); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
cmd, err := c.StringArg(0)
|
cmd, err := c.StringArg(0)
|
||||||
|
@ -264,10 +250,6 @@ func (j *jobHandler) luaAddJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
execPath, err := c.StringArg(2)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var args []string
|
var args []string
|
||||||
util.ForEach(largs, func(k rt.Value, v rt.Value) {
|
util.ForEach(largs, func(k rt.Value, v rt.Value) {
|
||||||
|
@ -275,8 +257,8 @@ func (j *jobHandler) luaAddJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
args = append(args, v.AsString())
|
args = append(args, v.AsString())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
// TODO: change to lookpath for args[0]
|
||||||
jb := j.add(cmd, args, execPath)
|
jb := j.add(cmd, args, args[0])
|
||||||
|
|
||||||
return c.PushingNext1(t.Runtime, jb.lua()), nil
|
return c.PushingNext1(t.Runtime, jb.lua()), nil
|
||||||
}
|
}
|
||||||
|
@ -321,3 +303,4 @@ func (j *jobHandler) luaLastJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
|
|
||||||
return c.PushingNext1(t.Runtime, job.lua()), nil
|
return c.PushingNext1(t.Runtime, job.lua()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue