Skip to content

Commit

Permalink
Add micro's own lua timer function micro.After()
Browse files Browse the repository at this point in the history
Directly using Go's time.AfterFunc() from lua is tricky. First, it
requires the lua timer callback to explicitly lock ulua.Lock to prevent
races. Second, it requires the lua timer callback to explicitly redraw
the screen if the callback changes the screen contents (see zyedidia#2923).

So instead provide micro's own timer API which ensures both
synchronization and redrawing on its own, instead of leaving this burden
to lua code. In fact, its implementation runs the lua timer callback in
the main micro's goroutine (i.e. from micro's perspective it is
synchronous, not asynchronous), so both redrawing and synchronization
are ensured automatically.

Fixes zyedidia#2923
  • Loading branch information
dmaluka committed Mar 14, 2024
1 parent 3dba23a commit 9089e9e
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 0 deletions.
6 changes: 6 additions & 0 deletions cmd/micro/initlua.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"log"
"time"

lua "github.com/yuin/gopher-lua"
luar "layeh.com/gopher-luar"
Expand Down Expand Up @@ -55,6 +56,11 @@ func luaImportMicro() *lua.LTable {
return action.Tabs
}))
ulua.L.SetField(pkg, "Lock", luar.New(ulua.L, &ulua.Lock))
ulua.L.SetField(pkg, "After", luar.New(ulua.L, func(t time.Duration, f func()) {
time.AfterFunc(t, func() {
timerChan <- f
})
}))

return pkg
}
Expand Down
6 changes: 6 additions & 0 deletions cmd/micro/micro.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ var (

sigterm chan os.Signal
sighup chan os.Signal

timerChan chan func()
)

func InitFlags() {
Expand Down Expand Up @@ -364,6 +366,8 @@ func main() {
signal.Notify(sigterm, syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGABRT)
signal.Notify(sighup, syscall.SIGHUP)

timerChan = make(chan func())

// Here is the event loop which runs in a separate thread
go func() {
for {
Expand Down Expand Up @@ -429,6 +433,8 @@ func DoEvent() {
for len(screen.DrawChan()) > 0 {
<-screen.DrawChan()
}
case f := <-timerChan:
f()
case <-sighup:
for _, b := range buffer.OpenBuffers {
if !b.Modified() {
Expand Down
5 changes: 5 additions & 0 deletions runtime/help/plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@ The packages and functions are listed below (in Go type signatures):
current pane is not a BufPane.

- `CurTab() *Tab`: returns the current tab.

- `After(t time.Duration, f func())`: run function `f` in the background
after time `t` elapses. See https://pkg.go.dev/time#Duration for the
usage of `time.Duration`.

* `micro/config`
- `MakeCommand(name string, action func(bp *BufPane, args[]string),
completer buffer.Completer)`:
Expand Down

0 comments on commit 9089e9e

Please sign in to comment.