diff --git a/base/cli/system.go b/base/cli/system.go index 75cf8978..ccb6ecf5 100644 --- a/base/cli/system.go +++ b/base/cli/system.go @@ -31,7 +31,7 @@ func _system_cmd(m *ice.Message, arg ...string) *exec.Cmd { } }) if bin == "" { - if text := kit.ReadFile(ice.ETC_PATH); len(text) > 0 { + if text := m.Cmdx(nfs.CAT, ice.ETC_PATH); len(text) > 0 { if bin = _system_find(m, arg[0], strings.Split(text, ice.NL)...); bin != "" { m.Logs(FIND, "etcpath cmd", bin) } @@ -106,7 +106,7 @@ func _system_exec(m *ice.Message, cmd *exec.Cmd) { func _system_code(cmd *exec.Cmd) string { return kit.Select("1", "0", cmd.ProcessState != nil && cmd.ProcessState.Success()) } -func _system_find(m Message, bin string, dir ...string) string { +func _system_find(m *ice.Message, bin string, dir ...string) string { if strings.Contains(bin, ice.DF) { return bin } @@ -203,13 +203,8 @@ func init() { }) } -type Message interface { - Append(key string, arg ...ice.Any) string - Optionv(key string, arg ...ice.Any) ice.Any -} - -func SystemFind(m Message, bin string, dir ...string) string { - if text := kit.ReadFile(ice.ETC_PATH); len(text) > 0 { +func SystemFind(m *ice.Message, bin string, dir ...string) string { + if text := m.Cmdx(nfs.CAT, ice.ETC_PATH); len(text) > 0 { dir = append(dir, strings.Split(text, ice.NL)...) } return _system_find(m, bin, append(dir, _path_split(kit.Env(PATH))...)...) @@ -218,4 +213,4 @@ func SystemExec(m *ice.Message, arg ...string) string { return strings.TrimSpace func SystemCmds(m *ice.Message, cmds string, args ...ice.Any) string { return strings.TrimRight(m.Cmdx(SYSTEM, "sh", "-c", kit.Format(cmds, args...), ice.Option{CMD_OUTPUT, ""}), ice.NL) } -func IsSuccess(m Message) bool { return m.Append(CODE) == "" || m.Append(CODE) == "0" } +func IsSuccess(m *ice.Message) bool { return m.Append(CODE) == "" || m.Append(CODE) == "0" } diff --git a/base/ctx/command.go b/base/ctx/command.go index c1d4674c..32cf6d67 100644 --- a/base/ctx/command.go +++ b/base/ctx/command.go @@ -24,12 +24,13 @@ func _command_list(m *ice.Message, name string) *ice.Message { if strings.HasPrefix(name, "can.") { return m.Push(mdb.INDEX, name).Push(mdb.NAME, name).Push(mdb.HELP, "").Push(mdb.META, "").Push(mdb.LIST, "") } + m.Spawn(m.Source()).Search(name, func(p *ice.Context, s *ice.Context, key string, cmd *ice.Command) { m.Push(mdb.INDEX, kit.Keys(s.Prefix(), key)) m.Push(mdb.NAME, kit.Format(cmd.Name)) m.Push(mdb.HELP, kit.Format(cmd.Help)) - m.Push(mdb.META, kit.Format(cmd.Meta)) - m.Push(mdb.LIST, kit.Format(cmd.List)) + m.Push(mdb.META, FormatPretty(cmd.Meta, 0, 2)) + m.Push(mdb.LIST, FormatPretty(cmd.List, 0, 2)) }) return m } diff --git a/base/ctx/config.go b/base/ctx/config.go index bce1f3d6..3b0a4f7c 100644 --- a/base/ctx/config.go +++ b/base/ctx/config.go @@ -12,6 +12,80 @@ import ( "shylinux.com/x/toolkits/miss" ) +func FormatPretty(v ice.Any, i, n int) string { + return kit.Formats(v) + switch v := v.(type) { + case map[string]ice.Any: + if n == 0 { + list := []string{"{"} + kit.For(v, func(k string, v ice.Any) { + list = append(list, kit.Format("%q", k), ice.DF, FormatPretty(v, 0, 0), ice.FS) + }) + list = list[:len(list)-1] + list = append(list, "}") + return strings.Join(list, "") + } + list := []string{"{", ice.NL} + kit.For(v, func(k string, v ice.Any) { + list = append(list, strings.Repeat(ice.TB, i+1), kit.Format("%q", k), ice.DF) + if i < n && !kit.IsIn(k, mdb.META) && !strings.HasPrefix(k, "_") { + list = append(list, FormatPretty(v, i+1, n)) + } else { + list = append(list, FormatPretty(v, 0, 0)) + } + list = append(list, ice.FS, ice.NL) + }) + list = append(list[:len(list)-2], ice.NL) + list = append(list, strings.Repeat(ice.TB, i), "}") + return strings.Join(list, "") + case []ice.Any: + if n == 0 { + list := []string{"["} + kit.For(v, func(k string, v ice.Any) { + list = append(list, FormatPretty(v, 0, 0), ice.FS) + }) + list = list[:len(list)-1] + list = append(list, "]") + return strings.Join(list, "") + } + list := []string{"[", ice.NL} + kit.For(v, func(v ice.Any) { + list = append(list, strings.Repeat(ice.TB, i+1)) + if i < n { + list = append(list, FormatPretty(v, i+1, n)) + } else { + list = append(list, FormatPretty(v, 0, 0)) + } + list = append(list, ice.FS, ice.NL) + }) + list = append(list[:len(list)-2], ice.NL) + list = append(list, strings.Repeat(ice.TB, i), "]") + return strings.Join(list, "") + case string: + return kit.Format(v) + return kit.Format("%q", v) + default: + return kit.Format(v) + } +} +func _config_format_list(m *ice.Message, v ice.Any) string { + list := []string{"{", ice.NL} + kit.For(v, func(k string, v ice.Any) { + if k == mdb.HASH { + list = append(list, ice.TB, kit.Format("%q", k), ice.DF, "{", ice.NL) + kit.For(v, func(k string, v ice.Any) { + list = append(list, ice.TB, ice.TB, kit.Format("%q", k), ice.DF, kit.Format(v), ice.FS, ice.NL) + }) + list = list[:len(list)-2] + list = append(list, ice.TB, ice.NL, ice.TB, "}", ice.FS, ice.NL) + } else { + list = append(list, ice.TB, kit.Format("%q", k), ice.DF, kit.Format(v), ice.FS, ice.NL) + } + }) + list = list[:len(list)-2] + list = append(list, ice.NL, "}") + return strings.Join(list, "") +} func _config_only(v ice.Any, arg ...string) bool { switch v := v.(type) { case nil: @@ -69,9 +143,9 @@ func _config_make(m *ice.Message, key string, arg ...string) { mdb.Confv(msg, key, arg[0], kit.Parse(nil, "", arg[1:]...)) } if len(arg) > 0 { - m.Echo(kit.Formats(mdb.Confv(msg, key, arg[0]))) + m.Echo(FormatPretty(mdb.Confv(msg, key, arg[0]), 0, 1)) } else { - m.Echo(kit.Formats(mdb.Confv(msg, key))) + m.Echo(FormatPretty(mdb.Confv(msg, key), 0, 1)) } } func _config_list(m *ice.Message) { diff --git a/base/mdb/mdb.go b/base/mdb/mdb.go index 7e5284de..fd6489a2 100644 --- a/base/mdb/mdb.go +++ b/base/mdb/mdb.go @@ -146,7 +146,13 @@ var Index = &ice.Context{Name: MDB, Help: "数据模块", Commands: ice.Commands INSERT: {Name: "insert key sub type arg...", Hand: func(m *ice.Message, arg ...string) { kit.Switch(arg[2], HASH, func() { _hash_insert(m, arg[0], arg[1], arg[3:]...) }, - ZONE, func() { _zone_insert(m, arg[0], arg[1], arg[3], arg[4:]...) }, + ZONE, func() { + if arg[3] == ZONE { + _zone_insert(m, arg[0], arg[1], arg[4], arg[5:]...) + } else { + _zone_insert(m, arg[0], arg[1], arg[3], arg[4:]...) + } + }, LIST, func() { _list_insert(m, arg[0], arg[1], arg[3:]...) }, ) }}, @@ -203,6 +209,13 @@ var Index = &ice.Context{Name: MDB, Help: "数据模块", Commands: ice.Commands func init() { ice.Index.Register(Index, nil, INPUTS, INSERT, DELETE, MODIFY, SELECT, PRUNES, EXPORT, IMPORT, PLUGIN, RENDER, ENGINE, SEARCH) } +func init() { + ice.Module(MDB, + HashInputs, HashCreate, HashRemove, func(m *ice.Message) { HashPrunes(m, nil) }, HashModify, HashSelect, + ZoneInputs, ZoneCreate, ZoneRemove, ZoneInsert, ZoneModify, ZoneSelect, + ) +} + func AutoConfig(arg ...Any) *ice.Action { return &ice.Action{Hand: func(m *ice.Message, args ...string) { if cs := m.Target().Configs; len(arg) > 0 { diff --git a/base/nfs/cat.go b/base/nfs/cat.go index 71bb0939..f8bc98cb 100644 --- a/base/nfs/cat.go +++ b/base/nfs/cat.go @@ -148,6 +148,9 @@ func Open(m *ice.Message, p string, cb ice.Any) { if p == "" { return } else if strings.HasSuffix(p, PS) { + if p == PS { + p = "" + } if ls, e := ReadDir(m, p); !m.Warn(e) { switch cb := cb.(type) { case func([]os.FileInfo): @@ -191,3 +194,6 @@ func ReadFile(m *ice.Message, p string) (b []byte, e error) { Open(m, p, func(r io.Reader) { b, e = ioutil.ReadAll(r) }) return } +func Rewrite(m *ice.Message, p string, cb func(string) string) { + m.Cmd(SAVE, p, m.Cmdx(CAT, p, func(s string, i int) string { return cb(s) })) +} diff --git a/base/nfs/dir.go b/base/nfs/dir.go index b26c5a51..bddd1154 100644 --- a/base/nfs/dir.go +++ b/base/nfs/dir.go @@ -182,7 +182,7 @@ func init() { } m.Logs(FIND, DIR_ROOT, root, PATH, dir, DIR_TYPE, m.Option(DIR_TYPE)) fields := kit.Split(kit.Select(kit.Select(DIR_DEF_FIELDS, m.OptionFields()), kit.Join(kit.Slice(arg, 1)))) - _dir_list(m, root, dir, 0, m.Option(DIR_DEEP) == ice.TRUE, kit.Select(TYPE_BOTH, m.Option(DIR_TYPE)), kit.Regexp(m.Option(DIR_REG)), fields).StatusTimeCount() + _dir_list(m, root, dir, 0, m.Option(DIR_DEEP) == ice.TRUE, kit.Select(TYPE_BOTH, m.Option(DIR_TYPE)), regexp.MustCompile(m.Option(DIR_REG)), fields).StatusTimeCount() }}, }) } diff --git a/base/nfs/grep.go b/base/nfs/grep.go index ea335732..06582d12 100644 --- a/base/nfs/grep.go +++ b/base/nfs/grep.go @@ -21,7 +21,10 @@ func init() { GREP: {Name: "grep word file path auto", Help: "搜索", Hand: func(m *ice.Message, arg ...string) { m.Options(mdb.VALUE, arg[0], CMD_DIR, kit.Select("", arg, 2)) kit.For(strings.Split(m.Cmdx("cli.system", GREP, "--exclude=.[a-z]*", "--exclude-dir=.[a-z]*", "-rni", arg[0], kit.Select(ice.PT, arg, 1)), ice.NL), func(s string) { + m.Debug("what %#v", s) if ls := strings.SplitN(s, ice.DF, 3); len(ls) > 2 { + m.Debug("what %#v", ls) + m.Debug("what %v", m.FormatMeta()) m.Push(FILE, strings.TrimPrefix(ls[0], PWD)).Push(s, ls[1]).Push(mdb.TEXT, ls[2]) } }) diff --git a/base/nfs/pack.go b/base/nfs/pack.go index 6fa53c6f..c5c7d875 100644 --- a/base/nfs/pack.go +++ b/base/nfs/pack.go @@ -43,7 +43,7 @@ func init() { if p := kit.Select("", arg, 0); p != "" && !strings.HasSuffix(p, PS) { Open(m, p, func(r io.Reader) { m.Echo(string(ReadAll(m, r))) }) } else { - Open(m, p+PS, func(s os.FileInfo) { + Open(m, path.Join(p)+PS, func(s os.FileInfo) { m.Push(mdb.TIME, s.ModTime().Format(ice.MOD_TIME)) m.Push(PATH, path.Join(p, s.Name())+kit.Select("", PS, s.IsDir())) m.Push(SIZE, kit.FmtSize(s.Size())) diff --git a/base/tcp/host.go b/base/tcp/host.go index d8e9445e..208de21a 100644 --- a/base/tcp/host.go +++ b/base/tcp/host.go @@ -86,17 +86,3 @@ func init() { func IsLocalHost(m *ice.Message, ip string) bool { return m.Cmdx(HOST, ISLOCAL, ip) == ice.OK } func PublishLocalhost(m *ice.Message, url string) string { return m.Cmdx(HOST, PUBLISH, url) } - -func init() { - ice.Info.Stack[Prefix(IsLocalHost)] = func(m *ice.Message, key string, arg ...ice.Any) ice.Any { - for _, v := range arg { - switch v := v.(type) { - case *ice.Message: - m = v - case string: - return IsLocalHost(m, v) - } - } - return false - } -} diff --git a/base/web/dream.go b/base/web/dream.go index b771dd3a..898ac43d 100644 --- a/base/web/dream.go +++ b/base/web/dream.go @@ -70,7 +70,7 @@ func _dream_template(m *ice.Message, p string) { } switch m.Cmdy(nfs.COPY, path.Join(p, file), path.Join(ice.USR_LOCAL_WORK, m.Option(nfs.TEMPLATE), file)); file { case ice.GO_MOD: - kit.Rewrite(path.Join(p, file), func(line string) string { + nfs.Rewrite(m, path.Join(p, file), func(line string) string { return kit.Select(line, nfs.MODULE+ice.SP+m.Option(mdb.NAME), strings.HasPrefix(line, nfs.MODULE)) }) } diff --git a/base/web/space.go b/base/web/space.go index 9682f56b..f926a53a 100644 --- a/base/web/space.go +++ b/base/web/space.go @@ -111,7 +111,7 @@ func _space_domain(m *ice.Message) (link string) { func _space_exec(m *ice.Message, source, target []string, c *websocket.Conn) { switch kit.Select(cli.PWD, m.Detailv(), 0) { case cli.PWD: - m.Push(mdb.LINK, kit.MergePOD(_space_domain(m), kit.Select("", source, -1))) + m.Push(mdb.LINK, m.MergePod(_space_domain(m), kit.Select("", source, -1))) default: kit.If(aaa.Right(m, m.Detailv()), func() { m = m.Cmd() }) } diff --git a/base/yac/error.go b/base/yac/error.go new file mode 100644 index 00000000..bd068252 --- /dev/null +++ b/base/yac/error.go @@ -0,0 +1,39 @@ +package yac + +import kit "shylinux.com/x/toolkits" + +type Error struct { + key string + detail string + fileline string + Position +} + +const ( + ERROR = "error" + + errNotImplement = "not implement: " + errNotSupport = "not support: " + errNotValid = "not valid: " + errNotFound = "not found: " +) + +func errCommon(key string, arg ...Any) Error { + detail := "" + if len(arg) == 1 { + switch v := arg[0].(type) { + case string: + detail = v + default: + kit.Format("%#v", v) + } + } else if len(arg) > 1 { + detail = kit.Format(arg[0], arg[1:]...) + } + + return Error{key: key, detail: detail, fileline: kit.FileLine(3, 100)} +} +func ErrNotImplement(arg ...Any) Error { return errCommon(errNotImplement, arg...) } +func ErrNotSupport(arg ...Any) Error { return errCommon(errNotSupport, arg...) } +func ErrNotValid(arg ...Any) Error { return errCommon(errNotValid, arg...) } +func ErrNotFound(arg ...Any) Error { return errCommon(errNotFound, arg...) } diff --git a/base/yac/expr.go b/base/yac/expr.go index 01cbb06a..4fd2c516 100644 --- a/base/yac/expr.go +++ b/base/yac/expr.go @@ -10,9 +10,10 @@ import ( const ( SPACE = "\t " - QUOTE = "\"" + QUOTE = "\"'`" TRANS = " " BLOCK = "[:](,){;}*/+-<>!=&|" + EXPAND = "..." DEFINE = ":=" ASSIGN = "=" SUBS = "[" @@ -111,7 +112,11 @@ func (s *Expr) ops(m *ice.Message) { if !s.runable() || s.getl(-2) < 10 { return } - s.pops(3, s.opv(m, -3, s.gets(-2), s.get(-1))) + if s.getl(-3) > 0 { + s.pops(3, s.opv(m, -1, s.gets(-2), nil)) + } else { + s.pops(3, s.opv(m, -3, s.gets(-2), s.get(-1))) + } } func (s *Expr) end(m *ice.Message) Any { if !s.runable() || len(s.list) == 0 { @@ -353,8 +358,17 @@ func (s *Expr) cals(m *ice.Message, arg ...string) Any { } s.push(k) } else { - if s.push(s.trans(m, k)); s.getl(-2) > 0 && (s.getl(-3) > 0 || len(s.list) == 2) { - s.pops(2, s.opv(m, -1, s.gets(-2), nil)) + if strings.HasSuffix(k, EXPAND) { + if v, ok := s.Stack.value(m, strings.TrimSuffix(k, EXPAND)).(Operater); ok { + if list, ok := v.Operate(EXPAND, nil).([]Any); ok && len(list) > 0 { + kit.For(list, func(v Any) { + s.list = append(s.list, v, FIELD) + }) + } + } + kit.If(s.gets(-1) == FIELD, func() { s.pop(1) }) + } else { + s.push(s.trans(m, k)) } } return false diff --git a/base/yac/import.go b/base/yac/import.go index 52dc97a1..c996f679 100644 --- a/base/yac/import.go +++ b/base/yac/import.go @@ -25,7 +25,8 @@ func init() { IMPORT: {Name: "import ice shylinux.com/x/icebergs", Hand: func(m *ice.Message, arg ...string) { load := func(pre string, u *url.URL, p string, r io.Reader) { if kit.Ext(p) == nfs.SHY { - s, f := _parse_frame(m) + s := _parse_stack(m) + f := s.pushf(m, "", pre, p) defer s.popf(m) kit.For(u.Query(), func(k string, v []string) { f.value[k] = v[0] }) s.parse(m, p, r) @@ -33,15 +34,17 @@ func init() { } } find := func(pre, url string) { + kit.If(url == "\"shylinux.com/x/ice\"", func() { pre, url = "ice", "\"shylinux.com/x/release\"" }) u := kit.ParseURL(strings.TrimSuffix(strings.TrimPrefix(url, "\""), "\"")) pre = kit.Select(path.Base(u.Path), pre) - kit.If(pre == ice.PT, func() { pre = "" }) - if ls := kit.Split(u.Path, ice.PS); path.Join(kit.Slice(ls, 0, 3)...) == ice.Info.Make.Module && nfs.Exists(m, path.Join(kit.Slice(ls, 3)...)) { - nfs.Open(m, path.Join(kit.Slice(ls, 3)...)+ice.PS, func(r io.Reader, p string) { load(pre, u, p, r) }) - } else if p := path.Join(ice.USR_REQUIRE, u.Path) + ice.PS; nfs.Exists(m, p) { - nfs.Open(m, p, func(r io.Reader, p string) { load(pre, u, p, r) }) - } else if p := nfs.USR + path.Join(kit.Slice(ls, 2)...) + ice.PS; nfs.Exists(m, p) { - nfs.Open(m, p, func(r io.Reader, p string) { load(pre, u, p, r) }) + kit.If(pre == nfs.PT, func() { pre = "" }) + m.Debug("import %v %v", pre, url) + if ls := kit.Split(u.Path, nfs.PS); path.Join(kit.Slice(ls, 0, 3)...) == ice.Info.Make.Module && nfs.Exists(m, path.Join(kit.Slice(ls, 3)...)) { + nfs.Open(m, path.Join(kit.Slice(ls, 3)...)+nfs.PS, func(r io.Reader, p string) { load(pre, u, p, r) }) + } else if p := path.Join(ice.USR_REQUIRE, u.Path); nfs.Exists(m, p) { + nfs.Open(m, p+nfs.PS, func(r io.Reader, p string) { load(pre, u, p, r) }) + } else if p := nfs.USR + path.Join(kit.Slice(ls, 2)...); nfs.Exists(m, p) { + nfs.Open(m, p+nfs.PS, func(r io.Reader, p string) { load(pre, u, p, r) }) } } s := _parse_stack(m) diff --git a/base/yac/stack.go b/base/yac/stack.go index 3c4c4cc8..24138f22 100644 --- a/base/yac/stack.go +++ b/base/yac/stack.go @@ -8,7 +8,6 @@ import ( "strings" ice "shylinux.com/x/icebergs" - "shylinux.com/x/icebergs/base/ctx" "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/nfs" kit "shylinux.com/x/toolkits" @@ -18,13 +17,12 @@ type Value struct { list []Any } type Function struct { - obj []Field - arg []Field - res []Field + obj Fields + arg Fields + res Fields Position object Object } - type Frame struct { key string name string @@ -37,6 +35,7 @@ type Stack struct { last *Frame frame []*Frame comment []string + Error []Error Position } type Position struct { @@ -133,9 +132,11 @@ func (s *Stack) value(m *ice.Message, key string, arg ...Any) Any { } return nil } +func (s *Stack) status_disable(f *Frame) { f.status = STATUS_DISABLE } +func (s *Stack) status_normal(f *Frame) { + kit.If(s.frame[len(s.frame)-2].status == STATUS_NORMAL, func() { f.status = STATUS_NORMAL }) +} func (s *Stack) runable() bool { return s.peekf().status > STATUS_DISABLE } -func (s *Stack) token() string { return kit.Select("", s.rest, s.skip) } -func (s *Stack) show() string { return Format(s.Position) } func (s *Stack) read(m *ice.Message) (text string, ok bool) { isvoid := func(text string) bool { return strings.TrimSpace(text) == "" } for s.line++; s.line < len(s.list); s.line++ { @@ -149,7 +150,7 @@ func (s *Stack) read(m *ice.Message) (text string, ok bool) { if s.line, s.list = len(s.list), append(s.list, text); isvoid(text) { continue } - m.Debug("input %d read \"%s\" %s", len(s.list), text, s.show()) + m.Debug("input %d read %q %s", len(s.list), text, s.show()) return text, true } return @@ -213,6 +214,8 @@ func (s *Stack) peek(m *ice.Message) string { s.reads(m, func(k string) bool { return true }) return s.token() } +func (s *Stack) token() string { return kit.Select("", s.rest, s.skip) } +func (s *Stack) show() string { return Format(s.Position) } func (s *Stack) pos(m *ice.Message, pos Position, n int) { s.Position = pos s.skip += n @@ -265,18 +268,35 @@ func (s *Stack) types(m *ice.Message) Any { s.skip += 2 return Slice{value: s.types(m)} case STRUCT: - key, t := []string{}, Struct{index: map[string]Any{}} + key, t := []string{}, Struct{index: map[string]Any{}, stack: s} for s.next(m); s.next(m) != END; { + line := s.line + kit.If(s.token() == "*", func() { s.next(m) }) if key = append(key, s.token()); s.next(m) == FIELD { continue } - types := s.types(m) + if s.line != line { + kit.For(key, func(key string) { + field := Field{types: key, name: kit.Select("", kit.Split(key, ice.PT), -1)} + m.Debug("value %s field %s %#v", Format(s), key, field) + t.index[field.name] = key + t.sups = append(t.sups, key) + }) + key, s.skip = key[:0], s.skip-1 + continue + } + types, tags := s.types(m), map[string]string{} + kit.If(strings.HasPrefix(s.peek(m), "`"), func() { + kit.For(kit.Split(strings.TrimPrefix(strings.TrimSuffix(s.next(m), "`"), "`"), ": "), func(k, v string) { tags[k] = v }) + }) kit.For(key, func(key string) { - field := Field{types, map[string]string{}, key} - if strings.HasSuffix(s.list[s.line], "`") { - kit.For(kit.Split(kit.Select("", kit.Split(s.list[s.line]), -1), ": "), func(k, v string) { field.tags[k] = v }) - } - t.index[key] = field + field := Field{types: types, name: key, tags: tags} + kit.If(field.types == nil, func() { + t.sups = append(t.sups, field.name) + field.types, field.name = field.name, kit.Select("", kit.Split(field.name, ice.PT), -1) + }) + m.Debug("value %s field %s %#v", Format(s), key, field) + t.index[field.name] = field }) key, s.skip = key[:0], len(s.rest) } @@ -308,10 +328,30 @@ func (s *Stack) types(m *ice.Message) Any { } } } + rename := func(list []Field) []Field { + for i := len(list) - 1; i > 0; i-- { + field = list[i] + if field.types != nil { + continue + } + if i+1 < len(list) { + field.types = list[i].types + } else { + field.types, field.name = field.name, "" + } + list[i] = field + } + return list + } kit.If(len(list) == 1, func() { list = append(list, []Field{}) }) - return Function{arg: list[0], res: list[1]} + return Function{arg: rename(list[0]), res: rename(list[1])} case "*": + continue default: + if strings.HasPrefix(s.token(), "`") { + s.skip-- + return nil + } return s.token() } } @@ -322,14 +362,21 @@ func (s *Stack) funcs(m *ice.Message, name string) Function { if f := s.pushf(m, FUNC, name); name == INIT { f.key = CALL } else { - f.status = STATUS_DISABLE + s.status_disable(f) } v.Position = s.Position s.run(m) return v } +func (s *Stack) pusherr(err Error) { + err.Position = s.Position + err.Position.skip = -1 + s.Error = append(s.Error, err) +} func (s *Stack) calls(m *ice.Message, obj Any, key string, cb func(*Frame, Function), arg ...Any) Any { m.Debug("calls %s %T %s(%s)", Format(s), obj, key, Format(arg...)) + m.Debug("calls %s %T %s(%#v)", Format(s), obj, key, arg) + _obj, _key := obj, key switch v := obj.(type) { case *Stack: if _v := v.value(m, key); _v != nil { @@ -339,21 +386,38 @@ func (s *Stack) calls(m *ice.Message, obj Any, key string, cb func(*Frame, Funct kit.For(kit.Split(key, ice.PT), func(k string) { switch v := obj.(type) { case Operater: - obj, key = v.Operate(SUBS, k), strings.TrimPrefix(strings.TrimPrefix(key, k), ice.PT) + obj = v.Operate(SUBS, k) case *Stack: - obj, key = v.value(m, k), strings.TrimPrefix(strings.TrimPrefix(key, k), ice.PT) + obj = v.value(m, k) + default: + return } + key = strings.TrimPrefix(strings.TrimPrefix(key, k), ice.PT) }) + m.Debug("calls %s %T %s(%s)", Format(s), obj, key, Format(arg...)) + if obj == nil { + if _obj == s { + s.pusherr(ErrNotFound(_key)) + } else { + s.pusherr(ErrNotFound(_obj, _key)) + } + return nil + } switch obj := obj.(type) { case Function: name := kit.Format("%s%s", kit.Select("", kit.Format("%s.", obj.obj[0].types), len(obj.obj) > 1), obj.obj[len(obj.obj)-1].name) m.Debug("calls %s %s(%s) %s", Format(s), name, Format(arg...), Format(obj.Position)) f := s.pushf(m, CALL, name, Format(obj.Position)) - for _, field := range obj.res { - f.value[field.name] = nil - } + obj.res.For(func(field Field) { f.value[field.name] = nil }) + obj.arg.For(func(field Field) { f.value[field.name] = nil }) for i, field := range obj.arg { - kit.If(i < len(arg), func() { f.value[field.name] = arg[i] }, func() { f.value[field.name] = nil }) + kit.If(i < len(arg), func() { + if strings.HasPrefix(kit.Format(field.types), EXPAND) { + f.value[field.name] = List{arg[i:]} + } else { + f.value[field.name] = arg[i] + } + }) } kit.If(len(obj.obj) > 1, func() { f.value[obj.obj[0].name] = obj.object }) value, pos := Value{list: kit.List()}, s.Position @@ -367,29 +431,34 @@ func (s *Stack) calls(m *ice.Message, obj Any, key string, cb func(*Frame, Funct } } s.Position, f.defers = obj.Position, append(f.defers, func() { - if len(obj.res) > 0 && len(value.list) == 0 { - for _, field := range obj.res { - value.list = append(value.list, f.value[field.name]) - } - } + kit.If(len(obj.res) > 0 && len(value.list) == 0, func() { obj.res.For(func(field Field) { value.list = append(value.list, f.value[field.name]) }) }) s.Position = pos }) kit.If(cb != nil, func() { cb(f, obj) }) s.run(m) return value case Caller: + if msg, ok := m.Optionv(ice.YAC_MESSAGE).(*ice.Message); ok { + m = msg + } kit.For(arg, func(i int, v Any) { arg[i] = Trans(arg[i]) }) m.Debug("calls %s %s.%s(%s)", Format(s), Format(obj), key, Format(arg...)) - return wrap(obj.Call(kit.Format(key), arg...)) + return Wraps(obj.Call(kit.Format(key), arg...)) case func(*ice.Message, string, ...Any) Any: + if msg, ok := m.Optionv(ice.YAC_MESSAGE).(*ice.Message); ok { + m = msg + } + m.Debug("calls %s %s %s %#v", Format(s), Format(obj), key, arg) kit.For(arg, func(i int, v Any) { arg[i] = Trans(arg[i]) }) m.Debug("calls %s %s %s %s", Format(s), Format(obj), key, Format(arg...)) - return wrap(obj(m, kit.Format(key), arg...)) + m.Debug("calls %s %s %s %#v", Format(s), Format(obj), key, arg) + return Wraps(obj(m, kit.Format(key), arg...)) case func(): obj() return nil default: if key == "" { + s.pusherr(ErrNotSupport(obj)) return nil } args := kit.List(key) @@ -400,17 +469,23 @@ func (s *Stack) calls(m *ice.Message, obj Any, key string, cb func(*Frame, Funct } func (s *Stack) Action(m *ice.Message, obj Any, key string, arg ...string) *ice.Message { s.calls(m, obj, key, func(f *Frame, v Function) { - i := 0 - for _, field := range v.arg { + n := 0 + for i, field := range v.arg { switch field.name { case "m", "msg": f.value[field.name] = Message{m} case ice.ARG: list := kit.List() kit.For(arg, func(v string) { list = append(list, String{v}) }) - f.value[field.name] = Value{list} + f.value[field.name] = List{list} default: - f.value[field.name], i = String{m.Option(field.name, kit.Select(m.Option(field.name), arg, i))}, i+1 + if strings.HasPrefix(kit.Format(field.types), EXPAND) { + list := kit.List() + kit.For(arg[i:], func(v string) { list = append(list, String{v}) }) + f.value[field.name] = List{list} + } else { + f.value[field.name], n = String{m.Option(field.name, kit.Select(m.Option(field.name), arg, n))}, n+1 + } } } }) @@ -418,34 +493,51 @@ func (s *Stack) Action(m *ice.Message, obj Any, key string, arg ...string) *ice. } func (s *Stack) Handler(obj Any) ice.Handler { return func(m *ice.Message, arg ...string) { - m.Copy(s.Action(m.Options(ice.YAC_STACK, s).Spawn(Index).Spawn(m.Target()), obj, "", arg...)) + m.Copy(s.Action(m.Options(ice.YAC_STACK, s, ice.YAC_MESSAGE, m).Spawn(Index).Spawn(m.Target()), obj, "", arg...)) + if m.Option(ice.DEBUG) == ice.TRUE && len(s.Error) > 0 { + m.EchoLine("") + for _, e := range s.Error { + m.EchoLine("%s%s %s %s", e.key, e.detail, Format(e.Position), e.fileline) + } + } } } func (s *Stack) parse(m *ice.Message, name string, r io.Reader) *Stack { pos := s.Position - defer func() { s.Position = pos }() + defer func() { s.Position, s.peekf().Position = pos, pos }() s.Position = Position{Buffer: &Buffer{name: name, input: bufio.NewScanner(r)}} s.peekf().Position = s.Position m.Debug("stack %s parse %s", Format(s), s.show()) s.run(m) return s } +func (s *Stack) load(m *ice.Message, cb func(*Frame)) *Stack { + f := s.peekf() + for k, v := range ice.Info.Stack { + kit.If(strings.HasPrefix(k, "web.code."), func() { k = strings.TrimPrefix(k, "web.") }) + f.value[k] = v + } + kit.If(cb != nil, func() { cb(f) }) + f.value["m"] = Message{m} + return s +} func NewStack(m *ice.Message, cb func(*Frame), arg ...string) *Stack { s := &Stack{} - s.pushf(m.Options(ice.YAC_STACK, s), kit.Simple(STACK, arg)...) - s.load(m, cb) - return s + s.pushf(m.Options(ice.YAC_STACK, s, ice.YAC_MESSAGE, m), kit.Simple(STACK, arg)...) + return s.load(m, cb) } func _parse_stack(m *ice.Message) *Stack { return m.Optionv(ice.YAC_STACK).(*Stack) } func _parse_frame(m *ice.Message) (*Stack, *Frame) { return _parse_stack(m), _parse_stack(m).pushf(m, "") } +func _parse_link(m *ice.Message, p string) string { + ls := nfs.SplitPath(m, p) + return ice.Render(m, ice.RENDER_ANCHOR, p, m.MergePodCmd("", "web.code.vimer", nfs.PATH, ls[0], nfs.FILE, ls[1], nfs.LINE, ls[2])) +} func _parse_const(m *ice.Message, key string) string { if k := kit.Select(key, strings.Split(key, ice.PT), -1); kit.IsUpper(k) { - // if c, ok := ice.Info.Index[strings.ToLower(k)].(*ice.Context); ok && (key == k || key == c.Prefix(k)) { return strings.ToLower(k) - // } } return "" } @@ -468,17 +560,16 @@ const STACK = "stack" func init() { Index.MergeCommands(ice.Commands{ - STACK: {Name: "stack path auto parse", Actions: ice.MergeActions(ice.Actions{ - "start": {Hand: func(m *ice.Message, arg ...string) {}}, - }, ctx.CmdAction()), Hand: func(m *ice.Message, arg ...string) { - if len(arg) == 0 || strings.HasSuffix(arg[0], ice.PS) { - m.Options(nfs.DIR_ROOT, nfs.SRC).Cmdy(nfs.CAT, arg) + STACK: {Name: "stack path auto", Hand: func(m *ice.Message, arg ...string) { + kit.If(len(arg) == 0, func() { arg = append(arg, nfs.SRC) }) + if strings.HasSuffix(arg[0], nfs.PS) { + m.Cmdy(nfs.CAT, arg) return } - nfs.Open(m, path.Join(nfs.SRC, strings.TrimPrefix(path.Join(arg...), nfs.SRC)), func(r io.Reader, p string) { - s := NewStack(m, nil, "", p).parse(m, p, r) + nfs.Open(m, path.Join(arg...), func(r io.Reader, p string) { + s := NewStack(m, nil, p, p).parse(m, p, r) if m.StatusTime(mdb.LINK, s.value(m, "_link")); m.Option(ice.DEBUG) == ice.TRUE { - m.Option("__index", kit.Format(s.value(m, "_index"))) + m.Options("__index", kit.Format(s.value(m, "_index"))) m.Cmdy(INFO, arg) } }) @@ -492,8 +583,9 @@ func init() { } func StackHandler(m *ice.Message, arg ...string) { - s := NewStack(m, nil) script := []string{} + m = m.Spawn(Index).Spawn(m.Target()) + s := NewStack(m, nil, m.PrefixKey()) nfs.Open(m, ice.SRC_SCRIPT+m.PrefixKey()+ice.PS, func(r io.Reader, p string) { kit.If(kit.Ext(p) == nfs.SHY, func() { if strings.HasPrefix(path.Base(p), "on") { @@ -509,26 +601,25 @@ func StackHandler(m *ice.Message, arg ...string) { }) script = append(script, "})") } else { - s.parse(m.Spawn(Index).Spawn(m.Target()), p, r) + s.parse(m, p, r) } }) }) if len(script) > 0 { p := ice.USR_SCRIPT + m.PrefixKey() + ice.PS + "list.js" - s.value(m, "_script", "/require/"+p) m.Cmd(nfs.SAVE, p, kit.Dict(nfs.CONTENT, strings.Join(script, ice.NL))) + s.value(m, "_script", "/require/"+p) } cmd := m.Commands("") kit.For(s.peekf().value, func(k string, v Any) { - switch v := v.(type) { + switch k = kit.LowerCapital(k); v := v.(type) { case Function: list := kit.List() - for _, field := range v.arg { + v.arg.For(func(field Field) { kit.If(!kit.IsIn(field.name, "m", "msg", ice.ARG), func() { list = append(list, kit.Dict(mdb.NAME, field.name, 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)) }) + }) if k == mdb.LIST { - cmd.Hand, cmd.List = s.Handler(v), list + cmd.Hand, cmd.List = s.Handler(v), append(list, kit.Dict(mdb.NAME, mdb.LIST, mdb.TYPE, "button", mdb.ACTION, ice.AUTO)) } else { cmd.Actions[k], cmd.Meta[k] = &ice.Action{Hand: s.Handler(v)}, list } diff --git a/base/yac/stmt.go b/base/yac/stmt.go index 9c170624..788d796b 100644 --- a/base/yac/stmt.go +++ b/base/yac/stmt.go @@ -1,11 +1,11 @@ package yac import ( - "io" "strings" ice "shylinux.com/x/icebergs" - "shylinux.com/x/icebergs/base/nfs" + "shylinux.com/x/icebergs/base/ctx" + "shylinux.com/x/icebergs/base/mdb" kit "shylinux.com/x/toolkits" ) @@ -20,14 +20,13 @@ const ( CASE = "case" DEFAULT = "default" FUNC = "func" - INIT = "init" - MAIN = "main" - CALL = "call" DEFER = "defer" RETURN = "return" - SOURCE = "source" - INFO = "info" - PWD = "pwd" + + CALL = "call" + INIT = "init" + MAIN = "main" + INFO = "info" ) const ( KEYWORD = "keyword" @@ -40,19 +39,19 @@ func init() { 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 = STATUS_DISABLE }) + kit.If(res == ice.FALSE, func() { s.status_disable(f) }) }}, ELSE: {Name: "else if a = 1; a > 1 {", Hand: func(m *ice.Message, arg ...string) { s, f := _parse_frame(m) if s.last.status == STATUS_DISABLE { - f.status = STATUS_NORMAL + s.status_normal(f) } else { - f.status, f.defers = STATUS_DISABLE, append(f.defers, func() { f.status = STATUS_NORMAL }) + f.status, f.defers = STATUS_DISABLE, append(f.defers, func() { s.status_normal(f) }) } if s.next(m) == IF { res := s.expr(m) kit.If(s.token() == SPLIT, func() { res = s.expr(m) }) - kit.If(res == ice.FALSE, func() { f.status = STATUS_DISABLE }) + kit.If(res == ice.FALSE, func() { s.status_disable(f) }) } }}, FOR: {Name: "for a = 1; a < 10; a++ {", Hand: func(m *ice.Message, arg ...string) { @@ -60,26 +59,30 @@ func init() { if strings.Contains(s.list[s.line], RANGE) { pos, key, list := s.Position, []string{}, []Any{} kit.If(s.last != nil && s.last.line == s.line, func() { list, _ = s.last.value["_range"].([]Any) }) - for { - if k := s.cals0(m, FIELD, DEFS, ASSIGN); k == RANGE { + for s.next(m) != BEGIN { + switch s.token() { + case RANGE: if obj, ok := s.cals(m).(Operater); ok { if list, ok := obj.Operate(RANGE, list).([]Any); ok { kit.For(key, func(i int, k string) { f.value[k] = list[i] }) + f.defers = append(f.defers, func() { kit.If(s.runable(), func() { s.pos(m, pos, -1) }) }) f.value["_range"] = list - break + return } } - f.status = STATUS_DISABLE - break - } else if k != "" { - key = append(key, k) + s.status_disable(f) + return + case ASSIGN: + case DEFS: + case FIELD: + default: + key = append(key, s.token()) } } - f.defers = append(f.defers, func() { kit.If(s.runable(), func() { s.pos(m, pos, -1) }) }) return } list, status := []Position{s.Position}, f.status - for f.status = STATUS_DISABLE; s.token() != BEGIN; list = append(list, s.Position) { + for s.status_disable(f); s.token() != BEGIN; list = append(list, s.Position) { s.expr(m) } f.status = status @@ -96,7 +99,7 @@ func init() { } res = s.expr(m, list[1]) } - kit.If(res == ice.FALSE, func() { f.status = STATUS_DISABLE }) + kit.If(res == ice.FALSE, func() { s.status_disable(f) }) s.Position, f.defers = list[len(list)-1], append(f.defers, func() { if s.runable() { kit.If(len(list) > 3, func() { s.expr(m, list[2]) }) @@ -110,8 +113,7 @@ func init() { return } s.stack(func(f *Frame, i int) bool { - f.status = STATUS_DISABLE - switch s.popf(m); f.key { + switch s.status_disable(f); f.key { case FOR, SWITCH: return true default: @@ -125,8 +127,9 @@ func init() { return } s.stack(func(f *Frame, i int) bool { - switch s.popf(m); f.key { + switch s.status_disable(f); f.key { case FOR: + f.defers = append(f.defers, func() { s.status_normal(f) }) return true default: return false @@ -142,23 +145,23 @@ func init() { CASE: {Name: "case b:", Hand: func(m *ice.Message, arg ...string) { s := _parse_stack(m) f := s.peekf() - f.status = STATUS_NORMAL + s.status_normal(f) v := s.cals(m) - f.status = STATUS_DISABLE - if f.value["_case"] == "done" { + if s.status_disable(f); f.value["_case"] == "done" { return } 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"] = STATUS_NORMAL, "done" + f.value["_case"] = "done" + s.status_normal(f) } } }}, DEFAULT: {Name: "default:", Hand: func(m *ice.Message, arg ...string) { s := _parse_stack(m) f := s.peekf() - if f.status = STATUS_NORMAL; f.value["_case"] == "done" { - f.status = STATUS_DISABLE + if s.status_normal(f); f.value["_case"] == "done" { + s.status_disable(f) } s.skip++ }}, @@ -169,8 +172,9 @@ func init() { for s.next(m) != CLOSE { kit.If(field.name == "", func() { field.name = s.token() }, func() { field.types = s.token() }) } - s.next(m) + kit.If(field.types == nil, func() { field.types = field.name }) list = append(list, field) + s.next(m) } name := s.token() list = append(list, Field{name: name}) @@ -181,7 +185,7 @@ func init() { m.Debug("value %s set %s.%s %s", Format(s), field.types, name, Format(v)) t.index[name] = v } - } else if name != INIT { + } else if !kit.IsIn(name, INIT, MAIN) { s.value(m, name, v) } }}, @@ -207,16 +211,13 @@ func init() { s := _parse_stack(m) args := _parse_res(m, s.cals(m)) s.stack(func(f *Frame, i int) bool { - f.status = STATUS_DISABLE - switch f.key { + switch s.status_disable(f); f.key { case FUNC: case CALL: switch cb := f.value["_return"].(type) { case func(...Any): cb(args...) } - case SOURCE: - s.input = nil case STACK: s.input = nil default: @@ -225,67 +226,54 @@ func init() { 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) { - s.parse(m, p, r) - s.skip = len(s.rest) - }) - }}, - INFO: {Name: "info", Hand: func(m *ice.Message, arg ...string) { - m.EchoLine("").EchoLine("stack: %s", arg[0]) - _parse_stack(m).stack(func(f *Frame, i int) bool { - m.EchoLine("frame: %s %v:%v:%v", f.key, f.name, f.line, f.skip) - show := func(p string) string { - ls := nfs.SplitPath(m, p) - return ice.Render(m, ice.RENDER_ANCHOR, p, m.MergePodCmd("", "web.code.vimer", nfs.PATH, ls[0], nfs.FILE, ls[1], nfs.LINE, ls[2])) + INFO: {Name: "info", Actions: ice.Actions{ + ERROR: {Hand: func(m *ice.Message, arg ...string) { + for _, e := range _parse_stack(m).Error { + m.EchoLine(" %s%s %s %s", e.key, e.detail, _parse_link(m, Format(e.Position)), _parse_link(m, e.fileline)) } - kit.For(f.value, func(k string, v Any) { - switch v := v.(type) { - case func(*ice.Message, string, ...Any) Any: - m.EchoLine(" %s: %v", k, show(kit.FileLine(v, 100))) - case Message: - m.EchoLine(" %s: %v", k, show(kit.FileLine(v.Call, 100))) - case Function: - m.EchoLine(" %s: %v", k, show(v.Position.name+":"+kit.Format(v.Position.line+1))) - case Struct: - m.EchoLine(" %s: struct", k) - kit.For(v.index, func(k string, v Any) { - switch v := v.(type) { - case Function: - m.EchoLine(" %s: %v", k, show(v.Position.name+":"+kit.Format(v.Position.line+1))) - case Field: - m.EchoLine(" %s: %v", k, v.Format()) - } - }) - case string: - m.EchoLine(" %s: %v", k, v) - default: - m.EchoLine(" %s: %v", k, Format(v)) - } + }}, + STACK: {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.name, f.line, f.skip) + show := func(p string) string { return _parse_link(m, p) } + kit.For(f.value, func(k string, v Any) { + switch v := v.(type) { + case func(*ice.Message, string, ...Any) Any: + m.EchoLine(" %s: %v", k, show(kit.FileLine(v, 100))) + case Message: + m.EchoLine(" %s: %v", k, show(kit.FileLine(v.Call, 100))) + case Function: + m.EchoLine(" %s: %v", k, show(v.Position.name+ice.DF+kit.Format(v.Position.line+1))) + case Struct: + m.EchoLine(" %s: %s", k, show(v.Position.name+ice.DF+kit.Format(v.Position.line+1))) + break + kit.For(v.index, func(k string, v Any) { + switch v := v.(type) { + case Function: + m.EchoLine(" %s: %v", k, show(v.Position.name+ice.DF+kit.Format(v.Position.line+1))) + case Field: + m.EchoLine(" %s: %v", k, v.Format()) + } + }) + case string: + m.EchoLine(" %s: %v", k, v) + default: + m.EchoLine(" %s: %v", k, Format(v)) + } + }) + return false }) - return false - }) - m.EchoLine("stmt: %s", arg[0]) - kit.For(kit.SortedKey(m.Target().Commands), func(key string) { - if strings.HasPrefix(key, "_") || strings.HasPrefix(key, ice.PS) { - return - } - cmd := m.Target().Commands[key] - m.EchoLine(" %s: %#v", key, cmd.Name) - }) - }}, - 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 %s %s:%d:%d", f.key, kit.Select(ice.FALSE, ice.TRUE, f.status > STATUS_DISABLE), f.name, f.line, f.skip)) - }) - return false - }) - m.Echo(strings.Join(res, " / ")).Echo(ice.NL) + }}, + ctx.CONFIG: {Hand: func(m *ice.Message, arg ...string) { + m.Cmdy(ctx.CONFIG, m.Option("__index")).EchoLine("") + }}, + ctx.COMMAND: {Hand: func(m *ice.Message, arg ...string) { + msg := m.Cmd(ctx.COMMAND, m.Option("__index")) + m.EchoLine(msg.Append(mdb.LIST)) + m.EchoLine(msg.Append(mdb.META)) + }}, + }, Hand: func(m *ice.Message, arg ...string) { + kit.For([]string{ERROR, STACK, ctx.CONFIG, ctx.COMMAND}, func(k string) { m.EchoLine("%s: %s", k, arg[0]).Cmdy("", k) }) }}, }) } diff --git a/base/yac/type.go b/base/yac/type.go index d29b4ee4..233c08b4 100644 --- a/base/yac/type.go +++ b/base/yac/type.go @@ -16,68 +16,145 @@ type Slice struct { } type Interface struct { index map[string]Function + sups []string name string + stack *Stack } type Struct struct { index map[string]Any + sups []string name string + stack *Stack + Position } +type Fields []Field type Field struct { types Any - tags map[string]string name string + tags map[string]string } - -func (s Field) MarshalJSON() ([]byte, error) { - return []byte(kit.Format("%q", s.Format())), nil -} -func (s Field) Format() string { - if len(s.tags) == 0 { - return kit.Format("%s", s.types) - } - res := []string{} - kit.For(s.tags, func(k, v string) { res = append(res, kit.Format("%s:\"%s\"", k, v)) }) - return kit.Format("%s `%s`", s.types, strings.Join(res, ice.SP)) -} - type Object struct { value Operater index Struct } +func (s Fields) For(cb func(Field)) { + for _, v := range s { + cb(v) + } +} +func (s Field) MarshalJSON() ([]byte, error) { + return []byte(kit.Format("%q", s.Format())), nil +} +func (s Field) Format() string { + if types := ""; len(s.tags) == 0 { + switch t := s.types.(type) { + case string: + types = t + default: + types = Format(s.types) + } + return types + } else { + res := []string{} + kit.For(s.tags, func(k, v string) { res = append(res, kit.Format("%s:\"%s\"", k, v)) }) + return kit.Format("%s `%s`", types, strings.Join(res, ice.SP)) + } +} +func (s Function) Operate(op string, v Any) Any { + switch op { + case "==": + switch v := v.(type) { + case Function: + if len(s.arg) != len(v.arg) { + return false + } + if len(s.res) != len(v.res) { + return false + } + for i, field := range v.arg { + if s.arg[i].types == field.types { + continue + } + return false + } + for i, field := range v.res { + if s.res[i].types == field.types { + continue + } + return false + } + return true + default: + return ErrNotSupport(v) + } + default: + return ErrNotImplement(op) + } +} + +func (s Struct) For(cb func(k string, v Any)) { + kit.For(s.index, cb) + kit.For(s.sups, func(sup string) { + if sup, ok := s.stack.value(ice.Pulse, sup).(Struct); ok { + sup.For(cb) + } + }) +} +func (s Struct) Find(k string) Any { + if v, ok := s.index[k]; ok { + return v + } + for _, sup := range s.sups { + if sup, ok := s.stack.value(ice.Pulse, sup).(Struct); ok { + if v := sup.Find(k); v != nil { + return v + } + } + } + return ErrNotFound(k) +} +func (s Struct) Operate(op string, v Any) Any { + switch op { + case "==": + switch v := v.(type) { + case Struct: + return Boolean{s.name == v.name} + default: + return ErrNotSupport(v) + } + default: + return ErrNotImplement(op) + } +} func (s Object) Operate(op string, v Any) Any { switch op { case "&", "*": return s case INSTANCEOF: if t, ok := v.(Struct); ok { - return Value{list: []Any{s, s.index.name == t.name}} + return Value{list: []Any{s, Boolean{s.index.name == t.name}}} } - return Value{list: []Any{s, false}} + return ErrNotSupport(v) case IMPLEMENTS: if t, ok := v.(Interface); ok { for k, v := range t.index { - if _v, ok := s.index.index[k].(Function); ok { - for i, field := range v.arg { - if i < len(_v.arg) && _v.arg[i].types == field.types { - continue - } - return Value{list: []Any{s, false}} - } - for i, field := range v.res { - if i < len(_v.res) && _v.res[i].types == field.types { - continue - } - return Value{list: []Any{s, false}} - } - } else { - return Value{list: []Any{s, false}} + if v.Operate("==", s.index.Find(k)) == false { + return Value{list: []Any{s, Boolean{false}}} } } + return Value{list: []Any{s, Boolean{true}}} } - return Value{list: []Any{s, true}} + return ErrNotSupport(v) case SUBS: - switch v := s.index.index[kit.Format(v)].(type) { + switch v := s.index.Find(kit.Format(v)).(type) { + case string: + switch _v := s.value.Operate(op, v).(type) { + case nil: + return Object{Dict{kit.Dict()}, s.index.stack.value(ice.Pulse, v).(Struct)} + default: + return _v + } case Function: v.object = s return v @@ -86,7 +163,6 @@ func (s Object) Operate(op string, v Any) Any { default: return s.value.Operate(op, v) } - return nil } const ( @@ -95,6 +171,7 @@ const ( STRUCT = "struct" INTERFACE = "interface" STRING = "string" + BOOL = "bool" INT = "int" INSTANCEOF = "instanceof" @@ -121,6 +198,7 @@ func init() { }}, TYPE: {Name: "type student struct {", Hand: func(m *ice.Message, arg ...string) { s := _parse_stack(m) + pos := s.Position switch name := s.next(m); s.next(m) { case ASSIGN: s.next(m) @@ -129,9 +207,12 @@ func init() { switch t := s.types(m).(type) { case Interface: t.name = name + t.stack = s s.value(m, name, t) case Struct: t.name = name + t.stack = s + t.Position = pos s.value(m, name, t) default: s.value(m, name, t) diff --git a/base/yac/value.go b/base/yac/value.go index fbc07cde..df8cf204 100644 --- a/base/yac/value.go +++ b/base/yac/value.go @@ -2,12 +2,14 @@ package yac import ( "encoding/json" + "reflect" "strconv" "strings" "time" ice "shylinux.com/x/icebergs" "shylinux.com/x/icebergs/base/mdb" + "shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/web" kit "shylinux.com/x/toolkits" ) @@ -30,12 +32,18 @@ func (s Function) MarshalJSON() ([]byte, error) { return []byte(kit.Format("%q", Format(s.Position))), nil } -func wrap(v Any) Any { +func Wraps(v Any) Any { switch v := v.(type) { + case *ice.Message: + return Message{v} case []Any: - return List{v} + list := []Any{} + kit.For(v, func(v Any) { list = append(list, Wraps(v)) }) + return List{list} case map[string]Any: - return Dict{v} + list := map[string]Any{} + kit.For(v, func(k string, v Any) { list[k] = Wraps(v) }) + return Dict{list} case string: return String{v} case int: @@ -48,16 +56,20 @@ func wrap(v Any) Any { } func Trans(v Any) Any { switch v := v.(type) { + case Message: + return v.Message case Value: - if len(v.list) > 0 { - return Trans(v.list[0]) - } else { - return nil - } + list := []Any{} + kit.For(v.list, func(v Any) { list = append(list, Trans(v)) }) + return list case List: - return v.value + list := []Any{} + kit.For(v.value, func(v Any) { list = append(list, Trans(v)) }) + return list case Dict: - return v.value + list := map[string]Any{} + kit.For(v.value, func(k string, v Any) { list[k] = Trans(v) }) + return list case String: return v.value case Number: @@ -70,22 +82,26 @@ func Trans(v Any) Any { } func (s List) Operate(op string, v Any) Any { switch op { + case LEN: + return len(s.value) case RANGE: switch list := v.(type) { case []Any: - if list != nil && len(list) > 1 { + if len(list) > 1 { if i := kit.Int(list[0]) + 1; i < len(s.value) { return []Any{i, s.value[i]} } - } else { - if len(s.value) > 0 { - return []Any{0, s.value[0]} - } + } else if len(s.value) > 0 { + return []Any{0, s.value[0]} } + default: + return ErrNotSupport(list) } return nil + case EXPAND: + return s.value case SUBS: - return wrap(kit.Value(s.value, kit.Format(v))) + return Wraps(kit.Value(s.value, kit.Format(v))) default: if i, e := strconv.ParseInt(op, 10, 32); e == nil { switch (int(i)+2+len(s.value)+2)%(len(s.value)+2) - 2 { @@ -97,33 +113,37 @@ func (s List) Operate(op string, v Any) Any { s.value[i] = v } return v + } else { + return ErrNotValid(op) } } - return nil } func (s Dict) Operate(op string, v Any) Any { switch op { + case LEN: + return len(s.value) case RANGE: switch list := v.(type) { case []Any: - if key := kit.SortedKey(s.value); list != nil && len(list) > 2 { + if key := kit.SortedKey(s.value); len(list) > 2 { if i := kit.Int(list[2]) + 1; i < len(key) { return []Any{key[i], s.value[key[i]], i} } - } else { - if len(key) > 0 { - return []Any{key[0], s.value[key[0]], 0} - } + } else if len(key) > 0 { + return []Any{key[0], s.value[key[0]], 0} } } - return nil + return ErrNotSupport(v) + case EXPAND: + list := []Any{} + kit.For(kit.KeyValue(nil, "", s.value), func(k string, v Any) { list = append(list, k, v) }) + return list case SUBS: - return wrap(kit.Value(s.value, kit.Format(v))) + return Wraps(kit.Value(s.value, kit.Format(v))) default: s.value[op] = v return v } - return nil } func (s String) Operate(op string, v Any) Any { switch a, b := s.value, kit.Format(v); op { @@ -144,7 +164,7 @@ func (s String) Operate(op string, v Any) Any { case "==": return Boolean{a == b} default: - return nil + return ErrNotImplement(op) } } func (s Number) Operate(op string, v Any) Any { @@ -174,7 +194,7 @@ func (s Number) Operate(op string, v Any) Any { case "==": return Boolean{a == b} default: - return nil + return ErrNotImplement(op) } } func (s Boolean) Operate(op string, v Any) Any { @@ -186,139 +206,122 @@ func (s Boolean) Operate(op string, v Any) Any { case "!": return Boolean{!a} default: - return nil + return ErrNotImplement(op) } } -func (s *Stack) load(m *ice.Message, cb func(*Frame)) *Stack { - f := s.peekf() - f.value["kit"] = func(m *ice.Message, key string, arg ...Any) Any { + +const ( + LEN = "len" + KIT = "kit" +) + +func init() { + ice.Info.Stack[LEN] = func(m *ice.Message, key string, arg ...Any) Any { + if len(arg) == 0 { + return ErrNotValid() + } + switch v := arg[0].(type) { + case Operater: + return v.Operate(LEN, nil) + case map[string]Any: + return len(v) + case []Any: + return len(v) + default: + return ErrNotSupport(v) + } + } +} +func init() { + ice.Info.Stack[KIT] = func(m *ice.Message, key string, arg ...Any) Any { switch key { - case "List": - return kit.List(arg...) case "Dict": return kit.Dict(arg...) + case "List": + return kit.List(arg...) + case "Slice": + args := []int{} + kit.For(arg, func(v string) { args = append(args, kit.Int(v)) }) + return kit.Slice(kit.Simple(arg[0]), args...) + case "Select": + return kit.Select(kit.Format(arg[0]), arg[1:]...) case "Format": return kit.Format(arg[0], arg[1:]...) case "Formats": return kit.Formats(arg[0]) default: - m.ErrorNotImplement(kit.Keys("kit", key)) - return nil + return ErrNotImplement(kit.Keys(KIT, key)) } } - f.value["ice.Cmd"] = func(m *ice.Message, key string, arg ...Any) Any { - stack := m.Optionv(ice.YAC_STACK).(*Stack) - command := &ice.Command{Name: "list hash auto", Help: "示例", Actions: ice.Actions{}} - obj := arg[1].(Object) - for k, v := range obj.index.index { - switch v := v.(type) { +} +func init() { + ice.Info.Stack["ice.Cmd"] = func(m *ice.Message, key string, arg ...Any) Any { + if len(arg) < 2 { + return ErrNotValid(arg) + } + obj, ok := arg[1].(Object) + if !ok { + return ErrNotSupport(arg[1]) + } + stack, ok := m.Optionv(ice.YAC_STACK).(*Stack) + if !ok { + return ErrNotFound(ice.YAC_STACK) + } + if key = kit.Format(arg[0]); key == "" { + ls := kit.Split(stack.Position.name, nfs.PS) + key = kit.Keys("web.code", kit.Select("", ls, -2), kit.TrimExt(kit.Select("", ls, -1))) + } + command, config := &ice.Command{Actions: ice.Actions{}}, &ice.Config{Value: kit.Data()} + obj.index.For(func(k string, v Any) { + switch k = kit.LowerCapital(k); v := v.(type) { case Function: - v.object = obj - if k == "List" { - command.Hand = stack.Handler(v) + if v.object = obj; k == mdb.LIST { + kit.If(command.Hand == nil, func() { command.Hand = stack.Handler(v) }) } else { - command.Actions[kit.LowerCapital(k)] = &ice.Action{Hand: stack.Handler(v)} + kit.If(command.Actions[k] == nil, func() { command.Actions[k] = &ice.Action{Hand: stack.Handler(v)} }) } } - } - for k, v := range obj.index.index { + }) + obj.index.For(func(k string, v Any) { switch v := v.(type) { case Field: - if k == "list" { - command.Name = v.tags[mdb.NAME] - } else { - command.Actions[k].Name = v.tags[mdb.NAME] + if k == mdb.LIST { + kit.If(command.Name == "", func() { command.Name, command.Help = v.tags[mdb.NAME], v.tags[mdb.HELP] }) + } else if action, ok := command.Actions[k]; ok { + kit.If(action.Name == "", func() { action.Name, action.Help = v.tags[mdb.NAME], v.tags[mdb.HELP] }) } + kit.If(v.tags[mdb.DATA] != "", func() { kit.Value(config.Value, kit.Keym(v.name), v.tags[mdb.DATA]) }) } - } - last, list := ice.Index, kit.Split(kit.Format(arg[0]), ice.PT) + }) + last, list := ice.Index, kit.Split(key, ice.PT) for i := 1; i < len(list); i++ { has := false if ice.Pulse.Search(strings.Join(list[:i], ice.PT)+ice.PT, func(p *ice.Context, s *ice.Context) { has, last = true, s }); !has { - context := &ice.Context{Name: list[i-1], Caches: ice.Caches{ice.CTX_FOLLOW: &ice.Cache{Value: strings.Join(list[:i], ice.PT)}}} - last = last.Register(context, &web.Frame{}) + last = last.Register(&ice.Context{Name: list[i-1], Caches: ice.Caches{ice.CTX_FOLLOW: &ice.Cache{Value: kit.Keys(list[i-1])}}}, &web.Frame{}) + } + if i == len(list)-1 { + last.Merge(&ice.Context{Commands: ice.Commands{list[i]: command}, Configs: ice.Configs{list[i]: config}}) } - kit.If(i == len(list)-1, func() { - last.Merge(&ice.Context{Commands: ice.Commands{list[i]: command}}) - last.Merge(last) - }) } - link := ice.Render(m, ice.RENDER_ANCHOR, kit.Format(arg[0]), m.MergePodCmd("", kit.Format(arg[0]))) - s.frame[0].value["_index"] = kit.Format(arg[0]) - s.frame[0].value["_link"] = link - return nil + stack.frame[0].value["_link"] = _parse_link(m, key) + stack.frame[0].value["_index"] = key + return key } - f.value["ice.MergeActions"] = func(m *ice.Message, key string, arg ...Any) Any { - _actions := ice.Actions{} - for _, v := range arg { - ice.MergeActions(_actions, TransActions(m, v)) - } - res := Dict{value: kit.Dict()} - for k, v := range _actions { - res.value[k] = Object{value: Dict{kit.Dict("Name", v.Name, "Help", v.Help, "Hand", v.Hand)}} + return + ice.Info.Stack["ice.MergeActions"] = func(m *ice.Message, key string, arg ...Any) Any { + list := ice.Actions{} + kit.For(arg, func(v Any) { ice.MergeActions(list, TransActions(m, v)) }) + res := Dict{kit.Dict()} + for k, v := range list { + res.value[k] = Dict{kit.Dict("Name", v.Name, "Help", v.Help, "Hand", v.Hand)} } return res } - for k, v := range ice.Info.Stack { - kit.If(strings.HasPrefix(k, "web.code."), func() { k = strings.TrimPrefix(k, "web.") }) - f.value[k] = v - } - f.value["m"] = Message{m} - kit.If(cb != nil, func() { cb(f) }) - return s } -func (m Message) Call(cmd string, arg ...Any) Any { - str := func(v Any) string { return kit.Format(Trans(v)) } - switch cmd { - case "Option": - return m.Option(str(arg[0]), arg[1:]...) - case "Cmd": - return Message{m.Cmd(arg...)} - case "Cmdy": - m.Cmdy(arg...) - case "Copy": - m.Copy(arg[0].(Message).Message, kit.Simple(arg[1:]...)...) - case "Push": - m.Push(str(arg[0]), arg[1], arg[2:]...) - case "Echo": - m.Echo(str(arg[0]), arg[1:]...) - case "Table": - s := _parse_stack(m.Message) - m.Table(func(val ice.Maps) { s.calls(m.Message, arg[0], "", nil, Dict{kit.Dict(val)}) }) - case "Sleep": - m.Sleep(str(arg[0])) - case "Action": - m.Action(arg...) - case "Display": - if len(arg) > 0 { - m.ProcessDisplay(arg...) - } else { - m.ProcessDisplay(kit.Format("%s?_t=%d", Trans(_parse_stack(m.Message).value(m.Message, "_script")), time.Now().Unix())) - } - case "StatusTime": - m.StatusTime(arg...) - case "DebugStack": - s := _parse_stack(m.Message) - list := []string{} - s.stack(func(f *Frame, i int) bool { - list = append(list, kit.Format("stack: %s", f.key)) - kit.For(f.value, func(k string, v Any) { - list = append(list, kit.Format("stack: %s %s:%#v", f.key, k, v)) - }) - return false - }) - m.Debug(ice.NL + strings.Join(list, ice.NL)) - default: - m.ErrorNotImplement(cmd) - } - return m -} - -type Message struct{ *ice.Message } - func TransContext(m *ice.Message, key string, arg ...Any) *ice.Context { s := &ice.Context{Caches: ice.Caches{ice.CTX_FOLLOW: &ice.Cache{}}} + defer func() { s.Merge(s).Cap(ice.CTX_FOLLOW, kit.Keys(key, s.Name)) }() kit.For(arg[0], func(k string, v ice.Any) { switch k { case "Name": @@ -329,7 +332,6 @@ func TransContext(m *ice.Message, key string, arg ...Any) *ice.Context { s.Commands = TransCommands(m, v) } }) - s.Merge(s).Cap(ice.CTX_FOLLOW, kit.Keys(key, s.Name)) return s } func TransCommands(m *ice.Message, arg ...Any) ice.Commands { @@ -337,6 +339,7 @@ func TransCommands(m *ice.Message, arg ...Any) ice.Commands { stack := m.Optionv(ice.YAC_STACK).(*Stack) kit.For(arg[0], func(k string, v ice.Any) { s := &ice.Command{} + defer func() { commands[k] = s }() kit.For(v, func(k string, v ice.Any) { switch k { case "Name": @@ -354,7 +357,6 @@ func TransCommands(m *ice.Message, arg ...Any) ice.Commands { } } }) - commands[k] = s }) return commands } @@ -367,6 +369,7 @@ func TransActions(m *ice.Message, arg ...Any) ice.Actions { stack := m.Optionv(ice.YAC_STACK).(*Stack) kit.For(arg[0], func(k string, v ice.Any) { s := &ice.Action{} + defer func() { actions[k] = s }() switch k { case "Name": s.Name = kit.Format(Trans(v)) @@ -380,11 +383,9 @@ func TransActions(m *ice.Message, arg ...Any) ice.Actions { s.Hand = v } } - actions[k] = s }) return actions } - func Format(arg ...Any) string { res := []string{} for _, v := range arg { @@ -403,19 +404,19 @@ func Format(arg ...Any) string { } else if v.skip == -1 { res = append(res, kit.Format("%s:%d", v.name, v.line+1)) } else { - res = append(res, kit.Format("%s:%d:%d", v.name, v.line+1, v.skip)) + res = append(res, kit.Format("%s:%d:%d", v.name, v.line+1, v.skip+1)) } case Map: res = append(res, kit.Format("map[%s]%s", v.key, v.value)) case Slice: res = append(res, kit.Format("[]%s", v.value)) case Interface: - res = append(res, kit.Format("interface%s", v.name)) + res = append(res, kit.Format("interface:%s", v.name)) case Struct: res = append(res, kit.Format("struct%s", Format(v.index))) case Object: res = append(res, kit.Format("%s:%s", v.index.name, Format(v.value))) - case []Field: + case Fields: for i, field := range v { res = append(res, kit.Select("", OPEN, i == 0)+field.name, kit.Format(field.types)+kit.Select(FIELD, CLOSE, i == len(v)-1)) } @@ -435,5 +436,37 @@ func Format(arg ...Any) string { res = append(res, kit.Format(v)) } } - return strings.Join(res, " ") + return strings.Join(res, ice.SP) +} + +type Message struct{ *ice.Message } + +func (m Message) Call(cmd string, arg ...Any) Any { + switch cmd { + case "Table": + s := _parse_stack(m.Message) + m.Table(func(val ice.Maps) { s.calls(m.Message, arg[0], "", nil, Dict{kit.Dict(val)}) }) + case "Display": + if len(arg) > 0 { + m.ProcessDisplay(arg...) + } else { + m.ProcessDisplay(kit.Format("%s?_t=%d", Trans(_parse_stack(m.Message).value(m.Message, "_script")), time.Now().Unix())) + } + case "DebugStack": + list := []string{} + s := _parse_stack(m.Message) + s.stack(func(f *Frame, i int) bool { + list = append(list, kit.Format("stack: %s", f.key)) + kit.For(f.value, func(k string, v Any) { list = append(list, kit.Format("stack: %s %s:%#v", f.key, k, v)) }) + return false + }) + m.Debug(ice.NL + strings.Join(list, ice.NL)) + default: + msg, args := reflect.ValueOf(m), []reflect.Value{} + kit.For(arg, func(v Any) { args = append(args, reflect.ValueOf(v)) }) + if res := msg.MethodByName(cmd).Call(args); len(res) > 0 && res[0].CanInterface() { + return res[0].Interface() + } + } + return m } diff --git a/conf.go b/conf.go index a9d69d43..dfa051a0 100644 --- a/conf.go +++ b/conf.go @@ -210,7 +210,8 @@ const ( // MSG MSG_HEIGHT = "sess.height" MSG_DAEMON = "sess.daemon" MSG_FILES = "file.system" - YAC_STACK = "stack" + YAC_STACK = "yac.stack" + YAC_MESSAGE = "yac.message" LOG_DISABLE = "log.disable" ) const ( // RENDER diff --git a/core/code/autogen.go b/core/code/autogen.go index d205b4e2..1a49edf2 100644 --- a/core/code/autogen.go +++ b/core/code/autogen.go @@ -66,7 +66,7 @@ func _autogen_version(m *ice.Message) string { func _autogen_gits(m *ice.Message, arg ...string) string { res := []string{} kit.For(_autogen_git(m, arg...), func(k, v string) { - res = append(res, kit.Format(` %s: "%s",`, kit.Capital(k), strings.TrimSpace(v))) + res = append(res, kit.Format(` %s: "%s",`, kit.LowerCapital(k), strings.TrimSpace(v))) }) return kit.Join(res, ice.NL) } diff --git a/core/code/binpack.go b/core/code/binpack.go index 09a83ae5..b8208a2d 100644 --- a/core/code/binpack.go +++ b/core/code/binpack.go @@ -82,6 +82,8 @@ func _binpack_all(m *ice.Message) { _binpack_file(m, w, value[nfs.PATH]) } }) + m.Option(nfs.DIR_REG, kit.ExtReg(nfs.SHY)) + _binpack_dir(m, w, "usr/release/") } } diff --git a/core/code/code.go b/core/code/code.go index faeaf18f..badb7f35 100644 --- a/core/code/code.go +++ b/core/code/code.go @@ -19,6 +19,7 @@ func init() { ) } func init() { + return ice.Info.Stack[Prefix(Index.Register)] = func(m *ice.Message, key string, arg ...ice.Any) ice.Any { return Index.Register(yac.TransContext(m, Prefix(), arg...), &web.Frame{}) } diff --git a/core/code/go.go b/core/code/go.go index 883d52ba..000e208a 100644 --- a/core/code/go.go +++ b/core/code/go.go @@ -10,6 +10,7 @@ import ( "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/ssh" + "shylinux.com/x/icebergs/base/yac" kit "shylinux.com/x/toolkits" ) @@ -100,6 +101,8 @@ func init() { Index.MergeCommands(ice.Commands{ GO: {Name: "go path auto", Help: "后端编程", Actions: ice.MergeActions(ice.Actions{ mdb.RENDER: {Hand: func(m *ice.Message, arg ...string) { + ctx.ProcessCommand(m, yac.STACK, kit.Simple(path.Join(arg[2], arg[1]))) + return cmds, text := "ice.bin source stdio", ctx.GetFileCmd(path.Join(arg[2], arg[1])) if text != "" { ls := strings.Split(text, ice.PT) @@ -110,6 +113,12 @@ func init() { ProcessXterm(m, cmds, text, arg[1]) }}, mdb.ENGINE: {Hand: func(m *ice.Message, arg ...string) { + if msg := m.Cmd(yac.STACK, path.Join(arg[2], arg[1])); msg.Option("__index") != "" { + ctx.ProcessCommand(m, msg.Option("__index"), kit.Simple()) + } else { + ctx.ProcessCommand(m, yac.STACK, kit.Simple(path.Join(arg[2], arg[1]))) + } + return if cmd := ctx.GetFileCmd(path.Join(arg[2], arg[1])); cmd != "" { ctx.ProcessCommand(m, cmd, kit.Simple()) } else { diff --git a/core/code/install.go b/core/code/install.go index f4bd6145..51c23498 100644 --- a/core/code/install.go +++ b/core/code/install.go @@ -207,5 +207,6 @@ func InstallAction(args ...ice.Any) ice.Actions { } } func init() { + return ice.Info.Stack[Prefix(InstallAction)] = func(m *ice.Message, key string, arg ...ice.Any) ice.Any { return InstallAction(arg...) } } diff --git a/core/code/shy.go b/core/code/shy.go index c224ca7f..41b1fcbf 100644 --- a/core/code/shy.go +++ b/core/code/shy.go @@ -27,13 +27,13 @@ func init() { // } else { // ctx.ProcessCommand(m, kit.TrimExt(arg[1], SHY), kit.Simple()) // } - ctx.ProcessCommand(m, yac.STACK, kit.Simple(arg[1])) + ctx.ProcessCommand(m, yac.STACK, kit.Simple(path.Join(arg[2], arg[1]))) }}, mdb.ENGINE: {Hand: func(m *ice.Message, arg ...string) { - if msg := m.Cmd(yac.STACK, arg[1]); msg.Option("__index") != "" { + if msg := m.Cmd(yac.STACK, path.Join(arg[2], arg[1])); msg.Option("__index") != "" { ctx.ProcessCommand(m, msg.Option("__index"), kit.Simple()) } else { - ctx.ProcessCommand(m, yac.STACK, kit.Simple(arg[1])) + ctx.ProcessCommand(m, yac.STACK, kit.Simple(path.Join(arg[2], arg[1]))) } }}, TEMPLATE: {Hand: func(m *ice.Message, arg ...string) { diff --git a/core/code/vimer.go b/core/code/vimer.go index 2300c094..87b08fe7 100644 --- a/core/code/vimer.go +++ b/core/code/vimer.go @@ -75,7 +75,7 @@ func init() { for _, ext := range []string{SH, SHY, PY, JS, CSS, HTML} { m.Push(nfs.PATH, kit.ExtChange(m.Option(nfs.FILE), ext)) } - m.Option(nfs.DIR_REG, kit.FileReg(SH, SHY, PY, JS, CSS, HTML)) + m.Option(nfs.DIR_REG, kit.ExtReg(SH, SHY, PY, JS, CSS, HTML)) nfs.DirDeepAll(m, nfs.SRC, nfs.PWD, nil, nfs.PATH) case web.DREAM, XTERM, AUTOGEN: m.Cmdy(m.Option(ctx.ACTION), mdb.INPUTS, arg) @@ -134,7 +134,7 @@ func init() { } }}, nfs.TRASH: {Hand: func(m *ice.Message, arg ...string) { nfs.Trash(m, arg[0]) }}, - nfs.MODULE: {Name: "create name*=h2 help=示例 type*=Zone,Hash,Data,Code main*=main.go zone key", Help: "模块", Hand: func(m *ice.Message, arg ...string) { + nfs.MODULE: {Name: "create name*=h2 help=示例 type*=Hash,Zone,Data,Code main*=main.go zone key", Help: "模块", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(AUTOGEN, nfs.MODULE, arg) }}, nfs.SCRIPT: {Name: "script file*=hi/hi.js", Help: "脚本", Hand: func(m *ice.Message, arg ...string) { diff --git a/core/wiki/wiki.go b/core/wiki/wiki.go index 470fd778..939db76d 100644 --- a/core/wiki/wiki.go +++ b/core/wiki/wiki.go @@ -81,7 +81,7 @@ func init() { func Prefix(arg ...string) string { return web.Prefix(WIKI, kit.Keys(arg)) } func WikiAction(dir string, ext ...string) ice.Actions { - return ice.Actions{ice.CTX_INIT: mdb.AutoConfig(nfs.PATH, dir, lex.REGEXP, kit.FileReg(ext...)), + return ice.Actions{ice.CTX_INIT: mdb.AutoConfig(nfs.PATH, dir, lex.REGEXP, kit.ExtReg(ext...)), web.UPLOAD: {Hand: func(m *ice.Message, arg ...string) { _wiki_upload(m, m.Option(nfs.PATH)) }}, nfs.TRASH: {Name: "trash path*", Hand: func(m *ice.Message, arg ...string) { nfs.Trash(m, _wiki_path(m, m.Option(nfs.PATH))) }}, nfs.SAVE: {Name: "save path* text", Hand: func(m *ice.Message, arg ...string) { _wiki_save(m, m.Option(nfs.PATH), m.Option(mdb.TEXT)) }}, diff --git a/exec.go b/exec.go index 7d20f1d9..084d969e 100644 --- a/exec.go +++ b/exec.go @@ -70,18 +70,18 @@ func (m *Message) Wait(cb ...Handler) (wait func(), done Handler) { } } -func (m *Message) Cmd(arg ...Any) *Message { return m._command(arg...) } +func (m *Message) Cmd(arg ...Any) *Message { return m._command(arg...) } +func (m *Message) Cmds(arg ...Any) *Message { return m.Cmd(append(arg, OptionFields(""))...) } func (m *Message) Cmdv(arg ...Any) string { args := kit.Simple(arg...) field := kit.Slice(args, -1)[0] return m._command(kit.Slice(args, 0, -1), OptionFields(field)).Append(field) } -func (m *Message) Cmds(arg ...Any) *Message { return m.Cmd(append(arg, OptionFields(""))...) } -func (m *Message) Cmdy(arg ...Any) *Message { return m.Copy(m._command(arg...)) } func (m *Message) Cmdx(arg ...Any) string { res := kit.Select("", m._command(arg...).meta[MSG_RESULT], 0) return kit.Select("", res, res != ErrWarn) } +func (m *Message) Cmdy(arg ...Any) *Message { return m.Copy(m._command(arg...)) } func (m *Message) CmdHand(cmd *Command, key string, arg ...string) *Message { if m._cmd, m._key = cmd, key; cmd == nil { return m diff --git a/info.go b/info.go index ac1995d2..08ab9967 100644 --- a/info.go +++ b/info.go @@ -1,6 +1,7 @@ package ice import ( + "reflect" "strings" kit "shylinux.com/x/toolkits" @@ -197,3 +198,40 @@ func SplitCmd(name string, actions Actions) (list []Any) { } return list } +func Module(prefix string, arg ...Any) { + list := map[string]Any{} + for _, v := range arg { + list[kit.FuncName(v)] = v + } + Info.Stack[prefix] = func(m *Message, key string, arg ...Any) Any { + if len(arg) > 0 { + switch v := arg[0].(type) { + case *Message: + m, arg = v, arg[1:] + } + } + if v, ok := list[key]; ok { + switch v := v.(type) { + case func(m *Message): + v(m) + case func(m *Message, arg ...Any): + v(m, arg...) + case func(m *Message, arg ...Any) string: + return v(m, arg...) + case func(m *Message, arg ...Any) *Message: + return v(m, arg...) + case func(m *Message, arg ...string) *Message: + return v(m, kit.Simple(arg...)...) + default: + cb, args := reflect.ValueOf(v), []reflect.Value{reflect.ValueOf(m)} + kit.For(arg, func(v Any) { args = append(args, reflect.ValueOf(v)) }) + if res := cb.Call(args); len(res) > 0 && res[0].CanInterface() { + return res[0].Interface() + } + } + } else { + m.ErrorNotImplement(key) + } + return m + } +} diff --git a/misc/alpha/alpha.go b/misc/alpha/alpha.go index 95009d6b..c19fd105 100644 --- a/misc/alpha/alpha.go +++ b/misc/alpha/alpha.go @@ -60,4 +60,4 @@ func (s alpha) List(m *ice.Message, arg ...string) { }).StatusTimeCount() } -func init() { ice.WikiCtxCmd(alpha{}) } +func init() { ice.Cmd("web.wiki.alpha.alpha", alpha{}) } diff --git a/misc/alpha/cache.go b/misc/alpha/cache.go index 89740018..1bd6c82d 100644 --- a/misc/alpha/cache.go +++ b/misc/alpha/cache.go @@ -11,4 +11,4 @@ type cache struct { list string `name:"list word auto create prunes" help:"缓存"` } -func init() { ice.WikiCtxCmd(cache{}) } +func init() { ice.Cmd("web.wiki.alpha.cache", cache{}) } diff --git a/misc/chrome/sync.go b/misc/chrome/sync.go index eaf6bb1f..ac404a1b 100644 --- a/misc/chrome/sync.go +++ b/misc/chrome/sync.go @@ -6,7 +6,6 @@ import ( ) type sync struct { - ice.Lists field string `data:"time,id,type,name,link"` insert string `name:"insert type name link" http:"/sync"` list string `name:"list id auto" help:"同步流"` @@ -17,13 +16,10 @@ func (s sync) Inputs(m *ice.Message, arg ...string) { case mdb.ZONE: m.Cmdy(arg) default: - m.Cmdy(s.Lists.Inputs, arg) } } func (s sync) Insert(m *ice.Message, arg ...string) { - s.Lists.Insert(m, arg...) } func (s sync) List(m *ice.Message, arg ...string) { - s.Lists.List(m, arg...) } func init() { ice.CodeCtxCmd(sync{}) } diff --git a/option.go b/option.go index 6768b4be..8a6bf849 100644 --- a/option.go +++ b/option.go @@ -60,7 +60,7 @@ func (m *Message) Fields(length int, fields ...string) string { return m.OptionDefault(MSG_FIELDS, kit.Select(FIELDS_DETAIL, fields, length)) } func (m *Message) Action(arg ...Any) *Message { - kit.For(arg, func(i int, v Any) { arg[i] = kit.Format(v) }) + kit.For(arg, func(i int, v Any) { arg[i] = kit.LowerCapital(kit.Format(v)) }) return m.Options(MSG_ACTION, kit.Format(arg)) } func (m *Message) Status(arg ...Any) *Message { diff --git a/render.go b/render.go index a38e464c..89c4278d 100644 --- a/render.go +++ b/render.go @@ -36,7 +36,7 @@ func Render(m *Message, cmd string, args ...Any) string { case Map: kit.For(k, func(k string) { list = append(list, kit.Format(``, k, k)) }) default: - list = append(list, Render(m, RENDER_BUTTON, kit.Format(k))) + list = append(list, Render(m, RENDER_BUTTON, kit.LowerCapital(kit.Format(k)))) } } return strings.Join(list, "") diff --git a/type.go b/type.go index 0003e9d6..8df9f5d7 100644 --- a/type.go +++ b/type.go @@ -176,7 +176,9 @@ func (c *Context) Merge(s *Context) *Context { } kit.If(c.Configs == nil, func() { c.Configs = Configs{} }) for k, v := range s.Configs { - c.Configs[k] = v + if c.Configs[k] == nil || c.Configs[k].Value == nil { + c.Configs[k] = v + } } kit.If(c.Caches == nil, func() { c.Caches = Caches{} }) return c