From ec75142f96311288f9b18d54a0e9965aa33d5994 Mon Sep 17 00:00:00 2001 From: shylinux Date: Sun, 2 Apr 2023 08:22:03 +0800 Subject: [PATCH] add expr --- base/ctx/command.go | 12 +- base/nfs/cat.go | 2 + base/yac/expr.go | 299 ++++++++++++++++++++++ base/yac/stack.go | 606 +++++++++++++------------------------------- base/yac/stmt.go | 229 +++++++++++++++++ base/yac/value.go | 175 +++++++++++++ core/code/shy.go | 3 +- go.mod | 2 + go.sum | 5 + meta.go | 15 ++ 10 files changed, 922 insertions(+), 426 deletions(-) create mode 100644 base/yac/expr.go create mode 100644 base/yac/stmt.go create mode 100644 base/yac/value.go diff --git a/base/ctx/command.go b/base/ctx/command.go index c1d4674c..971feb38 100644 --- a/base/ctx/command.go +++ b/base/ctx/command.go @@ -8,6 +8,7 @@ import ( "shylinux.com/x/icebergs/base/aaa" "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/nfs" + "shylinux.com/x/icebergs/base/yac" kit "shylinux.com/x/toolkits" ) @@ -31,6 +32,9 @@ func _command_list(m *ice.Message, name string) *ice.Message { m.Push(mdb.META, kit.Format(cmd.Meta)) m.Push(mdb.LIST, kit.Format(cmd.List)) }) + if m.Length() == 0 && yac.ExistsFile(m, name) { + m.Cmdy(yac.STACK, ice.CMD, name) + } return m } func _command_search(m *ice.Message, kind, name, text string) { @@ -91,7 +95,13 @@ func PodCmd(m *ice.Message, arg ...ice.Any) bool { return false } func Run(m *ice.Message, arg ...string) { - kit.If(!PodCmd(m, arg) && aaa.Right(m, arg), func() { m.Cmdy(arg) }) + kit.If(!PodCmd(m, arg) && aaa.Right(m, arg), func() { + if yac.ExistsFile(m, arg[0]) { + m.Cmdy(yac.STACK, ice.RUN, arg) + } else { + m.Cmdy(arg) + } + }) } func CmdHandler(args ...ice.Any) ice.Handler { return func(m *ice.Message, arg ...string) { m.Cmdy(args...) } diff --git a/base/nfs/cat.go b/base/nfs/cat.go index a7c9dbf4..48e9c2c7 100644 --- a/base/nfs/cat.go +++ b/base/nfs/cat.go @@ -162,6 +162,8 @@ func Open(m *ice.Message, p string, cb ice.Any) { case func(io.Reader, os.FileInfo): s, _ := StatFile(m, p) cb(f, s) + case func(io.Reader, string): + cb(f, p) case func(io.Reader): cb(f) case func(string): diff --git a/base/yac/expr.go b/base/yac/expr.go new file mode 100644 index 00000000..29924699 --- /dev/null +++ b/base/yac/expr.go @@ -0,0 +1,299 @@ +package yac + +import ( + "regexp" + "strings" + + ice "shylinux.com/x/icebergs" + kit "shylinux.com/x/toolkits" +) + +const ( + SPACE = "\t " + QUOTE = "\"" + TRANS = " " + BLOCK = "[:](,){;}*/+-<>!=&|" + DEFINE = ":=" + ASSIGN = "=" + SUBS = "[" + DEFS = ":" + SUPS = "]" + OPEN = "(" + FIELD = "," + CLOSE = ")" + BEGIN = "{" + SPLIT = ";" + END = "}" + DISABLE = -1 +) + +var level = map[string]int{ + "//": 200, "/*": 200, "*/": 200, + "!": 100, "++": 100, "--": 100, "[": 100, "]": 100, + "*": 40, "/": 40, "+": 30, "-": 30, + "<": 20, ">": 20, ">=": 20, "<=": 20, "!=": 20, "==": 20, "&&": 10, "||": 10, + DEFINE: 2, ASSIGN: 2, FIELD: 2, OPEN: 1, CLOSE: 1, +} + +type Expr struct { + list ice.List + s *Stack + m *ice.Message + n int +} + +func (s *Expr) push(v Any) *Expr { + s.list = append(s.list, v) + return s +} +func (s *Expr) pop(n int) *Expr { + s.list = s.list[:len(s.list)-n] + return s +} +func (s *Expr) get(p int) (v Any) { + kit.If(0 <= p+len(s.list) && p+len(s.list) < len(s.list), func() { v = s.list[p+len(s.list)] }) + kit.If(0 <= p && p < len(s.list), func() { v = s.list[p] }) + return +} +func (s *Expr) gets(p int) string { return kit.Format(s.get(p)) } +func (s *Expr) getl(p int) int { return level[s.gets(p)] } +func (s *Expr) getv(m *ice.Message, p int) (v Any) { + switch v := s.get(p); v := v.(type) { + case string: + return s.s.value(m, v) + default: + return v + } +} +func (s *Expr) setv(m *ice.Message, p int, op string, v Any) Any { + k := s.gets(p) + kit.If(s.s.runable(), func() { + switch v := v.(type) { + case string: + s.s.value(m, k, s.s.value(m, v), op) + case Value: + s.s.value(m, k, v.list[0], op) + default: + s.s.value(m, k, v, op) + } + }) + return s.s.value(m, k) +} +func (s *Expr) opv(m *ice.Message, p int, op string, v Any) Any { + if s.n++; s.n > 100 { + panic(s.n) + } + if !s.s.runable() { + return s.getv(m, p) + } + if obj, ok := s.getv(m, p).(Operater); ok { + return obj.Operate(op, trans(v)) + } + return s.getv(m, p) +} +func (s *Expr) ops(m *ice.Message) { + if !s.s.runable() || s.getl(-2) < 10 { + return + } + v := s.opv(m, -3, s.gets(-2), s.getv(m, -1)) + s.pop(3).push(v) +} +func (s *Expr) end(m *ice.Message) Any { + if !s.s.runable() || len(s.list) == 0 { + return nil + } + m.Debug("expr ops %v", s.list) + for len(s.list) > 1 { + switch s.ops(m); s.gets(-2) { + case FIELD: + list := kit.List() + for i := len(s.list) - 2; i > 0; i -= 2 { + if s.gets(i) == ASSIGN || s.gets(i) == DEFINE { + for j := 0; j < i; j += 2 { + list = append(list, s.setv(m, j, s.gets(i), s.getv(m, j+i+1))) + } + s.list = kit.List(Value{list: list}) + break + } else if i == 1 { + for i := 0; i < len(s.list); i += 2 { + list = append(list, s.getv(m, i)) + } + s.list = kit.List(Value{list: list}) + break + } + } + case ASSIGN, DEFINE: + list := kit.List() + switch v := s.getv(m, -1).(type) { + case Value: + for i := 0; i < len(s.list)-1; i += 2 { + if i/2 < len(v.list) { + list = append(list, s.setv(m, i, s.gets(-2), v.list[i/2])) + } + } + default: + s.setv(m, -3, s.gets(-2), s.getv(m, -1)) + } + s.list = kit.List(Value{list}) + } + } + m.Debug("expr ops %v", s.list) + return s.getv(m, 0) +} +func (s *Expr) cals(m *ice.Message) Any { + if s.s.skip == -1 { + m.Debug("expr calcs %v %s:%d", s.s.rest, s.s.name, s.s.line) + } else { + m.Debug("expr calcs %v %s:%d", s.s.rest[s.s.skip:], s.s.name, s.s.line) + } + s.s.reads(m, func(k string) bool { + if op := s.gets(-1) + k; level[op] > 0 && s.getl(-1) > 0 { + s.pop(1) + k = op + } + switch k { + case DEFS, SUPS, BEGIN, SPLIT: + return true + case END: + s.s.skip-- + return true + } + if len(s.list) > 0 && s.getl(-1) == 0 { + switch k { + case "++": + v := s.opv(m, -1, "+", 1) + s.setv(m, -1, ASSIGN, v) + s.pop(1).push(v) + return false + case "--": + v := s.opv(m, -1, "-", 1) + s.setv(m, -1, ASSIGN, v) + s.pop(1).push(v) + return false + case SUBS: + v := s.opv(m, -1, SUBS, s.s.cals(m)) + s.pop(1).push(v) + return false + case OPEN: + if s.gets(-1) == FUNC { + name := kit.Format("%s:%d:%d", s.s.name, s.s.line, s.s.skip) + s.s.skip-- + s.s.rest[s.s.skip] = name + s.s.skip-- + m.Cmd(FUNC, name) + s.s.skip++ + sub := NewStack() + sub.Position = s.s.Position + sub.pushf(m, FUNC).status = DISABLE + sub.run(m.Options(STACK, sub)) + s.s.Position = sub.Position + m.Options(STACK, s.s) + s.s.popf(m) + s.pop(1).push(s.s.value(m, name)) + } else { + v := s.call(m, s.s, s.gets(-1)) + s.pop(1).push(v) + } + return false + case CLOSE: + if s.gets(-2) == OPEN { + v := s.get(-1) + s.pop(2).push(v) + return false + } + m.Debug("what %v", k) + return true + } + if level[k] == 0 { + if strings.HasPrefix(k, ice.PT) && kit.Select("", s.s.rest, s.s.skip+1) == OPEN { + s.s.skip++ + v := s.call(m, s.getv(m, -1), strings.TrimPrefix(k, ice.PT)) + s.pop(1).push(v) + return false + } else { + s.s.skip-- + return true + } + } + } + if level[k] > 0 { + for level[k] >= 9 && level[k] <= s.getl(-2) { + s.ops(m) + } + s.push(k) + } else { + if strings.HasPrefix(k, "\"") { + s.push(String{value: k[1 : len(k)-1]}) + } else if k == ice.TRUE { + s.push(Boolean{value: true}) + } else if k == ice.FALSE { + s.push(Boolean{value: false}) + } else if b, e := regexp.MatchString("[_a-zA-Z][_a-zA-Z0-9]*", k); e == nil && b { + s.push(k) + } else { + s.push(Number{value: k}) + } + } + return false + }) + return s.end(m) +} +func (s *Expr) call(m *ice.Message, obj Any, key string) Any { + list := kit.List() + switch v := s.s.cals(m).(type) { + case Value: + list = append(list, v.list...) + default: + list = append(list, v) + } + if !s.s.runable() { + return nil + } + kit.For(kit.Slice(kit.Split(key, ice.PT), 0, -1), func(k string) { + switch v := obj.(type) { + case *Stack: + obj, key = v.value(m, k), strings.TrimPrefix(key, k+ice.PT) + } + }) + m.Debug("expr call %T %s %v", obj, key, kit.Format(list)) + switch obj := obj.(type) { + case *Stack: + return obj.call(m, obj.value(m, key), nil, list...) + case Caller: + return obj.Call(key, list...) + case func(string, ...Any) Any: + return obj(key, list...) + default: + args := kit.List(key) + for _, v := range list { + switch v := v.(type) { + case Value: + args = append(args, v.list...) + default: + args = append(args, trans(v)) + } + } + return Message{m.Cmd(args...)} + } +} +func NewExpr(m *ice.Message, s *Stack) *Expr { return &Expr{kit.List(), s, m, 0} } + +const EXPR = "expr" + +func init() { + Index.MergeCommands(ice.Commands{ + EXPR: {Name: "expr a = 1", Hand: func(m *ice.Message, arg ...string) { + s := _parse_stack(m) + arg = s.rest + m.Debug("what %v %d %d", s.rest[:], s.skip, s.line) + if v := s.cals(m); !s.runable() { + return + } else if v != nil { + m.Echo(kit.Format(trans(v))) + } else if s.token() == BEGIN { + m.Echo(ice.TRUE) + } + m.Debug("expr value %s %v %s:%d", m.Result(), arg, s.name, s.line) + }}, + }) +} diff --git a/base/yac/stack.go b/base/yac/stack.go index 119307eb..c8fb061d 100644 --- a/base/yac/stack.go +++ b/base/yac/stack.go @@ -1,22 +1,18 @@ package yac import ( - "encoding/json" + "bufio" "io" "path" "strings" ice "shylinux.com/x/icebergs" - "shylinux.com/x/icebergs/base/log" + "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/nfs" kit "shylinux.com/x/toolkits" ) -type Value struct{ list []ice.Any } - -func (s *Value) MarshalJSON() ([]byte, error) { return json.Marshal(s.list) } - -type Func struct { +type Function struct { obj []string arg []string res []string @@ -32,66 +28,63 @@ type Frame struct { type Stack struct { last *Frame frame []*Frame - input chan string - list []string - rest []string Position + n int +} +type Position struct { + rest []string + skip int + line int + *Buffer +} +type Buffer struct { + name string + list []string + input *bufio.Scanner } -type Position struct{ line, skip int } -func (s *Stack) peekf(m *ice.Message) *Frame { - kit.If(len(s.frame) == 0, func() { s.pushf(m, "") }) - return s.frame[len(s.frame)-1] -} +func (s *Stack) peekf() *Frame { return s.frame[len(s.frame)-1] } func (s *Stack) pushf(m *ice.Message, key string) *Frame { f := &Frame{key: kit.Select(m.CommandKey(), key), value: kit.Dict(), Position: s.Position} - kit.If(len(s.frame) > 0, func() { f.status = s.peekf(m).status }) - m.Debug("stack push %#v", f) + kit.If(len(s.frame) > 0, func() { f.status = s.peekf().status }) + m.Debug("stack push %d %v %s:%d", len(s.frame), f.key, f.name, f.line) s.frame = append(s.frame, f) return f } func (s *Stack) popf(m *ice.Message) *Frame { - f := s.peekf(m) - m.Debug("stack pop %#v", f) - kit.If(len(s.frame) > 1, func() { s.frame = s.frame[:len(s.frame)-1] }) + f := s.peekf() + kit.If(f.pop != nil, func() { f.pop() }) + m.Debug("stack pop %d %v %s:%d", len(s.frame)-1, f.key, f.name, f.line) + kit.If(len(s.frame) > 0, func() { s.frame = s.frame[:len(s.frame)-1] }) + s.last = f return f } -func (s *Stack) stack(cb ice.Any) { +func (s *Stack) stack(cb func(*Frame, int) bool) { for i := len(s.frame) - 1; i >= 0; i-- { - switch cb := cb.(type) { - case func(*Frame, int) bool: - if cb(s.frame[i], i) { - return - } - case func(*Frame, int): - cb(s.frame[i], i) - case func(*Frame): - cb(s.frame[i]) + if cb(s.frame[i], i) { + return } } } -func (s *Stack) value(m *ice.Message, key string, arg ...ice.Any) ice.Any { - f := s.peekf(m) - s.stack(func(_f *Frame, i int) bool { - if _f.value[key] != nil { - f = _f - return true - } - return false - }) +func (s *Stack) value(m *ice.Message, key string, arg ...Any) Any { + f, n := s.peekf(), len(s.frame)-1 + if len(arg) < 2 || arg[1] == ASSIGN { + s.stack(func(_f *Frame, i int) bool { + if _f.value[key] != nil { + f, n = _f, i + return true + } + return false + }) + } kit.If(len(arg) > 0, func() { - m.Debug("value set %v %#v", key, arg[0]) - switch v := arg[0].(type) { - case *Value: - f.value[key] = v.list[0] - default: - f.value[key] = arg[0] - } + m.Debug("value set %d %v %#v", n, key, arg[0]) + f.value[key] = arg[0] }) - // m.Debug("value get %v %v", key, f.value[key]) return f.value[key] } -func (s *Stack) runable(m *ice.Message) bool { return s.peekf(m).status > DISABLE } +func (s *Stack) runable() bool { return s.peekf().status > DISABLE } +func (s *Stack) token() string { return kit.Select("", s.rest, s.skip) } func (s *Stack) read(m *ice.Message) (text string, ok bool) { isvoid := func(text string) bool { return strings.TrimSpace(text) == "" || strings.HasPrefix(strings.TrimSpace(text), "#") @@ -102,434 +95,199 @@ func (s *Stack) read(m *ice.Message) (text string, ok bool) { } return s.list[s.line], true } - for { - if text, ok = <-s.input; !ok { - break - } - m.Debug("input read %v", text) - if s.list = append(s.list, text); isvoid(text) { + for s.input != nil && s.input.Scan() { + text = s.input.Text() + m.Debug("input read %d \"%s\" %s:%d", len(s.list), text, s.name, len(s.list)) + if s.line, s.list = len(s.list), append(s.list, text); isvoid(text) { continue } - s.line = len(s.list) - 1 - break + return text, true } return } -func (s *Stack) reads(m *ice.Message, cb func(i int, k string) bool) (arg []string) { - i := 0 +func (s *Stack) reads(m *ice.Message, cb func(k string) bool) { for { if s.skip++; s.skip < len(s.rest) { - arg = append(arg, s.rest[s.skip]) - if cb(i, s.rest[s.skip]) { + if cb(s.rest[s.skip]) { break } - i++ } else if text, ok := s.read(m); ok { - s.rest, s.skip = kit.Split(text, "\t ", OPS), -1 + s.rest, s.skip = kit.Split(text, SPACE, BLOCK, QUOTE, TRANS, ice.TRUE), -1 } else { + cb(SPLIT) break } } - return } -func (s *Stack) call(m *ice.Message) { - s.reads(m, func(i int, k string) bool { +func (s *Stack) run(m *ice.Message) { + s.reads(m, func(k string) bool { + if s.n++; s.n > 100 { + return true + } + if k == SPLIT { } else if k == END { - kit.If(s.peekf(m).pop != nil, func() { s.peekf(m).pop() }) s.last = s.popf(m) } else if _, ok := m.Target().Commands[k]; ok { - m.Cmdy(k) + m.Cmdy(k, kit.Slice(s.rest, s.skip+1)) } else { s.skip-- - m.Cmdy(EXPR) + m.Cmd(EXPR, kit.Slice(s.rest, s.skip)) + } + if len(s.frame) == 0 { + return true } return false }) } -func (s *Stack) parse(m *ice.Message, r io.Reader) *ice.Message { - s.input = make(chan string, 100) - m.Options(STACK, s) - kit.For(r, func(text string) { s.input <- text }) - close(s.input) - - // s.input = make(chan string) - // m.Options(STACK, s).Go(func() { - // defer func() { kit.If(s.input != nil, func() { close(s.input) }) }() - // kit.For(r, func(text string) { s.input <- text }) - // }) - s.peekf(m) - s.call(m) - return m -} -func (s *Stack) token(m *ice.Message) string { - if s.skip < len(s.rest) { - return s.rest[s.skip] +func (s *Stack) call(m *ice.Message, v Any, cb func(*Frame, Function), arg ...Any) Any { + switch v := v.(type) { + case Function: + f := s.pushf(m, CALL) + kit.For(v.res, func(k string) { f.value[k] = "" }) + kit.For(v.arg, func(i int, k string) { + if i < len(arg) { + f.value[k] = arg[i] + } else { + f.value[k] = "" + } + }) + f.value["_return"], f.value["_res"] = "", v.res + value, pos := Value{list: kit.List()}, s.Position + f.pop, s.Position = func() { + if len(v.res) == 0 { + value.list = append(value.list, f.value["_return"]) + } else { + kit.For(v.res, func(k string) { value.list = append(value.list, f.value[k]) }) + } + s.Position = pos + }, v.Position + cb(f, v) + s.run(m.Options(STACK, s)) + return value + default: + return nil } - return "" } -func (s *Stack) expr(m *ice.Message, pos Position) string { - s.Position = pos - return m.Cmdx(EXPR) +func (s *Stack) cals(m *ice.Message) Any { return NewExpr(m, s).cals(m) } +func (s *Stack) expr(m *ice.Message, pos ...Position) string { + kit.If(len(pos) > 0, func() { s.Position = pos[0] }) + return m.Cmdx(EXPR, kit.Slice(s.rest, s.skip)) } -func NewStack() *Stack { return &Stack{} } +func (s *Stack) load(m *ice.Message) *Stack { + f := s.pushf(m.Options(STACK, s), "") + f.value["kit"] = func(key string, arg ...Any) Any { + kit.For(arg, func(i int, v Any) { arg[i] = trans(v) }) + switch key { + case "Dict": + return Dict{kit.Dict(arg...)} + case "List": + return List{kit.List(arg...)} + default: + m.ErrorNotImplement(key) + return nil + } + } + f.value["m"] = Message{m} + return s +} +func (s *Stack) parse(m *ice.Message, name string, r io.Reader, cb func(*Frame)) *Stack { + s.Buffer = &Buffer{name: name, input: bufio.NewScanner(r)} + s.load(m) + kit.If(cb != nil, func() { cb(s.peekf()) }) + s.run(m) + return s +} +func NewStack() *Stack { return &Stack{} } + func _parse_stack(m *ice.Message) *Stack { return m.Optionv(STACK).(*Stack) } func _parse_frame(m *ice.Message) (*Stack, *Frame) { return _parse_stack(m), _parse_stack(m).pushf(m, "") } -const ( - PWD = "pwd" - CMD = "cmd" - LET = "let" - IF = "if" - FOR = "for" - FUNC = "func" - CALL = "call" - RETURN = "return" - EXPR = "expr" -) const STACK = "stack" func init() { Index.MergeCommands(ice.Commands{ - PWD: {Name: "pwd", Hand: func(m *ice.Message, arg ...string) { - s := _parse_stack(m) - res := []string{kit.Format("%d:%d", s.line, s.skip)} - s.stack(func(f *Frame, i int) { - kit.If(i > 0, func() { - res = append(res, kit.Format("%d:%d %s %v", f.line, f.skip, f.key, kit.Select(ice.FALSE, ice.TRUE, f.status > DISABLE))) + STACK: {Name: "stack path auto parse", Actions: ice.Actions{ + ice.CMD: {Hand: func(m *ice.Message, arg ...string) { + nfs.Open(m, existsFile(m, arg[0]), func(r io.Reader, p string) { + meta := kit.Dict() + kit.For(NewStack().parse(m.Spawn(), p, r, nil).peekf().value, func(k string, v Any) { + switch v := v.(type) { + case Function: + list := kit.List() + kit.For(v.arg, func(k string) { + switch k { + case "m", ice.ARG: + default: + list = append(list, kit.Dict(mdb.NAME, k, mdb.TYPE, mdb.TEXT, mdb.VALUE, "")) + } + }) + kit.If(k == mdb.LIST, func() { list = append(list, kit.Dict(mdb.NAME, mdb.LIST, mdb.TYPE, "button", mdb.ACTION, ice.AUTO)) }) + meta[k] = list + } + }) + m.Push(ice.INDEX, arg[0]) + m.Push(mdb.NAME, arg[0]) + m.Push(mdb.HELP, arg[0]) + m.Push(mdb.LIST, kit.Format(meta[mdb.LIST])) + m.Push(mdb.META, kit.Format(meta)) }) - }) - m.Echo(strings.Join(res, " / ")).Echo(ice.NL) - }}, - CMD: {Name: "cmd", Hand: func(m *ice.Message, arg ...string) { - s := _parse_stack(m) - kit.If(s.runable(m), func() { - m.Cmdy(s.rest[s.skip+1:]) - m.EchoLine("") - }) - s.skip = len(s.rest) - }}, - LET: {Name: "let a, b = 1, 2", Hand: func(m *ice.Message, arg ...string) { m.Cmd(EXPR) }}, - IF: {Name: "if a = 1; a > 1 {", Hand: func(m *ice.Message, arg ...string) { - s, f := _parse_frame(m) - res := m.Cmdx(EXPR) - kit.If(s.token(m) == SPLIT, func() { res = m.Cmdx(EXPR) }) - kit.If(res == ice.FALSE, func() { f.status = DISABLE }) - }}, - FOR: {Name: "for a = 1; a < 10; a++ {", Hand: func(m *ice.Message, arg ...string) { - s, f := _parse_frame(m) - list, status := []Position{s.Position}, f.status - for f.status = DISABLE; s.token(m) != BEGIN; { - m.Cmd(EXPR) - list = append(list, s.Position) - } - f.status = status - res := ice.TRUE - if len(list) < 3 { - res = s.expr(m, list[0]) - } else { - if s.last == nil || s.last.line != s.line { - res = s.expr(m, list[0]) - } else { - kit.For(s.last.value, func(k string, v ice.Any) { f.value[k] = v }) - } - res = s.expr(m, list[1]) - } - kit.If(res == ice.FALSE, func() { f.status = DISABLE }) - s.Position, f.pop = list[len(list)-1], func() { - if s.runable(m) { - kit.If(len(list) > 3, func() { s.expr(m, list[2]) }) - s.Position = list[0] - s.Position.skip-- - } - } - }}, - FUNC: {Name: "func show(a, b) (c, d)", Hand: func(m *ice.Message, arg ...string) { - s := _parse_stack(m) - list, key, kind := [][]string{[]string{}}, "", "" - push := func() { kit.If(key, func() { list[len(list)-1], key, kind = append(list[len(list)-1], key), "", "" }) } - s.reads(m, func(i int, k string) bool { - switch k { - case OPEN: - defer kit.If(i > 0, func() { list = append(list, []string{}) }) - case FIELD, CLOSE: - case BEGIN: - return true - default: - kit.If(key, func() { kind = k }, func() { key = k }) - return false - } - push() - return false - }) - kit.If(len(list) < 2, func() { list = append(list, []string{}) }) - kit.If(len(list) < 3, func() { list = append(list, []string{}) }) - s.value(m, kit.Select("", list[0], -1), &Func{obj: list[0], arg: list[1], res: list[2], Position: s.Position}) - s.pushf(m, "").status = DISABLE - }}, - CALL: {Name: "call show", Hand: func(m *ice.Message, arg ...string) { - m.Echo("%v", NewExpr(m, _parse_stack(m)).call(m, arg[0])) - }}, - RETURN: {Name: "return show", Hand: func(m *ice.Message, arg ...string) { - s := _parse_stack(m) - if len(s.frame) == 1 { - close(s.input) - s.input = nil - } - f := s.peekf(m) - f.status = DISABLE - }}, - STACK: {Name: "stack path auto parse", Hand: func(m *ice.Message, arg ...string) { + }}, + ice.RUN: {Hand: func(m *ice.Message, arg ...string) { + nfs.Open(m, existsFile(m, arg[0]), func(r io.Reader, p string) { + s := NewStack().parse(m.Spawn(), p, r, nil) + action := mdb.LIST + if len(arg) > 2 && arg[1] == ice.ACTION && s.value(m, arg[2]) != nil { + action, arg = arg[2], arg[3:] + } else { + arg = arg[1:] + } + i := 0 + s.call(m, s.value(m, action), func(f *Frame, v Function) { + kit.For(v.arg, func(k string) { + switch k { + case "m": + f.value[k] = Message{m} + case ice.ARG: + list := kit.List() + kit.For(arg, func(v string) { list = append(list, String{v}) }) + f.value[k] = Value{list} + default: + f.value[k] = String{m.Option(k, kit.Select(m.Option(k), arg, i))} + i++ + } + }) + }) + }) + }}, + }, Hand: func(m *ice.Message, arg ...string) { if m.Options(nfs.DIR_ROOT, nfs.SRC).Cmdy(nfs.CAT, arg); len(m.Result()) == 0 { return } - nfs.Open(m, path.Join(nfs.SRC, path.Join(arg...)), func(r io.Reader) { - msg := NewStack().parse(m.Spawn(), r) - if m.SetResult(); m.Option(log.DEBUG) != ice.TRUE { - m.Copy(msg) + nfs.Open(m, path.Join(nfs.SRC, path.Join(arg...)), func(r io.Reader, p string) { + s := NewStack().parse(m, p, r, nil) + if m.Option(ice.DEBUG) != ice.TRUE { return } - s := _parse_stack(msg) - m.EchoLine("script: %s", arg[0]) + m.EchoLine("").EchoLine("script: %s", arg[0]) span := func(s, k, t string) string { return strings.ReplaceAll(s, k, kit.Format("%s", t, k)) } kit.For(s.list, func(i int, s string) { - kit.For([]string{"let", "if", "for", "func"}, func(k string) { s = span(s, k, "keyword") }) - kit.For([]string{"pwd", "cmd"}, func(k string) { s = span(s, k, "function") }) + kit.For([]string{LET, IF, FOR, FUNC}, func(k string) { s = span(s, k, KEYWORD) }) + kit.For([]string{PWD, INFO, SOURCE}, func(k string) { s = span(s, k, FUNCTION) }) m.EchoLine("%2d: %s", i, s) }) - m.EchoLine("").EchoLine("output: %s", arg[0]).Copy(msg) + m.EchoLine("").EchoLine("stack: %s", arg[0]).Cmdy(INFO) + }) }}, - EXPR: {Name: "expr a = 1", Hand: func(m *ice.Message, arg ...string) { - s := _parse_stack(m) - arg = s.rest - if v := NewExpr(m, s).cals(m); !s.runable(m) { - m.Resultv(v) - } else if v != nil { - m.Echo(kit.Format(v)) - } else if s.token(m) == BEGIN { - m.Echo(ice.TRUE) - } - m.Debug("expr value %v %v", m.Result(), arg) - }}, }) } - -const ( - OPS = "(,){;}*/+-!=<>&|" - OPEN = "(" - FIELD = "," - CLOSE = ")" - BEGIN = "{" - SPLIT = ";" - END = "}" - DISABLE = -1 -) - -var level = map[string]int{ - "++": 100, "--": 100, "!": 90, - "*": 40, "/": 40, "+": 30, "-": 30, - "==": 20, "!=": 20, "<=": 20, ">=": 20, "<": 20, ">": 20, "&&": 10, "||": 10, - "=": 2, ",": 2, "(": 1, ")": 1, +func existsFile(m *ice.Message, p string) string { + return nfs.SRC + strings.Replace(p, ice.PT, ice.PS, -1) + ice.PT + nfs.SHY } - -type Expr struct { - list ice.List - s *Stack - m *ice.Message -} - -func (s *Expr) push(v ice.Any) *Expr { - s.list = append(s.list, v) - return s -} -func (s *Expr) pop(n int) *Expr { - s.list = s.list[:len(s.list)-n] - return s -} -func (s *Expr) get(p int) (v ice.Any) { - kit.If(0 <= p+len(s.list) && p+len(s.list) < len(s.list), func() { v = s.list[p+len(s.list)] }) - kit.If(0 <= p && p < len(s.list), func() { v = s.list[p] }) - return -} -func (s *Expr) gets(p int) string { return kit.Format(s.get(p)) } -func (s *Expr) getl(p int) int { return level[s.gets(p)] } -func (s *Expr) getv(m *ice.Message, p int) (v ice.Any) { - if !s.s.runable(m) { - return nil - } - k := s.get(p) - if v = s.s.value(m, kit.Format(k)); v != nil { - return v - } - return k -} -func (s *Expr) setv(m *ice.Message, k string, v ice.Any) *Expr { - kit.If(s.s.runable(m), func() { - switch v := v.(type) { - case *Value: - s.s.value(m, k, v.list[0]) - default: - s.s.value(m, k, v) - } - }) - return s -} -func (s *Expr) ops(m *ice.Message) { - m.Debug("expr ops %v", s.list) - bin := func(v ice.Any) { s.pop(3).push(v) } - switch a, b := kit.Int(s.getv(m, -3)), kit.Int(s.getv(m, -1)); s.gets(-2) { - case "*": - bin(a * b) - case "/": - bin(a / b) - case "+": - bin(a + b) - case "-": - bin(a - b) - case ">": - bin(a > b) - case "<": - bin(a < b) - case "<=": - bin(a <= b) - case ">=": - bin(a >= b) - case "!=": - bin(a != b) - case "==": - bin(a == b) - } -} -func (s *Expr) end(m *ice.Message, arg ...string) ice.Any { - if s.gets(-1) == CLOSE { - s.pop(1) - } - for len(s.list) > 1 { - switch s.ops(m); s.gets(-2) { - case ",": - list := kit.List() - for i := len(s.list) - 2; i > 0; i -= 2 { - if s.list[i] == "=" { - for j := 0; j < i; j += 2 { - s.setv(m, s.gets(j), s.getv(m, j+i+1)) - list = append(list, s.getv(m, j)) - } - s.list = kit.List(&Value{list: list}) - break - } - } - if len(s.list) == 1 { - break - } - for i := 0; i < len(s.list); i += 2 { - list = append(list, s.getv(m, i)) - } - s.list = kit.List(&Value{list: list}) - case "=": - if len(s.list) == 3 { - s.setv(m, s.gets(-3), s.getv(m, -1)).pop(2) - break - } - list := kit.List() - switch v := s.getv(m, -1).(type) { - case *Value: - for i := 0; i < len(s.list)-1; i += 2 { - if i/2 < len(v.list) { - s.setv(m, s.gets(i), v.list[i/2]) - list = append(list, s.getv(m, i)) - } - } - } - s.list = kit.List(&Value{list}) - } - } - if !s.s.runable(m) { - return arg - } - if len(s.list) > 0 { - return s.list[0] - } - return nil -} - -func (s *Expr) cals(m *ice.Message) ice.Any { - m.Debug("expr calcs %d %v", s.s.line, s.s.rest[s.s.skip:]) - arg := s.s.reads(m, func(i int, k string) bool { - switch k { - case SPLIT, BEGIN: - return true - case END: - s.s.skip-- - return true - } - if level[k] == 0 && len(s.list) > 0 && s.getl(-1) == 0 { - s.s.skip-- - return true - } else if k == OPEN && len(s.list) > 0 && s.getl(-1) == 0 { - value := s.call(m, s.get(-1)) - s.pop(1).push(value) - } else if op := s.gets(-1) + k; level[op] > 0 && s.getl(-1) > 0 { - if op == "++" { - s.setv(m, s.gets(-2), kit.Int(s.s.value(m, s.gets(-2)))+1).pop(1) - } else { - s.pop(1).push(op) - } - } else if level[k] > 0 { - for level[k] >= 9 && level[k] <= s.getl(-2) { - s.ops(m) - } - if k == CLOSE { - if s.gets(-2) == OPEN { - v := s.get(-1) - s.pop(2).push(v) - return false - } - return true - } - s.push(k) - } else { - s.push(k) - } - return false - }) - return s.end(m, arg...) -} -func (s *Expr) call(m *ice.Message, name ice.Any) (v ice.Any) { - m.Debug("call %v", name) - list := kit.List(name) - switch v = NewExpr(m, s.s).cals(m); v := v.(type) { - case *Value: - list = append(list, v.list...) - default: - list = append(list, v) - } - m.Debug("call %v", list) - switch v := s.s.value(m, kit.Format(name)).(type) { - case *Func: - f := s.s.pushf(m, "") - kit.For(v.res, func(k string) { f.value[k] = "" }) - kit.For(v.arg, func(k string) { f.value[k] = "" }) - kit.For(v.arg, func(i int, k string) { kit.If(i+1 < len(list), func() { f.value[k] = list[i+1] }) }) - value, pos := &Value{list: kit.List()}, s.s.Position - f.pop, s.s.Position = func() { - kit.For(v.res, func(k string) { value.list = append(value.list, f.value[k]) }) - s.s.Position = pos - }, v.Position - m.Debug("call %#v", f) - s.s.call(m) - m.Debug("call %#v", value) - return value - default: - if s.s.runable(m) { - return m.Cmdx(list...) - } - return nil - } -} -func NewExpr(m *ice.Message, s *Stack) *Expr { return &Expr{kit.List(), s, m} } +func ExistsFile(m *ice.Message, p string) bool { return nfs.Exists(m, existsFile(m, p)) } diff --git a/base/yac/stmt.go b/base/yac/stmt.go new file mode 100644 index 00000000..e46ab7aa --- /dev/null +++ b/base/yac/stmt.go @@ -0,0 +1,229 @@ +package yac + +import ( + "io" + "strings" + + ice "shylinux.com/x/icebergs" + "shylinux.com/x/icebergs/base/nfs" + kit "shylinux.com/x/toolkits" +) + +const ( + LET = "let" + IF = "if" + ELSE = "else" + FOR = "for" + BREAK = "break" + CONTINUE = "continue" + SWITCH = "switch" + CASE = "case" + DEFAULT = "default" + FUNC = "func" + CALL = "call" + RETURN = "return" + SOURCE = "source" + INFO = "info" + PWD = "pwd" +) +const ( + KEYWORD = "keyword" + FUNCTION = "function" +) + +func init() { + Index.MergeCommands(ice.Commands{ + LET: {Name: "let a, b = 1, 2", Hand: func(m *ice.Message, arg ...string) { m.Cmd(EXPR) }}, + IF: {Name: "if a = 1; a > 1 {", Hand: func(m *ice.Message, arg ...string) { + s, f := _parse_frame(m) + res := s.expr(m) + kit.If(s.token() == SPLIT, func() { res = s.expr(m) }) + kit.If(res == ice.FALSE, func() { f.status = DISABLE }) + }}, + ELSE: {Name: "else if a = 1; a > 1 {", Hand: func(m *ice.Message, arg ...string) { + s, f := _parse_frame(m) + if s.last.status == DISABLE { + f.status = 0 + } else { + f.status, f.pop = DISABLE, func() { f.status = 0 } + } + s.reads(m, func(k string) bool { + if k == IF { + res := s.expr(m) + kit.If(s.token() == SPLIT, func() { res = s.expr(m) }) + kit.If(res == ice.FALSE, func() { f.status = DISABLE }) + } + return true + }) + }}, + FOR: {Name: "for a = 1; a < 10; a++ {", Hand: func(m *ice.Message, arg ...string) { + s, f := _parse_frame(m) + list, status := []Position{s.Position}, f.status + for f.status = DISABLE; s.token() != BEGIN; list = append(list, s.Position) { + s.expr(m) + } + f.status = status + res := ice.TRUE + if len(list) == 1 { + + } else if len(list) == 2 { + res = s.expr(m, list[0]) + } else { + if s.last == nil || s.last.line != s.line { + res = s.expr(m, list[0]) + } else { + kit.For(s.last.value, func(k string, v Any) { f.value[k] = v }) + } + res = s.expr(m, list[1]) + } + kit.If(res == ice.FALSE, func() { f.status = DISABLE }) + s.Position, f.pop = list[len(list)-1], func() { + if s.runable() { + kit.If(len(list) > 3, func() { s.expr(m, list[2]) }) + s.Position = list[0] + s.Position.skip-- + } + } + }}, + BREAK: {Name: "break", Hand: func(m *ice.Message, arg ...string) { + s := _parse_stack(m) + if !s.runable() { + return + } + s.stack(func(f *Frame, i int) bool { + f.status = DISABLE + defer s.popf(m) + switch f.key { + case FOR: + return true + default: + return false + } + }) + }}, + CONTINUE: {Name: "continue", Hand: func(m *ice.Message, arg ...string) { + s := _parse_stack(m) + if !s.runable() { + return + } + s.stack(func(f *Frame, i int) bool { + defer s.popf(m) + switch f.key { + case FOR: + return true + default: + return false + } + }) + }}, + SWITCH: {Name: "switch a = 1; a {", Hand: func(m *ice.Message, arg ...string) { + s, f := _parse_frame(m) + res := s.cals(m) + kit.If(s.token() == SPLIT, func() { res = s.cals(m) }) + f.value["_switch"], f.value["_case"] = res, "" + }}, + CASE: {Name: "case b:", Hand: func(m *ice.Message, arg ...string) { + s := _parse_stack(m) + f := s.peekf() + f.status = 0 + v := s.cals(m) + f.status = DISABLE + if res, ok := v.(Operater); ok { + if res, ok := res.Operate("==", trans(s.value(m, "_switch"))).(Boolean); ok && res.value { + f.status, f.value["_case"] = 0, "done" + } + } + }}, + DEFAULT: {Name: "default:", Hand: func(m *ice.Message, arg ...string) { + s := _parse_stack(m) + f := s.peekf() + if f.status = 0; f.value["_case"] == "done" { + f.status = DISABLE + } + s.skip++ + }}, + FUNC: {Name: "func show(a, b) (c, d)", Hand: func(m *ice.Message, arg ...string) { + s := _parse_stack(m) + list, key, kind := [][]string{[]string{}}, "", "" + push := func() { kit.If(key, func() { list[len(list)-1], key, kind = append(list[len(list)-1], key), "", "" }) } + s.reads(m, func(k string) bool { + switch k { + case OPEN: + defer kit.If(key != "" || len(list) > 1, func() { list = append(list, []string{}) }) + case FIELD, CLOSE: + case BEGIN: + return true + default: + kit.If(key, func() { kind = k }, func() { key = k }) + return false + } + push() + return false + }) + kit.If(len(list) < 2, func() { list = append(list, []string{}) }) + kit.If(len(list) < 3, func() { list = append(list, []string{}) }) + s.value(m, kit.Select("", list[0], -1), Function{obj: list[0], arg: list[1], res: list[2], Position: s.Position}) + s.pushf(m, "").status = DISABLE + }}, + RETURN: {Name: "return show", Hand: func(m *ice.Message, arg ...string) { + s := _parse_stack(m) + res := kit.Simple(trans(s.value(m, "_res"))) + if v := s.cals(m); len(res) == 0 { + f := s.peekf() + f.value["_return"] = v + } else { + switch v := v.(type) { + case Value: + kit.For(res, func(i int, k string) { kit.If(i < len(v.list), func() { s.value(m, k, v.list[i]) }) }) + default: + s.value(m, kit.Select("_res", res, 0), v) + } + } + s.stack(func(f *Frame, i int) bool { + f.status = DISABLE + switch f.key { + case FUNC: + + case CALL: + + case STACK: + s.input = nil + case SOURCE: + s.input = nil + default: + return false + } + return true + }) + }}, + SOURCE: {Name: "source", Hand: func(m *ice.Message, arg ...string) { + s := _parse_stack(m) + u := kit.ParseURL(s.expr(m)) + nfs.Open(m, u.Path, func(r io.Reader, p string) { + f := s.parse(m, p, r, func(f *Frame) { kit.For(u.Query(), func(k string, v []string) { f.value[k] = v[0] }) }).popf(m) + s.Position = f.Position + s.skip = len(s.rest) + }) + }}, + INFO: {Name: "info", Hand: func(m *ice.Message, arg ...string) { + _parse_stack(m).stack(func(f *Frame, i int) bool { + m.EchoLine("frame: %s %v:%v:%v", f.key, f.Position.name, f.Position.line, f.Position.skip) + kit.For(f.value, func(k string, v Any) { + m.EchoLine(" %s: %#v", k, v) + }) + return false + }) + }}, + PWD: {Name: "pwd", Hand: func(m *ice.Message, arg ...string) { + s := _parse_stack(m) + res := []string{kit.Format("%d:%d", s.line, s.skip)} + s.stack(func(f *Frame, i int) bool { + kit.If(i > 0, func() { + res = append(res, kit.Format("%s:%d:%d %s %v", f.name, f.line, f.skip, f.key, kit.Select(ice.FALSE, ice.TRUE, f.status > DISABLE))) + }) + return false + }) + m.Echo(strings.Join(res, " / ")).Echo(ice.NL) + }}, + }) +} diff --git a/base/yac/value.go b/base/yac/value.go new file mode 100644 index 00000000..9f607bdb --- /dev/null +++ b/base/yac/value.go @@ -0,0 +1,175 @@ +package yac + +import ( + "encoding/json" + "strings" + + ice "shylinux.com/x/icebergs" + kit "shylinux.com/x/toolkits" +) + +type Any = ice.Any +type Dict struct{ value map[string]Any } +type List struct{ value []Any } +type Value struct{ list []Any } +type String struct{ value string } +type Number struct{ value string } +type Boolean struct{ value bool } +type Caller interface{ Call(string, ...Any) Any } +type Operater interface{ Operate(string, Any) Any } + +func (s Dict) MarshalJSON() ([]byte, error) { return json.Marshal(s.value) } +func (s List) MarshalJSON() ([]byte, error) { return json.Marshal(s.value) } +func (s Value) MarshalJSON() ([]byte, error) { return json.Marshal(s.list) } +func (s String) MarshalJSON() ([]byte, error) { return json.Marshal(s.value) } +func (s Number) MarshalJSON() ([]byte, error) { return json.Marshal(s.value) } +func (s Boolean) MarshalJSON() ([]byte, error) { return json.Marshal(s.value) } + +func wrap(v Any) Any { + switch v := v.(type) { + case string: + return String{v} + default: + return v + } +} +func trans(v Any) Any { + switch v := v.(type) { + case Dict: + return v.value + case List: + return v.value + case Value: + if len(v.list) > 0 { + return v.list[0] + } + return nil + case String: + return v.value + case Number: + return v.value + case Boolean: + return v.value + default: + return v + } +} +func (s Dict) Operate(op string, v Any) Any { + switch op { + case SUBS: + return wrap(kit.Value(s.value, kit.Format(v))) + } + return nil +} +func (s List) Operate(op string, v Any) Any { + switch op { + case SUBS: + return wrap(kit.Value(s.value, kit.Format(v))) + } + return nil +} +func (s Value) Operate(op string, v Any) Any { + switch op { + case SUBS: + if i := kit.Int(v); i < len(s.list) { + return s.list[i] + } + } + return nil +} +func (s String) Operate(op string, v Any) Any { + switch a, b := s.value, kit.Format(v); op { + case "+": + return String{a + b} + case "-": + return String{strings.Replace(a, b, "", -1)} + case "<": + return Boolean{a < b} + case ">": + return Boolean{a > b} + case ">=": + return Boolean{a >= b} + case "<=": + return Boolean{a <= b} + case "!=": + return Boolean{a != b} + case "==": + return Boolean{a == b} + default: + return nil + } +} +func (s Number) Operate(op string, v Any) Any { + switch a, b := kit.Int(s.value), kit.Int(v); op { + case "*": + return Number{kit.Format(a * b)} + case "/": + return Number{kit.Format(a / b)} + case "+": + return Number{kit.Format(a + b)} + case "-": + return Number{kit.Format(a - b)} + case "<": + return Boolean{a < b} + case ">": + return Boolean{a > b} + case ">=": + return Boolean{a >= b} + case "<=": + return Boolean{a <= b} + case "!=": + return Boolean{a != b} + case "==": + return Boolean{a == b} + default: + return nil + } +} +func (s Boolean) Operate(op string, v Any) Any { + switch a, b := s.value, !kit.IsIn(kit.Format(v), "", "0", ice.FALSE); op { + case "&&": + return Boolean{a && b} + case "||": + return Boolean{a || b} + case "!": + return Boolean{!a} + default: + return nil + } +} + +type Message struct{ *ice.Message } + +func (m Message) Call(cmd string, arg ...Any) Any { + str := func(v Any) string { return kit.Format(trans(v)) } + args := []Any{} + for _, v := range arg { + args = append(args, trans(v)) + } + switch cmd { + case "Option": + return String{m.Option(str(args[0]), args[1:]...)} + case "Cmd": + return Message{m.Cmd(args...)} + case "Action": + m.Action(args...) + case "Cmdy": + m.Cmdy(args...) + case "Copy": + m.Copy(args[0].(Message).Message, kit.Simple(args[1:]...)...) + case "Push": + m.Push(str(args[0]), args[1], args[2:]...) + case "Echo": + m.Echo(str(args[0]), args[1:]...) + case "Sleep": + m.Sleep(str(args[0])) + case "Table": + s := _parse_stack(m.Message) + var value Any + m.Table(func(v ice.Maps) { value = s.call(m.Message, v, nil, Dict{kit.Dict(v)}) }) + return value + default: + m.ErrorNotImplement(cmd) + } + return m +} diff --git a/core/code/shy.go b/core/code/shy.go index cfcdc5d4..cecd7d51 100644 --- a/core/code/shy.go +++ b/core/code/shy.go @@ -20,7 +20,8 @@ func init() { SHY: {Name: "shy path auto", Help: "笔记", Actions: ice.MergeActions(ice.Actions{ mdb.RENDER: {Hand: func(m *ice.Message, arg ...string) { // ctx.ProcessCommand(m, web.WIKI_WORD, kit.Simple(path.Join(arg[2], arg[1]))) - ctx.ProcessCommand(m, yac.STACK, kit.Simple(arg[1])) + // ctx.ProcessCommand(m, yac.STACK, kit.Simple(arg[1])) + ctx.ProcessCommand(m, kit.TrimExt(arg[1], SHY), kit.Simple()) }}, mdb.ENGINE: {Hand: func(m *ice.Message, arg ...string) { ctx.ProcessCommand(m, yac.STACK, kit.Simple(arg[1])) diff --git a/go.mod b/go.mod index 0cc57d82..77f1add8 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,8 @@ go 1.11 require ( shylinux.com/x/creackpty v0.0.2 shylinux.com/x/go-qrcode v0.0.2 + shylinux.com/x/gogit v0.0.7 + shylinux.com/x/ice v1.3.0 shylinux.com/x/toolkits v0.7.4 shylinux.com/x/websocket v0.0.2 ) diff --git a/go.sum b/go.sum index e31e398f..b99df9f5 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,11 @@ shylinux.com/x/creackpty v0.0.2 h1:1ekWD5zeKZiQZCYvKSkHnm819wryZxzoq3kmvheC7bA= shylinux.com/x/creackpty v0.0.2/go.mod h1:SOsAaW5FdicXUprrxgENk2JP1f8LdHBXZjqOFot488o= shylinux.com/x/go-qrcode v0.0.2 h1:/c0PLj+1RT+kUPfnZVXwgbgH5m1SxBUjM2MIKXbDk+E= shylinux.com/x/go-qrcode v0.0.2/go.mod h1:TlzGBENHXy19xC3AsC6h4Vs5fx2ZuDA4TZ0U3C2OeK4= +shylinux.com/x/gogit v0.0.7 h1:2ep5QpXWLs0UBCywJuUHda/aagskYvFmn0nj3vpEdY4= +shylinux.com/x/gogit v0.0.7/go.mod h1:wYfHxpQT1C8yNV+yC1jStIy0I12bfUCyJARhn0sNn1M= +shylinux.com/x/ice v1.3.0 h1:Ro0DpT/qeFPer8R3it9+dptCFprx3/416cJWT3bceWE= +shylinux.com/x/ice v1.3.0/go.mod h1:sgSlRKoEKnZbmHZ8QuQ3VrFOlW/imi12GX2Z9drkngY= +shylinux.com/x/icebergs v1.5.4/go.mod h1:njja7CnbJD39p4OGDvIxmh7p8206nAlDiAiTh34CNiw= shylinux.com/x/toolkits v0.7.4 h1:PACWkhi/Iv8I+DWUq5y5Uq/Yty58EpyAUeBtDfe6a5g= shylinux.com/x/toolkits v0.7.4/go.mod h1:8LbYHe7oxBIqb6s4MSOD+4d28QvPdvkyCVtwB/JW7AA= shylinux.com/x/websocket v0.0.2 h1:aeeZyAsh6QN7+l5oMXlO9/rlQgx6CHvDtpZyAqMCSlU= diff --git a/meta.go b/meta.go index 2f70f1eb..46c52f82 100644 --- a/meta.go +++ b/meta.go @@ -156,10 +156,25 @@ func (m *Message) Push(key string, value Any, arg ...Any) *Message { func (m *Message) EchoLine(str string, arg ...Any) *Message { return m.Echo(str, arg...).Echo(NL) } +func PushNotice(m *Message, arg ...Any) bool { + if m.Option(MSG_DAEMON) == "" { + return false + } else if m.Option(MSG_USERPOD) == "" { + m.Cmd("web.space", m.Option(MSG_DAEMON), arg, Maps{MSG_OPTION: "", MSG_OPTS: ""}) + } else { + // m.Cmd("web.spide", OPS, MergeURL2(m, "/share/toast/"+m.Option(MSG_DAEMON)), ARG, kit.Format(arg)) + } + return true +} func (m *Message) Echo(str string, arg ...Any) *Message { if str == "" { return m } + // if m.Option("output.stream") == "grow" { + // if PushNotice(m, "grow", kit.Format(str, arg...)) { + // return m + // } + // } return m.Add(MSG_RESULT, kit.Format(str, arg...)) } func (m *Message) Copy(msg *Message, arg ...string) *Message {