Fix EventStream.match randomness behaviour
This commit is contained in:
parent
e89b10ff4f
commit
1cb28b0a3c
@ -1,19 +0,0 @@
|
|||||||
// +build ignore
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import "github.com/gizak/termui"
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
termui.Init()
|
|
||||||
|
|
||||||
termui.UseTheme("helloworld")
|
|
||||||
b := termui.NewBlock()
|
|
||||||
b.Width = 20
|
|
||||||
b.Height = 30
|
|
||||||
b.BorderLabel = "[HELLO](fg-red,bg-white) [WORLD](fg-blue,bg-green)"
|
|
||||||
|
|
||||||
termui.Render(b)
|
|
||||||
<-termui.EventCh()
|
|
||||||
termui.Close()
|
|
||||||
}
|
|
125
events.go
125
events.go
@ -9,8 +9,8 @@
|
|||||||
package termui
|
package termui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -145,32 +145,12 @@ func NewSysEvtCh() chan Event {
|
|||||||
|
|
||||||
var DefaultEvtStream = NewEvtStream()
|
var DefaultEvtStream = NewEvtStream()
|
||||||
|
|
||||||
/*
|
|
||||||
type evtCtl struct {
|
|
||||||
in chan Event
|
|
||||||
out chan Event
|
|
||||||
suspend chan int
|
|
||||||
recover chan int
|
|
||||||
close chan int
|
|
||||||
}
|
|
||||||
|
|
||||||
func newEvtCtl() evtCtl {
|
|
||||||
ec := evtCtl{}
|
|
||||||
ec.in = make(chan Event)
|
|
||||||
ec.suspend = make(chan int)
|
|
||||||
ec.recover = make(chan int)
|
|
||||||
ec.close = make(chan int)
|
|
||||||
ec.out = make(chan Event)
|
|
||||||
return ec
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
||||||
//
|
|
||||||
type EvtStream struct {
|
type EvtStream struct {
|
||||||
|
sync.RWMutex
|
||||||
srcMap map[string]chan Event
|
srcMap map[string]chan Event
|
||||||
stream chan Event
|
stream chan Event
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
sigStopLoop chan int
|
sigStopLoop chan Event
|
||||||
Handlers map[string]func(Event)
|
Handlers map[string]func(Event)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,69 +159,40 @@ func NewEvtStream() *EvtStream {
|
|||||||
srcMap: make(map[string]chan Event),
|
srcMap: make(map[string]chan Event),
|
||||||
stream: make(chan Event),
|
stream: make(chan Event),
|
||||||
Handlers: make(map[string]func(Event)),
|
Handlers: make(map[string]func(Event)),
|
||||||
sigStopLoop: make(chan int),
|
sigStopLoop: make(chan Event),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (es *EvtStream) Init() {
|
func (es *EvtStream) Init() {
|
||||||
|
es.Merge("internal", es.sigStopLoop)
|
||||||
go func() {
|
go func() {
|
||||||
es.wg.Wait()
|
es.wg.Wait()
|
||||||
close(es.stream)
|
close(es.stream)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
// a: /sys/bell
|
func cleanPath(p string) string {
|
||||||
// b: /sys
|
if p == "" {
|
||||||
// score: 1
|
return "/"
|
||||||
//
|
|
||||||
// a: /sys
|
|
||||||
// b: /usr
|
|
||||||
// score: -1
|
|
||||||
//
|
|
||||||
// a: /sys
|
|
||||||
// b: /
|
|
||||||
// score: 0
|
|
||||||
func MatchScore(a, b string) int {
|
|
||||||
|
|
||||||
// divide by "" and rm heading ""
|
|
||||||
sliced := func(s string) []string {
|
|
||||||
ss := strings.Split(s, "/")
|
|
||||||
|
|
||||||
i := 0
|
|
||||||
for j := range ss {
|
|
||||||
if ss[j] == "" {
|
|
||||||
i++
|
|
||||||
} else {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ss[i:]
|
|
||||||
}
|
}
|
||||||
|
if p[0] != '/' {
|
||||||
sa := sliced(a)
|
p = "/" + p
|
||||||
sb := sliced(b)
|
|
||||||
|
|
||||||
score := 0
|
|
||||||
if len(sb) > len(sa) {
|
|
||||||
return -1 // sb couldnt be more deeper than sa
|
|
||||||
}
|
}
|
||||||
|
return path.Clean(p)
|
||||||
|
}
|
||||||
|
|
||||||
for i, s := range sa {
|
func isPathMatch(pattern, path string) bool {
|
||||||
if i >= len(sb) {
|
if len(pattern) == 0 {
|
||||||
break // exhaust b
|
return false
|
||||||
}
|
|
||||||
|
|
||||||
if s != sb[i] {
|
|
||||||
return -1 // mismatch
|
|
||||||
}
|
|
||||||
score++
|
|
||||||
}
|
}
|
||||||
|
n := len(pattern)
|
||||||
return score
|
return len(path) >= n && path[0:n] == pattern
|
||||||
}
|
}
|
||||||
|
|
||||||
func (es *EvtStream) Merge(name string, ec chan Event) {
|
func (es *EvtStream) Merge(name string, ec chan Event) {
|
||||||
|
es.Lock()
|
||||||
|
defer es.Unlock()
|
||||||
|
|
||||||
es.wg.Add(1)
|
es.wg.Add(1)
|
||||||
es.srcMap[name] = ec
|
es.srcMap[name] = ec
|
||||||
|
|
||||||
@ -255,38 +206,47 @@ func (es *EvtStream) Merge(name string, ec chan Event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (es *EvtStream) Handle(path string, handler func(Event)) {
|
func (es *EvtStream) Handle(path string, handler func(Event)) {
|
||||||
es.Handlers[path] = handler
|
es.Handlers[cleanPath(path)] = handler
|
||||||
}
|
}
|
||||||
|
|
||||||
func (es *EvtStream) match(path string) string {
|
func (es *EvtStream) match(path string) string {
|
||||||
n := 0
|
n := -1
|
||||||
pattern := ""
|
pattern := ""
|
||||||
for m := range es.Handlers {
|
for m := range es.Handlers {
|
||||||
if MatchScore(path, m) < 0 {
|
if !isPathMatch(m, path) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if pattern == "" || len(m) > n {
|
if len(m) > n {
|
||||||
pattern = m
|
pattern = m
|
||||||
|
n = len(m)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return pattern
|
return pattern
|
||||||
}
|
}
|
||||||
|
|
||||||
func (es *EvtStream) Loop() {
|
func (es *EvtStream) Loop() {
|
||||||
for {
|
for e := range es.stream {
|
||||||
select {
|
if e.Path == "/sig/stoploop" {
|
||||||
case e := <-es.stream:
|
|
||||||
if pattern := es.match(e.Path); pattern != "" {
|
|
||||||
es.Handlers[pattern](e)
|
|
||||||
}
|
|
||||||
case <-es.sigStopLoop:
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
go func(a Event) {
|
||||||
|
es.RLock()
|
||||||
|
defer es.RUnlock()
|
||||||
|
if pattern := es.match(a.Path); pattern != "" {
|
||||||
|
h := es.Handlers[pattern]
|
||||||
|
h(a)
|
||||||
|
}
|
||||||
|
}(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (es *EvtStream) StopLoop() {
|
func (es *EvtStream) StopLoop() {
|
||||||
go func() { es.sigStopLoop <- 1 }()
|
go func() {
|
||||||
|
e := Event{
|
||||||
|
Path: "/sig/stoploop",
|
||||||
|
}
|
||||||
|
es.sigStopLoop <- e
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
func Merge(name string, ec chan Event) {
|
func Merge(name string, ec chan Event) {
|
||||||
@ -319,7 +279,6 @@ func NewTimerCh(du time.Duration) chan Event {
|
|||||||
n++
|
n++
|
||||||
time.Sleep(du)
|
time.Sleep(du)
|
||||||
e := Event{}
|
e := Event{}
|
||||||
e.From = "timer"
|
|
||||||
e.Type = "timer"
|
e.Type = "timer"
|
||||||
e.Path = "/timer/" + du.String()
|
e.Path = "/timer/" + du.String()
|
||||||
e.Time = time.Now().Unix()
|
e.Time = time.Now().Unix()
|
||||||
@ -328,11 +287,11 @@ func NewTimerCh(du time.Duration) chan Event {
|
|||||||
Count: n,
|
Count: n,
|
||||||
}
|
}
|
||||||
t <- e
|
t <- e
|
||||||
|
|
||||||
}
|
}
|
||||||
}(t)
|
}(t)
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
var DefualtHandler = func(e Event) {
|
var DefualtHandler = func(e Event) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -23,16 +23,34 @@ func main() {
|
|||||||
}
|
}
|
||||||
defer termui.Close()
|
defer termui.Close()
|
||||||
|
|
||||||
|
termui.UseTheme("helloworld")
|
||||||
|
b := termui.NewBlock()
|
||||||
|
b.Width = 20
|
||||||
|
b.Height = 30
|
||||||
|
b.BorderLabel = "[HELLO](fg-red,bg-white) [WORLD](fg-blue,bg-green)"
|
||||||
|
|
||||||
|
termui.SendBufferToRender(b)
|
||||||
|
|
||||||
termui.Handle("/sys", func(e termui.Event) {
|
termui.Handle("/sys", func(e termui.Event) {
|
||||||
k, ok := e.Data.(termui.EvtKbd)
|
k, ok := e.Data.(termui.EvtKbd)
|
||||||
debug.Logf("-->%v\n", e)
|
debug.Logf("->%v\n", e)
|
||||||
if ok && k.KeyStr == "q" {
|
if ok && k.KeyStr == "q" {
|
||||||
termui.StopLoop()
|
termui.StopLoop()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
termui.Handle("/timer", func(e termui.Event) {
|
termui.Handle("/timer/1s", func(e termui.Event) {
|
||||||
//debug.Logf("-->%v\n", e)
|
//debug.Logf("<-%v\n", e)
|
||||||
|
t := e.Data.(termui.EvtTimer)
|
||||||
|
|
||||||
|
if t.Count%2 == 0 {
|
||||||
|
b.BorderLabel = "[HELLO](fg-red,bg-green) [WORLD](fg-blue,bg-white)"
|
||||||
|
} else {
|
||||||
|
b.BorderLabel = "[HELLO](fg-blue,bg-white) [WORLD](fg-red,bg-green)"
|
||||||
|
}
|
||||||
|
|
||||||
|
termui.SendBufferToRender(b)
|
||||||
|
|
||||||
})
|
})
|
||||||
termui.Loop()
|
termui.Loop()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user