1
0
forked from x/ContextOS

vps add cli.function 添加了一些语句的解析

This commit is contained in:
shaoying 2017-12-25 19:56:02 +08:00
parent 3b216d2cb9
commit 6342860073
3 changed files with 228 additions and 162 deletions

View File

@ -1,8 +1,18 @@
~cli ~cli
@lex lex @lex lex
~aaa login root root ~aaa login root root
~cli var a = 10
if $username == root
echo welcome root user: $username
end
~web serve ~web serve
~ssh dial chat.shylinux.com:9090 true
function nice
echo who
end
return hello hello
sleep 1 sleep 1
~host1 ~host1
remote context mpa register terminal shhylinux term term term 1 remote context mpa register terminal shhylinux term term term 1
@ -11,6 +21,7 @@ sleep 1
~nfs save usr/sess.txt "terminal: " $sessid ~nfs save usr/sess.txt "terminal: " $sessid
~nfs genqr usr/sess.png "terminal: " $sessid ~nfs genqr usr/sess.png "terminal: " $sessid
return return
# ~ssh dial chat.shylinux.com:9090 true
# ~cli # ~cli
# remote slaver listen ":9393" tcp # remote slaver listen ":9393" tcp
# ~ssh # ~ssh

View File

@ -1,6 +1,6 @@
package cli // {{{ package cli
// }}}
import ( // {{{ import (
"context" "context"
"bufio" "bufio"
@ -14,21 +14,22 @@ import ( // {{{
"unicode" "unicode"
) )
// }}}
type CLI struct { type CLI struct {
bio *bufio.Reader bio *bufio.Reader
out io.WriteCloser out io.WriteCloser
alias map[string]string which int
back string lines []string
exit bool
alias map[string]string
lex *ctx.Message lex *ctx.Message
target *ctx.Context target *ctx.Context
wait *ctx.Context wait *ctx.Context
exit bool
test bool
save bool
*ctx.Message
*ctx.Context *ctx.Context
} }
@ -43,15 +44,29 @@ func (cli *CLI) echo(str string, arg ...interface{}) bool {
func (cli *CLI) parse(m *ctx.Message) bool { func (cli *CLI) parse(m *ctx.Message) bool {
line := m.Cap("next") line := m.Cap("next")
if line == "" { if line == "" {
if m.Cap("level") == "0" {
cli.echo(m.Conf("PS1")) cli.echo(m.Conf("PS1"))
}
if cli.bio == nil {
if cli.which == len(cli.lines) {
cli.exit = true
cli.which = 0
m.Spawn(cli.target).Set("detail", "end").Post(cli.Context)
return false
}
line = cli.lines[cli.which]
cli.which++
} else {
l, e := cli.bio.ReadString('\n') l, e := cli.bio.ReadString('\n')
m.Assert(e) m.Assert(e)
line = l line = l
} }
}
m.Cap("next", "") m.Cap("next", "")
if line = strings.TrimSpace(line); len(line) == 0 { if line = strings.TrimSpace(line); len(line) == 0 && m.Cap("stream") == "stdout" {
line, cli.back = cli.back, "" line = m.Cap("back")
m.Cap("back", "")
} }
if len(line) == 0 || line[0] == '#' { if len(line) == 0 || line[0] == '#' {
return true return true
@ -95,21 +110,20 @@ func (cli *CLI) parse(m *ctx.Message) bool {
} }
msg.Wait = make(chan bool) msg.Wait = make(chan bool)
msg.Post(cli.Context.Master()) msg.Post(cli.Context)
if result := strings.TrimRight(strings.Join(msg.Meta["result"], ""), "\n"); len(result) > 0 { if msg.Target().Context() != nil || msg.Target() == ctx.Index {
cli.echo(m.Cap("result", result) + "\n") cli.target = msg.Target()
}
result := strings.TrimRight(strings.Join(msg.Meta["result"], ""), "\n")
m.Cap("result", result)
if len(result) > 0 {
cli.echo(result + "\n")
} }
m.Cap("target", cli.target.Name) m.Cap("target", cli.target.Name)
m.Cap("back", line) m.Cap("back", line)
m.Log("fuck", nil, "over") if cli.bio != nil {
if cli.wait != nil { cli.lines = append(cli.lines, line)
msg.Log("fuck", nil, "wait 1")
<-cli.wait.Exit
cli.wait = nil
msg.Log("fuck", nil, "wait 2")
} else {
cli.target = msg.Target()
} }
return !cli.exit return !cli.exit
} }
@ -120,6 +134,8 @@ func (cli *CLI) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server
s := new(CLI) s := new(CLI)
s.Context = c s.Context = c
s.lex = cli.lex
s.alias = cli.alias
return s return s
} }
@ -213,12 +229,16 @@ func (cli *CLI) Begin(m *ctx.Message, arg ...string) ctx.Server {
} }
func (cli *CLI) Start(m *ctx.Message, arg ...string) bool { func (cli *CLI) Start(m *ctx.Message, arg ...string) bool {
cli.Context.Exit = make(chan bool)
cli.bio = nil
cli.exit = false
cli.test = false
if stream, ok := m.Data["io"]; ok { if stream, ok := m.Data["io"]; ok {
cli.Context.Master(cli.Context)
io := stream.(io.ReadWriteCloser) io := stream.(io.ReadWriteCloser)
cli.bio = bufio.NewReader(io) cli.bio = bufio.NewReader(io)
cli.out = io cli.out = io
cli.Context.Master(cli.Context)
if msg := m.Find("aaa", true); msg != nil { if msg := m.Find("aaa", true); msg != nil {
cli.echo("username>") cli.echo("username>")
@ -244,49 +264,45 @@ func (cli *CLI) Start(m *ctx.Message, arg ...string) bool {
} }
cli.Sessions["aaa"] = msg cli.Sessions["aaa"] = msg
} }
} else if stream, ok := m.Data["bio"]; ok {
cli.Context.Exit = make(chan bool)
cli.bio = stream.(*bufio.Reader)
m.AssertOne(m, true, func(m *ctx.Message) {
for cli.parse(m) {
}
})
m.Log("fuck", nil, "done 1")
cli.Context.Exit <- true
m.Log("fuck", nil, "done 2")
return true
} else if stream, ok := m.Data["file"]; ok {
cli.Context.Exit = make(chan bool)
io := stream.(io.ReadWriteCloser)
cli.bio = bufio.NewReader(io)
m.AssertOne(m, true, func(m *ctx.Message) {
for cli.parse(m) {
}
})
m.Log("fuck", nil, "done 1")
cli.Context.Exit <- true
m.Log("fuck", nil, "done 2")
return true
} else if len(arg) > 0 { } else if len(arg) > 0 {
m.Cap("stream", "stdout")
m.Cap("next", "source "+m.Conf("init.sh"))
cli.Context.Master(cli.Context) cli.Context.Master(cli.Context)
cli.bio = bufio.NewReader(os.Stdin) cli.bio = bufio.NewReader(os.Stdin)
cli.out = os.Stdout cli.out = os.Stdout
m.Cap("stream", "stdout") cli.Caches["level"] = &ctx.Cache{Name: "操作目标", Value: "0", Help: "操作目标"}
} else if stream, ok := m.Data["file"]; ok {
if bio, ok := stream.(*bufio.Reader); ok {
m.Cap("stream", "file")
cli.bio = bio
} else {
m.Cap("stream", "file")
cli.bio = bufio.NewReader(stream.(io.ReadWriteCloser))
}
m.Capi("level", 1)
defer m.Capi("level", -1)
cli.test = m.Has("test")
cli.save = m.Has("save")
} }
if cli.bio != nil {
go m.AssertOne(m, true, func(m *ctx.Message) { go m.AssertOne(m, true, func(m *ctx.Message) {
m.Cap("next", "source "+m.Conf("init.sh"))
for cli.parse(m) { for cli.parse(m) {
} }
}) })
}
m.Capi("nterm", 1) m.Capi("nterm", 1)
defer m.Capi("nterm", -1) defer m.Capi("nterm", -1)
m.Deal(nil, func(msg *ctx.Message, arg ...string) bool { m.Deal(func(msg *ctx.Message, arg ...string) bool {
if cli.test {
if _, ok := Index.Commands[msg.Get("detail")]; ok {
msg.Exec(msg.Meta["detail"][0], msg.Meta["detail"][1:]...)
}
return false
}
return true
}, func(msg *ctx.Message, arg ...string) bool {
if msg.Get("result") == "error: " { if msg.Get("result") == "error: " {
if msg.Get("detail") != "login" { if msg.Get("detail") != "login" {
msg.Log("system", nil, "%v", msg.Meta["detail"]) msg.Log("system", nil, "%v", msg.Meta["detail"])
@ -310,17 +326,20 @@ func (cli *CLI) Start(m *ctx.Message, arg ...string) bool {
} }
} }
if msg.Target().Context() != nil || msg.Target() == ctx.Index {
cli.target = msg.Target() cli.target = msg.Target()
}
return cli.exit == false return cli.exit == false
}) })
return true m.Cap("status", "close")
return !cli.save
} }
func (cli *CLI) Close(m *ctx.Message, arg ...string) bool { // {{{ func (cli *CLI) Close(m *ctx.Message, arg ...string) bool {
switch cli.Context { switch cli.Context {
case m.Target(): case m.Target():
if cli.Context == Index { if m.Target() == Index && m.Capi("nserver") > 1 {
return false return false
} }
case m.Source(): case m.Source():
@ -336,8 +355,6 @@ func (cli *CLI) Close(m *ctx.Message, arg ...string) bool { // {{{
return true return true
} }
// }}}
var Pulse *ctx.Message var Pulse *ctx.Message
var Index = &ctx.Context{Name: "cli", Help: "管理中心", var Index = &ctx.Context{Name: "cli", Help: "管理中心",
Caches: map[string]*ctx.Cache{ Caches: map[string]*ctx.Cache{
@ -345,18 +362,6 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
}, },
Configs: map[string]*ctx.Config{}, Configs: map[string]*ctx.Config{},
Commands: map[string]*ctx.Command{ Commands: map[string]*ctx.Command{
"source": &ctx.Command{Name: "source file", Help: "运行脚本", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
cli := m.Master().Master().Server.(*CLI)
f, e := os.Open(arg[0])
m.Assert(e)
m.Put("option", "file", f).Start(arg[0], "脚本文件", key)
m.Log("fuck", nil, "source")
cli.wait = m.Target()
}},
"return": &ctx.Command{Name: "return", Help: "运行脚本", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
cli := m.Master().Master().Server.(*CLI)
cli.exit = true
}},
"sleep": &ctx.Command{Name: "sleep time", Help: "运行脚本", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { "sleep": &ctx.Command{Name: "sleep time", Help: "运行脚本", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
t, e := strconv.Atoi(arg[0]) t, e := strconv.Atoi(arg[0])
m.Assert(e) m.Assert(e)
@ -364,14 +369,70 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
time.Sleep(time.Second * time.Duration(t)) time.Sleep(time.Second * time.Duration(t))
m.Log("info", nil, "sleep %ds done", t) m.Log("info", nil, "sleep %ds done", t)
}}, }},
"if": &ctx.Command{Name: "if a [ = | != ] b", Help: "运行脚本", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { "source": &ctx.Command{Name: "source file", Help: "运行脚本", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
cli := m.Master().Master().Server.(*CLI) f, e := os.Open(arg[0])
m.Put("option", "bio", cli.bio).Start(strings.Join(arg, " "), "条件语句", key) m.Assert(e)
cli.wait = m.Target() m.Put("option", "file", f).Start(key, "脚本文件")
<-m.Target().Exit
}},
"return": &ctx.Command{Name: "return result...", Help: "运行脚本", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
cli, ok := m.Source().Server.(*CLI)
m.Assert(ok)
cli.exit = true
for _, v := range arg {
cli.Pulse.Echo(v)
}
}},
"if": &ctx.Command{Name: "if a [ == | != ] b", Help: "运行脚本", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
cli, ok := m.Source().Server.(*CLI)
m.Assert(ok)
if arg[1] == "==" && arg[0] != arg[2] {
m.Add("option", "test")
}
if arg[1] == "!=" && arg[0] == arg[2] {
m.Add("option", "test")
}
m.Put("option", "file", cli.bio).Start(key, "条件语句")
<-m.Target().Exit
}},
"for": &ctx.Command{Name: "for var in list", Help: "运行脚本", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
cli, ok := m.Source().Server.(*CLI)
m.Assert(ok)
if arg[1] == "==" && arg[0] != arg[2] {
m.Add("option", "test")
}
if arg[1] == "!=" && arg[0] == arg[2] {
m.Add("option", "test")
}
m.Put("option", "file", cli.bio).Start(key, "条件语句")
<-m.Target().Exit
}}, }},
"end": &ctx.Command{Name: "end", Help: "运行脚本", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { "end": &ctx.Command{Name: "end", Help: "运行脚本", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
cli := m.Master().Master().Server.(*CLI) cli, ok := m.Source().Server.(*CLI)
m.Assert(ok)
cli.exit = true cli.exit = true
m.Log("fuck", nil, "%v", cli.lines)
m.Echo(strings.Join(arg, ""))
}},
"var": &ctx.Command{Name: "var a [= b]", Help: "定义变量", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
cli, ok := m.Source().Server.(*CLI)
m.Assert(ok)
val := ""
if len(arg) > 2 {
val = arg[2]
}
cli.Pulse.Cap(arg[0], arg[0], val, "临时变量")
}},
"function": &ctx.Command{Name: "function name", Help: "运行脚本", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
cli, ok := m.Source().Server.(*CLI)
m.Target(m.Source().Context())
m.Assert(ok)
m.Add("option", "test")
m.Add("option", "save")
m.Put("option", "file", cli.bio).Start(arg[0], "定义函数")
m.Log("fuck", nil, "end function")
}}, }},
"alias": &ctx.Command{Name: "alias [short [long]]", Help: "查看日志", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { "alias": &ctx.Command{Name: "alias [short [long]]", Help: "查看日志", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
cli := c.Server.(*CLI) // {{{ cli := c.Server.(*CLI) // {{{
@ -419,12 +480,12 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
"master": &ctx.Command{Name: "open [master|slaver] [script [log]]", Help: "建立远程连接", "master": &ctx.Command{Name: "open [master|slaver] [script [log]]", Help: "建立远程连接",
Options: map[string]string{"master": "主控终端", "slaver": "被控终端", "args": "启动参数", "io": "读写流"}, Options: map[string]string{"master": "主控终端", "slaver": "被控终端", "args": "启动参数", "io": "读写流"},
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
cli, ok := c.Server.(*CLI) // {{{ _, ok := c.Server.(*CLI) // {{{
m.Assert(ok, "模块类型错误") m.Assert(ok, "模块类型错误")
m.Assert(m.Target() != c, "模块是主控模块") m.Assert(m.Target() != c, "模块是主控模块")
msg := m.Spawn(c) msg := m.Spawn(c)
msg.Start(fmt.Sprintf("PTS%d", cli.Capi("nterm")), arg[0], arg[1:]...) msg.Start(fmt.Sprintf("PTS%d", Pulse.Capi("nterm")), arg[0], arg[1:]...)
// }}} // }}}
}}, }},
}, },

