1
0
mirror of https://shylinux.com/x/ContextOS synced 2025-04-26 01:04:06 +08:00
This commit is contained in:
shaoying 2019-01-07 15:21:56 +08:00
parent 55fefaf130
commit dc791f2519
7 changed files with 984 additions and 1062 deletions

View File

@ -27,13 +27,11 @@ type Frame struct {
list []string
}
type CLI struct {
alias map[string][]string
label map[string]string
target *ctx.Context
stack []*Frame
label map[string]string
stack []*Frame
*time.Timer
*ctx.Context
Context *ctx.Context
}
func (cli *CLI) schedule(m *ctx.Message) string {
@ -50,74 +48,16 @@ func (cli *CLI) schedule(m *ctx.Message) string {
func (cli *CLI) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server {
c.Caches = map[string]*ctx.Cache{
"level": &ctx.Cache{Name: "level", Value: "0", Help: "嵌套层级"},
"parse": &ctx.Cache{Name: "parse(true/false)", Value: "true", Help: "命令解析"},
"last_msg": &ctx.Cache{Name: "last_msg", Value: "0", Help: "前一条消息"},
"ps_count": &ctx.Cache{Name: "ps_count", Value: "0", Help: "命令计数"},
"ps_target": &ctx.Cache{Name: "ps_target", Value: c.Name, Help: "当前模块", Hand: func(m *ctx.Message, x *ctx.Cache, arg ...string) string {
if len(arg) > 0 {
if cli, ok := m.Target().Server.(*CLI); ok {
if msg := m.Find(arg[0]); msg != nil {
cli.target = msg.Target()
return arg[0]
}
}
}
return x.Value
}},
}
c.Configs = map[string]*ctx.Config{
"ps_time": &ctx.Config{Name: "ps_time", Value: "[15:04:05]", Help: "当前时间", Hand: func(m *ctx.Message, x *ctx.Config, arg ...string) string {
if len(arg) > 0 {
return arg[0]
}
return time.Now().Format(x.Value.(string))
}},
"ps_end": &ctx.Config{Name: "ps_end", Value: "> ", Help: "命令行提示符结尾"},
"prompt": &ctx.Config{Name: "prompt(ps_count/ps_time/ps_target/ps_end/...)", Value: "ps_count ps_time ps_target ps_end", Help: "命令行提示符, 以空格分隔, 依次显示缓存或配置信息", Hand: func(m *ctx.Message, x *ctx.Config, arg ...string) string {
if len(arg) > 0 {
return arg[0]
}
ps := make([]string, 0, 3)
for _, v := range strings.Split(x.Value.(string), " ") {
if m.Conf(v) != "" {
ps = append(ps, m.Conf(v))
} else {
ps = append(ps, m.Cap(v))
}
}
return strings.Join(ps, "")
}},
"level": &ctx.Cache{Name: "level", Value: "0", Help: "嵌套层级"},
"parse": &ctx.Cache{Name: "parse(true/false)", Value: "true", Help: "命令解析"},
}
s := new(CLI)
s.Context = c
s.target = c
s.alias = map[string][]string{
"~": []string{"context"},
"!": []string{"message"},
":": []string{"command"},
"::": []string{"command", "list"},
"pwd": []string{"nfs.pwd"},
"path": []string{"nfs.path"},
"dir": []string{"nfs.dir"},
"git": []string{"nfs.git"},
"brow": []string{"web.brow"},
}
return s
return &CLI{Context: c}
}
func (cli *CLI) Begin(m *ctx.Message, arg ...string) ctx.Server {
cli.target = m.Target()
return cli
}
func (cli *CLI) Start(m *ctx.Message, arg ...string) bool {
m.Optionv("ps_target", cli.target)
m.Option("prompt", m.Conf("prompt"))
m.Cap("stream", m.Spawn(m.Sess("yac", false).Target()).Call(func(cmd *ctx.Message) *ctx.Message {
if !m.Caps("parse") {
switch cmd.Detail(0) {
@ -132,12 +72,14 @@ func (cli *CLI) Start(m *ctx.Message, arg ...string) bool {
}
}
if m.Option("prompt", cmd.Cmd().Conf("prompt")); cmd.Has("return") {
kit.Log("error", "waht ?????")
if cmd.Cmd(); cmd.Has("return") {
m.Options("scan_end", true)
m.Target().Close(m)
}
m.Optionv("ps_target", cli.target)
m.Optionv("ps_target", cmd.Optionv("ps_target"))
m.Set("append").Copy(cmd, "append")
m.Set("result").Copy(cmd, "result")
return nil
}, "scan", arg).Target().Name)
@ -148,8 +90,6 @@ func (cli *CLI) Close(m *ctx.Message, arg ...string) bool {
case m.Target():
case m.Source():
}
msg := cli.Message()
msg.Append("last_target", msg.Cap("ps_target"))
return true
}
@ -160,13 +100,24 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
Configs: map[string]*ctx.Config{
"init_shy": &ctx.Config{Name: "init_shy", Value: "etc/init.shy", Help: "启动脚本"},
"exit_shy": &ctx.Config{Name: "exit_shy", Value: "etc/exit.shy", Help: "启动脚本"},
"time_unit": &ctx.Config{Name: "time_unit", Value: "1000", Help: "时间倍数"},
"time_close": &ctx.Config{Name: "time_close(open/close)", Value: "open", Help: "时间区间"},
"cmd_script": &ctx.Config{Name: "cmd_script", Value: map[string]interface{}{
"sh": "bash", "shy": "source", "py": "python",
}, Help: "系统命令超时"},
"alias": &ctx.Config{Name: "alias", Value: map[string]interface{}{
"~": []string{"context"},
"!": []string{"message"},
":": []string{"command"},
"::": []string{"command", "list"},
"pwd": []string{"nfs.pwd"},
"path": []string{"nfs.path"},
"dir": []string{"nfs.dir"},
"git": []string{"nfs.git"},
"brow": []string{"web.brow"},
}, Help: "启动脚本"},
"time_unit": &ctx.Config{Name: "time_unit", Value: "1000", Help: "时间倍数"},
"time_close": &ctx.Config{Name: "time_close(open/close)", Value: "open", Help: "时间区间"},
"source_list": &ctx.Config{Name: "source_list", Value: []interface{}{}, Help: "系统命令超时"},
"system_env": &ctx.Config{Name: "system_env", Value: map[string]interface{}{}, Help: "系统命令超时"},
@ -184,198 +135,187 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
"alias": &ctx.Command{Name: "alias [short [long...]]|[delete short]|[import module [command [alias]]]",
Help: "查看、定义或删除命令别名, short: 命令别名, long: 命令原名, delete: 删除别名, import导入模块所有命令",
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) {
switch len(arg) {
case 0:
for k, v := range cli.alias {
m.Echo("%s: %v\n", k, v)
switch len(arg) {
case 0:
m.Cmdy("ctx.config", "alias")
case 1:
m.Cmdy("ctx.config", "alias", arg[0])
default:
switch arg[0] {
case "delete":
alias := m.Confm("alias")
m.Echo("delete: %s %v\n", arg[1], alias[arg[1]])
delete(alias, arg[1])
case "import":
msg := m.Find(arg[1], false)
if msg == nil {
msg = m.Find(arg[1], true)
}
if msg == nil {
m.Echo("%s not exist", arg[1])
return
}
module := msg.Cap("module")
for k, _ := range msg.Target().Commands {
if len(k) > 0 && k[0] == '/' {
continue
}
if len(arg) == 2 {
m.Confv("alias", k, []string{module + "." + k})
m.Log("info", "import %s.%s", module, k)
continue
}
if key := k; k == arg[2] {
if len(arg) > 3 {
key = arg[3]
}
m.Confv("alias", key, []string{module + "." + k})
m.Log("info", "import %s.%s as %s", module, k, key)
break
}
}
case 1:
m.Echo("%s: %v\n", arg[0], cli.alias[arg[0]])
default:
switch arg[0] {
case "delete":
m.Echo("delete: %s %v\n", arg[1], cli.alias[arg[1]])
delete(cli.alias, arg[1])
case "import":
msg := m.Find(arg[1], false)
if msg == nil {
msg = m.Find(arg[1], true)
}
if msg == nil {
m.Echo("%s not exist", arg[1])
return
}
m.Log("info", "import %s", arg[1])
module := msg.Cap("module")
for k, _ := range msg.Target().Commands {
if len(k) > 0 && k[0] == '/' {
continue
}
if len(arg) == 2 {
cli.alias[k] = []string{module + "." + k}
continue
}
if key := k; k == arg[2] {
if len(arg) > 3 {
key = arg[3]
}
cli.alias[key] = []string{module + "." + k}
break
}
}
default:
cli.alias[arg[0]] = arg[1:]
m.Echo("%s: %v\n", arg[0], cli.alias[arg[0]])
m.Log("info", "%s: %v", arg[0], cli.alias[arg[0]])
}
m.Confv("alias", arg[0], arg[1:])
m.Log("info", "%s: %v", arg[0], arg[1:])
}
}
return
}},
"cmd": &ctx.Command{Name: "cmd word", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) {
detail := []string{}
if a, ok := cli.alias[arg[0]]; ok {
detail = append(detail, a...)
detail = append(detail, arg[1:]...)
"cmd": &ctx.Command{Name: "cmd word", Help: "解析命令", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
// 解析别名
detail := []string{}
if alias, ok := m.Confv("alias", arg[0]).([]string); ok {
detail, arg = append(detail, alias...), arg[1:]
}
detail = append(detail, arg...)
// 目标切换
if detail[0] != "context" {
target := m.Optionv("ps_target")
defer func() { m.Optionv("ps_target", target) }()
}
// 解析脚本
msg := m
for k, v := range m.Confv("cmd_script").(map[string]interface{}) {
if strings.HasSuffix(detail[0], "."+k) {
msg = m.Spawn(m.Optionv("ps_target"))
detail[0] = m.Cmdx("nfs.path", detail[0])
detail = append([]string{v.(string)}, detail...)
break
}
}
// 解析路由
if msg == m {
if routes := strings.Split(detail[0], "."); len(routes) > 1 {
route := strings.Join(routes[:len(routes)-1], ".")
if msg = m.Find(route, false); msg == nil {
msg = m.Find(route, true)
}
if msg == nil {
m.Echo("%s not exist", route)
return
}
detail[0] = routes[len(routes)-1]
} else {
detail = append(detail, arg...)
msg = m.Spawn(m.Optionv("ps_target"))
}
}
msg.Copy(m, "option").Copy(m, "append")
if detail[0] != "context" {
target := m.Cap("ps_target")
defer func() {
m.Cap("ps_target", target)
}()
}
msg := m
for k, v := range m.Confv("cmd_script").(map[string]interface{}) {
if strings.HasSuffix(detail[0], "."+k) {
detail[0] = m.Sess("nfs").Cmd("path", detail[0]).Result(0)
detail = append([]string{v.(string)}, detail...)
msg = m.Spawn(cli.target)
// 解析命令
args, rest := []string{}, []string{}
exports := []map[string]string{}
exec, execexec := true, false
for i := 0; i < len(detail); i++ {
switch detail[i] {
case "?":
if !kit.Right(detail[i+1]) {
return
}
i++
case "??":
exec = false
execexec = execexec || kit.Right(detail[i+1])
i++
case "<":
m.Cmdy("nfs.import", detail[i+1])
i++
case ">":
exports = append(exports, map[string]string{"file": detail[i+1]})
i++
case ">$":
if i == len(detail)-2 {
exports = append(exports, map[string]string{"cache": detail[i+1], "index": "result"})
i += 1
break
}
}
if msg == m {
if routes := strings.Split(detail[0], "."); len(routes) > 1 {
route := strings.Join(routes[:len(routes)-1], ".")
if msg = m.Find(route, false); msg == nil {
msg = m.Find(route, true)
}
if msg == nil {
m.Echo("%s not exist", route)
return
}
detail[0] = routes[len(routes)-1]
} else {
msg = m.Spawn(cli.target)
exports = append(exports, map[string]string{"cache": detail[i+1], "index": detail[i+2]})
i += 2
case ">@":
if i == len(detail)-2 {
exports = append(exports, map[string]string{"config": detail[i+1], "index": "result"})
i += 1
break
}
exports = append(exports, map[string]string{"config": detail[i+1], "index": detail[i+2]})
i += 2
case "|":
detail, rest = detail[:i], detail[i+1:]
case "%":
rest = append(rest, "select")
detail, rest = detail[:i], append(rest, detail[i+1:]...)
default:
args = append(args, detail[i])
}
msg.Copy(m, "append")
msg.Copy(m, "option")
args := []string{}
rest := []string{}
exec := true
execexec := false
exports := []map[string]string{}
for i := 0; i < len(detail); i++ {
switch detail[i] {
case "?":
if !kit.Right(detail[i+1]) {
return
}
i++
case "??":
exec = false
execexec = execexec || kit.Right(detail[i+1])
i++
case "<":
pipe := m.Sess("nfs").Cmd("import", detail[i+1])
msg.Copy(pipe, "append")
i++
case ">":
exports = append(exports, map[string]string{"file": detail[i+1]})
i++
case ">$":
if i == len(detail)-2 {
exports = append(exports, map[string]string{"cache": detail[i+1], "index": "result"})
i += 1
break
}
exports = append(exports, map[string]string{"cache": detail[i+1], "index": detail[i+2]})
i += 2
case ">@":
if i == len(detail)-2 {
exports = append(exports, map[string]string{"config": detail[i+1], "index": "result"})
i += 1
break
}
exports = append(exports, map[string]string{"config": detail[i+1], "index": detail[i+2]})
i += 2
case "|":
detail, rest = detail[:i], detail[i+1:]
case "%":
rest = append(rest, "select")
detail, rest = detail[:i], append(rest, detail[i+1:]...)
default:
args = append(args, detail[i])
}
}
if !exec && !execexec {
return
}
detail = args
msg.Set("detail", detail)
if msg.Cmd(); msg.Hand {
m.Cap("ps_target", msg.Cap("module"))
} else {
msg.Copy(m, "target").Copy(m, "result").Detail(-1, "system")
msg.Cmd()
}
for _, v := range exports {
if v["file"] != "" {
m.Sess("nfs").Copy(msg, "option").Copy(msg, "append").Copy(msg, "result").Cmd("export", v["file"])
}
if v["cache"] != "" {
if v["index"] == "result" {
m.Cap(v["cache"], strings.Join(msg.Meta["result"], ""))
} else {
m.Cap(v["cache"], msg.Append(v["index"]))
}
}
if v["config"] != "" {
if v["index"] == "result" {
m.Conf(v["config"], strings.Join(msg.Meta["result"], ""))
} else {
m.Conf(v["config"], msg.Append(v["index"]))
}
}
}
if len(rest) > 0 {
pipe := m.Spawn().Copy(msg, "option").Copy(msg, "append").Copy(msg, "result").Cmd("cmd", rest)
msg.Set("result").Set("append")
msg.Copy(pipe, "result").Copy(pipe, "append")
}
m.Target().Message().Set("result").Set("append").Copy(msg, "result").Copy(msg, "append")
m.Set("append").Copy(msg, "append")
m.Set("result").Copy(msg, "result")
// m.Capi("last_msg", 0, msg.Code())
// m.Capi("ps_count", 1)
}
if !exec && !execexec {
return
}
// 执行命令
if msg.Set("detail", args).Cmd(); !msg.Hand {
msg.Cmd("system", args)
}
// 管道命令
if len(rest) > 0 {
pipe := m.Spawn().Copy(msg, "option")
pipe.Copy(msg, "append").Copy(msg, "result").Cmd("cmd", rest)
msg.Set("append").Copy(pipe, "append")
msg.Set("result").Copy(pipe, "result")
}
// 导出结果
for _, v := range exports {
if v["file"] != "" {
m.Sess("nfs").Copy(msg, "option").Copy(msg, "append").Copy(msg, "result").Cmd("export", v["file"])
}
if v["cache"] != "" {
if v["index"] == "result" {
m.Cap(v["cache"], strings.Join(msg.Meta["result"], ""))
} else {
m.Cap(v["cache"], msg.Append(v["index"]))
}
}
if v["config"] != "" {
if v["index"] == "result" {
m.Conf(v["config"], strings.Join(msg.Meta["result"], ""))
} else {
m.Conf(v["config"], msg.Append(v["index"]))
}
}
}
// 返回结果
m.Optionv("ps_target", msg.Target())
m.Set("append").Copy(msg, "append")
m.Set("result").Copy(msg, "result")
return
}},
"str": &ctx.Command{Name: "str word", Help: "解析字符串", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
@ -383,33 +323,30 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
return
}},
"exe": &ctx.Command{Name: "exe $ ( cmd )", Help: "解析嵌套命令", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) {
switch len(arg) {
case 1:
m.Echo(arg[0])
case 2:
msg := m.Spawn(cli.target)
switch arg[0] {
case "$":
m.Echo(msg.Cap(arg[1]))
case "@":
value := msg.Option(arg[1])
if value == "" {
value = msg.Conf(arg[1])
}
switch len(arg) {
case 1:
m.Echo(arg[0])
case 2:
msg := m.Spawn(m.Optionv("ps_target"))
switch arg[0] {
case "$":
m.Echo(msg.Cap(arg[1]))
case "@":
value := msg.Option(arg[1])
if value == "" {
value = msg.Conf(arg[1])
}
m.Echo(value)
default:
m.Echo(arg[0]).Echo(arg[1])
}
m.Echo(value)
default:
switch arg[0] {
case "$", "@":
m.Result(0, arg[2:len(arg)-1])
}
m.Echo(arg[0]).Echo(arg[1])
}
return
} //}}}
default:
switch arg[0] {
case "$", "@":
m.Result(0, arg[2:len(arg)-1])
}
}
return
}},
"val": &ctx.Command{Name: "val exp", Help: "表达式运算", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
@ -614,10 +551,6 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
return
}},
"return": &ctx.Command{Name: "return result...", Help: "结束脚本, result: 返回值", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if cli, ok := m.Target().Server.(*CLI); ok {
msg := cli.Message()
msg.Result(-2, arg[1:])
}
m.Add("append", "return", arg[1:])
return
}},
@ -630,6 +563,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
if (len(arg) == 0 || arg[0] == "stdio") && m.Target().Name == "cli" {
// 启动终端
m.Cmd("yac.init")
m.Optionv("ps_target", m.Target())
if m.Start("shy", "shell", "stdio"); m.Cmds("nfs.path", m.Confx("init_shy", arg, 1)) {
// msg := m.Spawn().Add("option", "scan_end", "false").Cmd("source", m.Conf("init_shy"))
@ -682,10 +616,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
return
}},
"arguments": &ctx.Command{Name: "arguments", Help: "脚本参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if cli, ok := m.Source().Server.(*CLI); ok {
msg := cli.Message().Spawn().Cmd("detail", arg)
m.Copy(msg, "append").Copy(msg, "result")
}
m.Set("result", m.Optionv("arguments"))
return
}},
"run": &ctx.Command{Name: "run", Help: "脚本参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
@ -803,45 +734,37 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
} else {
wait := make(chan bool, 1)
go func() {
if m.Has("cmd_error") {
if out, e := cmd.CombinedOutput(); e != nil {
m.Echo("error: ").Echo("%s\n", e)
m.Echo("%s\n", string(out))
} else {
m.Echo(string(out))
}
} else {
if out, e := cmd.Output(); e != nil {
if e == exec.ErrNotFound {
m.Echo("error: ").Echo("not found\n")
} else {
m.Echo("error: ").Echo("%s\n", e)
m.Echo("%s\n", string(out))
}
} else {
switch m.Option("cmd_parse") {
case "json":
var data interface{}
if json.Unmarshal(out, &data) == nil {
msg := m.Spawn().Put("option", "data", data).Cmd("trans", "data", "")
m.Copy(msg, "append").Copy(msg, "result")
} else {
m.Echo(string(out))
}
case "csv":
data, e := csv.NewReader(bytes.NewReader(out)).ReadAll()
m.Assert(e)
for i := 1; i < len(data); i++ {
for j := 0; j < len(data[i]); j++ {
m.Add("append", data[0][j], data[i][j])
}
}
m.Table()
default:
out := bytes.NewBuffer(make([]byte, 1024))
err := bytes.NewBuffer(make([]byte, 1024))
cmd.Stdout = out
cmd.Stderr = err
if e := cmd.Run(); e == nil {
m.Echo("error: ").Echo("%s", e).Echo(string(err))
} else {
switch m.Option("cmd_parse") {
case "json":
var data interface{}
if json.Unmarshal(out, &data) == nil {
msg := m.Spawn().Put("option", "data", data).Cmd("trans", "data", "")
m.Copy(msg, "append").Copy(msg, "result")
} else {
m.Echo(string(out))
}
case "csv":
data, e := csv.NewReader(bytes.NewReader(out)).ReadAll()
m.Assert(e)
for i := 1; i < len(data); i++ {
for j := 0; j < len(data[i]); j++ {
m.Add("append", data[0][j], data[i][j])
}
}
m.Table()
default:
m.Echo(string(out))
}
}
wait <- true

File diff suppressed because it is too large Load Diff

View File

@ -2,12 +2,13 @@ package gdb
import (
"contexts/ctx"
"toolkit"
"fmt"
"io/ioutil"
"os"
"os/signal"
"syscall"
"toolkit"
)
type GDB struct {

View File

@ -89,13 +89,15 @@ var Index = &ctx.Context{Name: "log", Help: "日志中心",
Configs: map[string]*ctx.Config{
"output": &ctx.Config{Name: "output", Value: map[string]interface{}{
"error": map[string]interface{}{"value": map[string]interface{}{"file": "error.log", "meta": []interface{}{"time", "ship"}, "color_begin": "\033[31m", "color_end": "\033[0m"}},
"trace": map[string]interface{}{"value": map[string]interface{}{"file": "error.log", "meta": []interface{}{"time", "ship"}, "color_begin": "\033[32m", "color_end": "\033[0m"}},
"debug": map[string]interface{}{"value": map[string]interface{}{"file": "debug.log", "meta": []interface{}{"time", "ship"}}},
"bench": map[string]interface{}{"value": map[string]interface{}{"file": "bench.log", "meta": []interface{}{"time", "ship"}}},
"begin": map[string]interface{}{"value": map[string]interface{}{"file": "bench.log", "meta": []interface{}{"time", "ship"}, "color_begin": "\033[31m", "color_end": "\033[0m"}},
"start": map[string]interface{}{"value": map[string]interface{}{"file": "bench.log", "meta": []interface{}{"time", "ship"}, "color_begin": "\033[31m", "color_end": "\033[0m"}},
"cmd": map[string]interface{}{"value": map[string]interface{}{"file": "bench.log", "meta": []interface{}{"time", "ship"}, "color_begin": "\033[32m", "color_end": "\033[0m"},
"lex": map[string]interface{}{"value": map[string]interface{}{"file": "debug.log", "meta": []interface{}{"time", "ship"}, "color_begin": "\033[32m", "color_end": "\033[0m"}},
},
"debug": map[string]interface{}{"value": map[string]interface{}{"file": "debug.log", "meta": []interface{}{"time", "ship"}}},
}, Help: "日志输出配置"},
},
Commands: map[string]*ctx.Command{

View File

@ -239,40 +239,6 @@ func (nfs *NFS) print(str string) bool {
return true
}
func (nfs *NFS) prompt(arg ...string) string {
nfs.out.WriteString("> ")
return "> "
ps := nfs.Option("prompt")
if nfs.Caps("windows") {
nfs.color(ps)
return ps
}
line, rest := "", ""
if len(arg) > 0 {
line = arg[0]
}
if len(arg) > 1 {
rest = arg[1]
}
if !nfs.Caps("windows") && len(nfs.pages) > 0 && nfs.width > 0 {
for i := (len(nfs.pages[len(nfs.pages)-1]) - 1) / (nfs.width); i > 0; i-- {
nfs.escape("2K").escape("A")
}
nfs.escape("2K").escape("G").escape("?25h")
}
if len(nfs.pages) > 0 {
nfs.pages = nfs.pages[:len(nfs.pages)-1]
}
nfs.pages = append(nfs.pages, ps+line+rest+"\n")
if nfs.color(ps, nfs.Confi("pscolor")).color(line).color(rest); len(rest) > 0 {
nfs.escape("%dD", len(rest))
}
return ps
}
func (nfs *NFS) zone(buf []string, top, height int) (row, col int) {
row, col = len(buf)-1, 0
for i := nfs.Capi("cursor_pos"); i > top-1; {
@ -558,6 +524,54 @@ func (nfs *NFS) Read(p []byte) (n int, err error) {
return
}
func (nfs *NFS) prompt(arg ...string) string {
m := nfs.Context.Message()
target := m.Optionv("ps_target").(*ctx.Context)
nfs.out.WriteString(fmt.Sprintf("%d[%s]%s> ", m.Capi("ninput"), time.Now().Format("15:04:05"), target.Name))
return "> "
ps := nfs.Option("prompt")
if nfs.Caps("windows") {
nfs.color(ps)
return ps
}
line, rest := "", ""
if len(arg) > 0 {
line = arg[0]
}
if len(arg) > 1 {
rest = arg[1]
}
if !nfs.Caps("windows") && len(nfs.pages) > 0 && nfs.width > 0 {
for i := (len(nfs.pages[len(nfs.pages)-1]) - 1) / (nfs.width); i > 0; i-- {
nfs.escape("2K").escape("A")
}
nfs.escape("2K").escape("G").escape("?25h")
}
if len(nfs.pages) > 0 {
nfs.pages = nfs.pages[:len(nfs.pages)-1]
}
nfs.pages = append(nfs.pages, ps+line+rest+"\n")
if nfs.color(ps, nfs.Confi("pscolor")).color(line).color(rest); len(rest) > 0 {
nfs.escape("%dD", len(rest))
}
return ps
}
func (nfs *NFS) printf(arg ...interface{}) *NFS {
for _, v := range arg {
if nfs.io != nil {
fmt.Fprint(nfs.io, kit.Format(v))
} else if nfs.out != nil {
nfs.out.WriteString(kit.Format(v))
}
}
return nfs
}
func (nfs *NFS) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server {
if len(arg) > 0 && (arg[0] == "scan" || arg[0] == "open" || arg[0] == "append") {
c.Caches = map[string]*ctx.Cache{
@ -591,7 +605,22 @@ func (nfs *NFS) Begin(m *ctx.Message, arg ...string) ctx.Server {
return nfs
}
func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool {
if len(arg) > 0 && (arg[0] == "open" || arg[0] == "append") {
nfs.out = m.Optionv("out").(*os.File)
nfs.in = m.Optionv("in").(*os.File)
m.Cap("stream", arg[1])
if s, e := nfs.in.Stat(); m.Assert(e) {
if m.Capi("size", int(s.Size())); arg[0] == "append" {
m.Capi("pos", int(s.Size()))
}
}
return false
}
if len(arg) > 0 && arg[0] == "scan" {
m.Cap("stream", arg[1])
nfs.Caches["ninput"] = &ctx.Cache{Value: "0"}
nfs.Caches["noutput"] = &ctx.Cache{Value: "0"}
nfs.Configs["input"] = &ctx.Config{Value: []interface{}{}}
@ -609,30 +638,38 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool {
}
line = strings.TrimSuffix(line, "\\")
}
m.Confv("input", -2, map[string]interface{}{"time": time.Now().Unix(), "line": line})
m.Log("debug", "%s %d %d [%s]", "input", m.Capi("ninput", 1), len(line), line)
for i := m.Capi("ninput") - 1; i < m.Capi("ninput"); i++ {
line = m.Conf("input", []interface{}{i, "line"})
msg := m.Spawn(m.Source()).Set("detail", line).Set("option", "file_pos", i)
m.Back(msg)
msg := m.Backs(m.Spawn(m.Source()).Set("detail", line).Set("option", "file_pos", i))
lines := strings.Split(strings.Join(msg.Meta["result"], ""), "\n")
for _, line := range lines {
if line != "" {
m.Log("debug", "%s %d %d [%s]", "output", m.Capi("noutput", 1), len(line), line)
m.Confv("output", -2, map[string]interface{}{"time": time.Now().Unix(), "line": line})
nfs.print(line)
nfs.print("\n")
for j := len(lines) - 1; j > 0; j-- {
if strings.TrimSpace(lines[j]) != "" {
break
}
lines = lines[:j]
}
for _, line := range lines {
m.Confv("output", -2, map[string]interface{}{"time": time.Now().Unix(), "line": line})
m.Log("debug", "%s %d %d [%s]", "output", m.Capi("noutput", 1), len(line), line)
nfs.printf(line).printf("\n")
}
if msg.Appends("file_pos0") {
i = msg.Appendi("file_pos0") - 1
msg.Append("file_pos0", "")
}
}
line = ""
}
if !m.Options("scan_end") {
m.Backs(m.Spawn(m.Source()).Set("detail", "return"))
}
return true
}
@ -649,12 +686,13 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool {
// nfs.Configs["statusfgcolor"] = &ctx.Config{Name: "statusfgcolor", Value: "1", Help: "pscolor"}
// nfs.Configs["statusbgcolor"] = &ctx.Config{Name: "statusbgcolor", Value: "2", Help: "pscolor"}
//
nfs.in = m.Optionv("in").(*os.File)
bio := bufio.NewScanner(nfs)
s, e := nfs.in.Stat()
m.Assert(e)
m.Capi("size", int(s.Size()))
// nfs.in = m.Optionv("in").(*os.File)
// bio := bufio.NewScanner(nfs)
//
// s, e := nfs.in.Stat()
// m.Assert(e)
// m.Capi("size", int(s.Size()))
if m.Cap("stream", arg[1]) == "stdio" {
nfs.out = m.Optionv("out").(*os.File)
@ -689,61 +727,6 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool {
// }
// }
}
line := ""
for nfs.prompt(); !m.Options("scan_end") && bio.Scan(); nfs.prompt() {
kit.Log("error", "stdio read %v", "text")
text := bio.Text()
m.Capi("nread", len(text)+1)
kit.Log("error", "stdio read %v", text)
continue
if line += text; len(text) > 0 && text[len(text)-1] == '\\' {
line = line[:len(line)-1]
continue
}
m.Capi("nline", 1)
m.Confv("history", -2, line)
history := m.Confv("history").([]interface{})
for i := len(history) - 1; i < len(history); i++ {
line = history[i].(string)
msg := m.Spawn(m.Source()).Set("detail", line)
msg.Option("file_pos", i)
m.Back(msg)
for _, v := range msg.Meta["result"] {
m.Capi("nwrite", len(v))
nfs.print(v)
}
if msg.Append("file_pos0") != "" {
i = msg.Appendi("file_pos0") - 1
msg.Append("file_pos0", "")
}
}
line = ""
}
kit.Log("error", "stdio read %v", line)
if !m.Options("scan_end") {
msg := m.Spawn(m.Source()).Set("detail", "return")
m.Back(msg)
}
return true
}
if len(arg) > 0 && (arg[0] == "open" || arg[0] == "append") {
nfs.out = m.Optionv("out").(*os.File)
nfs.in = m.Optionv("in").(*os.File)
s, e := nfs.in.Stat()
m.Assert(e)
m.Capi("size", int(s.Size()))
m.Cap("stream", arg[1])
if arg[0] == "append" {
m.Capi("pos", int(s.Size()))
}
return false
}
m.Cap("stream", m.Option("stream"))
@ -864,7 +847,7 @@ func (nfs *NFS) Close(m *ctx.Message, arg ...string) bool {
var FileNotExist = errors.New("file not exist")
var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
Caches: map[string]*ctx.Cache{
"nfile": &ctx.Cache{Name: "nfile", Value: "-1", Help: "已经打开的文件数量"},
"nfile": &ctx.Cache{Name: "nfile", Value: "0", Help: "已经打开的文件数量"},
},
Configs: map[string]*ctx.Config{
"term_simple": &ctx.Config{Name: "term_simple", Value: "false", Help: "二维码的默认大小"},
@ -902,6 +885,86 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
"paths": &ctx.Config{Name: "paths", Value: []interface{}{"var", "usr", "etc", ""}, Help: "文件路径"},
},
Commands: map[string]*ctx.Command{
"open": &ctx.Command{Name: "open file", Help: "打开文件, file: 文件名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if m.Has("io") {
} else if p, f, e := open(m, arg[0], os.O_RDWR|os.O_CREATE); e == nil {
m.Put("option", "in", f).Put("option", "out", f)
arg[0] = p
} else {
return nil
}
m.Start(fmt.Sprintf("file%d", m.Capi("nfile")), fmt.Sprintf("file %s", arg[0]), "open", arg[0])
m.Echo(arg[0])
return
}},
"read": &ctx.Command{Name: "read [buf_size [pos]]", Help: "读取文件, buf_size: 读取大小, pos: 读取位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) && nfs.in != nil {
if len(arg) > 1 {
m.Cap("pos", arg[1])
}
buf := make([]byte, kit.Int(m.Confx("buf_size", arg, 0)))
if n, e := nfs.in.ReadAt(buf, int64(m.Capi("pos"))); e == io.EOF || m.Assert(e) {
m.Capi("nread", n)
if m.Capi("pos", n); n == 0 {
m.Cap("pos", "0")
}
}
m.Echo(string(buf))
}
return
}},
"write": &ctx.Command{Name: "write string [pos]", Help: "写入文件, string: 写入内容, pos: 写入位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) && nfs.out != nil {
if len(arg) > 1 {
m.Cap("pos", arg[1])
}
if len(arg[0]) == 0 {
m.Assert(nfs.out.Truncate(int64(m.Capi("pos"))))
m.Cap("size", m.Cap("pos"))
m.Cap("pos", "0")
} else {
n, e := nfs.out.WriteAt([]byte(arg[0]), int64(m.Capi("pos")))
if m.Capi("nwrite", n); m.Assert(e) && m.Capi("pos", n) > m.Capi("size") {
m.Cap("size", m.Cap("pos"))
}
nfs.out.Sync()
}
m.Echo(m.Cap("pos"))
}
return
}},
"scan": &ctx.Command{Name: "scan file name", Help: "扫描文件, file: 文件名, name: 模块名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if _, ok := m.Target().Server.(*NFS); m.Assert(ok) {
if help := fmt.Sprintf("scan %s", arg[0]); arg[0] == "stdio" {
m.Put("option", "in", os.Stdin).Put("option", "out", os.Stdout).Start(arg[0], help, key, arg[0])
} else if p, f, e := open(m, arg[0]); m.Assert(e) {
m.Put("option", "in", f).Start(fmt.Sprintf("file%s", m.Capi("nfile")), help, key, p)
}
}
return
}},
"prompt": &ctx.Command{Name: "prompt arg", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) && nfs.out != nil {
nfs.prompt()
for _, v := range arg {
nfs.printf(v)
m.Echo(v)
}
}
return
}},
"printf": &ctx.Command{Name: "printf arg", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) {
nfs.printf(arg)
}
return
}},
"listen": &ctx.Command{Name: "listen args...", Help: "启动文件服务, args: 参考tcp模块, listen命令的参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if _, ok := m.Target().Server.(*NFS); m.Assert(ok) { //{{{
m.Sess("tcp").Call(func(sub *ctx.Message) *ctx.Message {
@ -942,34 +1005,6 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
return
}},
"scan": &ctx.Command{Name: "scan file name", Help: "扫描文件, file: 文件名, name: 模块名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if _, ok := m.Target().Server.(*NFS); m.Assert(ok) {
help := fmt.Sprintf("scan %s", arg[0])
if arg[0] == "stdio" {
m.Optionv("in", os.Stdin)
m.Optionv("out", os.Stdout)
m.Start(arg[0], help, key, arg[0])
return
}
if p, f, e := open(m, arg[0]); m.Assert(e) {
m.Optionv("in", f)
m.Start(m.Confx("nfs_name", arg, 1), help, key, p)
}
}
return
}},
"prompt": &ctx.Command{Name: "prompt arg", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) && nfs.out != nil {
nfs.prompt()
for _, v := range arg {
nfs.out.WriteString(v)
m.Echo(v)
}
}
return
}},
"exec": &ctx.Command{Name: "exec cmd", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) && nfs.out != nil {
nfs.prompt()
@ -987,75 +1022,6 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
}
return
}},
"show": &ctx.Command{Name: "show arg", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) && nfs.out != nil {
for _, v := range arg {
nfs.out.WriteString(v)
m.Echo(v)
}
}
return
}},
"open": &ctx.Command{Name: "open file name", Help: "打开文件, file: 文件名, name: 模块名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
file := arg[0]
if m.Has("io") {
} else if p, f, e := open(m, file, os.O_RDWR|os.O_CREATE); e == nil {
m.Put("option", "in", f).Put("option", "out", f)
file = p
} else {
return nil
}
m.Start(m.Confx("nfs_name", arg, 1), fmt.Sprintf("file %s", file), "open", file)
m.Echo(file)
return
}},
"read": &ctx.Command{Name: "read [buf_size [pos]]", Help: "读取文件, buf_size: 读取大小, pos: 读取位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) && nfs.in != nil {
n, e := strconv.Atoi(m.Confx("buf_size", arg, 0))
m.Assert(e)
if len(arg) > 1 {
m.Cap("pos", arg[1])
}
buf := make([]byte, n)
if n, e = nfs.in.ReadAt(buf, int64(m.Capi("pos"))); e != io.EOF {
m.Assert(e)
}
m.Capi("nread", n)
m.Echo(string(buf))
if m.Capi("pos", n); n == 0 {
m.Cap("pos", "0")
}
}
return
}},
"write": &ctx.Command{Name: "write string [pos]", Help: "写入文件, string: 写入内容, pos: 写入位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) && nfs.out != nil {
if len(arg) > 1 {
m.Cap("pos", arg[1])
}
if len(arg[0]) == 0 {
m.Assert(nfs.out.Truncate(int64(m.Capi("pos"))))
m.Cap("size", m.Cap("pos"))
m.Cap("pos", "0")
} else {
n, e := nfs.out.WriteAt([]byte(arg[0]), int64(m.Capi("pos")))
if m.Capi("nwrite", n); m.Assert(e) && m.Capi("pos", n) > m.Capi("size") {
m.Cap("size", m.Cap("pos"))
}
nfs.out.Sync()
}
m.Echo(m.Cap("pos"))
}
return
}},
"load": &ctx.Command{Name: "load file [buf_size [pos]]", Help: "加载文件, buf_size: 加载大小, pos: 加载位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if p, f, e := open(m, arg[0]); m.Assert(e) {

View File

@ -218,9 +218,10 @@ func (yac *YAC) parse(m *ctx.Message, out *ctx.Message, page int, void int, line
s, star = star, 0
}
}
if hash == 0 {
word = word[:0]
} else if out != nil { //执行命令
} else if !m.Confs("exec", []string{yac.hand[hash], "disable"}) { //执行命令
msg := out.Spawn(m.Source()).Add("detail", yac.hand[hash], word)
if m.Back(msg); msg.Hand { //命令替换
m.Assert(!msg.Has("return"))
@ -316,6 +317,10 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心",
map[string]interface{}{"page": "line", "hash": "line", "word": []interface{}{"opt{", "mul{", "stm", "cmd", "}", "}", "mul{", ";", "\n", "#[^\n]*\n", "}"}},
}, Help: "语法集合的最大数量"},
"info": &ctx.Config{Name: "info", Value: map[string]interface{}{"ncell": 128, "nlang": 64}, Help: "嵌套层级日志的标记"},
"exec": &ctx.Config{Name: "info", Value: map[string]interface{}{
"line": map[string]interface{}{"disable": true},
"word": map[string]interface{}{"disable": true},
}, Help: "嵌套层级日志的标记"},
},
Commands: map[string]*ctx.Command{
"init": &ctx.Command{Name: "init", Help: "添加语法规则, page: 语法集合, hash: 语句类型, word: 语法模板", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {

View File

@ -94,6 +94,12 @@ func Format(arg ...interface{}) string {
result = append(result, val...)
case float64:
result = append(result, fmt.Sprintf("%d", int(val)))
case *os.File:
if s, e := val.Stat(); e == nil {
result = append(result, fmt.Sprintf("%T [name: %s]", v, s.Name()))
} else {
result = append(result, fmt.Sprintf("%T", v))
}
case time.Time:
result = append(result, fmt.Sprintf("%d", val.Format("2006-01-02 15:03:04")))
// case error: