1
0
forked from x/ContextOS

Merge branch '0.1.0' of https://github.com/shylinux/context into 0.2.0

This commit is contained in:
shaoying 2018-01-08 09:50:21 +08:00
commit 9b2190cf42
6 changed files with 691 additions and 397 deletions

18
etc/cert.pem Normal file
View File

@ -0,0 +1,18 @@
-----BEGIN CERTIFICATE-----
MIIC9TCCAl4CCQCHSqshz+HyLTANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMC
R0IxHzAdBgNVBAgTFlRlc3QgU3RhdGUgb3IgUHJvdmluY2UxFjAUBgNVBAcTDVRl
c3QgTG9jYWxpdHkxGjAYBgNVBAoTEU9yZ2FuaXphdGlvbiBOYW1lMSEwHwYDVQQL
ExhPcmdhbml6YXRpb25hbCBVbml0IE5hbWUxFDASBgNVBAMTC0NvbW1vbiBOYW1l
MSEwHwYJKoZIhvcNAQkBFhJ0ZXN0QGVtYWlsLmFkZHJlc3MwHhcNMTcxMDMxMTYw
NDM5WhcNMTcxMTMwMTYwNDM5WjCBvjELMAkGA1UEBhMCR0IxHzAdBgNVBAgTFlRl
c3QgU3RhdGUgb3IgUHJvdmluY2UxFjAUBgNVBAcTDVRlc3QgTG9jYWxpdHkxGjAY
BgNVBAoTEU9yZ2FuaXphdGlvbiBOYW1lMSEwHwYDVQQLExhPcmdhbml6YXRpb25h
bCBVbml0IE5hbWUxFDASBgNVBAMTC0NvbW1vbiBOYW1lMSEwHwYJKoZIhvcNAQkB
FhJ0ZXN0QGVtYWlsLmFkZHJlc3MwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB
AOw3gvdtfKWkSEl2l30V7irBhkrD6IVd6AzxaAYL97giDglPvu7ng2PXYlF5pjjf
mxDYtjAGuq1itnN0LKRe6CjUOuGtC2KMlZ8121fQCNw8M6TLPSpDjVuzysaUb2ds
+OClb0uC8SmSy3bOCGsicI77yXvEuKFkm43ikyVounmRAgMBAAEwDQYJKoZIhvcN
AQELBQADgYEAkOk7DVR/XgJdMSXXGd/OtWmTfVp2sIyyy37zSoc4uRFWwPqbzLPf
NgUKGNHEYvJY7/bWQ3p2D+u1U2PUfv/t6SQcAu3Nkw7sd7PoeeDZcRau84NevgoR
HfQKirJQgZd0hKFwiBnDspYbi8IL2mHEJOlzw1priY9v8MVIscyFVbE=
-----END CERTIFICATE-----

15
etc/key.pem Normal file
View File

@ -0,0 +1,15 @@
-----BEGIN RSA PRIVATE KEY-----
MIICXwIBAAKBgQDsN4L3bXylpEhJdpd9Fe4qwYZKw+iFXegM8WgGC/e4Ig4JT77u
54Nj12JReaY435sQ2LYwBrqtYrZzdCykXugo1DrhrQtijJWfNdtX0AjcPDOkyz0q
Q41bs8rGlG9nbPjgpW9LgvEpkst2zghrInCO+8l7xLihZJuN4pMlaLp5kQIDAQAB
AoGBAOasYwG68pFTN6A95jupsdYg/EKAw82RYa1aBUp6X2N6JhjjvkHQ5ZcXWxTT
ZgZ+HhC6gFewCpaNIjzmwz2UzMJJ4empijEbJFuwZCq4M/Adca2BhduV2YIwqvi8
MHGmHMB81zYKA0E4j+vahJnn8aAqSoPnaM9MBw5vhggU5YodAkEA/IwRTVNOHmIm
1XCfvPoSpDBpSJh6V1mPyBuPs/2Fr52j+L+6qOhNML0O063az44/dR8RZytcaGYQ
7EByYbeCZwJBAO9ySW4TbDLRejSmFWHmflrnjV7s4DqE6OBbCRJF3aIleELYaTPC
Q0kOKRZTCr1PwopIdAOOOgaSWgsX75zU2UcCQQDMCwb3qLTXC4pArMwCzTE+gvat
drRx2qS2kr4aOF1ItF8E3TOcwIONO1K9aBv/0fgnUsCm0HvKxZwqpS9FEBVFAkEA
ntgeRlu0J3I3s72J6cxSflOlwRc7GRcatdsuhWS7xtk8knumLqPspwYx05F7SmMj
F0FBVSqA6+MiwME8P7oj+QJBAJFv2HKAaGElXkaJJzmQPHGJdGLUMb9oHXPtzcpz
HLtT2kHK1LlQqsOEacivPCKtnnLkX6Xsl8pMpe8EV43t718=
-----END RSA PRIVATE KEY-----

85
etc/shy.vim Normal file
View File

@ -0,0 +1,85 @@
syn keyword shStatement break cd chdir continue eval exec exit kill newgrp pwd read readonly return shift test trap ulimit umask wait
syn keyword shStatement source return function
syn keyword shStatement if else elif end for
syn keyword shStatement let var
syn match shOperator "\~[-_a-zA-Z0-9]\+\>"
syn match shShellVariables "\$[-_a-zA-Z0-9]\+\>"
syn match shShellVariables "@[-_a-zA-Z0-9]\+\>"
hi def link shArithRegion shShellVariables
hi def link shBeginHere shRedir
hi def link shCaseBar shConditional
hi def link shCaseCommandSub shCommandSub
hi def link shCaseDoubleQuote shDoubleQuote
hi def link shCaseIn shConditional
hi def link shQuote shOperator
hi def link shCaseSingleQuote shSingleQuote
hi def link shCaseStart shConditional
hi def link shCmdSubRegion shShellVariables
hi def link shColon shComment
hi def link shDerefOp shOperator
hi def link shDerefPOL shDerefOp
hi def link shDerefPPS shDerefOp
hi def link shDeref shShellVariables
hi def link shDerefDelim shOperator
hi def link shDerefSimple shDeref
hi def link shDerefSpecial shDeref
hi def link shDerefString shDoubleQuote
hi def link shDerefVar shDeref
hi def link shDoubleQuote shString
hi def link shEcho shString
hi def link shEchoDelim shOperator
hi def link shEchoQuote shString
hi def link shEmbeddedEcho shString
hi def link shEscape shCommandSub
hi def link shExDoubleQuote shDoubleQuote
hi def link shExSingleQuote shSingleQuote
hi def link shFunction Function
hi def link shHereDoc shString
hi def link shHerePayload shHereDoc
hi def link shLoop shStatement
hi def link shMoreSpecial shSpecial
hi def link shOption shCommandSub
hi def link shPattern shString
hi def link shParen shArithmetic
hi def link shPosnParm shShellVariables
hi def link shQuickComment shComment
hi def link shRange shOperator
hi def link shRedir shOperator
hi def link shSetListDelim shOperator
hi def link shSetOption shOption
hi def link shSingleQuote shString
hi def link shSource shOperator
hi def link shStringSpecial shSpecial
hi def link shSubShRegion shOperator
hi def link shTestOpr shConditional
hi def link shTestPattern shString
hi def link shTestDoubleQuote shString
hi def link shTestSingleQuote shString
hi def link shVariable shSetList
hi def link shWrapLineOperator shOperator
hi def link shArithmetic Special
hi def link shCharClass Identifier
hi def link shSnglCase Statement
hi def link shCommandSub Special
hi def link shComment Comment
hi def link shConditional Conditional
hi def link shCtrlSeq Special
hi def link shExprRegion Delimiter
hi def link shFunctionKey Function
hi def link shFunctionName Function
hi def link shNumber Number
hi def link shOperator Operator
hi def link shRepeat Repeat
hi def link shSet Statement
hi def link shSetList Identifier
hi def link shShellVariables PreProc
hi def link shSpecial Special
hi def link shStatement Statement
hi def link shString String
hi def link shTodo Todo
hi def link shAlias Identifier

