mirror of
https://shylinux.com/x/ContextOS
synced 2025-04-26 09:14:06 +08:00
add m.Cmdp
This commit is contained in:
parent
78df5d2ba3
commit
b3486b5e37
@ -34,8 +34,10 @@ install() {
|
|||||||
"armv7l") GOARCH=arm;;
|
"armv7l") GOARCH=arm;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
target=system && [ -n "$2" ] && target=$2
|
||||||
|
|
||||||
wget -O ${ctx_app} "$ctx_dev/publish/${ctx_app}?GOOS=$GOOS&GOARCH=$GOARCH" && chmod a+x ${ctx_app} \
|
wget -O ${ctx_app} "$ctx_dev/publish/${ctx_app}?GOOS=$GOOS&GOARCH=$GOARCH" && chmod a+x ${ctx_app} \
|
||||||
&& ./${ctx_app} upgrade system && ${md5} ${ctx_app} \
|
&& ./${ctx_app} upgrade ${target} && ${md5} ${ctx_app} \
|
||||||
&& mv ${ctx_app} bin/${ctx_app}
|
&& mv ${ctx_app} bin/${ctx_app}
|
||||||
}
|
}
|
||||||
main() {
|
main() {
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
~cli
|
~cli
|
||||||
config load var/tmp/runtime.json runtime
|
config load tmp/runtime.json runtime
|
||||||
~aaa
|
~aaa
|
||||||
config load var/tmp/auth.json auth
|
config load tmp/auth.json auth
|
||||||
~ssh
|
~ssh
|
||||||
config load var/tmp/cert.json work flow trust
|
config load tmp/cert.json work flow trust
|
||||||
~wiki
|
~wiki
|
||||||
config load var/tmp/wiki.json wiki_visit
|
config load tmp/wiki.json wiki_visit
|
||||||
source etc/common.shy
|
source etc/common.shy
|
||||||
~ssh
|
~ssh
|
||||||
remote auto
|
remote auto
|
||||||
|
@ -130,6 +130,20 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
|
|||||||
"daemon": &ctx.Config{Name: "daemon", Value: map[string]interface{}{}, Help: "守护任务"},
|
"daemon": &ctx.Config{Name: "daemon", Value: map[string]interface{}{}, Help: "守护任务"},
|
||||||
"action": &ctx.Config{Name: "action", Value: map[string]interface{}{}, Help: "交互任务"},
|
"action": &ctx.Config{Name: "action", Value: map[string]interface{}{}, Help: "交互任务"},
|
||||||
|
|
||||||
|
"project": &ctx.Config{Name: "project", Value: map[string]interface{}{
|
||||||
|
"github": "https://github.com/shylinux/context",
|
||||||
|
"env": map[string]interface{}{
|
||||||
|
"GOPATH": "https://github.com/shylinux/context",
|
||||||
|
},
|
||||||
|
"import": []interface{}{
|
||||||
|
"github.com/nsf/termbox-go",
|
||||||
|
"github.com/skip2/go-qrcode",
|
||||||
|
"github.com/go-sql-driver/mysql",
|
||||||
|
"github.com/gomarkdown/markdown",
|
||||||
|
"github.com/PuerkitoBio/goquery",
|
||||||
|
"github.com/go-cas/cas",
|
||||||
|
},
|
||||||
|
}, Help: "运行环境"},
|
||||||
"compile": &ctx.Config{Name: "compile", Value: map[string]interface{}{
|
"compile": &ctx.Config{Name: "compile", Value: map[string]interface{}{
|
||||||
"bench": "src/examples/app/bench.go",
|
"bench": "src/examples/app/bench.go",
|
||||||
"env": []interface{}{"GOPATH", "PATH"},
|
"env": []interface{}{"GOPATH", "PATH"},
|
||||||
@ -216,6 +230,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
|
|||||||
if name, e := os.Getwd(); e == nil {
|
if name, e := os.Getwd(); e == nil {
|
||||||
_, file := path.Split(kit.Select(name, os.Getenv("PWD")))
|
_, file := path.Split(kit.Select(name, os.Getenv("PWD")))
|
||||||
m.Conf("runtime", "boot.pathname", file)
|
m.Conf("runtime", "boot.pathname", file)
|
||||||
|
m.Conf("runtime", "boot.ctx_path", name)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}},
|
}},
|
||||||
@ -501,6 +516,28 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
|
|||||||
return
|
return
|
||||||
}},
|
}},
|
||||||
|
|
||||||
|
"project": &ctx.Command{Name: "project", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
||||||
|
switch arg[0] {
|
||||||
|
case "init":
|
||||||
|
m.Cmdp(time.Second, []string{"git init"}, []string{"cli.system", "git"}, [][]string{
|
||||||
|
[]string{"git", "init"},
|
||||||
|
[]string{"git", "remote", "add", kit.Select("origin", arg, 1), kit.Select(m.Conf("project", "github"), arg, 2)},
|
||||||
|
[]string{"git", "stash"},
|
||||||
|
[]string{"git", "pull"},
|
||||||
|
[]string{"git", "checkout", "-f", "master"},
|
||||||
|
[]string{"git", "stash", "pop"},
|
||||||
|
})
|
||||||
|
|
||||||
|
list := [][]string{}
|
||||||
|
m.Confm("project", "import", func(index int, value string) {
|
||||||
|
list = append(list, []string{value})
|
||||||
|
})
|
||||||
|
|
||||||
|
m.Cmdp(time.Second, []string{"go init"}, []string{"cli.system", "go", "get",
|
||||||
|
"cmd_env", "GOPATH", m.Conf("runtime", "boot.ctx_path")}, list)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}},
|
||||||
"compile": &ctx.Command{Name: "compile [OS [ARCH]]", Help: "解析脚本, script: 脚本文件, stdio: 命令终端, snippet: 代码片段", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
"compile": &ctx.Command{Name: "compile [OS [ARCH]]", Help: "解析脚本, script: 脚本文件, stdio: 命令终端, snippet: 代码片段", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
||||||
if len(arg) > 0 && arg[0] == "self" {
|
if len(arg) > 0 && arg[0] == "self" {
|
||||||
if m.Cmdy("cli.system", "go", "install", m.Cmdx("nfs.path", m.Conf("compile", "bench"))); m.Result(0) == "" {
|
if m.Cmdy("cli.system", "go", "install", m.Cmdx("nfs.path", m.Conf("compile", "bench"))); m.Result(0) == "" {
|
||||||
@ -510,13 +547,14 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(arg) > 0 && arg[0] == "all" {
|
if len(arg) > 0 && arg[0] == "all" {
|
||||||
m.Cmdy("cli.compile", "linux", "386")
|
m.Cmdp(time.Second, []string{"go build"}, []string{"cli.compile"}, [][]string{
|
||||||
m.Cmdy("cli.compile", "linux", "amd64")
|
[]string{"linux", "386"},
|
||||||
m.Cmdy("cli.compile", "linux", "arm")
|
[]string{"linux", "amd64"},
|
||||||
m.Cmdy("cli.compile", "windows", "386")
|
[]string{"linux", "arm"},
|
||||||
m.Cmdy("cli.compile", "windows", "amd64")
|
[]string{"windows", "386"},
|
||||||
m.Cmdy("cli.compile", "darwin", "amd64")
|
[]string{"windows", "amd64"},
|
||||||
m.Set("result").Table()
|
[]string{"darwin", "amd64"},
|
||||||
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -547,7 +585,17 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
|
|||||||
dir := m.Conf("publish", "path")
|
dir := m.Conf("publish", "path")
|
||||||
m.Assert(os.MkdirAll(dir, 0777))
|
m.Assert(os.MkdirAll(dir, 0777))
|
||||||
|
|
||||||
m.Confm("publish", "list", func(key string, value string) {
|
if len(arg) == 0 {
|
||||||
|
list := [][]string{}
|
||||||
|
m.Confm("publish", "list", func(key string, value string) {
|
||||||
|
list = append(list, []string{key})
|
||||||
|
})
|
||||||
|
m.Cmdp(time.Second, []string{"copy"}, []string{"cli.publish"}, list)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, key := range arg {
|
||||||
|
value := m.Conf("publish", []string{"list", key})
|
||||||
p := m.Cmdx("nfs.path", value)
|
p := m.Cmdx("nfs.path", value)
|
||||||
if s, e := os.Stat(p); e == nil {
|
if s, e := os.Stat(p); e == nil {
|
||||||
if s.IsDir() {
|
if s.IsDir() {
|
||||||
@ -555,18 +603,24 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
|
|||||||
} else {
|
} else {
|
||||||
m.Cmd("nfs.copy", path.Join(dir, key), p)
|
m.Cmd("nfs.copy", path.Join(dir, key), p)
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
m.Cmdy("nfs.dir", dir, "dir_sort", "time", "time_r")
|
|
||||||
|
// m.Cmdy("nfs.dir", dir, "dir_sort", "time", "time_r")
|
||||||
|
|
||||||
return
|
return
|
||||||
}},
|
}},
|
||||||
"upgrade": &ctx.Command{Name: "upgrade bench|system|extend|plugin|portal|client|script", Help: "服务升级", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
"upgrade": &ctx.Command{Name: "upgrade bench|system|extend|plugin|portal|client|script|project", Help: "服务升级", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
||||||
if len(arg) == 0 {
|
if len(arg) == 0 {
|
||||||
m.Cmdy("ctx.config", "upgrade")
|
m.Cmdy("ctx.config", "upgrade")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if len(arg) > 0 && arg[0] == "project" {
|
||||||
|
m.Cmd("cli.project", "init")
|
||||||
|
m.Cmd("cli.compile", "all")
|
||||||
|
m.Cmd("cli.publish")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
restart := false
|
restart := false
|
||||||
for _, link := range kit.View([]string{arg[0]}, m.Confm("upgrade")) {
|
for _, link := range kit.View([]string{arg[0]}, m.Confm("upgrade")) {
|
||||||
|
@ -1230,6 +1230,14 @@ func (m *Message) Log(action string, str string, arg ...interface{}) *Message {
|
|||||||
|
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
func (m *Message) Show(args ...interface{}) *Message {
|
||||||
|
if m.Option("cli.modal") == "action" {
|
||||||
|
fmt.Printf(kit.Format(args...))
|
||||||
|
} else if kit.STDIO != nil {
|
||||||
|
kit.STDIO.Show(args...)
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
func (m *Message) Assert(e interface{}, msg ...string) bool {
|
func (m *Message) Assert(e interface{}, msg ...string) bool {
|
||||||
switch v := e.(type) {
|
switch v := e.(type) {
|
||||||
case nil:
|
case nil:
|
||||||
@ -1541,6 +1549,19 @@ func (m *Message) Free(cbs ...func(msg *Message) (done bool)) *Message {
|
|||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Message) Cmdp(t time.Duration, head []string, prefix []string, suffix [][]string) *Message {
|
||||||
|
if head != nil && len(head) > 0 {
|
||||||
|
m.Show(strings.Join(head, " "), "...\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, v := range suffix {
|
||||||
|
m.Show(fmt.Sprintf("%v/%v %v...\n", i+1, len(suffix), v))
|
||||||
|
m.Cmd(prefix, v)
|
||||||
|
time.Sleep(t)
|
||||||
|
}
|
||||||
|
m.Show("\n")
|
||||||
|
return m
|
||||||
|
}
|
||||||
func (m *Message) Cmdm(args ...interface{}) *Message {
|
func (m *Message) Cmdm(args ...interface{}) *Message {
|
||||||
m.Log("info", "current: %v", m.Magic("session", "current"))
|
m.Log("info", "current: %v", m.Magic("session", "current"))
|
||||||
|
|
||||||
|
@ -151,7 +151,9 @@ var Index = &ctx.Context{Name: "log", Help: "日志中心",
|
|||||||
"search": map[string]interface{}{"value": []interface{}{"debug"}},
|
"search": map[string]interface{}{"value": []interface{}{"debug"}},
|
||||||
"call": map[string]interface{}{"value": []interface{}{"debug"}},
|
"call": map[string]interface{}{"value": []interface{}{"debug"}},
|
||||||
"back": map[string]interface{}{"value": []interface{}{"debug"}},
|
"back": map[string]interface{}{"value": []interface{}{"debug"}},
|
||||||
"send": map[string]interface{}{"value": []interface{}{"debug"}},
|
|
||||||
|
"send": map[string]interface{}{"value": []interface{}{"debug"}},
|
||||||
|
"recv": map[string]interface{}{"value": []interface{}{"debug"}},
|
||||||
|
|
||||||
"bench": map[string]interface{}{"value": []interface{}{"bench"}},
|
"bench": map[string]interface{}{"value": []interface{}{"bench"}},
|
||||||
"begin": map[string]interface{}{"value": []interface{}{"bench", "red"}},
|
"begin": map[string]interface{}{"value": []interface{}{"bench", "red"}},
|
||||||
|
@ -784,6 +784,10 @@ func (nfs *NFS) printf(arg ...interface{}) *NFS {
|
|||||||
}
|
}
|
||||||
return nfs
|
return nfs
|
||||||
}
|
}
|
||||||
|
func (nfs *NFS) Show(arg ...interface{}) bool {
|
||||||
|
nfs.prompt(arg...)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (nfs *NFS) Recv(line string) (field string, value string) {
|
func (nfs *NFS) Recv(line string) (field string, value string) {
|
||||||
m := nfs.Context.Message()
|
m := nfs.Context.Message()
|
||||||
@ -885,6 +889,7 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool {
|
|||||||
// 终端控制
|
// 终端控制
|
||||||
if nfs.in = m.Optionv("in").(*os.File); m.Has("out") {
|
if nfs.in = m.Optionv("in").(*os.File); m.Has("out") {
|
||||||
if nfs.out = m.Optionv("out").(*os.File); m.Cap("goos") != "windows" && !m.Options("daemon") {
|
if nfs.out = m.Optionv("out").(*os.File); m.Cap("goos") != "windows" && !m.Options("daemon") {
|
||||||
|
kit.STDIO = nfs
|
||||||
nfs.Term(m, "init")
|
nfs.Term(m, "init")
|
||||||
defer nfs.Term(m, "exit")
|
defer nfs.Term(m, "exit")
|
||||||
}
|
}
|
||||||
|
@ -768,6 +768,15 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
|
|||||||
return
|
return
|
||||||
}},
|
}},
|
||||||
"brow": &ctx.Command{Name: "brow url", Help: "浏览网页", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
"brow": &ctx.Command{Name: "brow url", Help: "浏览网页", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
||||||
|
if len(arg) == 0 {
|
||||||
|
m.Cmd("tcp.ifconfig").Table(func(index int, value map[string]string) {
|
||||||
|
m.Append("index", index)
|
||||||
|
m.Append("site", fmt.Sprintf("%s://%s%s", m.Conf("serve", "protocol"), value["ip"], m.Conf("runtime", "boot.web_port")))
|
||||||
|
})
|
||||||
|
m.Table()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
switch runtime.GOOS {
|
switch runtime.GOOS {
|
||||||
case "windows":
|
case "windows":
|
||||||
m.Cmd("cli.system", "explorer", arg[0])
|
m.Cmd("cli.system", "explorer", arg[0])
|
||||||
@ -1113,6 +1122,22 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
|
|||||||
m.Cmdy("web.get", "which", fields[2], "method", fields[3], strings.Join(fields, "/"))
|
m.Cmdy("web.get", "which", fields[2], "method", fields[3], strings.Join(fields, "/"))
|
||||||
return
|
return
|
||||||
}},
|
}},
|
||||||
|
|
||||||
|
"/publish/": &ctx.Command{Name: "/publish/", Help: "下载文件", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
||||||
|
key = strings.TrimPrefix(key, "/publish/")
|
||||||
|
if strings.HasSuffix(key, "bench") {
|
||||||
|
key = key + "." + m.Option("GOOS") + "." + m.Option("GOARCH")
|
||||||
|
}
|
||||||
|
key = strings.Replace(key, ".", "_", -1)
|
||||||
|
p := m.Cmdx("nfs.path", path.Join(m.Conf("publish", "path"), key))
|
||||||
|
if p == "" {
|
||||||
|
p = m.Cmdx("nfs.path", m.Conf("publish", []string{"list", key}))
|
||||||
|
}
|
||||||
|
|
||||||
|
m.Log("info", "publish %s %s", kit.Hashs(p), p)
|
||||||
|
http.ServeFile(m.Optionv("response").(http.ResponseWriter), m.Optionv("request").(*http.Request), p)
|
||||||
|
return
|
||||||
|
}},
|
||||||
"/shadow": &ctx.Command{Name: "/shadow", Help: "暗网", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
"/shadow": &ctx.Command{Name: "/shadow", Help: "暗网", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
||||||
m.Confm("runtime", "node.port", func(index int, value string) {
|
m.Confm("runtime", "node.port", func(index int, value string) {
|
||||||
m.Add("append", "ports", value)
|
m.Add("append", "ports", value)
|
||||||
@ -1149,22 +1174,6 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}},
|
}},
|
||||||
|
|
||||||
"/publish/": &ctx.Command{Name: "/publish/", Help: "下载文件", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
|
||||||
key = strings.TrimPrefix(key, "/publish/")
|
|
||||||
if strings.HasSuffix(key, "bench") {
|
|
||||||
key = key + "." + m.Option("GOOS") + "." + m.Option("GOARCH")
|
|
||||||
}
|
|
||||||
key = strings.Replace(key, ".", "_", -1)
|
|
||||||
p := m.Cmdx("nfs.path", path.Join(m.Conf("publish", "path"), key))
|
|
||||||
if p == "" {
|
|
||||||
p = m.Cmdx("nfs.path", m.Conf("publish", []string{"list", key}))
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Log("info", "publish %s %s", kit.Hashs(p), p)
|
|
||||||
http.ServeFile(m.Optionv("response").(http.ResponseWriter), m.Optionv("request").(*http.Request), p)
|
|
||||||
return
|
|
||||||
}},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,8 @@ var Index = &ctx.Context{Name: "code", Help: "代码中心",
|
|||||||
map[string]interface{}{"name": "viewport", "content": "width=device-width, initial-scale=0.7, user-scalable=no"},
|
map[string]interface{}{"name": "viewport", "content": "width=device-width, initial-scale=0.7, user-scalable=no"},
|
||||||
}, "favicon": "favicon.ico", "styles": []interface{}{"example.css", "code.css"}},
|
}, "favicon": "favicon.ico", "styles": []interface{}{"example.css", "code.css"}},
|
||||||
|
|
||||||
map[string]interface{}{"componet_name": "login", "componet_help": "login", "componet_tmpl": "componet",
|
map[string]interface{}{"componet_name": "login", "componet_help": "login",
|
||||||
|
"componet_tmpl": "componet", "componet_init": "initLogin",
|
||||||
"componet_ctx": "aaa", "componet_cmd": "auth", "componet_args": []interface{}{"@sessid", "ship", "username", "@username", "password", "@password"}, "inputs": []interface{}{
|
"componet_ctx": "aaa", "componet_cmd": "auth", "componet_args": []interface{}{"@sessid", "ship", "username", "@username", "password", "@password"}, "inputs": []interface{}{
|
||||||
map[string]interface{}{"type": "text", "name": "username", "value": "", "label": "username"},
|
map[string]interface{}{"type": "text", "name": "username", "value": "", "label": "username"},
|
||||||
map[string]interface{}{"type": "password", "name": "password", "value": "", "label": "password"},
|
map[string]interface{}{"type": "password", "name": "password", "value": "", "label": "password"},
|
||||||
|
@ -16,6 +16,12 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type TERM interface {
|
||||||
|
Show(...interface{}) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
var STDIO TERM
|
||||||
|
|
||||||
var DisableLog = false
|
var DisableLog = false
|
||||||
var EnableDebug = false
|
var EnableDebug = false
|
||||||
|
|
||||||
|
@ -1,609 +1,4 @@
|
|||||||
var page = Page({
|
page({
|
||||||
initComList: function(page, field, option, append, result) {
|
init: function() {
|
||||||
return
|
|
||||||
},
|
|
||||||
|
|
||||||
initScheduleText: function(page, field, option, append, result) {
|
|
||||||
option.ondaemon = function(msg) {
|
|
||||||
page.reload()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
initScheduleList: function(page, field, option) {
|
|
||||||
ctx.Runs(page, option)
|
|
||||||
},
|
|
||||||
|
|
||||||
initFlashText: function(page, field, option, append, result) {
|
|
||||||
option.ondaemon = function(msg) {
|
|
||||||
page.reload()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
initFlashList: function(page, field, option) {
|
|
||||||
option.dataset.flash_index = ctx.Search("flash_index")
|
|
||||||
option.ondaemon = function(msg) {
|
|
||||||
page.showFlashList(msg, field, option)
|
|
||||||
}
|
|
||||||
ctx.Runs(page, option)
|
|
||||||
},
|
|
||||||
showFlashList: function(msg, field, option) {
|
|
||||||
var page = this
|
|
||||||
var result = field.querySelector("div.result")
|
|
||||||
|
|
||||||
result.innerHTML = ""
|
|
||||||
ctx.Table(msg, function(tip) {
|
|
||||||
var ui = kit.AppendChild(result, [{"list": [
|
|
||||||
{"text": [tip.text, "div", "detail"]},
|
|
||||||
{"code": [tip.code, "result", "result"]},
|
|
||||||
{"view": ["action"], "list": [
|
|
||||||
{"button": ["查看详情", function(event) {
|
|
||||||
ctx.Search("flash_index", tip.index)
|
|
||||||
}]},
|
|
||||||
{"button": ["执行代码", function(event) {
|
|
||||||
tip.code && ctx.Run(page, option.dataset, [tip.index, "run"], function(msg) {
|
|
||||||
ui.output.innerText = msg.result
|
|
||||||
})
|
|
||||||
}]},
|
|
||||||
{"button": ["清空结果", function(event) {
|
|
||||||
ui.output.innerText = ""
|
|
||||||
}]},
|
|
||||||
]},
|
|
||||||
{"code": [tip.output, "output", "output"]},
|
|
||||||
]}])
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
initKitList: function(page, field, option, append, result) {
|
|
||||||
var ui = kit.AppendChild(field, [
|
|
||||||
{"styles": {
|
|
||||||
"fieldset.KitList": {
|
|
||||||
"top": conf.toolkit_view.top, "left": conf.toolkit_view.left,
|
|
||||||
},
|
|
||||||
"fieldset.KitList:hover, fieldset.KitList.max": {
|
|
||||||
"width": conf.toolkit_view.width, "height": conf.toolkit_view.height,
|
|
||||||
},
|
|
||||||
}},
|
|
||||||
{"type": "ul", "list": [
|
|
||||||
{"fork": ["粘贴板", [
|
|
||||||
{"leaf": ["+ 保存粘贴板(Ctrl+S)", function(event) {
|
|
||||||
console.log("save_txt")
|
|
||||||
}]},
|
|
||||||
{"leaf": ["+ 添加粘贴板(Ctrl+Y)", function(event) {
|
|
||||||
console.log("create_txt")
|
|
||||||
}]},
|
|
||||||
{"leaf": ["+ 快捷粘贴板(Ctrl+P)", function(event) {
|
|
||||||
console.log("quick_txt")
|
|
||||||
}]},
|
|
||||||
]]},
|
|
||||||
{"fork": ["命令行", [
|
|
||||||
{"leaf": ["+ 折叠命令行(Ctrl+Z)", function(event, target) {
|
|
||||||
target.className = page.conf.show_result? "": "stick"
|
|
||||||
page.showResult(page)
|
|
||||||
}]},
|
|
||||||
{"leaf": ["+ 添加命令行(Ctrl+M)", function(event) {
|
|
||||||
page.addCmdList("cmd", page.conf.ncommand++)
|
|
||||||
}]},
|
|
||||||
]]},
|
|
||||||
{"fork": ["工作流", [
|
|
||||||
{"leaf": ["+ 刷新工作流(Ctrl+R)", function(event) {
|
|
||||||
console.log("refresh_fly")
|
|
||||||
}]},
|
|
||||||
{"leaf": ["+ 添加工作流(Ctrl+T)", function(event) {
|
|
||||||
console.log("create_fly")
|
|
||||||
}]},
|
|
||||||
{"leaf": ["+ 命名工作流", function(event) {
|
|
||||||
console.log("rename_fly")
|
|
||||||
}]},
|
|
||||||
{"leaf": ["+ 删除工作流", function(event) {
|
|
||||||
console.log("remove_fly")
|
|
||||||
}]},
|
|
||||||
]]},
|
|
||||||
]},
|
|
||||||
])
|
|
||||||
/*
|
|
||||||
<li><div>命令行</div>
|
|
||||||
<ul class="cmd">
|
|
||||||
{{range $name, $cmd := conf . "toolkit"}}
|
|
||||||
<li>{{$name}} <input type="text" data-cmd="{{$name}}" onkeyup="onaction(event, 'toolkit')"><label class="result"></label></li>
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
<li class="stick" data-action="shrink_cmd">+ 折叠命令行(Ctrl+Z)</li>
|
|
||||||
<li data-action="create_cmd">+ 添加命令行(Ctrl+M)</li>
|
|
||||||
{{range $index, $cmd := index $bench_data "commands"}}
|
|
||||||
<li class="cmd{{$index}}" data-cmd="{{$index}}">{{index $cmd "now"|option}} {{$index}}: {{index $cmd "cmd"|option}}</li>
|
|
||||||
{{end}}
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><div>工作流</div>
|
|
||||||
<ul class="fly">
|
|
||||||
<li data-action="refresh_fly">+ 刷新工作流(Ctrl+R)</li>
|
|
||||||
<li data-action="create_fly">+ 添加工作流(Ctrl+T)</li>
|
|
||||||
{{range $key, $item := work .}}
|
|
||||||
<li data-key="{{$key}}">{{index $item "create_time"}} {{index $item "data" "name"}}({{slice $key 0 6}})</li>
|
|
||||||
{{end}}
|
|
||||||
<li data-action="rename_fly">+ 命名工作流</li>
|
|
||||||
<li data-action="remove_fly">+ 删除工作流</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
*/
|
|
||||||
return
|
|
||||||
|
|
||||||
text = JSON.parse(bench_data.clipstack || "[]")
|
|
||||||
for (var i = 0; i < text.length; i++) {
|
|
||||||
copy_to_clipboard(text[i])
|
|
||||||
}
|
|
||||||
bench_data.board = bench_data.board || {}
|
|
||||||
|
|
||||||
document.querySelectorAll("div.workflow").forEach(function(workflow) {
|
|
||||||
// 移动面板
|
|
||||||
workflow.style.left = context.Cookie("toolkit_left")
|
|
||||||
workflow.style.top = context.Cookie("toolkit_top")
|
|
||||||
var moving = false, left0 = 0, top0 = 0, x0 = 0, y0 = 0
|
|
||||||
workflow.onclick = function(event) {
|
|
||||||
if (event.target != workflow) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
moving = !moving
|
|
||||||
if (moving) {
|
|
||||||
left0 = workflow.offsetLeft
|
|
||||||
top0 = workflow.offsetTop
|
|
||||||
x0 = event.clientX
|
|
||||||
y0 = event.clientY
|
|
||||||
}
|
|
||||||
}
|
|
||||||
workflow.onmousemove = function(event) {
|
|
||||||
if (moving) {
|
|
||||||
workflow.style.left = (left0+(event.clientX-x0))+"px"
|
|
||||||
workflow.style.top = (top0+(event.clientY-y0))+"px"
|
|
||||||
context.Cookie("toolkit_left", workflow.style.left)
|
|
||||||
context.Cookie("toolkit_top", workflow.style.top)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 固定面板
|
|
||||||
if (context.Cookie("toolkit_class")) {
|
|
||||||
workflow.className = context.Cookie("toolkit_class")
|
|
||||||
}
|
|
||||||
var head = workflow.querySelector("div")
|
|
||||||
head.onclick = function(event) {
|
|
||||||
head.dataset["show"] = !right(head.dataset["show"])
|
|
||||||
workflow.className = right(head.dataset["show"])? "workflow max": "workflow"
|
|
||||||
context.Cookie("toolkit_class", workflow.className)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 折叠目录
|
|
||||||
var toolkit = workflow.querySelector("ul.toolkit")
|
|
||||||
toolkit.querySelectorAll("li>div").forEach(function(menu) {
|
|
||||||
menu.onclick = function(event) {
|
|
||||||
menu.dataset["hide"] = !right(menu.dataset["hide"])
|
|
||||||
menu.nextElementSibling.style.display = right(menu.dataset["hide"])? "none": ""
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// 事件
|
|
||||||
toolkit.querySelectorAll("li>ul>li").forEach(function(item) {
|
|
||||||
// if (bench_data.board["key"] == item.dataset["key"]) {
|
|
||||||
// // item.className = "stick"
|
|
||||||
// }
|
|
||||||
|
|
||||||
item.onclick = function(event) {
|
|
||||||
var target = event.target
|
|
||||||
var data = item.dataset
|
|
||||||
switch (data["action"]) {
|
|
||||||
case "quick_txt":
|
|
||||||
code.quick_txt = !code.quick_txt
|
|
||||||
target.className= code.quick_txt? "stick": ""
|
|
||||||
break
|
|
||||||
case "copy_txt":
|
|
||||||
if (event.altKey) {
|
|
||||||
target.parentElement.removeChild(target)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (event.shiftKey) {
|
|
||||||
var cmd = document.querySelector("form.option.cmd"+code.current_cmd+" input[name=cmd]")
|
|
||||||
cmd && (cmd.value += " "+text)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
copy_to_clipboard(data["text"], true)
|
|
||||||
break
|
|
||||||
case "save_txt":
|
|
||||||
save_clipboard(item)
|
|
||||||
return
|
|
||||||
case "create_txt":
|
|
||||||
var text = prompt("text")
|
|
||||||
text && copy_to_clipboard(text)
|
|
||||||
return
|
|
||||||
case "refresh_fly":
|
|
||||||
location.reload()
|
|
||||||
return
|
|
||||||
case "create_fly":
|
|
||||||
context.Command(["sess", "bench", "create"], function(msg) {
|
|
||||||
context.Search("bench", msg.result[0])
|
|
||||||
})
|
|
||||||
return
|
|
||||||
case "rename_fly":
|
|
||||||
context.Command(["work", context.Search("bench"), "rename", prompt("name")], function() {
|
|
||||||
location.reload()
|
|
||||||
})
|
|
||||||
return
|
|
||||||
case "remove_fly":
|
|
||||||
var b = ""
|
|
||||||
document.querySelectorAll("div.workflow>ul.toolkit>li>ul.fly>li[data-key]").forEach(function(item){
|
|
||||||
if (!b && item.dataset["key"] != context.Search("bench")) {
|
|
||||||
b = item.dataset["key"]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
context.Search("bench", b)
|
|
||||||
context.Command(["work", context.Search("bench"), "delete"])
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 切换工作流
|
|
||||||
if (data["key"] && data["key"] != context.Search("bench")) {
|
|
||||||
context.Search("bench", data["key"])
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 切换命令行
|
|
||||||
var cmd = document.querySelector("form.option.cmd"+data["cmd"]+" input[name=cmd]")
|
|
||||||
cmd && cmd.focus()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
return
|
|
||||||
},
|
|
||||||
|
|
||||||
initDirList: function(page, field, option, append, result) {
|
|
||||||
var history = []
|
|
||||||
function change(value) {
|
|
||||||
return page.setCurrent(page, option, "dir", value)
|
|
||||||
}
|
|
||||||
function brow(value, dir, event) {
|
|
||||||
page.setCurrent(page, option, "dir", value)
|
|
||||||
page.setCurrent(page, option, "dir", dir)
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
"button": ["root", "back"], "action": function(value) {
|
|
||||||
switch (value) {
|
|
||||||
case "back": history.length > -1 && change(history.pop() || "/"); break
|
|
||||||
case "root": change("/"); break
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"table": {"filename": function(value, key, row, index, event) {
|
|
||||||
var dir = option.dir.value
|
|
||||||
var file = dir + ((dir && !dir.endsWith("/"))? "/": "") + value
|
|
||||||
file.endsWith("/")? history.push(change(file)): brow(file, dir, event)
|
|
||||||
}},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
initPodList: function(page, field, option, append, result) {
|
|
||||||
return {"button": ["local"], "action": function(value) {
|
|
||||||
value == "local" && (value = "''")
|
|
||||||
page.setCurrent(page, option, "pod", value)
|
|
||||||
}, "table": {"key": function(value) {
|
|
||||||
page.setCurrent(page, option, "pod", value)
|
|
||||||
}}}
|
|
||||||
},
|
|
||||||
initCtxList: function(page, field, option, append, result) {
|
|
||||||
return {"button": ["ctx", "shy", "web", "mdb"], "action": function(value) {
|
|
||||||
page.setCurrent(page, option, "ctx", value)
|
|
||||||
}, "table": {"names": function(value) {
|
|
||||||
page.setCurrent(page, option, "ctx", value)
|
|
||||||
}}}
|
|
||||||
},
|
|
||||||
setCurrent: function(page, option, type, value) {
|
|
||||||
option[type].value = ctx.Current(type, value)
|
|
||||||
page.History.add(type, value)
|
|
||||||
ctx.Runs(page, option)
|
|
||||||
return value
|
|
||||||
},
|
|
||||||
|
|
||||||
initCmdList: function(page, field, option, append, result) {
|
|
||||||
option.dataset["componet_name_alias"] = "cmd"
|
|
||||||
option.dataset["componet_name_order"] = 0
|
|
||||||
|
|
||||||
var cmd = option.querySelector("input[name=cmd]")
|
|
||||||
cmd.onkeyup = function(event) {
|
|
||||||
page.onCmdList(event, cmd, "input", field, option, append, result)
|
|
||||||
}
|
|
||||||
|
|
||||||
var action = conf.bench_data.action
|
|
||||||
action && action["cmd"] && page.runCmdList(page, option, cmd, action["cmd"].cmd[1])
|
|
||||||
|
|
||||||
var max = 0
|
|
||||||
for (var k in action) {
|
|
||||||
var order = parseInt(action[k].order)
|
|
||||||
order > max && (max = order)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = 1; i <= max; i++) {
|
|
||||||
var ui = page.addCmdList("cmd", i)
|
|
||||||
action["cmd"+i] && page.runCmdList(page, ui.option, ui.cmd, action["cmd"+i].cmd[1])
|
|
||||||
}
|
|
||||||
page.conf.ncommand = i
|
|
||||||
return
|
|
||||||
},
|
|
||||||
runCmdList: function(page, option, target, value) {
|
|
||||||
target.value = value
|
|
||||||
target.dataset.history_last = kit.History.add("cmd", target.value)
|
|
||||||
ctx.Runs(page, option)
|
|
||||||
},
|
|
||||||
getCmdList: function(input, step, cmd) {
|
|
||||||
var history = kit.History.get("cmd")
|
|
||||||
var length = history.length
|
|
||||||
var last = (parseInt(input.dataset["history_last"]||length)+step+length)%length
|
|
||||||
if (0 <= last && last < length) {
|
|
||||||
input.dataset["history_last"] = last
|
|
||||||
cmd = history[last].data
|
|
||||||
}
|
|
||||||
return cmd
|
|
||||||
},
|
|
||||||
addCmdList: function(name, order) {
|
|
||||||
var page = this
|
|
||||||
var alias = name+order
|
|
||||||
var ui = kit.AppendChild(document.body, [{"view": ["CmdList", "fieldset"], "list": [
|
|
||||||
{"text": [alias, "legend"]},
|
|
||||||
{"view": ["option "+alias, "form", "", "option"],
|
|
||||||
"data": {"dataset": {
|
|
||||||
"componet_group": "index", "componet_name": name, "componet_name_alias": alias, "componet_name_order": order,
|
|
||||||
}},
|
|
||||||
"list": [
|
|
||||||
{"type": "input", "data": {"style": {"display": "none"}}},
|
|
||||||
{"name": "cmd", "type": "input", "data": {"name": "cmd", "className": "cmd", "onkeyup": function(event) {
|
|
||||||
page.onCmdList(event, ui.cmd, "input", ui.field, ui.option, ui.append, ui.result)
|
|
||||||
}}},
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{"view": ["append "+alias, "table", "", "append"]},
|
|
||||||
{"code": ["", "result", "result "+alias]},
|
|
||||||
]}])
|
|
||||||
|
|
||||||
kit.OrderForm(page, ui.field, ui.option, ui.append, ui.result)
|
|
||||||
kit.OrderTable(ui.append)
|
|
||||||
kit.OrderCode(ui.result)
|
|
||||||
ui.cmd.focus()
|
|
||||||
return ui
|
|
||||||
},
|
|
||||||
delCmdList: function(name, order) {
|
|
||||||
var option = document.querySelector("form.option.cmd"+order)
|
|
||||||
option && document.body.removeChild(option.parentElement)
|
|
||||||
|
|
||||||
for (;order < page.conf.ncommand; order++) {
|
|
||||||
var input = document.querySelector("form.option.cmd"+order+" input[name=cmd]")
|
|
||||||
if (input) {
|
|
||||||
input.focus()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (;order >= 0; order--) {
|
|
||||||
var input = document.querySelector("form.option.cmd"+(order? order: "")+" input[name=cmd]")
|
|
||||||
page.conf.ncommand = order+1
|
|
||||||
if (input) {
|
|
||||||
input.focus()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onCmdList: function(event, target, action, field, option, append, result) {
|
|
||||||
var page = this
|
|
||||||
var order = option.dataset.componet_name_order
|
|
||||||
var prev_order = (parseInt(order)-1+page.conf.ncommand)%page.conf.ncommand||""
|
|
||||||
var next_order = (parseInt(order)+1)%page.conf.ncommand||""
|
|
||||||
|
|
||||||
switch (action) {
|
|
||||||
case "input":
|
|
||||||
kit.History.add("key", (event.ctrlKey? "Control+": "")+(event.shiftKey? "Shift+": "")+event.key)
|
|
||||||
|
|
||||||
if (event.key == "Escape") {
|
|
||||||
target.blur()
|
|
||||||
|
|
||||||
} else if (event.key == "Enter") {
|
|
||||||
page.runCmdList(page, option, target, target.value)
|
|
||||||
|
|
||||||
} else if (event.ctrlKey) {
|
|
||||||
switch (event.key) {
|
|
||||||
case "0":
|
|
||||||
var pre_pre = document.querySelector("code.result.cmd"+(event.shiftKey? next_order: prev_order)+" pre")
|
|
||||||
pre_pre && (target.value += pre_pre.innerText)
|
|
||||||
break
|
|
||||||
case "1":
|
|
||||||
case "2":
|
|
||||||
case "3":
|
|
||||||
case "4":
|
|
||||||
case "5":
|
|
||||||
case "6":
|
|
||||||
case "7":
|
|
||||||
case "8":
|
|
||||||
case "9":
|
|
||||||
if (code.quick_txt) {
|
|
||||||
var item = document.querySelectorAll("div.workflow>ul>li>ul.txt>li[data-text]")
|
|
||||||
target.value += item[parseInt(event.key)-1].dataset["text"]
|
|
||||||
} else {
|
|
||||||
var item = document.querySelectorAll("table.append.cmd"+(event.shiftKey? next_order: prev_order)+" td")
|
|
||||||
target.value += item[parseInt(event.key)-1].innerText
|
|
||||||
}
|
|
||||||
break
|
|
||||||
case "p":
|
|
||||||
target.value = page.getCmdList(target, -1, target.value)
|
|
||||||
break
|
|
||||||
case "n":
|
|
||||||
target.value = page.getCmdList(target, 1, target.value)
|
|
||||||
break
|
|
||||||
case "g":
|
|
||||||
var value = target.value.substr(0, target.selectionStart)
|
|
||||||
var last = parseInt(target.dataset.search_last || kit.History.get("cmd").length-1)
|
|
||||||
for (var i = last; i >= 0; i--) {
|
|
||||||
var cmd = kit.History.get("cmd", i).data
|
|
||||||
if (cmd.startsWith(value)) {
|
|
||||||
target.value = cmd
|
|
||||||
target.dataset.search_last = i-1
|
|
||||||
target.setSelectionRange(value.length, cmd.length)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
target.dataset.search_last = ""
|
|
||||||
break
|
|
||||||
|
|
||||||
case "y":
|
|
||||||
case "v":
|
|
||||||
case "s":
|
|
||||||
case "t":
|
|
||||||
break
|
|
||||||
|
|
||||||
case "a":
|
|
||||||
case "e":
|
|
||||||
case "f":
|
|
||||||
case "b":
|
|
||||||
case "h":
|
|
||||||
case "d":
|
|
||||||
break
|
|
||||||
case "k":
|
|
||||||
kit.DelText(target, target.selectionStart)
|
|
||||||
break
|
|
||||||
case "u":
|
|
||||||
kit.DelText(target, 0, target.selectionEnd)
|
|
||||||
break
|
|
||||||
case "w":
|
|
||||||
var start = target.selectionStart-2
|
|
||||||
var end = target.selectionEnd-1
|
|
||||||
for (var i = start; i >= 0; i--) {
|
|
||||||
if (target.value[end] == " " && target.value[i] != " ") {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if (target.value[end] != " " && target.value[i] == " ") {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
kit.DelText(target, i+1, end-i)
|
|
||||||
break
|
|
||||||
|
|
||||||
case "c":
|
|
||||||
append.innerHTML = ""
|
|
||||||
result.innerHTML = ""
|
|
||||||
break
|
|
||||||
case "r":
|
|
||||||
append.innerHTML = ""
|
|
||||||
result.innerHTML = ""
|
|
||||||
case "j":
|
|
||||||
page.runCmdList(page, option, target, target.value)
|
|
||||||
break
|
|
||||||
case "l":
|
|
||||||
window.scrollTo(0, option.parentElement.offsetTop)
|
|
||||||
break
|
|
||||||
case "m":
|
|
||||||
page.addCmdList("cmd", page.conf.ncommand++)
|
|
||||||
break
|
|
||||||
case "i":
|
|
||||||
var input = document.querySelector("form.option.cmd"+next_order+" input[name=cmd]")
|
|
||||||
input && input.focus()
|
|
||||||
break
|
|
||||||
case "o":
|
|
||||||
var input = document.querySelector("form.option.cmd"+prev_order+" input[name=cmd]")
|
|
||||||
input && input.focus()
|
|
||||||
break
|
|
||||||
case "x":
|
|
||||||
result.style.height = result.style.height? "": page.conf.hide_height
|
|
||||||
break
|
|
||||||
case "z":
|
|
||||||
result.style.height = result.style.height? "": page.conf.show_height
|
|
||||||
break
|
|
||||||
case "q":
|
|
||||||
page.delCmdList("cmd", order)
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (kit.HitText(target, "jk")) {
|
|
||||||
kit.DelText(target, target.selectionStart-2, 2)
|
|
||||||
target.blur()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
event.stopPropagation()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
onaction: function(event, target, action) {
|
|
||||||
var page = this
|
|
||||||
switch (action) {
|
|
||||||
case "scroll":
|
|
||||||
break
|
|
||||||
case "keymap":
|
|
||||||
if (event.key == "Escape") {
|
|
||||||
|
|
||||||
} else if (event.key == "Enter") {
|
|
||||||
|
|
||||||
} else if (event.ctrlKey) {
|
|
||||||
switch (event.key) {
|
|
||||||
case "m":
|
|
||||||
page.addCmdList("cmd", page.conf.ncommand++)
|
|
||||||
break
|
|
||||||
case "z":
|
|
||||||
page.showResult(page)
|
|
||||||
break
|
|
||||||
case "0":
|
|
||||||
case "1":
|
|
||||||
case "2":
|
|
||||||
case "3":
|
|
||||||
case "4":
|
|
||||||
case "5":
|
|
||||||
case "6":
|
|
||||||
case "7":
|
|
||||||
case "8":
|
|
||||||
case "9":
|
|
||||||
document.querySelector("form.option.cmd"+(event.key||"")+" input[name=cmd]").focus()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
showResult: function(page, type) {
|
|
||||||
page.conf.show_result = !page.conf.show_result
|
|
||||||
document.querySelectorAll("body>fieldset>code.result>pre").forEach(function(result) {
|
|
||||||
result.style.height = (page.conf.show_result || result.innerText=="")? "": page.conf.show_height
|
|
||||||
})
|
|
||||||
},
|
|
||||||
init: function(exp) {
|
|
||||||
var page = this
|
|
||||||
var body = document.body
|
|
||||||
body.onkeyup = function(event) {
|
|
||||||
page.onaction(event, body, "keymap")
|
|
||||||
}
|
|
||||||
|
|
||||||
document.querySelectorAll("body>fieldset").forEach(function(field) {
|
|
||||||
var option = field.querySelector("form.option")
|
|
||||||
var append = field.querySelector("table.append")
|
|
||||||
var result = field.querySelector("code.result pre")
|
|
||||||
kit.OrderForm(page, field, option, append, result)
|
|
||||||
append && kit.OrderTable(append)
|
|
||||||
result && kit.OrderCode(result)
|
|
||||||
|
|
||||||
var init = page[field.dataset.init]
|
|
||||||
if (typeof init == "function") {
|
|
||||||
var conf = init(page, field, option, append, result)
|
|
||||||
if (conf && conf["button"]) {
|
|
||||||
var buttons = []
|
|
||||||
conf.button.forEach(function(value, index) {
|
|
||||||
buttons.push({"button": [value, function(event) {
|
|
||||||
typeof conf["action"] == "function" && conf["action"](value, event)
|
|
||||||
}]})
|
|
||||||
})
|
|
||||||
kit.InsertChild(field, append, "div", buttons)
|
|
||||||
}
|
|
||||||
if (conf && conf["table"]) {
|
|
||||||
option.daemon_action = conf["table"]
|
|
||||||
ctx.Runs(page, option)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
conf: {
|
|
||||||
scroll_x: 50,
|
|
||||||
scroll_y: 50,
|
|
||||||
|
|
||||||
ncommand: 1,
|
|
||||||
show_result: true,
|
|
||||||
show_height: "30px",
|
|
||||||
hide_height: "14px",
|
|
||||||
|
|
||||||
quick_txt: false,
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -5,7 +5,7 @@ ctx = context = {
|
|||||||
option[k] = dataset[k].split(",")
|
option[k] = dataset[k].split(",")
|
||||||
}
|
}
|
||||||
this.GET("", option, function(msg) {
|
this.GET("", option, function(msg) {
|
||||||
msg = msg && msg[0]
|
msg[0] && (msg = msg[0])
|
||||||
// msg && (msg.__proto__ = (page || {}))
|
// msg && (msg.__proto__ = (page || {}))
|
||||||
msg.Result = msg.result? msg.result.join(""): ""
|
msg.Result = msg.result? msg.result.join(""): ""
|
||||||
msg.Results = function() {
|
msg.Results = function() {
|
||||||
|
@ -2,26 +2,271 @@
|
|||||||
|
|
||||||
context是一种新的应用框架,通过模块化、集群化、自动化,实现软件的快速开发,快速共享,快速使用。
|
context是一种新的应用框架,通过模块化、集群化、自动化,实现软件的快速开发,快速共享,快速使用。
|
||||||
|
|
||||||
### 下载安装
|
## 下载安装
|
||||||
在Linux或Mac上,可以直接用脚本下载,在Windows上,可以先安装[GitBash](https://www.git-scm.com/download/),然后下载。
|
在Linux或Mac上,可以直接用脚本下载,
|
||||||
|
在Windows上,可以先安装[GitBash](https://www.git-scm.com/download/),然后在GitBash中执行命令下载。
|
||||||
```
|
```
|
||||||
$ mkdir context && cd context
|
$ curl https://shylinux.com/publish/boot.sh | bash -s install context
|
||||||
$ curl https://shylinux.com/publish/boot.sh | bash -s install
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 使用方式
|
install后面的参数context,就是指定的下载目录,
|
||||||
|
进入下载目录,可以看到的有六个文件。
|
||||||
|
|
||||||
|
在bin目录下,就是各种执行文件
|
||||||
|
|
||||||
|
- bin/bench,context的执行程序
|
||||||
|
- bin/boot.sh,context的启动脚本
|
||||||
|
- bin/node.sh,简化版的启动脚本
|
||||||
|
|
||||||
|
context内部实现了语法解析,通过自定义的脚本语言,实现功能的灵活控制。
|
||||||
|
|
||||||
|
在etc目录下,就是context执行过程中用到的脚本。
|
||||||
|
|
||||||
|
- etc/init.shy,启动时加载的脚本
|
||||||
|
- etc/exit.shy,结束时运行的脚本
|
||||||
|
- etc/common.shy,init.shy调用到的脚本
|
||||||
|
|
||||||
|
## 使用方式
|
||||||
|
|
||||||
context内部实现了很多功能模块,每个模块下有很多命令,每条命令就是一种应用。
|
context内部实现了很多功能模块,每个模块下有很多命令,每条命令就是一种应用。
|
||||||
|
|
||||||
#### 命令模式
|
context的使用方式有很多种,
|
||||||
|
|
||||||
|
- 可以直接调用,像Shell一样,去解析一条命令
|
||||||
|
- 可以启动cli服务,像MySQL一样,交互式使用格式化命令
|
||||||
|
- 可以启动web服务,像LabView一样,可以自定义各种图形界面
|
||||||
|
- 可以自动组网,将任意台设备组合在一起,实现分布式应用
|
||||||
|
- 可以自动建群,在群聊场景中,实现多用户、多会话、多任务、多设备的使用
|
||||||
|
|
||||||
|
### 命令模式
|
||||||
|
如果只是使用一条命令,或是写在脚本文件中,可以使用这种方式。
|
||||||
|
|
||||||
|
例如,dir命令就是查看目录,
|
||||||
```
|
```
|
||||||
$ bin/bench dir
|
$ bin/bench dir
|
||||||
|
time size line filename
|
||||||
|
2019-06-16 10:35:18 324 11 common.shy
|
||||||
|
2019-06-16 10:35:18 201 9 exit.shy
|
||||||
|
2019-06-16 10:35:18 261 13 init.shy
|
||||||
|
```
|
||||||
|
|
||||||
|
还可以加更多参数,dir_deep递归查询目录,dir_type文件类型过滤,dir_sort输出表排序。
|
||||||
|
```
|
||||||
|
$ bin/bench dir ../ dir_deep dir_type file dir_sort line int_r
|
||||||
|
time size line filename
|
||||||
|
2019-06-16 10:22:52 13256968 91314 bench
|
||||||
|
2019-06-16 11:10:16 1535 66 boot.sh
|
||||||
|
2019-06-16 11:10:16 613 31 node.sh
|
||||||
|
2019-06-16 11:10:16 261 13 init.shy
|
||||||
|
2019-06-16 11:10:16 324 11 common.shy
|
||||||
|
2019-06-16 11:10:16 201 9 exit.shy
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 交互模式
|
### 交互模式
|
||||||
|
|
||||||
|
启动服务,可以提供更丰富的命令与环境。
|
||||||
|
```
|
||||||
|
$ bin/bench
|
||||||
|
0[11:35:46]ssh> dir
|
||||||
|
time size line filename
|
||||||
|
2019-06-16 11:35:06 160 3 log/
|
||||||
|
2019-06-16 11:35:06 96 1 run/
|
||||||
|
2019-06-16 11:35:44 192 4 tmp/
|
||||||
|
1[11:35:46]ssh>
|
||||||
|
```
|
||||||
|
|
||||||
|
如果集中管理,命令越多,系统只会越复杂,学习成本越高,使用越低效,开发越困难。
|
||||||
|
|
||||||
|
所以通过模块化,分而治之,更高效的管理丰富的命令。
|
||||||
|
|
||||||
|
context命令就是用来管理模块,没有参数时,直接查看当前模块的信息。
|
||||||
|
|
||||||
|
如下,第二行是当前模块,第一行是当前模块的父模块,其它行都是当前模块的子模块。
|
||||||
|
|
||||||
|
```
|
||||||
|
1[11:39:01]ssh> context
|
||||||
|
names ctx msg status stream helps
|
||||||
|
ctx 0 start shy 模块中心
|
||||||
|
ssh ctx 10 begin ctx.nfs.file3 集群中心
|
||||||
|
```
|
||||||
|
|
||||||
|
context第一个参数,可以指定当前模块,
|
||||||
|
如下,切换到nfs模块,然后查看各种IO模块,
|
||||||
|
切换到ctx根模块,查看所有模块。
|
||||||
|
```
|
||||||
|
2[11:43:57]ssh> context nfs
|
||||||
|
|
||||||
|
3[11:43:58]nfs> context
|
||||||
|
names ctx msg status stream helps
|
||||||
|
ctx 0 start shy 模块中心
|
||||||
|
nfs ctx 9 begin 存储中心
|
||||||
|
stdio nfs 1174 start stdio scan stdio
|
||||||
|
|
||||||
|
4[11:44:22]ssh> context ctx
|
||||||
|
|
||||||
|
5[11:45:17]ctx> context
|
||||||
|
names ctx msg status stream helps
|
||||||
|
ctx 0 start shy 模块中心
|
||||||
|
aaa ctx 3 begin 认证中心
|
||||||
|
cli ctx 4 begin 管理中心
|
||||||
|
gdb ctx 232 start 调试中心
|
||||||
|
lex ctx 6 begin 词法中心
|
||||||
|
log ctx 31 start bench 日志中心
|
||||||
|
mdb ctx 8 begin 数据中心
|
||||||
|
nfs ctx 9 begin 存储中心
|
||||||
|
ssh ctx 10 begin 集群中心
|
||||||
|
tcp ctx 11 begin 网络中心
|
||||||
|
web ctx 1094 start :9094 应用中心
|
||||||
|
yac ctx 13 begin 35,14,23 语法中心
|
||||||
|
shy cli 1171 start engine shell
|
||||||
|
matrix1 lex 34 start 76,28,2 matrix
|
||||||
|
stdio nfs 1174 start stdio scan stdio
|
||||||
|
chat web 14 begin 会议中心
|
||||||
|
code web 15 begin 代码中心
|
||||||
|
wiki web 16 begin 文档中心
|
||||||
|
engine yac 1173 start stdio parse
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
command命令,就是用来管理当前模块的命令,
|
||||||
|
```
|
||||||
|
17[11:52:02]nfs> context nfs
|
||||||
|
|
||||||
|
17[11:52:02]nfs> command
|
||||||
|
key name
|
||||||
|
_init _init
|
||||||
|
action action cmd
|
||||||
|
copy copy to from
|
||||||
|
dir dir [path [fields...]]
|
||||||
|
export export filename
|
||||||
|
git git sum
|
||||||
|
hash hash filename
|
||||||
|
import import filename [index]
|
||||||
|
json json str
|
||||||
|
load load file [buf_size [pos]]
|
||||||
|
open open file
|
||||||
|
path path filename
|
||||||
|
printf printf arg
|
||||||
|
prompt prompt arg
|
||||||
|
pwd pwd [all] | [[index] path]
|
||||||
|
read read [buf_size [pos]]
|
||||||
|
remote remote listen|dial args...
|
||||||
|
save save file string...
|
||||||
|
scan scan file name
|
||||||
|
send send [file] args...
|
||||||
|
temp temp data
|
||||||
|
term term action args...
|
||||||
|
trash trash file
|
||||||
|
write write string [pos]
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
help子命令,查看命令帮助信息。
|
||||||
|
```
|
||||||
|
18[11:59:19]nfs> command help dir
|
||||||
|
dir: dir [path [fields...]]
|
||||||
|
查看目录, path: 路径, fields...: 查询字段, time|type|full|path|tree|filename|size|line|hash
|
||||||
|
dir_deep: 递归查询
|
||||||
|
dir_type both|file|dir|all: 文件类型
|
||||||
|
dir_reg reg: 正则表达式
|
||||||
|
dir_sort field order: 排序
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### 集群模式
|
||||||
|
|
||||||
|
context提供自动化集群的功能,可以自动组网、自动认证。从而快速实现多台设备的协同工作。
|
||||||
|
|
||||||
|
#### 启动服务节点
|
||||||
|
```
|
||||||
|
$ bin/boot.sh
|
||||||
|
0[11:35:12]ssh>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 启动工作节点
|
||||||
|
|
||||||
|
新打开一个终端,启动工作节点,执行remote命令,查看上级节点,
|
||||||
|
```
|
||||||
|
$ bin/boot.sh create app/demo
|
||||||
|
0[15:15:30]ssh> remote
|
||||||
|
key type module create_time
|
||||||
|
mac master ctx.nfs.file3 2019-06-16 15:15:23
|
||||||
|
```
|
||||||
|
|
||||||
|
回到服务节点终端,执行remote命令,可以查看到所有远程节点。
|
||||||
|
```
|
||||||
|
2[15:15:31]ssh> remote
|
||||||
|
key type module create_time
|
||||||
|
com master ctx.nfs.file4 2019-06-16 14:25:10
|
||||||
|
demo worker ctx.nfs.file7 2019-06-16 15:15:23
|
||||||
|
```
|
||||||
|
|
||||||
|
默认配置中,子节点信任父,所以父节点可以调用子节点的命令。还有更复杂的认证机制,可以灵活配置。
|
||||||
|
|
||||||
|
远程命令和本地命令一样,没有任何区别。如下调用demo节点的pwd命令。还支持更复杂的多节点命令,可以更快速的同时管理多台设备。
|
||||||
|
```
|
||||||
|
2[15:15:31]ssh> remote demo pwd
|
||||||
|
/Users/shaoying/context/app/demo/var
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 启动分机节点
|
||||||
|
|
||||||
|
在服务节点的终端,查看服务地址
|
||||||
|
```
|
||||||
|
3[15:49:00]ssh> web.brow
|
||||||
|
index site
|
||||||
|
0 http://192.168.199.139:9094
|
||||||
|
```
|
||||||
|
|
||||||
|
同样,在另一台设备上下载context,然后启动服务节点。
|
||||||
|
通过环境变量ctx_dev指定上级节点。
|
||||||
|
```
|
||||||
|
$ ctx_dev="http://192.168.199.139:9094" bin/boot.sh
|
||||||
|
0[15:49:00]ssh> remote
|
||||||
|
key type module create_time
|
||||||
|
mac master ctx.nfs.file3 2019-06-16 15:15:23
|
||||||
|
```
|
||||||
|
|
||||||
|
回到服务节点终端,执行remote命令,可以查看到新添加了一个服务子节点。
|
||||||
|
```
|
||||||
|
2[15:15:31]ssh> remote
|
||||||
|
key type module create_time
|
||||||
|
com master ctx.nfs.file4 2019-06-16 14:25:10
|
||||||
|
demo worker ctx.nfs.file7 2019-06-16 15:15:23
|
||||||
|
sub server ctx.nfs.file8 2019-06-16 16:15:23
|
||||||
|
```
|
||||||
|
|
||||||
|
同样可以远程调用命令。
|
||||||
|
```
|
||||||
|
2[15:15:31]ssh> remote sub pwd
|
||||||
|
/Users/shaoying/context/app/sub/var
|
||||||
|
```
|
||||||
|
|
||||||
|
### 开源模式
|
||||||
|
|
||||||
|
context是一种通用的应用框架,可以快速开发出各种工具。
|
||||||
|
```
|
||||||
|
2[15:15:31]ssh> project init
|
||||||
|
done
|
||||||
|
2[15:15:31]ssh> project init
|
||||||
|
```
|
||||||
|
|
||||||
|
### 网页模式
|
||||||
|
### 工具链
|
||||||
|
### 知识库
|
||||||
|
### 信息流
|
||||||
|
```
|
||||||
|
$ bin/bench
|
||||||
|
19[11:59:19]nfs> upgrade portal
|
||||||
|
hash file
|
||||||
|
ef1998b38af0888cb56dd5e1448a68ad usr/template.tar.gz
|
||||||
|
6_043a93fa03273744be42c7ab898b2 usr/librarys.tar.gz
|
||||||
|
|
||||||
|
19[11:59:19]nfs> upgrade portal
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
#### 集群模式
|
|
||||||
|
|
||||||
#### 完整版
|
#### 完整版
|
||||||
如果对源码有兴趣,使用更丰富的功能,可以直接下载源码,
|
如果对源码有兴趣,使用更丰富的功能,可以直接下载源码,
|
||||||
@ -109,103 +354,6 @@ index name ip mask hard
|
|||||||
5 en0 192.168.0.106 24 c4:b3:01:cf:0b:51
|
5 en0 192.168.0.106 24 c4:b3:01:cf:0b:51
|
||||||
```
|
```
|
||||||
|
|
||||||
### 组建集群
|
|
||||||
|
|
||||||
context不仅只是一个shell,还可以用来组建集群。
|
|
||||||
|
|
||||||
#### 启动服务节点
|
|
||||||
|
|
||||||
启动服务节点,使用脚本boot.sh,
|
|
||||||
与node.sh不同的是,boot.sh启动的context,
|
|
||||||
会启动web模块监听9094端口,会启动ssh模块监听9090端口。
|
|
||||||
```
|
|
||||||
$ cd context
|
|
||||||
$ bin/boot.sh
|
|
||||||
0[11:23:03]ssh>
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 启动工作节点
|
|
||||||
启动工作节点,使用脚本node.sh,
|
|
||||||
它启动的context,会主动连接本地9090端口,向服务节点注册自己。
|
|
||||||
|
|
||||||
如下,新打开一个终端,调用boot.sh,创建并启动服务节点demo。
|
|
||||||
```
|
|
||||||
$ cd context
|
|
||||||
$ bin/node.sh create app/demo
|
|
||||||
0[11:23:03]ssh>
|
|
||||||
```
|
|
||||||
|
|
||||||
如下,再打开一个终端,调用boot.sh,创建并启动服务节点led。
|
|
||||||
```
|
|
||||||
$ cd context
|
|
||||||
$ bin/node.sh create app/led
|
|
||||||
0[11:23:03]ssh>
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 调用远程命令
|
|
||||||
如下回到服务节点终端,执行remote命令,可以查看到所有远程节点。
|
|
||||||
```
|
|
||||||
22[11:35:12]ssh> remote
|
|
||||||
key create_time module name type
|
|
||||||
com 2019-05-09 20:57:21 ctx.nfs.file4 com master
|
|
||||||
led 2019-05-09 20:59:28 ctx.nfs.file5 led worker
|
|
||||||
demo 2019-05-09 20:59:28 ctx.nfs.file5 demo worker
|
|
||||||
```
|
|
||||||
|
|
||||||
远程命令只需要在命令前加上节点名与冒号即可。
|
|
||||||
|
|
||||||
如下,远程调用led节点的命令。
|
|
||||||
```
|
|
||||||
24[11:41:15]ssh> led:pwd
|
|
||||||
/Users/shaoying/context/app/led/var
|
|
||||||
```
|
|
||||||
|
|
||||||
如下,远程调用demo节点的命令。
|
|
||||||
```
|
|
||||||
24[11:41:15]ssh> demo:pwd
|
|
||||||
/Users/shaoying/context/app/demo/var
|
|
||||||
```
|
|
||||||
|
|
||||||
如下,远程调用所有子节点的命令。
|
|
||||||
```
|
|
||||||
29[11:44:09]ssh> *:pwd
|
|
||||||
/Users/shaoying/context/app/led/var
|
|
||||||
|
|
||||||
/Users/shaoying/context/app/demo/var
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 启动分机服务
|
|
||||||
|
|
||||||
boot.sh不仅可以用来启动本地服务,还可以将不同的主机组建在一起。
|
|
||||||
|
|
||||||
在另外一台计算机上,重新下载安装一下context,然后启动服务节点。
|
|
||||||
|
|
||||||
其中环境变量ctx_dev,用来指定上级服务节点。
|
|
||||||
|
|
||||||
```
|
|
||||||
$ cd context
|
|
||||||
$ ctx_dev=http://192.168.0.106:9094 boot.sh
|
|
||||||
0[11:53:11]ssh>
|
|
||||||
```
|
|
||||||
|
|
||||||
回到原主机的服务节点终端,
|
|
||||||
使用remote命令,可以查看到新加的从机节点。
|
|
||||||
```
|
|
||||||
30[11:55:38]ssh> remote
|
|
||||||
key create_time module name type
|
|
||||||
com 2019-05-09 20:57:21 ctx.nfs.file4 com master
|
|
||||||
mac 2019-05-10 10:53:00 ctx.nfs.file13 mac server
|
|
||||||
led 2019-05-09 20:59:28 ctx.nfs.file5 led worker
|
|
||||||
demo 2019-05-09 20:59:28 ctx.nfs.file5 demo worker
|
|
||||||
```
|
|
||||||
|
|
||||||
当然,也可以在本地启动多个服务节点,根据ctx_dev指定不同的上级节点,可以级联,也可以并联。
|
|
||||||
```
|
|
||||||
$ cd context
|
|
||||||
$ ctx_dev=http://localhost:9094 boot.sh create app/sub
|
|
||||||
```
|
|
||||||
***注意,不指定ctx_dev时,默认连接 https://shylinux.com ,如果不信任此主机,记得设置ctx_dev***
|
|
||||||
|
|
||||||
### 网页服务
|
### 网页服务
|
||||||
|
|
||||||
下载完整版的context,启动的服务节点,就会带有前端网页服务。
|
下载完整版的context,启动的服务节点,就会带有前端网页服务。
|
||||||
|
Loading…
x
Reference in New Issue
Block a user