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
@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
~ssh dial chat.shylinux.com:9090 true
function nice
echo who
end
return hello hello
sleep 1
~host1
remote context mpa register terminal shhylinux term term term 1
@ -11,6 +21,7 @@ sleep 1
~nfs save usr/sess.txt "terminal: " $sessid
~nfs genqr usr/sess.png "terminal: " $sessid
return
# ~ssh dial chat.shylinux.com:9090 true
# ~cli
# remote slaver listen ":9393" tcp
# ~ssh

View File

@ -1,6 +1,6 @@
package cli // {{{
// }}}
import ( // {{{
package cli
import (
"context"
"bufio"
@ -14,21 +14,22 @@ import ( // {{{
"unicode"
)
// }}}
type CLI struct {
bio *bufio.Reader
out io.WriteCloser
alias map[string]string
back string
exit bool
which int
lines []string
alias map[string]string
lex *ctx.Message
target *ctx.Context
wait *ctx.Context
exit bool
test bool
save bool
*ctx.Message
*ctx.Context
}
@ -43,15 +44,29 @@ func (cli *CLI) echo(str string, arg ...interface{}) bool {
func (cli *CLI) parse(m *ctx.Message) bool {
line := m.Cap("next")
if line == "" {
if m.Cap("level") == "0" {
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')
m.Assert(e)
line = l
}
}
m.Cap("next", "")
if line = strings.TrimSpace(line); len(line) == 0 {
line, cli.back = cli.back, ""
if line = strings.TrimSpace(line); len(line) == 0 && m.Cap("stream") == "stdout" {
line = m.Cap("back")
m.Cap("back", "")
}
if len(line) == 0 || line[0] == '#' {
return true
@ -95,21 +110,20 @@ func (cli *CLI) parse(m *ctx.Message) 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 {
cli.echo(m.Cap("result", result) + "\n")
if msg.Target().Context() != nil || msg.Target() == ctx.Index {
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("back", line)
m.Log("fuck", nil, "over")
if cli.wait != nil {
msg.Log("fuck", nil, "wait 1")
<-cli.wait.Exit
cli.wait = nil
msg.Log("fuck", nil, "wait 2")
} else {
cli.target = msg.Target()
if cli.bio != nil {
cli.lines = append(cli.lines, line)
}
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.Context = c
s.lex = cli.lex
s.alias = cli.alias
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 {
cli.Context.Exit = make(chan bool)
cli.bio = nil
cli.exit = false
cli.test = false
if stream, ok := m.Data["io"]; ok {
cli.Context.Master(cli.Context)
io := stream.(io.ReadWriteCloser)
cli.bio = bufio.NewReader(io)
cli.out = io
cli.Context.Master(cli.Context)
if msg := m.Find("aaa", true); msg != nil {
cli.echo("username>")
@ -244,49 +264,45 @@ func (cli *CLI) Start(m *ctx.Message, arg ...string) bool {
}
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 {
m.Cap("stream", "stdout")
m.Cap("next", "source "+m.Conf("init.sh"))
cli.Context.Master(cli.Context)
cli.bio = bufio.NewReader(os.Stdin)
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) {
m.Cap("next", "source "+m.Conf("init.sh"))
for cli.parse(m) {
}
})
}
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("detail") != "login" {
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()
}
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 {
case m.Target():
if cli.Context == Index {
if m.Target() == Index && m.Capi("nserver") > 1 {
return false
}
case m.Source():
@ -336,8 +355,6 @@ func (cli *CLI) Close(m *ctx.Message, arg ...string) bool { // {{{
return true
}
// }}}
var Pulse *ctx.Message
var Index = &ctx.Context{Name: "cli", Help: "管理中心",
Caches: map[string]*ctx.Cache{
@ -345,18 +362,6 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
},
Configs: map[string]*ctx.Config{},
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) {
t, e := strconv.Atoi(arg[0])
m.Assert(e)
@ -364,14 +369,70 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
time.Sleep(time.Second * time.Duration(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) {
cli := m.Master().Master().Server.(*CLI)
m.Put("option", "bio", cli.bio).Start(strings.Join(arg, " "), "条件语句", key)
cli.wait = m.Target()
"source": &ctx.Command{Name: "source file", Help: "运行脚本", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
f, e := os.Open(arg[0])
m.Assert(e)
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) {
cli := m.Master().Master().Server.(*CLI)
cli, ok := m.Source().Server.(*CLI)
m.Assert(ok)
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) {
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: "建立远程连接",
Options: map[string]string{"master": "主控终端", "slaver": "被控终端", "args": "启动参数", "io": "读写流"},
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(m.Target() != 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.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 {
if x.Hand != nil {
m.Conf(k, x.Value)
@ -156,7 +156,7 @@ func (c *Context) Start(m *Message) bool { // {{{
if m.Cap("status") != "start" {
running := make(chan bool)
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"]...) {
c.Close(m, m.Meta["detail"]...)
@ -217,6 +217,10 @@ func (c *Context) Close(m *Message, arg ...string) bool { // {{{
if c.context != nil {
m.Log("close", nil, "%d context %v", m.root.Capi("ncontext", -1)+1, arg)
delete(c.context.contexts, c.Name)
c.context = nil
if c.Exit != nil {
c.Exit <- true
}
}
return true
}
@ -969,12 +973,9 @@ func (m *Message) Deal(pre func(msg *Message, arg ...string) bool, post func(msg
return
}
if pre != nil && !pre(msg, msg.Meta["detail"]...) {
run = false
return
}
if pre == nil || pre(msg, msg.Meta["detail"]...) {
msg.Exec(msg.Meta["detail"][0], msg.Meta["detail"][1:]...)
}
if post != nil && !post(msg, msg.Meta["result"]...) {
run = false
@ -1029,7 +1030,8 @@ func (m *Message) Confi(key string, arg ...int) int { // {{{
// }}}
func (m *Message) Conf(key string, 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 !m.Check(s, "configs", key) {
continue
@ -1054,8 +1056,7 @@ func (m *Message) Conf(key string, arg ...string) string { // {{{
return x.Hand(m, x)
}
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])
}
m.Assert(false, key+"配置项操作错误")
m.Log("error", nil, "配置项不存在")
return ""
}
@ -1090,7 +1091,8 @@ func (m *Message) Capi(key string, arg ...int) int { // {{{
// }}}
func (m *Message) Cap(key string, 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 !m.Check(s, "caches", key) {
continue
@ -1113,8 +1115,7 @@ func (m *Message) Cap(key string, arg ...string) string { // {{{
return x.Hand(m, x)
}
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])
}
m.Assert(false, key+"缓存项操作错误")
m.Log("error", nil, "缓存项不存在")
return ""
}
// }}}
@ -1558,6 +1558,8 @@ var Index = &Context{Name: "ctx", Help: "模块中心",
case 2:
m.Conf(arg[0], arg[1])
case 3:
m.Conf(arg[0], arg[2])
case 4:
m.Conf(arg[0], arg[1:]...)
}
@ -1597,30 +1599,22 @@ var Index = &Context{Name: "ctx", Help: "模块中心",
m.Cap(arg[0], "")
}
m.BackTrace(func(m *Message) bool {
// 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
})
m.Echo("%s", m.Cap(arg[0]))
case 2:
m.Cap(arg[0], arg[1])
case 3:
m.Cap(arg[0], arg[2])
case 4:
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{
"void": &Context{Name: "void",