View File

@ -1,40 +1,38 @@
package cli package cli // {{{
// }}}
import ( import ( // {{{
"context" "context"
"bufio" "bufio"
"fmt"
"io" "io"
"os"
"os/exec" "fmt"
"regexp"
"strconv" "strconv"
"strings" "strings"
"time"
"unicode" "unicode"
"os"
"os/exec"
"time"
"regexp"
) )
// }}}
type CLI struct { type CLI struct {
bio *bufio.Reader bio *bufio.Reader
out io.WriteCloser out io.WriteCloser
which int
lines []string lines []string
pos int
alias map[string]string
lex *ctx.Message lex *ctx.Message
alias map[string][]string
target *ctx.Context target *ctx.Context
wait *ctx.Context
exit bool
test bool
save bool
*ctx.Context *ctx.Context
} }
func (cli *CLI) echo(str string, arg ...interface{}) bool { func (cli *CLI) print(str string, arg ...interface{}) bool { // {{{
if cli.out != nil { if cli.out != nil {
fmt.Fprintf(cli.out, str, arg...) fmt.Fprintf(cli.out, str, arg...)
return true return true
@ -42,127 +40,267 @@ func (cli *CLI) echo(str string, arg ...interface{}) bool {
return false return false
} }
func (cli *CLI) parse(m *ctx.Message) bool { // }}}
func (cli *CLI) parse(m *ctx.Message) (cmd []string) { // {{{
line := m.Cap("next") line := m.Cap("next")
if line == "" { if m.Cap("next", ""); line == "" {
if m.Cap("level") == "0" {
cli.echo(m.Conf("PS1"))
}
if cli.bio == nil { if cli.bio == nil {
if cli.which == len(cli.lines) { line = cli.lines[cli.pos]
cli.exit = true cli.pos++
cli.which = 0
m.Spawn(cli.Context).Set("detail", "end").Post(cli.Context)
return false
}
line = cli.lines[cli.which]
cli.which++
} else { } else {
cli.print(m.Conf("PS1"))
l, e := cli.bio.ReadString('\n') l, e := cli.bio.ReadString('\n')
if e == io.EOF {
cli.exit = true
m.Spawn(cli.Context).Set("detail", "end").Post(cli.Context)
return false
}
m.Assert(e) m.Assert(e)
line = l line = l
} }
} }
m.Cap("next", "")
if line = strings.TrimSpace(line); len(line) == 0 && m.Cap("stream") == "stdout" { if line = strings.TrimSpace(line); len(line) == 0 && cli.out != nil {
line = m.Cap("back") line = m.Cap("back")
m.Cap("back", "") m.Cap("back", "")
} }
if len(line) == 0 || line[0] == '#' { if len(line) == 0 || line[0] == '#' {
return true return nil
} }
ls := []string{} ls := []string{}
if cli.lex == nil { if cli.lex == nil {
ls = strings.Split(line, " ") ls = strings.Split(line, " ")
} else { cs := []string{}
lex := m.Spawn(cli.lex.Target())
m.Assert(lex.Cmd("split", line, "void"))
ls = lex.Meta["result"]
}
msg := m.Spawn(cli.target)
for i := 0; i < len(ls); i++ { for i := 0; i < len(ls); i++ {
if cli.lex == nil {
if ls[i] = strings.TrimSpace(ls[i]); ls[i] == "" { if ls[i] = strings.TrimSpace(ls[i]); ls[i] == "" {
continue continue
} }
if ls[i][0] == '#' { if ls[i][0] == '#' {
break break
} }
cs = append(cs, ls[i])
}
ls = cs
} else {
lex := m.Spawn(cli.lex.Target())
m.Assert(lex.Cmd("split", line, "void"))
ls = lex.Meta["result"]
} }
if len(ls[i]) > 0 && !cli.test { if !cli.Has("skip") || !cli.Pulse.Caps("skip") {
ls = cli.expand(ls)
}
if m.Cap("back", line); cli.bio != nil {
cli.lines = append(cli.lines, line)
m.Capi("nline", 1)
}
return ls
}
// }}}
func (cli *CLI) expand(ls []string) []string { // {{{
cs := []string{}
for i := 0; i < len(ls); i++ {
if len(ls[i]) > 0 {
if r := rune(ls[i][0]); r == '$' || r == '_' || (!unicode.IsNumber(r) && !unicode.IsLetter(r)) { if r := rune(ls[i][0]); r == '$' || r == '_' || (!unicode.IsNumber(r) && !unicode.IsLetter(r)) {
if c, ok := cli.alias[string(r)]; ok { if c, ok := cli.alias[string(r)]; ok {
if i == 0 { if i == 0 {
if msg.Add("detail", c); len(ls[i]) == 1 { ns := []string{}
continue ns = append(ns, c...)
if ls[0] = ls[i][1:]; len(ls[0]) > 0 {
ns = append(ns, ls...)
} else {
ns = append(ns, ls[1:]...)
} }
ls[i] = ls[i][1:] ls = ns
} else if len(ls[i]) > 1 && !cli.test { } else if len(ls[i]) > 1 {
key := ls[i][1:] key := ls[i][1:]
switch c {
case "config", "cache":
if cli.Context.Has(key, c) {
ls[i] = m.Cap(key)
break
}
msg := m.Spawn(cli.target) if r == rune(key[0]) {
m.Assert(msg.Exec(c, key)) ls[i] = key
} else {
if cli.Context.Has(key, c[0]) {
switch c[0] {
case "config":
ls[i] = cli.Pulse.Conf(key)
case "cache":
ls[i] = cli.Pulse.Cap(key)
}
} else {
msg := cli.Pulse.Spawn(cli.target)
if msg.Exec(c[0], key) != "error: " {
ls[i] = msg.Get("result") ls[i] = msg.Get("result")
} }
} }
} }
} }
} }
msg.Add("detail", ls[i])
} }
msg.Wait = make(chan bool) if c, ok := cli.alias[ls[i]]; ok && i == 0 {
msg.Post(cli.Context) ns := []string{}
ns = append(ns, c...)
if msg.Target().Context() != nil || msg.Target() == ctx.Index { ns = append(ns, ls[1:]...)
cli.target = msg.Target()
} }
m.Cap("target", cli.target.Name)
result := strings.TrimRight(strings.Join(msg.Meta["result"], ""), "\n")
if m.Cap("result", result); len(result) > 0 {
cli.echo(result + "\n")
} }
if m.Cap("back", line); cli.bio != nil { cs = append(cs, ls[i])
cli.lines = append(cli.lines, line)
} }
return !cli.exit
return cs
} }
func (cli *CLI) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { // }}}
func (cli *CLI) express(arg []string) string { // {{{
result := "false"
switch len(arg) {
case 0:
result = ""
case 1:
result = arg[0]
case 2:
switch arg[0] {
case "-z":
if arg[1] == "" {
result = "true"
}
case "-n":
result = arg[1]
case "-e":
if _, e := os.Stat(arg[1]); e == nil {
result = "true"
}
case "-f":
if info, e := os.Stat(arg[1]); e == nil && !info.IsDir() {
result = "true"
}
case "-d":
if info, e := os.Stat(arg[1]); e == nil && info.IsDir() {
result = "true"
}
}
case 3:
v1, e1 := strconv.Atoi(arg[0])
v2, e2 := strconv.Atoi(arg[2])
switch arg[1] {
case "+":
result = arg[0] + arg[2]
if e1 == nil && e2 == nil {
result = fmt.Sprintf("%d", v1+v2)
}
case "-":
result = arg[0]
if e1 == nil && e2 == nil {
result = fmt.Sprintf("%d", v1-v2)
}
case "*":
result = arg[0]
if e1 == nil && e2 == nil {
result = fmt.Sprintf("%d", v1*v2)
}
case "/":
result = arg[0]
if e1 == nil && e2 == nil {
result = fmt.Sprintf("%d", v1/v2)
}
case "%":
result = arg[0]
if e1 == nil && e2 == nil {
result = fmt.Sprintf("%d", v1%v2)
}
case "<":
if e1 == nil && e2 == nil {
result = fmt.Sprintf("%t", v1 < v2)
} else {
result = fmt.Sprintf("%t", arg[0] < arg[2])
}
case "<=":
if e1 == nil && e2 == nil {
result = fmt.Sprintf("%t", v1 <= v2)
} else {
result = fmt.Sprintf("%t", arg[0] <= arg[2])
}
case ">":
if e1 == nil && e2 == nil {
result = fmt.Sprintf("%t", v1 > v2)
} else {
result = fmt.Sprintf("%t", arg[0] > arg[2])
}
case ">=":
if e1 == nil && e2 == nil {
result = fmt.Sprintf("%t", v1 >= v2)
} else {
result = fmt.Sprintf("%t", arg[0] >= arg[2])
}
case "==":
if arg[0] == arg[2] {
result = "true"
}
case "!=":
if arg[0] != arg[2] {
result = "true"
}
case "~":
if m, e := regexp.MatchString(arg[1], arg[0]); m && e == nil {
result = "true"
}
case "!~":
if m, e := regexp.MatchString(arg[1], arg[0]); !m || e != nil {
result = "true"
}
}
}
cli.Pulse.Log("info", nil, "result: %v", result)
return result
}
// }}}
func (cli *CLI) check(arg []string) bool { // {{{
switch cli.express(arg) {
case "", "0", "false":
return false
}
return true
}
// }}}
func (cli *CLI) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { // {{{
c.Caches = map[string]*ctx.Cache{} c.Caches = map[string]*ctx.Cache{}
c.Configs = map[string]*ctx.Config{} c.Configs = map[string]*ctx.Config{}
c.Caches["skip"] = &ctx.Cache{Name: "下一条指令", Value: "0", Help: "下一条指令"}
if cli.Has("skip") {
m.Cap("skip", cli.Pulse.Cap("skip"))
}
s := new(CLI) s := new(CLI)
s.Context = c s.Context = c
s.lex = cli.lex s.lex = cli.lex
s.alias = cli.alias s.alias = cli.alias
s.lines = cli.lines[cli.pos:]
return s return s
} }
func (cli *CLI) Begin(m *ctx.Message, arg ...string) ctx.Server { // }}}
func (cli *CLI) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{
cli.Caches["target"] = &ctx.Cache{Name: "操作目标", Value: "", Help: "操作目标"} cli.Caches["target"] = &ctx.Cache{Name: "操作目标", Value: "", Help: "操作目标"}
cli.Caches["result"] = &ctx.Cache{Name: "前一条指令执行结果", Value: "", Help: "前一条指令执行结果"} cli.Caches["result"] = &ctx.Cache{Name: "前一条指令执行结果", Value: "", Help: "前一条指令执行结果"}
cli.Caches["back"] = &ctx.Cache{Name: "前一条指令", Value: "", Help: "前一条指令"} cli.Caches["back"] = &ctx.Cache{Name: "前一条指令", Value: "", Help: "前一条指令"}
cli.Caches["next"] = &ctx.Cache{Name: "下一条指令", Value: "", Help: "下一条指令"} cli.Caches["next"] = &ctx.Cache{Name: "下一条指令", Value: "", Help: "下一条指令"}
cli.Caches["exit"] = &ctx.Cache{Name: "下一条指令", Value: "0", Help: "下一条指令"}
cli.Caches["else"] = &ctx.Cache{Name: "下一条指令", Value: "0", Help: "下一条指令"}
cli.Caches["nline"] = &ctx.Cache{Name: "下一条指令", Value: "0", Help: "下一条指令"}
cli.Configs["PS1"] = &ctx.Config{Name: "命令行提示符(target/detail)", Value: "target", Help: "命令行提示符target:显示当前模块detail:显示详细信息", Hand: func(m *ctx.Message, x *ctx.Config, arg ...string) string { cli.Configs["PS1"] = &ctx.Config{Name: "命令行提示符(target/detail)", Value: "target", Help: "命令行提示符target:显示当前模块detail:显示详细信息", Hand: func(m *ctx.Message, x *ctx.Config, arg ...string) string {
if len(arg) > 0 { // {{{ if len(arg) > 0 { // {{{
@ -228,7 +366,7 @@ func (cli *CLI) Begin(m *ctx.Message, arg ...string) ctx.Server {
}} }}
if len(arg) > 0 { if len(arg) > 0 {
cli.Configs["init.sh"] = &ctx.Config{Name: "启动脚本", Value: arg[0], Help: "模块启动时自动运行的脚本"} cli.Configs["init.shy"] = &ctx.Config{Name: "启动脚本", Value: arg[0], Help: "模块启动时自动运行的脚本"}
} }
if cli.Context == Index { if cli.Context == Index {
@ -236,57 +374,44 @@ func (cli *CLI) Begin(m *ctx.Message, arg ...string) ctx.Server {
} }
cli.target = cli.Context cli.target = cli.Context
cli.alias = map[string]string{ cli.alias = map[string][]string{
"~": "context", "~": []string{"context"},
"!": "message", "!": []string{"message"},
"@": "config", "@": []string{"config"},
"$": "cache", "$": []string{"cache"},
"&": "server", "&": []string{"server"},
":": "command", ":": []string{"command"},
} }
return cli return cli
} }
func (cli *CLI) Start(m *ctx.Message, arg ...string) bool { // }}}
cli.Context.Exit = make(chan bool) func (cli *CLI) Start(m *ctx.Message, arg ...string) bool { // {{{
cli.pos = 0
cli.bio = nil cli.bio = nil
cli.exit = false cli.Context.Exit = make(chan bool)
cli.test = false
if stream, ok := m.Data["io"]; ok { cli.Caches["#"] = &ctx.Cache{Name: "前一条指令", Value: fmt.Sprintf("%d", len(arg)), Help: "前一条指令"}
cli.Context.Master(cli.Context) for i, v := range arg {
io := stream.(io.ReadWriteCloser) cli.Caches[fmt.Sprintf("%d", i)] = &ctx.Cache{Name: "前一条指令", Value: v, Help: "前一条指令"}
cli.bio = bufio.NewReader(io)
cli.out = io
if msg := m.Find("aaa", true); msg != nil {
cli.echo("username>")
username, e := cli.bio.ReadString('\n')
msg.Assert(e)
username = strings.TrimSpace(username)
cli.echo("password>")
password, e := cli.bio.ReadString('\n')
msg.Assert(e)
password = strings.TrimSpace(password)
msg.Name = "aaa"
msg.Wait = make(chan bool)
if msg.Cmd("login", username, password) == "" {
cli.echo("登录失败")
io.Close()
return true
} }
if cli.Sessions == nil { m.Caps("exit", false)
cli.Sessions = make(map[string]*ctx.Message) m.Caps("else", false)
if m.Has("skip") {
if m.Capi("skip", 1) == 1 {
if !m.Has("save") {
m.Caps("else", true)
} }
cli.Sessions["aaa"] = msg
} }
} else if len(arg) > 0 && arg[0] == "stdout" { } else {
m.Caps("skip", false)
}
if m.Has("stdio") {
m.Cap("stream", "stdout") m.Cap("stream", "stdout")
m.Cap("next", "source "+m.Conf("init.sh")) m.Cap("next", "source "+m.Conf("init.shy"))
cli.bio = bufio.NewReader(os.Stdin) cli.bio = bufio.NewReader(os.Stdin)
cli.out = os.Stdout cli.out = os.Stdout
cli.Caches["level"] = &ctx.Cache{Name: "操作目标", Value: "0", Help: "操作目标"} cli.Caches["level"] = &ctx.Cache{Name: "操作目标", Value: "0", Help: "操作目标"}
@ -298,39 +423,49 @@ func (cli *CLI) Start(m *ctx.Message, arg ...string) bool {
m.Cap("stream", "file") m.Cap("stream", "file")
cli.bio = bufio.NewReader(stream.(io.ReadWriteCloser)) cli.bio = bufio.NewReader(stream.(io.ReadWriteCloser))
} }
cli.test = m.Has("test") }
cli.save = m.Has("save")
if cli.bio != nil {
cli.lines = []string{m.Get("for")}
} }
go m.AssertOne(m, true, func(m *ctx.Message) { go m.AssertOne(m, true, func(m *ctx.Message) {
for cli.parse(m) { for !m.Caps("exit") {
if cmd := cli.parse(m); cmd != nil {
m.Spawn(cli.target).Set("detail", cmd...).Post(cli.Context)
} }
}
}, func(m *ctx.Message) {
m.Caps("exit", true)
m.Spawn(cli.Context).Set("detail", "end").Post(cli.Context)
}) })
m.Capi("nterm", 1) m.Capi("nterm", 1)
defer m.Capi("nterm", -1) defer m.Capi("nterm", -1)
m.Deal(func(msg *ctx.Message, arg ...string) bool { m.Deal(func(msg *ctx.Message, arg ...string) bool {
if cli.test { return !cli.Has("skip") || !m.Caps("skip") || Index.Has(msg.Get("detail"), "command")
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 { }, func(msg *ctx.Message, arg ...string) bool {
if msg.Get("result") == "error: " { if cli.Has("skip") && m.Caps("skip") {
if msg.Get("detail") != "login" { return !m.Caps("exit")
}
if !msg.Has("result") && cli.Owner == ctx.Index.Owner {
msg.Log("system", nil, "%v", msg.Meta["detail"]) msg.Log("system", nil, "%v", msg.Meta["detail"])
msg.Set("result") msg.Set("result").Set("append")
msg.Set("append")
c := exec.Command(msg.Meta["detail"][0], msg.Meta["detail"][1:]...) c := exec.Command(msg.Meta["detail"][0], msg.Meta["detail"][1:]...)
if cli.out == os.Stdout { if cli.out == os.Stdout {
c.Stdin, c.Stdout, c.Stderr = os.Stdin, os.Stdout, os.Stderr c.Stdin, c.Stdout, c.Stderr = os.Stdin, os.Stdout, os.Stderr
msg.Assert(c.Start()) if e := c.Start(); e != nil {
msg.Assert(c.Wait()) msg.Echo("error: ")
msg.Echo("%s\n", e)
} else if e := c.Wait(); e != nil {
msg.Echo("error: ")
msg.Echo("%s\n", e)
}
} else { } else {
if out, e := c.CombinedOutput(); e == nil { if out, e := c.CombinedOutput(); e == nil {
msg.Echo(string(out)) msg.Echo(string(out))
@ -340,22 +475,38 @@ func (cli *CLI) Start(m *ctx.Message, arg ...string) bool {
} }
} }
} }
result := strings.TrimRight(strings.Join(msg.Meta["result"], ""), "\n")
if m.Cap("result", result); len(result) > 0 {
cli.print(result + "\n")
} }
if msg.Target().Context() != nil || msg.Target() == ctx.Index { if msg.Target().Context() != nil || msg.Target() == ctx.Index {
cli.target = msg.Target() cli.target = msg.Target()
} }
return cli.exit == false m.Cap("target", cli.target.Name)
return !m.Caps("exit")
}) })
return !cli.save if cli.Pulse.Has("save") {
m.Cap("status", "stop")
cli.Exit <- true
}
return !cli.Pulse.Has("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 m.Target() == Index && m.Capi("nserver") > 1 { if p, ok := cli.Context.Context().Server.(*CLI); ok {
return false if p.bio != nil {
p.lines = append(p.lines, cli.lines...)
} else {
p.pos += cli.pos
}
} }
case m.Source(): case m.Source():
if m.Name == "aaa" { if m.Name == "aaa" {
@ -369,205 +520,177 @@ 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{
"nterm": &ctx.Cache{Name: "终端数量", Value: "0", Help: "已经运行的终端数量"}, "nterm": &ctx.Cache{Name: "终端数量", Value: "0", Help: "正在运行的终端数量"},
}, },
Configs: map[string]*ctx.Config{}, Configs: map[string]*ctx.Config{},
Commands: map[string]*ctx.Command{ Commands: map[string]*ctx.Command{
"sleep": &ctx.Command{Name: "sleep time", Help: "运行脚本", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { "alias": &ctx.Command{Name: "alias [short [long]]|[delete short]", Help: "查看、定义或删除命令别名, short: 命令别名, long: 命令原名, delete: 删除别名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
t, e := strconv.Atoi(arg[0]) // {{{ cli, ok := m.Target().Server.(*CLI) // {{{
m.Assert(e) m.Assert(ok, "目标模块类型错误")
m.Log("info", nil, "sleep %ds", t)
time.Sleep(time.Second * time.Duration(t))
m.Log("info", nil, "sleep %ds done", t)
// }}}
}},
"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(fmt.Sprintf("%s(%d)", key, Pulse.Capi("level", 1)), "脚本文件")
<-m.Target().Exit
Pulse.Capi("level", -1)
// }}}
}},
"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: "条件语句",
Formats: map[string]int{"~": 0, "!~": 0, "==": 0, "!=": 0, "-z": 0, "-n": 0, "-e": 0, "-f": 0, "-d": 0},
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
cli, ok := m.Source().Server.(*CLI) // {{{
m.Assert(ok)
run := false
switch {
case m.Has("-e"):
_, e := os.Stat(arg[0])
run = e == nil
case m.Has("-f"):
info, e := os.Stat(arg[0])
run = e == nil && !info.IsDir()
case m.Has("-d"):
info, e := os.Stat(arg[0])
run = e == nil && info.IsDir()
case m.Has("-z"):
run = len(arg) == 0 || len(arg[0]) == 0
case m.Has("-n"):
run = len(arg) > 0 && len(arg[0]) > 0
case m.Has("=="):
run = arg[0] == arg[1]
case m.Has("!="):
run = arg[0] != arg[1]
case m.Has("~"):
m, e := regexp.MatchString(arg[1], arg[0])
run = m && e == nil
case m.Has("!~"):
m, e := regexp.MatchString(arg[1], arg[0])
run = !m || e != nil
}
if !run {
m.Add("option", "test")
}
m.Target(m.Source())
m.Put("option", "file", cli.bio).Start(key, "条件语句")
<-m.Target().Exit
// }}}
}},
"else": &ctx.Command{Name: "else", Help: "条件切换", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
cli, ok := m.Source().Server.(*CLI) // {{{
m.Assert(ok)
cli.test = !cli.test
// }}}
}},
"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, ok := m.Source().Server.(*CLI) // {{{
m.Assert(ok)
cli.exit = true
// }}}
}},
"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)
if m.Assert(ok); cli.test {
return
}
val := ""
if len(arg) > 2 {
val = arg[2]
}
m.Assert(!m.Source().Has(arg[0], "cache"))
m.Spawn(m.Source()).Cap(arg[0], arg[0], val, "临时变量")
}},
"let": &ctx.Command{Name: "let a [=] b", Help: "设置变量", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
cli, ok := m.Source().Server.(*CLI)
if m.Assert(ok); cli.test {
return
}
val := arg[1]
if len(arg) > 2 {
val = arg[2]
}
m.Spawn(m.Source()).Cap(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], "定义函数")
// }}}
}},
"alias": &ctx.Command{Name: "alias [short [long]]", Help: "定义别名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
cli := c.Server.(*CLI) // {{{
switch len(arg) { switch len(arg) {
case 0: case 0:
for k, v := range cli.alias { for k, v := range cli.alias {
m.Echo("%s: %s\n", k, v) m.Echo("%s: %v\n", k, v)
} }
case 2: case 1:
switch arg[0] { m.Echo("%s: %v\n", arg[0], cli.alias[arg[0]])
case "delete": default:
if arg[0] == "delete" {
m.Echo("delete: %s %v\n", arg[1], cli.alias[arg[1]])
delete(cli.alias, arg[1]) delete(cli.alias, arg[1])
default: } else {
cli.alias[arg[0]] = arg[1] cli.alias[arg[0]] = arg[1:]
m.Echo("%s: %s\n", arg[0], cli.alias[arg[0]]) m.Echo("%s: %v\n", arg[0], cli.alias[arg[0]])
} }
default:
cli.alias[arg[0]] = strings.Join(arg[1:], " ")
m.Echo("%s: %s\n", arg[0], cli.alias[arg[0]])
} }
// }}} // }}}
}}, }},
// "remote": &ctx.Command{Name: "remote [send args...]|[[master|slaver] listen|dial address protocol]", Help: "建立远程连接", "sleep": &ctx.Command{Name: "sleep time", Help: "睡眠, time(ns/us/ms/s/m/h): 时间值(纳秒/微秒/毫秒/秒/分钟/小时)", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
// Formats: map[string]int{"send": -1, "master": 0, "slaver": 0, "listen": 1, "dial": 1}, if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) && (!cli.Has("skip") || !cli.Pulse.Caps("skip")) { // {{{
// Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { if d, e := time.ParseDuration(arg[0]); m.Assert(e) {
// action := "dial" // {{{ m.Log("info", nil, "sleep %v", d)
// if m.Has("listen") { time.Sleep(d)
// action = "listen" m.Log("info", nil, "sleep %v done", d)
// } }
// }
// msg := m.Find(m.Get("args"), true) // }}}
// }},
// if m.Has("master") { "var": &ctx.Command{Name: "var a [= exp]", Help: "定义变量, a: 变量名, exp: 表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
// msg.Template = msg.Spawn(msg.Source()).Add("option", "master") if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) && (!cli.Has("skip") || !cli.Pulse.Caps("skip")) { // {{{
// } val := ""
// msg.Cmd(action, m.Get(action)) if len(arg) > 2 {
// val = cli.express(arg[2:])
// }}, // }}} }
// "open": &ctx.Command{Name: "open [master|slaver] [script [log]]", Help: "建立远程连接", cli.Pulse.Cap(arg[0], arg[0], val, "临时变量")
// Options: map[string]string{"master": "主控终端", "slaver": "被控终端", "args": "启动参数", "io": "读写流"}, }
// Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { // }}}
// m.Start(fmt.Sprintf("PTS%d", m.Capi("nterm")), "管理终端", "void.sh") // {{{ }},
// // }}} "let": &ctx.Command{Name: "let a = exp", Help: "设置变量, a: 变量名, exp: 表达式(a {+|-|*|/|%} b)", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
// }}, if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) && (!cli.Has("skip") || !cli.Pulse.Caps("skip")) { // {{{
// "master": &ctx.Command{Name: "open [master|slaver] [script [log]]", Help: "建立远程连接", m.Echo(cli.Pulse.Cap(arg[0], cli.express(arg[2:])))
// Options: map[string]string{"master": "主控终端", "slaver": "被控终端", "args": "启动参数", "io": "读写流"}, }
// Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { // }}}
// _, ok := c.Server.(*CLI) // {{{ }},
// m.Assert(ok, "模块类型错误") "source": &ctx.Command{Name: "source file", Help: "运行脚本, file: 脚本文件名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
// m.Assert(m.Target() != c, "模块是主控模块") if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) && (!cli.Has("skip") || !cli.Pulse.Caps("skip")) { // {{{
// if f, e := os.Open(arg[0]); m.Assert(e) {
// msg := m.Spawn(c) m.Put("option", "file", f).Start(fmt.Sprintf("%s%d", key, Pulse.Capi("level", 1)), "脚本文件")
// msg.Start(fmt.Sprintf("PTS%d", Pulse.Capi("nterm")), arg[0], arg[1:]...) <-m.Target().Exit
// // }}} Pulse.Capi("level", -1)
// }}, }
}, }
Index: map[string]*ctx.Context{ // }}}
"void": &ctx.Context{Name: "void", }},
Commands: map[string]*ctx.Command{ "return": &ctx.Command{Name: "return result...", Help: "结束脚本, rusult: 返回值", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
"open": &ctx.Command{}, if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) && (!cli.Has("skip") || !cli.Pulse.Caps("skip")) { // {{{
}, call := cli.Requests[len(cli.Requests)-1]
}, call.Log("fuck", nil, "return")
for _, v := range arg {
call.Echo(v)
}
cli.Pulse.Caps("exit", true)
}
// }}}
}},
"if": &ctx.Command{Name: "if exp", Help: "条件语句, exp: 表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) { // {{{
if m.Target(m.Source()); (cli.Has("skip") && cli.Pulse.Caps("skip")) || !cli.check(arg) {
m.Add("option", "skip")
}
m.Put("option", "file", cli.bio).Start(fmt.Sprintf("%s%d", key, Pulse.Capi("level", 1)), "条件语句")
<-m.Target().Exit
Pulse.Capi("level", -1)
}
// }}}
}},
"elif": &ctx.Command{Name: "elif exp", Help: "条件语句, exp: 表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) { // {{{
if !cli.Pulse.Caps("else") {
cli.Pulse.Capi("skip", 1)
return
}
cli.Pulse.Caps("else", cli.Pulse.Caps("skip", !cli.check(arg)))
}
// }}}
}},
"else": &ctx.Command{Name: "else", Help: "条件切换", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) { // {{{
if cli.Pulse.Caps("else") {
cli.Pulse.Capi("skip", -1)
} else {
cli.Pulse.Capi("skip", 1)
}
}
// }}}
}},
"end": &ctx.Command{Name: "end", Help: "结束语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) { // {{{
cli.Pulse.Caps("exit", true)
if cli.Pulse.Has("for") && !cli.Pulse.Caps("skip") {
cli.Pulse.Caps("exit", false)
cli.pos = 0
}
cli.bio = nil
}
// }}}
}},
"for": &ctx.Command{Name: "for exp", Help: "循环语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) { // {{{
if cli.Pulse.Has("for") && cli.pos > 0 {
if m.Target(m.Source()); (cli.Has("skip") && cli.Pulse.Caps("skip")) || !cli.check(arg) {
m.Capi("skip", 1)
}
return
}
m.Log("fuck", nil, "%d %d %v", cli.pos, len(cli.lines), cli.lines)
if m.Target(m.Source()); (cli.Has("skip") && cli.Pulse.Caps("skip")) || !cli.check(arg) {
m.Add("option", "skip")
}
m.Add("option", "for", cli.Pulse.Cap("back"))
m.Put("option", "file", cli.bio).Start(fmt.Sprintf("%s%d", key, Pulse.Capi("level", 1)), "循环语句")
<-m.Target().Exit
Pulse.Capi("level", -1)
}
// }}}
}},
"function": &ctx.Command{Name: "function name", Help: "定义函数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) { // {{{
if _, ok := cli.Context.Context().Server.(*CLI); ok {
m.Target(m.Source().Context())
} else {
m.Target(m.Source())
}
m.Add("option", "skip")
m.Add("option", "save")
m.Put("option", "file", cli.bio).Start(arg[0], "定义函数")
<-m.Target().Exit
}
// }}}
}},
"call": &ctx.Command{Name: "call name arg...", Help: "定义函数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
m.Target(m.Source()) // {{{
m.BackTrace(func(msg *ctx.Message) bool {
if fun := msg.Find(arg[0], false); fun != nil {
fun.Add("detail", arg[0], arg[1:]...).Target().Start(fun)
<-fun.Target().Exit
m.Set("result", fun.Meta["result"]...)
return false
}
return true
})
// }}}
}},
}, },
} }

