1
0
mirror of https://shylinux.com/x/ContextOS synced 2025-04-25 08:48:06 +08:00

opt nfs.dir

This commit is contained in:
shaoying 2019-07-24 09:48:31 +08:00
parent 002b42b68e
commit d8c56f8eba
3 changed files with 270 additions and 295 deletions

View File

@ -4,5 +4,5 @@ var version = struct {
host string
self int
}{
"2019-07-23 21:26:44", "ZYB-20190522USI", 232,
"2019-07-24 09:10:27", "com.mac_14", 216,
}

View File

@ -1,35 +1,34 @@
package nfs
import (
"github.com/skip2/go-qrcode"
"contexts/ctx"
"crypto/md5"
"toolkit"
"bufio"
"crypto/sha1"
"encoding/csv"
"encoding/hex"
"encoding/json"
"fmt"
"github.com/skip2/go-qrcode"
"net/url"
"regexp"
"strings"
"bufio"
"github.com/nsf/termbox-go"
"io"
"io/ioutil"
"net/url"
"os"
"os/exec"
"path"
"regexp"
"sort"
"strings"
"time"
)
type NFS struct {
io io.ReadWriter
in *os.File
out *os.File
io io.ReadWriter
send chan *ctx.Message
echo chan *ctx.Message
@ -38,21 +37,19 @@ type NFS struct {
*ctx.Context
}
func dir(m *ctx.Message, name string, level int, deep bool, dir_type string, trip int, dir_reg *regexp.Regexp, fields []string, format string) {
back, e := os.Getwd()
m.Assert(e)
func dir(m *ctx.Message, root string, name string, level int, deep bool, dir_type string, dir_reg *regexp.Regexp, fields []string, format string) {
if fs, e := ioutil.ReadDir(name); m.Assert(e) {
for _, f := range fs {
if f.Name() == "." || f.Name() == ".." {
continue
}
if strings.HasPrefix(f.Name(), ".") && dir_type != "all" {
continue
}
f, e := os.Stat(path.Join(name, f.Name()))
p := path.Join(name, f.Name())
f, e := os.Stat(p)
if e != nil {
m.Log("info", "%s", e)
continue
@ -71,15 +68,21 @@ func dir(m *ctx.Message, name string, level int, deep bool, dir_type string, tri
}
case "full":
if f.IsDir() {
m.Add("append", "full", path.Join(back, name, f.Name())+"/")
m.Add("append", "full", path.Join(root, name, f.Name())+"/")
} else {
m.Add("append", "full", path.Join(back, name, f.Name()))
m.Add("append", "full", path.Join(root, name, f.Name()))
}
case "path":
if f.IsDir() {
m.Add("append", "path", path.Join(back, name, f.Name())[trip:]+"/")
m.Add("append", "path", path.Join(name, f.Name())+"/")
} else {
m.Add("append", "path", path.Join(back, name, f.Name())[trip:])
m.Add("append", "path", path.Join(name, f.Name()))
}
case "name":
if f.IsDir() {
m.Add("append", "name", f.Name()+"/")
} else {
m.Add("append", "name", f.Name())
}
case "tree":
if level == 0 {
@ -87,51 +90,39 @@ func dir(m *ctx.Message, name string, level int, deep bool, dir_type string, tri
} else {
m.Add("append", "tree", strings.Repeat("| ", level-1)+"|-"+f.Name())
}
case "filename":
if f.IsDir() {
m.Add("append", "filename", f.Name()+"/")
} else {
m.Add("append", "filename", f.Name())
}
case "size":
m.Add("append", "size", f.Size())
case "line":
nline := 0
if f.IsDir() {
d, e := ioutil.ReadDir(path.Join(name, f.Name()))
m.Assert(e)
nline = len(d)
if d, e := ioutil.ReadDir(p); m.Assert(e) {
m.Add("append", "line", len(d))
}
} else {
f, e := os.Open(path.Join(name, f.Name()))
m.Assert(e)
defer f.Close()
bio := bufio.NewScanner(f)
for bio.Scan() {
bio.Text()
nline++
nline := 0
if f, e := os.Open(p); m.Assert(e) {
defer f.Close()
for bio := bufio.NewScanner(f); bio.Scan(); nline++ {
bio.Text()
}
}
m.Add("append", "line", nline)
}
m.Add("append", "line", nline)
case "hash", "hashs":
var h [20]byte
if f.IsDir() {
d, e := ioutil.ReadDir(path.Join(name, f.Name()))
m.Assert(e)
meta := []string{}
for _, v := range d {
meta = append(meta, fmt.Sprintf("%s%d%s", v.Name(), v.Size(), v.ModTime()))
if d, e := ioutil.ReadDir(p); m.Assert(e) {
meta := []string{}
for _, v := range d {
meta = append(meta, fmt.Sprintf("%s%d%s", v.Name(), v.Size(), v.ModTime()))
}
sort.Strings(meta)
h = sha1.Sum([]byte(strings.Join(meta, "")))
}
} else {
if f, e := ioutil.ReadFile(path.Join(name, f.Name())); m.Assert(e) {
h = sha1.Sum(f)
}
sort.Strings(meta)
h := sha1.Sum([]byte(strings.Join(meta, "")))
m.Add("append", "hash", hex.EncodeToString(h[:]))
break
}
f, e := ioutil.ReadFile(path.Join(name, f.Name()))
m.Assert(e)
h := sha1.Sum(f)
if field == "hash" {
m.Add("append", "hash", hex.EncodeToString(h[:]))
} else {
@ -141,25 +132,65 @@ func dir(m *ctx.Message, name string, level int, deep bool, dir_type string, tri
}
}
if f.IsDir() && deep {
dir(m, path.Join(name, f.Name()), level+1, deep, dir_type, trip, dir_reg, fields, format)
dir(m, root, p, level+1, deep, dir_type, dir_reg, fields, format)
}
}
}
}
func sed(m *ctx.Message, p string, args []string) error {
p0 := p + ".tmp0"
p1 := p + ".tmp1"
if _, e := os.Stat(p1); e == nil {
return e
}
out, e := os.Create(p1)
defer os.Remove(p1)
defer out.Close()
m.Log("info", "open %v", p1)
if _, e := os.Stat(p0); e != nil {
m.Cmd("nfs.copy", p0, p)
}
in, e := os.Open(p0)
defer in.Close()
m.Log("info", "open %v", p0)
switch args[0] {
case "set":
defer os.Rename(p1, p0)
defer os.Remove(p0)
index := kit.Int(args[1])
for bio, i := bufio.NewScanner(in), 0; bio.Scan(); i++ {
if i == index {
out.WriteString(args[2])
} else {
out.WriteString(bio.Text())
}
out.WriteString("\n")
}
return e
case "add":
out0, _ := os.OpenFile(p0, os.O_WRONLY|os.O_APPEND, 0666)
defer out0.Close()
out0.WriteString("\n")
case "put":
defer os.Rename(p0, p)
}
return nil
}
func open(m *ctx.Message, name string, arg ...int) (string, *os.File, error) {
if !path.IsAbs(name) {
pwd := m.Confv("pwd").([]interface{})
for _, v := range pwd {
p := path.Join(v.(string), name)
if len(arg) > 0 {
name = p
break
}
m.Confm("pwd", func(i int, v string) bool {
p := path.Join(v, name)
if s, e := os.Stat(p); e == nil && !s.IsDir() {
name = p
break
return true
}
}
return false
})
}
flag := os.O_RDONLY
@ -170,9 +201,9 @@ func open(m *ctx.Message, name string, arg ...int) (string, *os.File, error) {
f, e := os.OpenFile(name, flag, 0660)
if e == nil {
m.Log("info", "open %s", name)
return name, f, e
} else {
m.Log("warn", "%v", e)
}
m.Log("warn", "%v", e)
return name, f, e
}
@ -382,7 +413,7 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool {
// 消息接收队列
msg, code, head, body := m, "0", "result", "append"
bio := bufio.NewScanner(nfs.io)
bio.Buffer(make([]byte, m.Confi("buf_size")), m.Confi("buf_size"))
bio.Buffer(make([]byte, m.Confi("buf", "size")), m.Confi("buf", "size"))
for bio.Scan() {
m.TryCatch(m, true, func(m *ctx.Message) {
@ -440,7 +471,7 @@ func (nfs *NFS) Close(m *ctx.Message, arg ...string) bool {
var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
Caches: map[string]*ctx.Cache{
"nfile": &ctx.Cache{Name: "nfile", Value: "0", Help: "已经打开的文件数量"},
"bio": &ctx.Cache{Name: "bio", Value: "0", Help: "文件数量"},
},
Configs: map[string]*ctx.Config{
"term": &ctx.Config{Name: "term", Value: map[string]interface{}{
@ -471,7 +502,7 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
"help_next_auto": "=",
"help_stack": []interface{}{},
"help_table": map[string]interface{}{},
}, Help: "二维码的默认大小"},
}, Help: "终端管理"},
"auto": &ctx.Config{Name: "auto", Value: map[string]interface{}{
"!": map[string]interface{}{
"state": "message",
@ -516,12 +547,14 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
"table": "cache", "field": "key",
"format": "%s(%s) %s", "fields": []interface{}{"key", "value", "name"},
},
}, Help: "读取文件的缓存区的大小"},
}, Help: "自动补全"},
"buf_size": &ctx.Config{Name: "buf_size", Value: "81920", Help: "读取文件的缓存区的大小"},
"buf": &ctx.Config{Name: "buf", Value: map[string]interface{}{
"size": "81920",
}, Help: "文件缓存"},
"grep": &ctx.Config{Name: "grep", Value: map[string]interface{}{
"list": []interface{}{},
}, Help: "dir命令输出文件名的类型, name: 文件名, tree: 带缩进的文件名, path: 相对路径, full: 绝对路径"},
}, Help: "文件搜索"},
"git": &ctx.Config{Name: "git", Value: map[string]interface{}{
"args": []interface{}{"-C", "@git_dir"},
"info": map[string]interface{}{"cmds": []interface{}{"log", "status", "branch"}},
@ -535,14 +568,16 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
"date": "--date=format:%m/%d %H:%M",
"pretty": "--pretty=format:%h %ad %an %s",
},
}, Help: "命令集合"},
"dir_fields": &ctx.Config{Name: "dir_fields(time/type/name/size/line/hash)", Value: "time size line filename", Help: "dir命令输出文件名的类型, name: 文件名, tree: 带缩进的文件名, path: 相对路径, full: 绝对路径"},
"dir_type": &ctx.Config{Name: "dir_type(file/dir/both/all)", Value: "both", Help: "dir命令输出的文件类型, file: 只输出普通文件, dir: 只输出目录文件, 否则输出所有文件"},
}, Help: "版本管理"},
"dir": &ctx.Config{Name: "dir", Value: map[string]interface{}{
"temp": "var/tmp/file",
"trash": "var/tmp/trash",
}, Help: ""},
"pwd": &ctx.Config{Name: "pwd", Value: []interface{}{"var", "usr", "bin", "etc", ""}, Help: "当前目录"},
"fields": "time size line path",
"type": "both",
"temp": "var/tmp/file",
"trash": "var/tmp/trash",
}, Help: "目录管理"},
"pwd": &ctx.Config{Name: "pwd", Value: []interface{}{
"var", "usr", "bin", "etc", "",
}, Help: "当前目录"},
},
Commands: map[string]*ctx.Command{
"_init": &ctx.Command{Name: "_init", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
@ -551,9 +586,7 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
return
}},
"_exit": &ctx.Command{Name: "_init", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if m.Confs("term", "use") {
termbox.Close()
}
m.Cmd("nfs.term", "exit")
return
}},
"path": &ctx.Command{Name: "path filename", Help: "查找文件路径", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
@ -593,7 +626,8 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
}
return
}},
"dir": &ctx.Command{Name: "dir [path [fields...]]", Help: []string{"查看目录, path: 路径, fields...: 查询字段, time|type|full|path|tree|filename|size|line|hash",
"dir": &ctx.Command{Name: "dir [path [fields...]]", Help: []string{
"查看目录, path: 路径, fields...: 查询字段, time|type|full|path|name|tree|size|line|hash|hashs",
"dir_deep: 递归查询", "dir_type both|file|dir|all: 文件类型", "dir_reg reg: 正则表达式", "dir_sort field order: 排序"},
Form: map[string]int{"dir_deep": 0, "dir_type": 1, "dir_reg": 1, "dir_sort": 2, "dir_sed": -1},
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
@ -601,86 +635,41 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
arg = append(arg, "")
}
p := arg[0]
p0 := p + ".tmp0"
p1 := p + ".tmp1"
if args := kit.Trans(m.Optionv("dir_sed")); len(args) > 0 {
if _, e := os.Stat(p1); e == nil {
return e
}
out, e := os.Create(p1)
defer os.Remove(p1)
defer out.Close()
m.Log("info", "open %v", p1)
if _, e := os.Stat(p0); e != nil {
m.Cmd("nfs.copy", p0, p)
}
in, e := os.Open(p0)
defer in.Close()
m.Log("info", "open %v", p0)
switch args[0] {
case "set":
defer os.Rename(p1, p0)
defer os.Remove(p0)
index := kit.Int(args[1])
for bio, i := bufio.NewScanner(in), 0; bio.Scan(); i++ {
if i == index {
out.WriteString(args[2])
} else {
out.WriteString(bio.Text())
}
out.WriteString("\n")
}
return e
case "add":
out0, _ := os.OpenFile(p0, os.O_WRONLY|os.O_APPEND, 0666)
defer out0.Close()
out0.WriteString("\n")
case "put":
defer os.Rename(p0, p)
}
return e
return sed(m, arg[0], args)
}
wd, e := os.Getwd()
m.Assert(e)
trip := len(wd) + 1
rg, e := regexp.Compile(m.Option("dir_reg"))
m.Confm("pwd", func(index int, value string) bool {
// p := path.Join(value, m.Option("dir_root"), arg[0])
p := path.Join(value, arg[0])
if s, e := os.Stat(p); e == nil {
if s.IsDir() {
dir(m, p, 0, kit.Right(m.Has("dir_deep")), m.Confx("dir_type"), trip, rg,
strings.Split(m.Confx("dir_fields", strings.Join(arg[1:], " ")), " "),
m.Conf("time", "format"))
rg, _ := regexp.Compile(m.Option("dir_reg"))
dir_type := kit.Select(m.Conf("dir", "type"), m.Option("dir_type"))
fields := strings.Split(kit.Select(m.Conf("dir", "fields"), strings.Join(arg[1:], " ")), " ")
dir(m, kit.Pwd(), p, 0, kit.Right(m.Has("dir_deep")),
dir_type, rg, fields, m.Conf("time", "format"))
} else if s.Size() > int64(m.Confi("buf", "size")) {
m.Append("directory", p)
} else {
if s.Size() < int64(m.Confi("buf_size")) {
p0 := p + ".tmp0"
f, e := os.Open(p0)
if e != nil {
f, e = os.Open(p)
m.Log("info", "open %v", p)
} else {
p = p0
m.Log("info", "open %v", p0)
p0 := p + ".tmp0"
f, e := os.Open(p0)
if e != nil {
if f, e = os.Open(p); e == nil {
p0 = p
}
for bio := bufio.NewScanner(f); bio.Scan(); {
m.Echo(bio.Text())
}
m.Append("file", p)
m.Append("size", s.Size())
m.Append("time", s.ModTime().Format(m.Conf("time", "format")))
} else {
m.Append("directory", p)
}
m.Log("info", "open %v", p0)
for bio := bufio.NewScanner(f); bio.Scan(); {
m.Echo(bio.Text())
}
m.Append("file", p)
m.Append("size", s.Size())
m.Append("time", s.ModTime().Format(m.Conf("time", "format")))
}
return true
}
@ -696,9 +685,7 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
m.Echo(v).Echo(" ")
}
} else {
if !m.Appends("file") {
m.Table()
}
m.Table()
}
return
}},
@ -920,7 +907,7 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
if p, f, e := open(m, arg[0]); e == nil {
defer f.Close()
size := kit.Int(m.Confx("buf_size", arg, 1))
size := kit.Int(kit.Select(m.Conf("buf", "size"), arg, 1))
if size == -1 {
if s, e := f.Stat(); m.Assert(e) {
size = int(s.Size())
@ -1099,7 +1086,7 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
m.Cap("pos", arg[1])
}
buf := make([]byte, kit.Int(m.Confx("buf_size", arg, 0)))
buf := make([]byte, kit.Int(kit.Select(m.Conf("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 {
@ -1133,33 +1120,6 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
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.print(arg...)
}
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.prompt(arg)
}
return
}},
"term": &ctx.Command{Name: "term action args...", 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.Term(m, arg[0], arg[1:])
}
return
}},
"action": &ctx.Command{Name: "action 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) {
msg := m.Cmd("cli.source", arg)
// nfs.print(msg.Conf("prompt"), arg, "\n")
nfs.print(msg.Meta["result"]...)
}
return
}},
"source": &ctx.Command{Name: "source [script|stdio|snippet]", Help: "解析脚本, script: 脚本文件, stdio: 命令终端, snippet: 代码片段", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if len(arg) == 0 {
m.Cmdy("dir", "src", "time", "line", "path", "dir_deep", "dir_reg", ".*\\.(sh|shy|py)$")
@ -1180,26 +1140,42 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
}
return
}},
"arguments": &ctx.Command{Name: "arguments", Help: "脚本参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
args := kit.Trans(m.Optionv("bio.args"))
if len(arg) == 0 {
m.Set("result", args)
} else {
m.Echo(kit.Select("", args, kit.Int(arg[0])))
"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.prompt(strings.Join(arg, ""))
}
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.print(arg...)
}
return
}},
"action": &ctx.Command{Name: "action 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) {
msg := m.Cmd("nfs.source", arg)
nfs.print(msg.Meta["result"]...)
}
return
}},
"term": &ctx.Command{Name: "term action args...", 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.Term(m, arg[0], arg[1:])
}
return
}},
"remote": &ctx.Command{Name: "remote listen|dial 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 {
if sub.Has("node.port") {
return sub
m.Sess("tcp").Call(func(msg *ctx.Message) *ctx.Message {
if msg.Has("node.port") {
return msg
}
sub.Sess("ms_source", sub)
sub.Sess("ms_target", m.Source())
sub.Start(fmt.Sprintf("file%d", m.Capi("nfile", 1)), "远程文件")
return sub
msg.Sess("ms_source", msg)
msg.Sess("ms_target", m.Source())
msg.Start(fmt.Sprintf("file%d", m.Capi("nfile", 1)), "远程文件")
return msg
}, arg)
}
return

View File

@ -243,7 +243,7 @@ func (yac *YAC) parse(m *ctx.Message, msg *ctx.Message, stack *kit.Stack, page i
word = word[:0]
} else if !m.Confs("exec", []string{"disable", yac.hand[hash]}) {
if stack.Peek().Run || m.Confs("exec", []string{"always", yac.hand[hash]}) {
if stack == nil || stack.Peek().Run || m.Confs("exec", []string{"always", yac.hand[hash]}) {
//执行命令
cmd := msg.Spawn(m.Optionv("bio.ctx"))
if cmd.Cmd(yac.hand[hash], word); cmd.Hand {
@ -317,8 +317,6 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心",
map[string]interface{}{"page": "op2", "hash": "op2", "word": []interface{}{"mul{", "<", "<=", ">", ">=", "==", "!=", "}"}},
map[string]interface{}{"page": "val", "hash": "val", "word": []interface{}{"opt{", "op1", "}", "mul{", "num", "key", "str", "exe", "}"}},
map[string]interface{}{"page": "exp", "hash": "exp", "word": []interface{}{"val", "rep{", "op2", "val", "}"}},
map[string]interface{}{"page": "stm", "hash": "let", "word": []interface{}{"let", "key", "opt{", "=", "exp", "}"}},
map[string]interface{}{"page": "stm", "hash": "var", "word": []interface{}{"var", "key", "opt{", "=", "exp", "}"}},
map[string]interface{}{"page": "stm", "hash": "return", "word": []interface{}{"return", "rep{", "exp", "}"}},
// 命令语句
@ -329,12 +327,13 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心",
// 复合语句
map[string]interface{}{"page": "exe", "hash": "exe", "word": []interface{}{"$", "(", "cmd", ")"}},
map[string]interface{}{"page": "stm", "hash": "var", "word": []interface{}{"var", "key", "opt{", "=", "exp", "}"}},
map[string]interface{}{"page": "stm", "hash": "let", "word": []interface{}{"let", "key", "opt{", "=", "exp", "}"}},
map[string]interface{}{"page": "stm", "hash": "if", "word": []interface{}{"if", "exp"}},
map[string]interface{}{"page": "stm", "hash": "for", "word": []interface{}{"for", "rep{", "exp", "}"}},
map[string]interface{}{"page": "stm", "hash": "fun", "word": []interface{}{"fun", "key", "rep{", "key", "}"}},
map[string]interface{}{"page": "stm", "hash": "else", "word": []interface{}{"else", "opt{", "if", "exp", "}"}},
map[string]interface{}{"page": "stm", "hash": "end", "word": []interface{}{"end"}},
map[string]interface{}{"page": "stm", "hash": "fun", "word": []interface{}{"fun", "key", "rep{", "key", "}"}},
/*
map[string]interface{}{"page": "op1", "hash": "op1", "word": []interface{}{"mul{", "-z", "-n", "}"}},
@ -420,7 +419,7 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心",
}},
"parse": &ctx.Command{Name: "parse line", Help: "解析语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if yac, ok := m.Target().Server.(*YAC); m.Assert(ok) {
stack := m.Optionv("bio.stack").(*kit.Stack)
stack, _ := m.Optionv("bio.stack").(*kit.Stack)
m.Optioni("yac.page", yac.page[m.Conf("nline")])
m.Optioni("yac.void", yac.page[m.Conf("nvoid")])
@ -734,29 +733,6 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心",
m.Echo("%s", num[0])
return
}},
"let": &ctx.Command{Name: "let a = exp", Help: "设置变量, a: 变量名, exp: 表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
switch arg[2] {
case "=":
m.Cap(arg[1], arg[3])
m.Log("stack", "let %v = %v", arg[1], arg[3])
case "<-":
m.Cap(arg[1], m.Cap("last_msg"))
}
m.Echo(m.Cap(arg[1]))
return
}},
"var": &ctx.Command{Name: "var a [= exp]", Help: "定义变量, a: 变量名, exp: 表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if m.Cap(arg[1], arg[1], "", "临时变量"); len(arg) > 1 {
switch arg[2] {
case "=":
m.Cap(arg[1], arg[3])
case "<-":
m.Cap(arg[1], m.Cap("last_msg"))
}
}
m.Echo(m.Cap(arg[1]))
return
}},
"return": &ctx.Command{Name: "return result...", Help: "结束脚本, result: 返回值", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
m.Appends("bio.end", true)
m.Result(arg[1:])
@ -956,6 +932,29 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心",
return
}},
"var": &ctx.Command{Name: "var a [= exp]", Help: "定义变量, a: 变量名, exp: 表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if m.Cap(arg[1], arg[1], "", "临时变量"); len(arg) > 1 {
switch arg[2] {
case "=":
m.Cap(arg[1], arg[3])
case "<-":
m.Cap(arg[1], m.Cap("last_msg"))
}
}
m.Echo(m.Cap(arg[1]))
return
}},
"let": &ctx.Command{Name: "let a = exp", Help: "设置变量, a: 变量名, exp: 表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
switch arg[2] {
case "=":
m.Cap(arg[1], arg[3])
m.Log("stack", "let %v = %v", arg[1], arg[3])
case "<-":
m.Cap(arg[1], m.Cap("last_msg"))
}
m.Echo(m.Cap(arg[1]))
return
}},
"if": &ctx.Command{Name: "if exp", Help: "条件语句, exp: 表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
stack := m.Optionv("bio.stack").(*kit.Stack)
p := stack.Push(arg[0], stack.Peek().Run && kit.Right(arg[1]), m.Optioni("stack.pos"))
@ -965,77 +964,6 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心",
}
return
}},
"else": &ctx.Command{Name: "else", Help: "条件语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
p := m.Optionv("bio.stack").(*kit.Stack).Peek()
p.Run = !p.Done && !p.Run && (len(arg) == 1 || kit.Right(arg[2]))
m.Log("stack", "set: run = %v", p.Run)
if p.Run {
p.Done = true
}
return
}},
"end": &ctx.Command{Name: "end", Help: "结束语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
p := m.Optionv("bio.stack").(*kit.Stack).Pop()
m.Log("stack", "pop: %v", p.String("/"))
switch p.Key {
case "for":
if p.Run {
m.Appendi("bio.pos0", p.Pos)
}
case "fun":
end := m.Optioni("stack.pos")
self := p.Data.(*ctx.Command)
help := []string{}
for i, v := range m.Optionv("input").([]interface{}) {
if p.Pos < i && i < end {
val := v.(map[string]interface{})
help = append(help, val["line"].(string))
}
}
self.Help = help
}
return
}},
"fun": &ctx.Command{Name: "fun", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
p := m.Optionv("bio.stack").(*kit.Stack).Push(arg[0], false, m.Optioni("stack.pos"))
m.Log("stack", "push %v", p.String("\\"))
self := &ctx.Command{Name: strings.Join(arg[1:], " "), Help: []string{"pwd", "ls"}}
self.Hand = func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
stack := &kit.Stack{}
stack.Push("fun", true, 0)
m.Optionv("bio.stack", stack)
help := self.Help.([]string)
// 解析数据
for i := 0; i < len(help); i++ {
line := help[i]
m.Optioni("stack.pos", i)
// 执行语句
msg := m.Cmd("yac.parse", line+"\n")
// 跳转语句
if msg.Appends("bio.pos0") {
i = int(msg.Appendi("bio.pos0")) - 1
msg.Append("bio.pos0", "")
}
// 结束脚本
if msg.Appends("bio.end") {
m.Copy(msg, "append")
m.Copy(msg, "result")
msg.Appends("bio.end", "")
break
}
}
return
}
m.Target().Commands[arg[1]] = self
p.Data = self
return
}},
"for": &ctx.Command{Name: "for [[express ;] condition]|[index message meta value]",
Help: "循环语句, express: 每次循环运行的表达式, condition: 循环条件, index: 索引消息, message: 消息编号, meta: value: ",
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
@ -1100,6 +1028,77 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心",
*/
return
}},
"fun": &ctx.Command{Name: "fun", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
p := m.Optionv("bio.stack").(*kit.Stack).Push(arg[0], false, m.Optioni("stack.pos"))
m.Log("stack", "push %v", p.String("\\"))
self := &ctx.Command{Name: strings.Join(arg[1:], " "), Help: []string{"pwd", "ls"}}
self.Hand = func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
stack := &kit.Stack{}
stack.Push("fun", true, 0)
m.Optionv("bio.stack", stack)
help := self.Help.([]string)
// 解析数据
for i := 0; i < len(help); i++ {
line := help[i]
m.Optioni("stack.pos", i)
// 执行语句
msg := m.Cmd("yac.parse", line+"\n")
// 跳转语句
if msg.Appends("bio.pos0") {
i = int(msg.Appendi("bio.pos0")) - 1
msg.Append("bio.pos0", "")
}
// 结束脚本
if msg.Appends("bio.end") {
m.Copy(msg, "append")
m.Copy(msg, "result")
msg.Appends("bio.end", "")
break
}
}
return
}
m.Target().Commands[arg[1]] = self
p.Data = self
return
}},
"else": &ctx.Command{Name: "else", Help: "条件语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
p := m.Optionv("bio.stack").(*kit.Stack).Peek()
p.Run = !p.Done && !p.Run && (len(arg) == 1 || kit.Right(arg[2]))
m.Log("stack", "set: run = %v", p.Run)
if p.Run {
p.Done = true
}
return
}},
"end": &ctx.Command{Name: "end", Help: "结束语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
p := m.Optionv("bio.stack").(*kit.Stack).Pop()
m.Log("stack", "pop: %v", p.String("/"))
switch p.Key {
case "for":
if p.Run {
m.Appendi("bio.pos0", p.Pos)
}
case "fun":
end := m.Optioni("stack.pos")
self := p.Data.(*ctx.Command)
help := []string{}
for i, v := range m.Optionv("input").([]interface{}) {
if p.Pos < i && i < end {
val := v.(map[string]interface{})
help = append(help, val["line"].(string))
}
}
self.Help = help
}
return
}},
"label": &ctx.Command{Name: "label name", Help: "记录当前脚本的位置, name: 位置名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if cli, ok := m.Target().Server.(*YAC); m.Assert(ok) {