mirror of
https://github.com/Hilbis/Hilbish
synced 2025-04-21 21:13:22 +00:00
Compare commits
8 Commits
f6b3ed6407
...
51a8258e47
Author | SHA1 | Date | |
---|---|---|---|
51a8258e47 | |||
fb9d30520a | |||
521298733e | |||
f8a391e24f | |||
|
aa376f9b14 | ||
16b39fe157 | |||
459c9baa89 | |||
be4b86f5c5 |
@ -1,5 +1,13 @@
|
||||
# 🎀 Changelog
|
||||
|
||||
## [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
|
||||
### Fixed
|
||||
- Line refresh fixes (less flicker)
|
||||
|
11
api.go
11
api.go
@ -712,5 +712,14 @@ func hlhinter(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||
// #example
|
||||
// #param line string
|
||||
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
|
||||
}
|
||||
|
1
go.mod
1
go.mod
@ -8,6 +8,7 @@ require (
|
||||
github.com/blackfireio/osinfo v1.0.3
|
||||
github.com/maxlandon/readline v0.1.0-beta.0.20211027085530-2b76cabb8036
|
||||
github.com/pborman/getopt v1.1.0
|
||||
github.com/rjeczalik/notify v0.9.3
|
||||
github.com/sahilm/fuzzy v0.1.0
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a
|
||||
golang.org/x/term v0.0.0-20220411215600-e5f449aeb171
|
||||
|
3
go.sum
3
go.sum
@ -40,6 +40,8 @@ github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsK
|
||||
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rjeczalik/notify v0.9.3 h1:6rJAzHTGKXGj76sbRgDiDcYj/HniypXmSJo1SWakZeY=
|
||||
github.com/rjeczalik/notify v0.9.3/go.mod h1:gF3zSOrafR9DQEWSE8TjfI9NkooDxbyT4UgRGKZA0lc=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.8.1-0.20210923151022-86f73c517451 h1:d1PiN4RxzIFXCJTvRkvSkKqwtRAl5ZV4lATKtQI0B7I=
|
||||
github.com/rogpeppe/go-internal v1.8.1-0.20210923151022-86f73c517451/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
|
||||
@ -48,6 +50,7 @@ github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220513210516-0976fa681c29 h1:w8s32wxx3sY+OjLlv9qltkLU5yvJzxjjgiHWLjdIcw4=
|
||||
golang.org/x/sync v0.0.0-20220513210516-0976fa681c29/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
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=
|
||||
|
@ -20,12 +20,39 @@ import (
|
||||
"github.com/arnodel/golua/lib/packagelib"
|
||||
)
|
||||
|
||||
var rtmm *rt.Runtime
|
||||
var watcherMetaKey = rt.StringValue("hshwatcher")
|
||||
var Loader = packagelib.Loader{
|
||||
Load: loaderFunc,
|
||||
Name: "fs",
|
||||
}
|
||||
|
||||
func loaderFunc(rtm *rt.Runtime) (rt.Value, func()) {
|
||||
rtmm = rtm
|
||||
watcherMethods := rt.NewTable()
|
||||
watcherFuncs := map[string]util.LuaExport{
|
||||
"start": {watcherStart, 1, false},
|
||||
"stop": {watcherStop, 1, false},
|
||||
}
|
||||
util.SetExports(rtm, watcherMethods, watcherFuncs)
|
||||
|
||||
watcherMeta := rt.NewTable()
|
||||
watcherIndex := func(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||
//ti, _ := watcherArg(c, 0)
|
||||
|
||||
arg := c.Arg(1)
|
||||
val := watcherMethods.Get(arg)
|
||||
|
||||
if val != rt.NilValue {
|
||||
return c.PushingNext1(t.Runtime, val), nil
|
||||
}
|
||||
|
||||
return c.PushingNext1(t.Runtime, val), nil
|
||||
}
|
||||
|
||||
watcherMeta.Set(rt.StringValue("__index"), rt.FunctionValue(rt.NewGoFunction(watcherIndex, "__index", 2, false)))
|
||||
rtm.SetRegistry(watcherMetaKey, rt.TableValue(watcherMeta))
|
||||
|
||||
exports := map[string]util.LuaExport{
|
||||
"cd": util.LuaExport{fcd, 1, false},
|
||||
"mkdir": util.LuaExport{fmkdir, 2, false},
|
||||
@ -36,6 +63,7 @@ func loaderFunc(rtm *rt.Runtime) (rt.Value, func()) {
|
||||
"dir": util.LuaExport{fdir, 1, false},
|
||||
"glob": util.LuaExport{fglob, 1, false},
|
||||
"join": util.LuaExport{fjoin, 0, true},
|
||||
"watch": util.LuaExport{fwatch, 2, false},
|
||||
}
|
||||
mod := rt.NewTable()
|
||||
util.SetExports(rtm, mod, exports)
|
||||
@ -301,3 +329,22 @@ func fstat(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||
return c.PushingNext1(t.Runtime, rt.TableValue(statTbl)), nil
|
||||
}
|
||||
|
||||
func fwatch(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||
if err := c.CheckNArgs(2); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dir, err := c.StringArg(0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
watcher, err := c.ClosureArg(1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dw := newWatcher(dir, watcher)
|
||||
|
||||
return c.PushingNext1(t.Runtime, rt.UserDataValue(dw.ud)), nil
|
||||
}
|
||||
|
101
golibs/fs/watcher.go
Normal file
101
golibs/fs/watcher.go
Normal file
@ -0,0 +1,101 @@
|
||||
package fs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/rjeczalik/notify"
|
||||
rt "github.com/arnodel/golua/runtime"
|
||||
)
|
||||
|
||||
type pathWatcher struct{
|
||||
path string
|
||||
callback *rt.Closure
|
||||
paused bool
|
||||
started bool
|
||||
ud *rt.UserData
|
||||
notifyChan chan notify.EventInfo
|
||||
}
|
||||
|
||||
func (w *pathWatcher) start() {
|
||||
if w.callback == nil || w.started {
|
||||
return
|
||||
}
|
||||
|
||||
w.started = true
|
||||
w.notifyChan = make(chan notify.EventInfo)
|
||||
notify.Watch(w.path, w.notifyChan, notify.All)
|
||||
|
||||
go func() {
|
||||
for notif := range w.notifyChan {
|
||||
ev := notif.Event().String()
|
||||
path := notif.Path()
|
||||
|
||||
_, err := rt.Call1(rtmm.MainThread(), rt.FunctionValue(w.callback), rt.StringValue(ev), rt.StringValue(path))
|
||||
if err != nil {
|
||||
// TODO: throw error
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (w *pathWatcher) stop() {
|
||||
w.started = false
|
||||
notify.Stop(w.notifyChan)
|
||||
}
|
||||
|
||||
func watcherStart(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||
pw, err := watcherArg(c, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pw.start()
|
||||
|
||||
return c.Next(), nil
|
||||
}
|
||||
|
||||
func watcherStop(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||
pw, err := watcherArg(c, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pw.stop()
|
||||
|
||||
return c.Next(), nil
|
||||
}
|
||||
|
||||
func newWatcher(path string, callback *rt.Closure) *pathWatcher {
|
||||
pw := &pathWatcher{
|
||||
path: path,
|
||||
callback: callback,
|
||||
}
|
||||
pw.ud = watcherUserData(pw)
|
||||
pw.start()
|
||||
|
||||
return pw
|
||||
}
|
||||
|
||||
func watcherArg(c *rt.GoCont, arg int) (*pathWatcher, error) {
|
||||
j, ok := valueToWatcher(c.Arg(arg))
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("#%d must be a watcher", arg + 1)
|
||||
}
|
||||
|
||||
return j, nil
|
||||
}
|
||||
|
||||
func valueToWatcher(val rt.Value) (*pathWatcher, bool) {
|
||||
u, ok := val.TryUserData()
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
j, ok := u.Value().(*pathWatcher)
|
||||
return j, ok
|
||||
}
|
||||
|
||||
func watcherUserData(j *pathWatcher) *rt.UserData {
|
||||
watcherMeta := rtmm.Registry(watcherMetaKey)
|
||||
return rt.NewUserData(j, watcherMeta.AsTable())
|
||||
}
|
@ -9,6 +9,8 @@ commander.register('cat', function(args, sinks)
|
||||
usage: cat [file]...]]
|
||||
end
|
||||
|
||||
local chunkSize = 2^13 -- 8K buffer size
|
||||
|
||||
for _, fName in ipairs(args) do
|
||||
local f = io.open(fName)
|
||||
if f == nil then
|
||||
@ -17,7 +19,11 @@ usage: cat [file]...]]
|
||||
goto continue
|
||||
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::
|
||||
end
|
||||
io.flush()
|
||||
|
@ -271,6 +271,15 @@ end
|
||||
function Greenhouse:input(char)
|
||||
end
|
||||
|
||||
local function read()
|
||||
terminal.saveState()
|
||||
terminal.setRaw()
|
||||
local c = hilbish.editor.readChar()
|
||||
|
||||
terminal.restoreState()
|
||||
return c
|
||||
end
|
||||
|
||||
function Greenhouse:initUi()
|
||||
local ansikit = require 'ansikit'
|
||||
local bait = require 'bait'
|
||||
@ -280,14 +289,17 @@ function Greenhouse:initUi()
|
||||
local Page = require 'nature.greenhouse.page'
|
||||
local done = false
|
||||
|
||||
bait.catch('signal.sigint', function()
|
||||
local function sigint()
|
||||
ansikit.clear()
|
||||
done = true
|
||||
end)
|
||||
end
|
||||
|
||||
bait.catch('signal.resize', function()
|
||||
local function resize()
|
||||
self:update()
|
||||
end)
|
||||
end
|
||||
bait.catch('signal.sigint', sigint)
|
||||
|
||||
bait.catch('signal.resize', resize)
|
||||
|
||||
ansikit.screenAlt()
|
||||
ansikit.clear(true)
|
||||
@ -311,15 +323,10 @@ function Greenhouse:initUi()
|
||||
|
||||
ansikit.showCursor()
|
||||
ansikit.screenMain()
|
||||
end
|
||||
|
||||
function read()
|
||||
terminal.saveState()
|
||||
terminal.setRaw()
|
||||
local c = hilbish.editor.readChar()
|
||||
|
||||
terminal.restoreState()
|
||||
return c
|
||||
self = nil
|
||||
bait.release('signal.sigint', sigint)
|
||||
bait.release('signal.resize', resize)
|
||||
end
|
||||
|
||||
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)
|
||||
}
|
||||
rl.HintText = func(line []rune, pos int) []rune {
|
||||
if hinter == nil {
|
||||
return []rune{}
|
||||
}
|
||||
|
||||
retVal, err := rt.Call1(l.MainThread(), rt.FunctionValue(hinter),
|
||||
hinter := hshMod.Get(rt.StringValue("hinter"))
|
||||
retVal, err := rt.Call1(l.MainThread(), hinter,
|
||||
rt.StringValue(string(line)), rt.IntValue(int64(pos)))
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
@ -89,10 +86,8 @@ func newLineReader(prompt string, noHist bool) *lineReader {
|
||||
return []rune(hintText)
|
||||
}
|
||||
rl.SyntaxHighlighter = func(line []rune) string {
|
||||
if highlighter == nil {
|
||||
return string(line)
|
||||
}
|
||||
retVal, err := rt.Call1(l.MainThread(), rt.FunctionValue(highlighter),
|
||||
highlighter := hshMod.Get(rt.StringValue("highlighter"))
|
||||
retVal, err := rt.Call1(l.MainThread(), highlighter,
|
||||
rt.StringValue(string(line)))
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
|
Loading…
x
Reference in New Issue
Block a user