View File

@ -608,7 +608,13 @@ func (m *Message) Assert(e interface{}, msg ...string) bool { // {{{
return true return true
} }
if len(msg) > 0 { if len(msg) > 1 {
arg := make([]interface{}, 0, len(msg)-1)
for _, m := range msg[1:] {
arg = append(arg, m)
}
e = errors.New(fmt.Sprintf(msg[0], arg...))
} else if len(msg) > 0 {
e = errors.New(msg[0]) e = errors.New(msg[0])
} }
if _, ok := e.(error); !ok { if _, ok := e.(error); !ok {
@ -635,9 +641,7 @@ func (m *Message) AssertOne(msg *Message, safe bool, hand ...func(msg *Message))
fmt.Printf("\033[31m%s error: %v\033[0m\n\n", msg.target.Name, e) fmt.Printf("\033[31m%s error: %v\033[0m\n\n", msg.target.Name, e)
} }
if e == io.EOF { if len(hand) > 1 {
return
} else if len(hand) > 1 {
m.AssertOne(msg, safe, hand[1:]...) m.AssertOne(msg, safe, hand[1:]...)
} else if !safe { } else if !safe {
msg.Assert(e) msg.Assert(e)
@ -809,14 +813,22 @@ func (m *Message) Add(meta string, key string, value ...string) *Message { // {{
case "detail", "result": case "detail", "result":
m.Meta[meta] = append(m.Meta[meta], key) m.Meta[meta] = append(m.Meta[meta], key)
m.Meta[meta] = append(m.Meta[meta], value...) m.Meta[meta] = append(m.Meta[meta], value...)
case "option", "append": case "option", "append":
if _, ok := m.Meta[key]; !ok { if _, ok := m.Meta[key]; !ok {
m.Meta[key] = make([]string, 0, 3) m.Meta[key] = make([]string, 0, 3)
m.Meta[meta] = append(m.Meta[meta], key)
} }
m.Meta[key] = append(m.Meta[key], value...) m.Meta[key] = append(m.Meta[key], value...)
for _, v := range m.Meta[meta] {
if v == key {
return m
}
}
m.Meta[meta] = append(m.Meta[meta], key)
default: default:
m.Assert(false, "消息参数错误") m.Log("error", nil, "%s 消息参数错误", meta)
} }
return m return m
@ -824,20 +836,12 @@ func (m *Message) Add(meta string, key string, value ...string) *Message { // {{
// }}} // }}}
func (m *Message) Set(meta string, arg ...string) *Message { // {{{ func (m *Message) Set(meta string, arg ...string) *Message { // {{{
if m.Meta == nil {
m.Meta = make(map[string][]string)
}
if _, ok := m.Meta[meta]; !ok {
m.Meta[meta] = make([]string, 0, 3)
}
switch meta { switch meta {
case "detail", "result": case "detail", "result":
m.Meta[meta] = arg delete(m.Meta, meta)
case "option", "append": case "option", "append":
if len(arg) > 0 { if len(arg) > 0 {
m.Meta[meta] = []string{arg[0]} delete(m.Meta, arg[0])
m.Meta[arg[0]] = arg[1:]
} else { } else {
for _, k := range m.Meta[meta] { for _, k := range m.Meta[meta] {
delete(m.Meta, k) delete(m.Meta, k)
@ -846,7 +850,11 @@ func (m *Message) Set(meta string, arg ...string) *Message { // {{{
delete(m.Meta, meta) delete(m.Meta, meta)
} }
default: default:
m.Assert(false, "消息参数错误") m.Log("error", nil, "%s 消息参数错误", meta)
}
if len(arg) > 0 {
m.Add(meta, arg[0], arg[1:]...)
} }
return m return m
@ -863,15 +871,20 @@ func (m *Message) Put(meta string, key string, value interface{}) *Message { //
if m.Data == nil { if m.Data == nil {
m.Data = make(map[string]interface{}) m.Data = make(map[string]interface{})
} }
m.Data[key] = value
if _, ok := m.Meta[meta]; !ok { if _, ok := m.Meta[meta]; !ok {
m.Meta[meta] = make([]string, 0, 3) m.Meta[meta] = make([]string, 0, 3)
} }
if _, ok := m.Data[key]; !ok { for _, v := range m.Meta[meta] {
m.Meta[meta] = append(m.Meta[meta], key) if v == key {
return m
} }
m.Data[key] = value }
m.Meta[meta] = append(m.Meta[meta], key)
default: default:
m.Assert(false, "消息参数错误") m.Log("error", nil, "%s 消息参数错误", meta)
} }
return m return m
@ -904,15 +917,14 @@ func (m *Message) Geti(key string) int { // {{{
} }
// }}} // }}}
func (m *Message) Echo(str string, arg ...interface{}) *Message { // {{{ func (m *Message) Gets(key string) bool { // {{{
return m.Add("result", fmt.Sprintf(str, arg...)) b := m.Get(key)
return b != "" && b != "0"
} }
// }}} // }}}
func (m *Message) End(s bool) { // {{{ func (m *Message) Echo(str string, arg ...interface{}) *Message { // {{{
if m.Wait != nil { return m.Add("result", fmt.Sprintf(str, arg...))
m.Wait <- s
}
} }
// }}} // }}}
@ -962,6 +974,9 @@ func (m *Message) Exec(key string, arg ...string) string { // {{{
} }
x.Hand(m.Set("result").Set("append"), s, key, arg...) x.Hand(m.Set("result").Set("append"), s, key, arg...)
if !m.Has("result") {
m.Meta["result"] = nil
}
if x.Appends != nil { if x.Appends != nil {
for _, v := range m.Meta["append"] { for _, v := range m.Meta["append"] {
@ -981,8 +996,6 @@ func (m *Message) Exec(key string, arg ...string) string { // {{{
} }
} }
} }
m.Set("result", "error: ", "命令不存在")
return "" return ""
} }
@ -994,7 +1007,11 @@ func (m *Message) Deal(pre func(msg *Message, arg ...string) bool, post func(msg
for run := true; run; { for run := true; run; {
m.AssertOne(<-m.target.messages, true, func(msg *Message) { m.AssertOne(<-m.target.messages, true, func(msg *Message) {
defer msg.End(true) defer func() {
if msg.Wait != nil {
msg.Wait <- true
}
}()
if len(msg.Meta["detail"]) == 0 { if len(msg.Meta["detail"]) == 0 {
return return
@ -1013,22 +1030,26 @@ func (m *Message) Deal(pre func(msg *Message, arg ...string) bool, post func(msg
} }
// }}} // }}}
func (m *Message) Post(s *Context) string { // {{{ func (m *Message) Post(s *Context, async ...bool) string { // {{{
if s == nil { if s == nil {
s = m.target.master s = m.target.master
} }
m.Assert(s.messages != nil, s.Name+" 没有开启消息处理") if s != nil && s.messages != nil {
if len(async) == 0 || async[0] == false {
m.Wait = make(chan bool)
}
if s.messages <- m; m.Wait != nil { if s.messages <- m; m.Wait != nil {
<-m.Wait <-m.Wait
} }
return m.Get("result") return m.Get("result")
}
return m.Exec(m.Meta["detail"][0], m.Meta["detail"][1:]...)
} }
// }}} // }}}
func (m *Message) Cmd(arg ...string) string { // {{{ func (m *Message) Cmd(arg ...string) string { // {{{
if len(arg) > 0 { if len(arg) > 0 {
m.Set("detail", arg...) m.Set("detail", arg...)
@ -1041,6 +1062,21 @@ func (m *Message) Cmd(arg ...string) string { // {{{
return m.Exec(m.Meta["detail"][0], m.Meta["detail"][1:]...) return m.Exec(m.Meta["detail"][0], m.Meta["detail"][1:]...)
} }
// }}}
func (m *Message) Confs(key string, arg ...bool) bool { // {{{
if len(arg) > 0 {
if arg[0] {
m.Conf(key, "1")
} else {
m.Conf(key, "0")
}
}
b := m.Conf(key)
return b != "" && b != "0"
}
// }}} // }}}
func (m *Message) Confi(key string, arg ...int) int { // {{{ func (m *Message) Confi(key string, arg ...int) int { // {{{
n, e := strconv.Atoi(m.Conf(key)) n, e := strconv.Atoi(m.Conf(key))
@ -1057,6 +1093,7 @@ 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 _, c := range []*Context{m.target, m.target.master, m.target.Owner, m.source, m.source.master, m.source.Owner} { 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 { for s := c; s != nil; s = s.context {
if x, ok := s.Configs[key]; ok { if x, ok := s.Configs[key]; ok {
@ -1070,13 +1107,12 @@ func (m *Message) Conf(key string, arg ...string) string { // {{{
hand = x.Hand hand = x.Hand
} }
case 1: case 1:
m.Log("conf", s, "%s %v", key, arg)
if x.Hand != nil { if x.Hand != nil {
x.Value = x.Hand(m, x, arg[0]) x.Value = x.Hand(m, x, arg[0])
} else { } else {
x.Value = arg[0] x.Value = arg[0]
} }
m.Log("conf", s, "%s %v", x.Name, x.Value)
return x.Value return x.Value
case 0: case 0:
if x.Hand != nil { if x.Hand != nil {
@ -1102,13 +1138,30 @@ func (m *Message) Conf(key string, arg ...string) string { // {{{
return "" return ""
} }
// }}}
func (m *Message) Caps(key string, arg ...bool) bool { // {{{
if len(arg) > 0 {
if arg[0] {
m.Cap(key, "1")
} else {
m.Cap(key, "0")
}
}
b := m.Cap(key)
return b != "" && b != "0"
}
// }}} // }}}
func (m *Message) Capi(key string, arg ...int) int { // {{{ func (m *Message) Capi(key string, arg ...int) int { // {{{
n, e := strconv.Atoi(m.Cap(key)) n, e := strconv.Atoi(m.Cap(key))
m.Assert(e) m.Assert(e)
if len(arg) > 0 { for _, i := range arg {
n, e = strconv.Atoi(m.Cap(key, fmt.Sprintf("%d", arg[0]+n))) if i == 0 {
i = -n
}
n, e = strconv.Atoi(m.Cap(key, fmt.Sprintf("%d", n+i)))
m.Assert(e) m.Assert(e)
} }
@ -1118,6 +1171,7 @@ 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 _, c := range []*Context{m.target, m.target.master, m.target.Owner, m.source, m.source.master, m.source.Owner} { 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 { for s := c; s != nil; s = s.context {
if x, ok := s.Caches[key]; ok { if x, ok := s.Caches[key]; ok {
@ -1176,7 +1230,7 @@ var Index = &Context{Name: "ctx", Help: "模块中心",
"default": &Config{Name: "默认的搜索起点(root/back/home)", Value: "root", Help: "模块搜索的默认起点root:从根模块back:从父模块home:从当前模块"}, "default": &Config{Name: "默认的搜索起点(root/back/home)", Value: "root", Help: "模块搜索的默认起点root:从根模块back:从父模块home:从当前模块"},
"start": &Config{Name: "启动模块", Value: "cli", Help: "启动时自动运行的模块"}, "start": &Config{Name: "启动模块", Value: "cli", Help: "启动时自动运行的模块"},
"init.sh": &Config{Name: "启动脚本", Value: "etc/init.sh", Help: "模块启动时自动运行的脚本"}, "init.shy": &Config{Name: "启动脚本", Value: "etc/init.shy", Help: "模块启动时自动运行的脚本"},
"bench.log": &Config{Name: "日志文件", Value: "var/bench.log", Help: "模块日志输出的文件", Hand: func(m *Message, x *Config, arg ...string) string { "bench.log": &Config{Name: "日志文件", Value: "var/bench.log", Help: "模块日志输出的文件", Hand: func(m *Message, x *Config, arg ...string) string {
if len(arg) > 0 { // {{{ if len(arg) > 0 { // {{{
if e := os.MkdirAll(path.Dir(arg[0]), os.ModePerm); e == nil { if e := os.MkdirAll(path.Dir(arg[0]), os.ModePerm); e == nil {
@ -1510,6 +1564,7 @@ var Index = &Context{Name: "ctx", Help: "模块中心",
} }
return all return all
}) })
m.Assert(m.Has("result"), "%s 命令不存在", arg[0])
case 3: case 3:
cmd := &Command{} cmd := &Command{}
m.BackTrace(func(m *Message) bool { m.BackTrace(func(m *Message) bool {
@ -1686,7 +1741,7 @@ func Start(args ...string) {
Pulse.Conf("start", args[0]) Pulse.Conf("start", args[0])
} }
if len(args) > 1 { if len(args) > 1 {
Pulse.Conf("init.sh", args[1]) Pulse.Conf("init.shy", args[1])
} }
if len(args) > 2 { if len(args) > 2 {
Pulse.Conf("bench.log", args[2]) Pulse.Conf("bench.log", args[2])
@ -1705,13 +1760,11 @@ func Start(args ...string) {
m.target.root = Index m.target.root = Index
m.target.Begin(m) m.target.Begin(m)
} }
Index.Requests = append(Index.Requests, Pulse)
log.Println() log.Println()
for _, m := range Pulse.Search(Pulse.Conf("start")) { for _, m := range Pulse.Search(Pulse.Conf("start")) {
m.Set("detail", "stdout").target.Start(m) m.Set("option", "stdio").target.Start(m)
} }
for <-Pulse.Wait; Pulse.Capi("nserver") > 0; <-Pulse.Wait { <-Index.master.Exit
}
} }