diff --git a/bin/boot.sh b/bin/boot.sh
index 3bc33f99..a17c5760 100755
--- a/bin/boot.sh
+++ b/bin/boot.sh
@@ -34,8 +34,10 @@ install() {
"armv7l") GOARCH=arm;;
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} \
- && ./${ctx_app} upgrade system && ${md5} ${ctx_app} \
+ && ./${ctx_app} upgrade ${target} && ${md5} ${ctx_app} \
&& mv ${ctx_app} bin/${ctx_app}
}
main() {
diff --git a/etc/init.shy b/etc/init.shy
index 1a2c5f9c..17ed1a32 100644
--- a/etc/init.shy
+++ b/etc/init.shy
@@ -1,11 +1,11 @@
~cli
- config load var/tmp/runtime.json runtime
+ config load tmp/runtime.json runtime
~aaa
- config load var/tmp/auth.json auth
+ config load tmp/auth.json auth
~ssh
- config load var/tmp/cert.json work flow trust
+ config load tmp/cert.json work flow trust
~wiki
- config load var/tmp/wiki.json wiki_visit
+ config load tmp/wiki.json wiki_visit
source etc/common.shy
~ssh
remote auto
diff --git a/src/contexts/cli/cli.go b/src/contexts/cli/cli.go
index 46eb85c1..0d9cff43 100644
--- a/src/contexts/cli/cli.go
+++ b/src/contexts/cli/cli.go
@@ -130,6 +130,20 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
"daemon": &ctx.Config{Name: "daemon", 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{}{
"bench": "src/examples/app/bench.go",
"env": []interface{}{"GOPATH", "PATH"},
@@ -216,6 +230,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
if name, e := os.Getwd(); e == nil {
_, file := path.Split(kit.Select(name, os.Getenv("PWD")))
m.Conf("runtime", "boot.pathname", file)
+ m.Conf("runtime", "boot.ctx_path", name)
}
return
}},
@@ -501,6 +516,28 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
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) {
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) == "" {
@@ -510,13 +547,14 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
}
if len(arg) > 0 && arg[0] == "all" {
- m.Cmdy("cli.compile", "linux", "386")
- m.Cmdy("cli.compile", "linux", "amd64")
- m.Cmdy("cli.compile", "linux", "arm")
- m.Cmdy("cli.compile", "windows", "386")
- m.Cmdy("cli.compile", "windows", "amd64")
- m.Cmdy("cli.compile", "darwin", "amd64")
- m.Set("result").Table()
+ m.Cmdp(time.Second, []string{"go build"}, []string{"cli.compile"}, [][]string{
+ []string{"linux", "386"},
+ []string{"linux", "amd64"},
+ []string{"linux", "arm"},
+ []string{"windows", "386"},
+ []string{"windows", "amd64"},
+ []string{"darwin", "amd64"},
+ })
return
}
@@ -547,7 +585,17 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
dir := m.Conf("publish", "path")
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)
if s, e := os.Stat(p); e == nil {
if s.IsDir() {
@@ -555,18 +603,24 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
} else {
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
}},
- "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 {
m.Cmdy("ctx.config", "upgrade")
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
for _, link := range kit.View([]string{arg[0]}, m.Confm("upgrade")) {
diff --git a/src/contexts/ctx/ctx.go b/src/contexts/ctx/ctx.go
index 04c54193..0588ee9a 100644
--- a/src/contexts/ctx/ctx.go
+++ b/src/contexts/ctx/ctx.go
@@ -1230,6 +1230,14 @@ func (m *Message) Log(action string, str string, arg ...interface{}) *Message {
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 {
switch v := e.(type) {
case nil:
@@ -1541,6 +1549,19 @@ func (m *Message) Free(cbs ...func(msg *Message) (done bool)) *Message {
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 {
m.Log("info", "current: %v", m.Magic("session", "current"))
diff --git a/src/contexts/log/log.go b/src/contexts/log/log.go
index 5ac95044..eb556c78 100644
--- a/src/contexts/log/log.go
+++ b/src/contexts/log/log.go
@@ -151,7 +151,9 @@ var Index = &ctx.Context{Name: "log", Help: "日志中心",
"search": map[string]interface{}{"value": []interface{}{"debug"}},
"call": 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"}},
"begin": map[string]interface{}{"value": []interface{}{"bench", "red"}},
diff --git a/src/contexts/nfs/nfs.go b/src/contexts/nfs/nfs.go
index 2b7a606a..719ba976 100644
--- a/src/contexts/nfs/nfs.go
+++ b/src/contexts/nfs/nfs.go
@@ -784,6 +784,10 @@ func (nfs *NFS) printf(arg ...interface{}) *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) {
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.out = m.Optionv("out").(*os.File); m.Cap("goos") != "windows" && !m.Options("daemon") {
+ kit.STDIO = nfs
nfs.Term(m, "init")
defer nfs.Term(m, "exit")
}
diff --git a/src/contexts/web/web.go b/src/contexts/web/web.go
index 2aadb53d..f6d79d99 100644
--- a/src/contexts/web/web.go
+++ b/src/contexts/web/web.go
@@ -768,6 +768,15 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
return
}},
"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 {
case "windows":
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, "/"))
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) {
m.Confm("runtime", "node.port", func(index int, value string) {
m.Add("append", "ports", value)
@@ -1149,22 +1174,6 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
}
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
- }},
},
}
diff --git a/src/examples/code/code.go b/src/examples/code/code.go
index 63c11dd6..cb63b93b 100644
--- a/src/examples/code/code.go
+++ b/src/examples/code/code.go
@@ -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"},
}, "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{}{
map[string]interface{}{"type": "text", "name": "username", "value": "", "label": "username"},
map[string]interface{}{"type": "password", "name": "password", "value": "", "label": "password"},
diff --git a/src/toolkit/kit.go b/src/toolkit/kit.go
index 7769dadf..7f7bfb3b 100644
--- a/src/toolkit/kit.go
+++ b/src/toolkit/kit.go
@@ -16,6 +16,12 @@ import (
"time"
)
+type TERM interface {
+ Show(...interface{}) bool
+}
+
+var STDIO TERM
+
var DisableLog = false
var EnableDebug = false
diff --git a/usr/librarys/code.js b/usr/librarys/code.js
index 5b56ba9a..9d9f3b1d 100644
--- a/usr/librarys/code.js
+++ b/usr/librarys/code.js
@@ -1,609 +1,4 @@
-var page = Page({
- initComList: function(page, field, option, append, result) {
- 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")
- }]},
- ]]},
- ]},
- ])
- /*
-
命令行
-
-
- 工作流
-
- - + 刷新工作流(Ctrl+R)
- - + 添加工作流(Ctrl+T)
- {{range $key, $item := work .}}
- - {{index $item "create_time"}} {{index $item "data" "name"}}({{slice $key 0 6}})
- {{end}}
- - + 命名工作流
- - + 删除工作流
-
-
- */
- 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,
+page({
+ init: function() {
},
})
diff --git a/usr/librarys/context.js b/usr/librarys/context.js
index b94e377e..a1c42771 100644
--- a/usr/librarys/context.js
+++ b/usr/librarys/context.js
@@ -5,7 +5,7 @@ ctx = context = {
option[k] = dataset[k].split(",")
}
this.GET("", option, function(msg) {
- msg = msg && msg[0]
+ msg[0] && (msg = msg[0])
// msg && (msg.__proto__ = (page || {}))
msg.Result = msg.result? msg.result.join(""): ""
msg.Results = function() {
diff --git a/usr/wiki/自然/编程/终端工具链/context.md b/usr/wiki/自然/编程/终端工具链/context.md
index 8d4608ec..248539fa 100644
--- a/usr/wiki/自然/编程/终端工具链/context.md
+++ b/usr/wiki/自然/编程/终端工具链/context.md
@@ -2,26 +2,271 @@
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
+$ curl https://shylinux.com/publish/boot.sh | bash -s install context
```
-### 使用方式
+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的使用方式有很多种,
+
+- 可以直接调用,像Shell一样,去解析一条命令
+- 可以启动cli服务,像MySQL一样,交互式使用格式化命令
+- 可以启动web服务,像LabView一样,可以自定义各种图形界面
+- 可以自动组网,将任意台设备组合在一起,实现分布式应用
+- 可以自动建群,在群聊场景中,实现多用户、多会话、多任务、多设备的使用
+
+### 命令模式
+如果只是使用一条命令,或是写在脚本文件中,可以使用这种方式。
+
+例如,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
```
-### 组建集群
-
-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,启动的服务节点,就会带有前端网页服务。