forked from x/ContextOS
Merge branch '0.2.0' of https://github.com/shylinux/context
This commit is contained in:
commit
11b0ea19b7
18
etc/cert.pem
Normal file
18
etc/cert.pem
Normal 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
15
etc/key.pem
Normal 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
85
etc/shy.vim
Normal 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
|
||||
|
@ -1,40 +1,38 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
package cli // {{{
|
||||
// }}}
|
||||
import ( // {{{
|
||||
"context"
|
||||
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
"os"
|
||||
"os/exec"
|
||||
"time"
|
||||
|
||||
"regexp"
|
||||
)
|
||||
|
||||
// }}}
|
||||
|
||||
type CLI struct {
|
||||
bio *bufio.Reader
|
||||
out io.WriteCloser
|
||||
|
||||
which int
|
||||
lines []string
|
||||
pos int
|
||||
|
||||
alias map[string]string
|
||||
lex *ctx.Message
|
||||
|
||||
alias map[string][]string
|
||||
target *ctx.Context
|
||||
wait *ctx.Context
|
||||
exit bool
|
||||
test bool
|
||||
save bool
|
||||
|
||||
*ctx.Context
|
||||
}
|
||||
|
||||
func (cli *CLI) echo(str string, arg ...interface{}) bool {
|
||||
func (cli *CLI) print(str string, arg ...interface{}) bool { // {{{
|
||||
if cli.out != nil {
|
||||
fmt.Fprintf(cli.out, str, arg...)
|
||||
return true
|
||||
@ -42,127 +40,267 @@ func (cli *CLI) echo(str string, arg ...interface{}) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (cli *CLI) parse(m *ctx.Message) bool {
|
||||
// }}}
|
||||
func (cli *CLI) parse(m *ctx.Message) (cmd []string) { // {{{
|
||||
|
||||
line := m.Cap("next")
|
||||
if line == "" {
|
||||
if m.Cap("level") == "0" {
|
||||
cli.echo(m.Conf("PS1"))
|
||||
}
|
||||
if m.Cap("next", ""); line == "" {
|
||||
|
||||
if cli.bio == nil {
|
||||
if cli.which == len(cli.lines) {
|
||||
cli.exit = true
|
||||
cli.which = 0
|
||||
m.Spawn(cli.Context).Set("detail", "end").Post(cli.Context)
|
||||
return false
|
||||
}
|
||||
line = cli.lines[cli.which]
|
||||
cli.which++
|
||||
line = cli.lines[cli.pos]
|
||||
cli.pos++
|
||||
} else {
|
||||
cli.print(m.Conf("PS1"))
|
||||
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)
|
||||
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")
|
||||
m.Cap("back", "")
|
||||
}
|
||||
if len(line) == 0 || line[0] == '#' {
|
||||
return true
|
||||
return nil
|
||||
}
|
||||
|
||||
ls := []string{}
|
||||
if cli.lex == nil {
|
||||
ls = strings.Split(line, " ")
|
||||
} else {
|
||||
lex := m.Spawn(cli.lex.Target())
|
||||
m.Assert(lex.Cmd("split", line, "void"))
|
||||
ls = lex.Meta["result"]
|
||||
}
|
||||
|
||||
msg := m.Spawn(cli.target)
|
||||
|
||||
cs := []string{}
|
||||
for i := 0; i < len(ls); i++ {
|
||||
if cli.lex == nil {
|
||||
if ls[i] = strings.TrimSpace(ls[i]); ls[i] == "" {
|
||||
continue
|
||||
}
|
||||
if ls[i][0] == '#' {
|
||||
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 c, ok := cli.alias[string(r)]; ok {
|
||||
if i == 0 {
|
||||
if msg.Add("detail", c); len(ls[i]) == 1 {
|
||||
continue
|
||||
ns := []string{}
|
||||
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:]
|
||||
} else if len(ls[i]) > 1 && !cli.test {
|
||||
ls = ns
|
||||
} else if len(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)
|
||||
m.Assert(msg.Exec(c, key))
|
||||
if r == rune(key[0]) {
|
||||
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")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
msg.Add("detail", ls[i])
|
||||
}
|
||||
|
||||
msg.Wait = make(chan bool)
|
||||
msg.Post(cli.Context)
|
||||
|
||||
if msg.Target().Context() != nil || msg.Target() == ctx.Index {
|
||||
cli.target = msg.Target()
|
||||
if c, ok := cli.alias[ls[i]]; ok && i == 0 {
|
||||
ns := []string{}
|
||||
ns = append(ns, c...)
|
||||
ns = append(ns, ls[1:]...)
|
||||
}
|
||||
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 {
|
||||
cli.lines = append(cli.lines, line)
|
||||
cs = append(cs, ls[i])
|
||||
}
|
||||
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.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.Context = c
|
||||
s.lex = cli.lex
|
||||
s.alias = cli.alias
|
||||
s.lines = cli.lines[cli.pos:]
|
||||
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["result"] = &ctx.Cache{Name: "前一条指令执行结果", Value: "", Help: "前一条指令执行结果"}
|
||||
cli.Caches["back"] = &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 {
|
||||
if len(arg) > 0 { // {{{
|
||||
@ -228,7 +366,7 @@ func (cli *CLI) Begin(m *ctx.Message, arg ...string) ctx.Server {
|
||||
}}
|
||||
|
||||
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 {
|
||||
@ -236,57 +374,44 @@ func (cli *CLI) Begin(m *ctx.Message, arg ...string) ctx.Server {
|
||||
}
|
||||
|
||||
cli.target = cli.Context
|
||||
cli.alias = map[string]string{
|
||||
"~": "context",
|
||||
"!": "message",
|
||||
"@": "config",
|
||||
"$": "cache",
|
||||
"&": "server",
|
||||
":": "command",
|
||||
cli.alias = map[string][]string{
|
||||
"~": []string{"context"},
|
||||
"!": []string{"message"},
|
||||
"@": []string{"config"},
|
||||
"$": []string{"cache"},
|
||||
"&": []string{"server"},
|
||||
":": []string{"command"},
|
||||
}
|
||||
|
||||
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.exit = false
|
||||
cli.test = false
|
||||
cli.Context.Exit = make(chan bool)
|
||||
|
||||
if stream, ok := m.Data["io"]; ok {
|
||||
cli.Context.Master(cli.Context)
|
||||
io := stream.(io.ReadWriteCloser)
|
||||
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
|
||||
cli.Caches["#"] = &ctx.Cache{Name: "前一条指令", Value: fmt.Sprintf("%d", len(arg)), Help: "前一条指令"}
|
||||
for i, v := range arg {
|
||||
cli.Caches[fmt.Sprintf("%d", i)] = &ctx.Cache{Name: "前一条指令", Value: v, Help: "前一条指令"}
|
||||
}
|
||||
|
||||
if cli.Sessions == nil {
|
||||
cli.Sessions = make(map[string]*ctx.Message)
|
||||
m.Caps("exit", false)
|
||||
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("next", "source "+m.Conf("init.sh"))
|
||||
m.Cap("next", "source "+m.Conf("init.shy"))
|
||||
cli.bio = bufio.NewReader(os.Stdin)
|
||||
cli.out = os.Stdout
|
||||
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")
|
||||
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) {
|
||||
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)
|
||||
defer m.Capi("nterm", -1)
|
||||
|
||||
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
|
||||
return !cli.Has("skip") || !m.Caps("skip") || Index.Has(msg.Get("detail"), "command")
|
||||
|
||||
}, func(msg *ctx.Message, arg ...string) bool {
|
||||
if msg.Get("result") == "error: " {
|
||||
if msg.Get("detail") != "login" {
|
||||
if cli.Has("skip") && m.Caps("skip") {
|
||||
return !m.Caps("exit")
|
||||
}
|
||||
|
||||
if !msg.Has("result") && cli.Owner == ctx.Index.Owner {
|
||||
msg.Log("system", nil, "%v", msg.Meta["detail"])
|
||||
|
||||
msg.Set("result")
|
||||
msg.Set("append")
|
||||
msg.Set("result").Set("append")
|
||||
c := exec.Command(msg.Meta["detail"][0], msg.Meta["detail"][1:]...)
|
||||
|
||||
if cli.out == os.Stdout {
|
||||
c.Stdin, c.Stdout, c.Stderr = os.Stdin, os.Stdout, os.Stderr
|
||||
msg.Assert(c.Start())
|
||||
msg.Assert(c.Wait())
|
||||
if e := c.Start(); e != nil {
|
||||
msg.Echo("error: ")
|
||||
msg.Echo("%s\n", e)
|
||||
} else if e := c.Wait(); e != nil {
|
||||
msg.Echo("error: ")
|
||||
msg.Echo("%s\n", e)
|
||||
}
|
||||
} else {
|
||||
if out, e := c.CombinedOutput(); e == nil {
|
||||
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 {
|
||||
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 {
|
||||
case m.Target():
|
||||
if m.Target() == Index && m.Capi("nserver") > 1 {
|
||||
return false
|
||||
if p, ok := cli.Context.Context().Server.(*CLI); ok {
|
||||
if p.bio != nil {
|
||||
p.lines = append(p.lines, cli.lines...)
|
||||
} else {
|
||||
p.pos += cli.pos
|
||||
}
|
||||
}
|
||||
case m.Source():
|
||||
if m.Name == "aaa" {
|
||||
@ -369,205 +520,177 @@ 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{
|
||||
"nterm": &ctx.Cache{Name: "终端数量", Value: "0", Help: "已经运行的终端数量"},
|
||||
"nterm": &ctx.Cache{Name: "终端数量", Value: "0", Help: "正在运行的终端数量"},
|
||||
},
|
||||
Configs: map[string]*ctx.Config{},
|
||||
Commands: map[string]*ctx.Command{
|
||||
"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)
|
||||
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)
|
||||
"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) {
|
||||
cli, ok := m.Target().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) {
|
||||
case 0:
|
||||
for k, v := range cli.alias {
|
||||
m.Echo("%s: %s\n", k, v)
|
||||
m.Echo("%s: %v\n", k, v)
|
||||
}
|
||||
case 2:
|
||||
switch arg[0] {
|
||||
case "delete":
|
||||
case 1:
|
||||
m.Echo("%s: %v\n", arg[0], cli.alias[arg[0]])
|
||||
default:
|
||||
if arg[0] == "delete" {
|
||||
m.Echo("delete: %s %v\n", arg[1], cli.alias[arg[1]])
|
||||
delete(cli.alias, arg[1])
|
||||
default:
|
||||
cli.alias[arg[0]] = arg[1]
|
||||
m.Echo("%s: %s\n", arg[0], cli.alias[arg[0]])
|
||||
} else {
|
||||
cli.alias[arg[0]] = arg[1:]
|
||||
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: "建立远程连接",
|
||||
// Formats: map[string]int{"send": -1, "master": 0, "slaver": 0, "listen": 1, "dial": 1},
|
||||
// Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||
// action := "dial" // {{{
|
||||
// if m.Has("listen") {
|
||||
// action = "listen"
|
||||
// }
|
||||
//
|
||||
// msg := m.Find(m.Get("args"), true)
|
||||
//
|
||||
// if m.Has("master") {
|
||||
// msg.Template = msg.Spawn(msg.Source()).Add("option", "master")
|
||||
// }
|
||||
// msg.Cmd(action, m.Get(action))
|
||||
//
|
||||
// }}, // }}}
|
||||
// "open": &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) {
|
||||
// m.Start(fmt.Sprintf("PTS%d", m.Capi("nterm")), "管理终端", "void.sh") // {{{
|
||||
// // }}}
|
||||
// }},
|
||||
// "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) {
|
||||
// _, ok := c.Server.(*CLI) // {{{
|
||||
// m.Assert(ok, "模块类型错误")
|
||||
// m.Assert(m.Target() != c, "模块是主控模块")
|
||||
//
|
||||
// msg := m.Spawn(c)
|
||||
// msg.Start(fmt.Sprintf("PTS%d", Pulse.Capi("nterm")), arg[0], arg[1:]...)
|
||||
// // }}}
|
||||
// }},
|
||||
},
|
||||
Index: map[string]*ctx.Context{
|
||||
"void": &ctx.Context{Name: "void",
|
||||
Commands: map[string]*ctx.Command{
|
||||
"open": &ctx.Command{},
|
||||
},
|
||||
},
|
||||
"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) {
|
||||
if cli, ok := m.Source().Server.(*CLI); m.Assert(ok) && (!cli.Has("skip") || !cli.Pulse.Caps("skip")) { // {{{
|
||||
if d, e := time.ParseDuration(arg[0]); m.Assert(e) {
|
||||
m.Log("info", nil, "sleep %v", d)
|
||||
time.Sleep(d)
|
||||
m.Log("info", nil, "sleep %v done", d)
|
||||
}
|
||||
}
|
||||
// }}}
|
||||
}},
|
||||
"var": &ctx.Command{Name: "var a [= exp]", Help: "定义变量, a: 变量名, exp: 表达式", 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")) { // {{{
|
||||
val := ""
|
||||
if len(arg) > 2 {
|
||||
val = cli.express(arg[2:])
|
||||
}
|
||||
cli.Pulse.Cap(arg[0], arg[0], val, "临时变量")
|
||||
}
|
||||
// }}}
|
||||
}},
|
||||
"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")) { // {{{
|
||||
m.Echo(cli.Pulse.Cap(arg[0], cli.express(arg[2:])))
|
||||
}
|
||||
// }}}
|
||||
}},
|
||||
"source": &ctx.Command{Name: "source file", Help: "运行脚本, file: 脚本文件名", 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")) { // {{{
|
||||
if 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: "结束脚本, rusult: 返回值", 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")) { // {{{
|
||||
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
|
||||
})
|
||||
// }}}
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -608,7 +608,13 @@ func (m *Message) Assert(e interface{}, msg ...string) bool { // {{{
|
||||
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])
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
if e == io.EOF {
|
||||
return
|
||||
} else if len(hand) > 1 {
|
||||
if len(hand) > 1 {
|
||||
m.AssertOne(msg, safe, hand[1:]...)
|
||||
} else if !safe {
|
||||
msg.Assert(e)
|
||||
@ -809,14 +813,22 @@ func (m *Message) Add(meta string, key string, value ...string) *Message { // {{
|
||||
case "detail", "result":
|
||||
m.Meta[meta] = append(m.Meta[meta], key)
|
||||
m.Meta[meta] = append(m.Meta[meta], value...)
|
||||
|
||||
case "option", "append":
|
||||
if _, ok := m.Meta[key]; !ok {
|
||||
m.Meta[key] = make([]string, 0, 3)
|
||||
m.Meta[meta] = append(m.Meta[meta], key)
|
||||
}
|
||||
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:
|
||||
m.Assert(false, "消息参数错误")
|
||||
m.Log("error", nil, "%s 消息参数错误", meta)
|
||||
}
|
||||
|
||||
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 { // {{{
|
||||
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 {
|
||||
case "detail", "result":
|
||||
m.Meta[meta] = arg
|
||||
delete(m.Meta, meta)
|
||||
case "option", "append":
|
||||
if len(arg) > 0 {
|
||||
m.Meta[meta] = []string{arg[0]}
|
||||
m.Meta[arg[0]] = arg[1:]
|
||||
delete(m.Meta, arg[0])
|
||||
} else {
|
||||
for _, k := range m.Meta[meta] {
|
||||
delete(m.Meta, k)
|
||||
@ -846,7 +850,11 @@ func (m *Message) Set(meta string, arg ...string) *Message { // {{{
|
||||
delete(m.Meta, meta)
|
||||
}
|
||||
default:
|
||||
m.Assert(false, "消息参数错误")
|
||||
m.Log("error", nil, "%s 消息参数错误", meta)
|
||||
}
|
||||
|
||||
if len(arg) > 0 {
|
||||
m.Add(meta, arg[0], arg[1:]...)
|
||||
}
|
||||
|
||||
return m
|
||||
@ -863,15 +871,20 @@ func (m *Message) Put(meta string, key string, value interface{}) *Message { //
|
||||
if m.Data == nil {
|
||||
m.Data = make(map[string]interface{})
|
||||
}
|
||||
m.Data[key] = value
|
||||
|
||||
if _, ok := m.Meta[meta]; !ok {
|
||||
m.Meta[meta] = make([]string, 0, 3)
|
||||
}
|
||||
if _, ok := m.Data[key]; !ok {
|
||||
m.Meta[meta] = append(m.Meta[meta], key)
|
||||
for _, v := range m.Meta[meta] {
|
||||
if v == key {
|
||||
return m
|
||||
}
|
||||
m.Data[key] = value
|
||||
}
|
||||
m.Meta[meta] = append(m.Meta[meta], key)
|
||||
|
||||
default:
|
||||
m.Assert(false, "消息参数错误")
|
||||
m.Log("error", nil, "%s 消息参数错误", meta)
|
||||
}
|
||||
|
||||
return m
|
||||
@ -904,15 +917,14 @@ func (m *Message) Geti(key string) int { // {{{
|
||||
}
|
||||
|
||||
// }}}
|
||||
func (m *Message) Echo(str string, arg ...interface{}) *Message { // {{{
|
||||
return m.Add("result", fmt.Sprintf(str, arg...))
|
||||
func (m *Message) Gets(key string) bool { // {{{
|
||||
b := m.Get(key)
|
||||
return b != "" && b != "0"
|
||||
}
|
||||
|
||||
// }}}
|
||||
func (m *Message) End(s bool) { // {{{
|
||||
if m.Wait != nil {
|
||||
m.Wait <- s
|
||||
}
|
||||
func (m *Message) Echo(str string, arg ...interface{}) *Message { // {{{
|
||||
return m.Add("result", fmt.Sprintf(str, arg...))
|
||||
}
|
||||
|
||||
// }}}
|
||||
@ -962,6 +974,9 @@ func (m *Message) Exec(key string, arg ...string) string { // {{{
|
||||
}
|
||||
|
||||
x.Hand(m.Set("result").Set("append"), s, key, arg...)
|
||||
if !m.Has("result") {
|
||||
m.Meta["result"] = nil
|
||||
}
|
||||
|
||||
if x.Appends != nil {
|
||||
for _, v := range m.Meta["append"] {
|
||||
@ -981,8 +996,6 @@ func (m *Message) Exec(key string, arg ...string) string { // {{{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m.Set("result", "error: ", "命令不存在")
|
||||
return ""
|
||||
}
|
||||
|
||||
@ -994,7 +1007,11 @@ func (m *Message) Deal(pre func(msg *Message, arg ...string) bool, post func(msg
|
||||
|
||||
for run := true; run; {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
<-m.Wait
|
||||
}
|
||||
|
||||
return m.Get("result")
|
||||
}
|
||||
|
||||
return m.Exec(m.Meta["detail"][0], m.Meta["detail"][1:]...)
|
||||
}
|
||||
|
||||
// }}}
|
||||
|
||||
func (m *Message) Cmd(arg ...string) string { // {{{
|
||||
if len(arg) > 0 {
|
||||
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:]...)
|
||||
}
|
||||
|
||||
// }}}
|
||||
|
||||
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 { // {{{
|
||||
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 { // {{{
|
||||
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 s := c; s != nil; s = s.context {
|
||||
if x, ok := s.Configs[key]; ok {
|
||||
@ -1070,13 +1107,12 @@ func (m *Message) Conf(key string, arg ...string) string { // {{{
|
||||
hand = x.Hand
|
||||
}
|
||||
case 1:
|
||||
m.Log("conf", s, "%s %v", key, arg)
|
||||
|
||||
if x.Hand != nil {
|
||||
x.Value = x.Hand(m, x, arg[0])
|
||||
} else {
|
||||
x.Value = arg[0]
|
||||
}
|
||||
m.Log("conf", s, "%s %v", x.Name, x.Value)
|
||||
return x.Value
|
||||
case 0:
|
||||
if x.Hand != nil {
|
||||
@ -1102,13 +1138,30 @@ func (m *Message) Conf(key string, arg ...string) string { // {{{
|
||||
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 { // {{{
|
||||
n, e := strconv.Atoi(m.Cap(key))
|
||||
m.Assert(e)
|
||||
|
||||
if len(arg) > 0 {
|
||||
n, e = strconv.Atoi(m.Cap(key, fmt.Sprintf("%d", arg[0]+n)))
|
||||
for _, i := range arg {
|
||||
if i == 0 {
|
||||
i = -n
|
||||
}
|
||||
n, e = strconv.Atoi(m.Cap(key, fmt.Sprintf("%d", n+i)))
|
||||
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 { // {{{
|
||||
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 s := c; s != nil; s = s.context {
|
||||
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:从当前模块"},
|
||||
|
||||
"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 {
|
||||
if len(arg) > 0 { // {{{
|
||||
if e := os.MkdirAll(path.Dir(arg[0]), os.ModePerm); e == nil {
|
||||
@ -1510,6 +1564,7 @@ var Index = &Context{Name: "ctx", Help: "模块中心",
|
||||
}
|
||||
return all
|
||||
})
|
||||
m.Assert(m.Has("result"), "%s 命令不存在", arg[0])
|
||||
case 3:
|
||||
cmd := &Command{}
|
||||
m.BackTrace(func(m *Message) bool {
|
||||
@ -1686,7 +1741,7 @@ func Start(args ...string) {
|
||||
Pulse.Conf("start", args[0])
|
||||
}
|
||||
if len(args) > 1 {
|
||||
Pulse.Conf("init.sh", args[1])
|
||||
Pulse.Conf("init.shy", args[1])
|
||||
}
|
||||
if len(args) > 2 {
|
||||
Pulse.Conf("bench.log", args[2])
|
||||
@ -1705,13 +1760,11 @@ func Start(args ...string) {
|
||||
m.target.root = Index
|
||||
m.target.Begin(m)
|
||||
}
|
||||
Index.Requests = append(Index.Requests, Pulse)
|
||||
log.Println()
|
||||
|
||||
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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user