View File

@ -133,7 +133,7 @@ func (c *Context) Begin(m *Message) *Context { // {{{
c.Owner = m.master.Owner c.Owner = m.master.Owner
c.Group = m.master.Group c.Group = m.master.Group
m.Log("begin", nil, "%d context %v", m.root.Capi("ncontext", 1), m.Meta["detail"]) m.Log("begin", nil, "%d context %v %v", m.root.Capi("ncontext", 1), m.Meta["detail"], m.Meta["option"])
for k, x := range c.Configs { for k, x := range c.Configs {
if x.Hand != nil { if x.Hand != nil {
m.Conf(k, x.Value) m.Conf(k, x.Value)
@ -156,7 +156,7 @@ func (c *Context) Start(m *Message) bool { // {{{
if m.Cap("status") != "start" { if m.Cap("status") != "start" {
running := make(chan bool) running := make(chan bool)
go m.AssertOne(m, true, func(m *Message) { go m.AssertOne(m, true, func(m *Message) {
m.Log(m.Cap("status", "start"), nil, "%d server %v", m.root.Capi("nserver", 1), m.Meta["detail"]) m.Log(m.Cap("status", "start"), nil, "%d server %v %v", m.root.Capi("nserver", 1), m.Meta["detail"], m.Meta["option"])
if running <- true; c.Server != nil && c.Server.Start(m, m.Meta["detail"]...) { if running <- true; c.Server != nil && c.Server.Start(m, m.Meta["detail"]...) {
c.Close(m, m.Meta["detail"]...) c.Close(m, m.Meta["detail"]...)
@ -217,6 +217,10 @@ func (c *Context) Close(m *Message, arg ...string) bool { // {{{
if c.context != nil { if c.context != nil {
m.Log("close", nil, "%d context %v", m.root.Capi("ncontext", -1)+1, arg) m.Log("close", nil, "%d context %v", m.root.Capi("ncontext", -1)+1, arg)
delete(c.context.contexts, c.Name) delete(c.context.contexts, c.Name)
c.context = nil
if c.Exit != nil {
c.Exit <- true
}
} }
return true return true
} }
@ -969,12 +973,9 @@ func (m *Message) Deal(pre func(msg *Message, arg ...string) bool, post func(msg
return return
} }
if pre != nil && !pre(msg, msg.Meta["detail"]...) { if pre == nil || pre(msg, msg.Meta["detail"]...) {
run = false
return
}
msg.Exec(msg.Meta["detail"][0], msg.Meta["detail"][1:]...) msg.Exec(msg.Meta["detail"][0], msg.Meta["detail"][1:]...)
}
if post != nil && !post(msg, msg.Meta["result"]...) { if post != nil && !post(msg, msg.Meta["result"]...) {
run = false run = false
@ -1029,7 +1030,8 @@ func (m *Message) Confi(key string, arg ...int) int { // {{{
// }}} // }}}
func (m *Message) Conf(key string, arg ...string) string { // {{{ func (m *Message) Conf(key string, arg ...string) string { // {{{
var hand func(m *Message, x *Config, arg ...string) string var hand func(m *Message, x *Config, arg ...string) string
for s := m.target; s != nil; s = s.context { for _, c := range []*Context{m.target, m.target.master, m.target.Owner, m.source, m.source.master, m.source.Owner} {
for s := c; s != nil; s = s.context {
if x, ok := s.Configs[key]; ok { if x, ok := s.Configs[key]; ok {
if !m.Check(s, "configs", key) { if !m.Check(s, "configs", key) {
continue continue
@ -1054,8 +1056,7 @@ func (m *Message) Conf(key string, arg ...string) string { // {{{
return x.Hand(m, x) return x.Hand(m, x)
} }
return x.Value return x.Value
default: }
panic(errors.New(key + "配置项参数错误"))
} }
} }
} }
@ -1070,7 +1071,7 @@ func (m *Message) Conf(key string, arg ...string) string { // {{{
return m.Conf(key, arg[1]) return m.Conf(key, arg[1])
} }
m.Assert(false, key+"配置项操作错误") m.Log("error", nil, "配置项不存在")
return "" return ""
} }
@ -1090,7 +1091,8 @@ func (m *Message) Capi(key string, arg ...int) int { // {{{
// }}} // }}}
func (m *Message) Cap(key string, arg ...string) string { // {{{ func (m *Message) Cap(key string, arg ...string) string { // {{{
var hand func(m *Message, x *Cache, arg ...string) string var hand func(m *Message, x *Cache, arg ...string) string
for s := m.target; s != nil; s = s.context { for _, c := range []*Context{m.target, m.target.master, m.target.Owner, m.source, m.source.master, m.source.Owner} {
for s := c; s != nil; s = s.context {
if x, ok := s.Caches[key]; ok { if x, ok := s.Caches[key]; ok {
if !m.Check(s, "caches", key) { if !m.Check(s, "caches", key) {
continue continue
@ -1113,8 +1115,7 @@ func (m *Message) Cap(key string, arg ...string) string { // {{{
return x.Hand(m, x) return x.Hand(m, x)
} }
return x.Value return x.Value
default: }
panic(errors.New(key + "缓存项参数错误"))
} }
} }
} }
@ -1129,9 +1130,8 @@ func (m *Message) Cap(key string, arg ...string) string { // {{{
return m.Cap(key, arg[1]) return m.Cap(key, arg[1])
} }
m.Assert(false, key+"缓存项操作错误") m.Log("error", nil, "缓存项不存在")
return "" return ""
} }
// }}} // }}}
@ -1558,6 +1558,8 @@ var Index = &Context{Name: "ctx", Help: "模块中心",
case 2: case 2:
m.Conf(arg[0], arg[1]) m.Conf(arg[0], arg[1])
case 3:
m.Conf(arg[0], arg[2])
case 4: case 4:
m.Conf(arg[0], arg[1:]...) m.Conf(arg[0], arg[1:]...)
} }
@ -1597,30 +1599,22 @@ var Index = &Context{Name: "ctx", Help: "模块中心",
m.Cap(arg[0], "") m.Cap(arg[0], "")
} }
m.BackTrace(func(m *Message) bool { m.Echo("%s", m.Cap(arg[0]))
// if all {
// m.Echo("%s config:\n", m.target.Name)
// }
if x, ok := m.target.Caches[arg[0]]; ok {
if m.Check(m.target, "caches", arg[0]) {
// if all {
// m.Echo(" ")
// }
// m.Echo("%s: %s\n", x.Name, x.Help)
m.Echo("%s", x.Value)
return false
}
}
return true
// return all
})
case 2: case 2:
m.Cap(arg[0], arg[1]) m.Cap(arg[0], arg[1])
case 3:
m.Cap(arg[0], arg[2])
case 4: case 4:
m.Cap(arg[0], arg[1:]...) m.Cap(arg[0], arg[1:]...)
} }
// }}} // }}}
}}, }},
"pulse": &Command{Name: "arg name", Help: "查看日志", Hand: func(m *Message, c *Context, key string, arg ...string) {
p := m.Target().Pulse
m.Echo("%d\n", p.code)
m.Echo("%v\n", p.Meta["detail"])
m.Echo("%v\n", p.Meta["option"])
}},
}, },
Index: map[string]*Context{ Index: map[string]*Context{
"void": &Context{Name: "void", "void": &Context{Name: "void",