1
0
forked from x/ContextOS

new web.code

This commit is contained in:
shaoying 2019-11-03 19:26:05 +08:00
parent 87b8f03e36
commit d9daf68f2b
14 changed files with 651 additions and 58 deletions

View File

@ -48,12 +48,13 @@ install() {
echo
echo
curl -o ${ctx_app} "$ctx_dev/publish/${ctx_app}?GOOS=$GOOS&GOARCH=$GOARCH" && chmod a+x ${ctx_app} || return
wget -O ${ctx_app} "$ctx_dev/publish/bench?GOOS=$GOOS&GOARCH=$GOARCH" && chmod a+x ${ctx_app} || return
target=install && [ -n "$1" ] && target=$1
${md5} ${ctx_app} && ./${ctx_app} upgrade ${target} || return
mv ${ctx_app} bin/${ctx_app} && bin/boot.sh
mv ${ctx_app} bin/${ctx_app}
# && bin/boot.sh
}
main() {
trap HUP hup

View File

@ -69,18 +69,38 @@ func format(m *ctx.Message, out *bytes.Buffer) {
}
m.Table()
case "cut":
c := byte(kit.Select(" ", m.Optionv("cmd_parse"), 2)[0])
c := byte(kit.Select(" ", m.Optionv("cmd_parse"), 1)[0])
bio := bufio.NewScanner(out)
pos := []int{}
heads := []string{}
if h := kit.Select("", m.Optionv("cmd_parse"), 3); h != "" {
heads = strings.Split(h, " ")
} else if bio.Scan() {
heads = kit.Split(bio.Text(), c, kit.Int(kit.Select("-1", m.Optionv("cmd_parse"), 1)))
h := bio.Text()
v := kit.Trans(m.Optionv("cmd_headers"))
for i := 0; i < len(v)-1; i += 2 {
h = strings.Replace(h, v[i], v[i+1], 1)
}
heads = kit.Split(h, c, kit.Int(kit.Select("-1", m.Optionv("cmd_parse"), 2)))
for _, v := range heads {
pos = append(pos, strings.Index(h, v))
}
}
for bio.Scan() {
if len(pos) > 0 {
for i, v := range pos {
if i == len(pos)-1 {
m.Add("append", heads[i], bio.Text()[v:])
} else {
m.Add("append", heads[i], bio.Text()[v:pos[i+1]])
}
}
continue
}
for i, v := range kit.Split(bio.Text(), c, len(heads)) {
m.Add("append", heads[i], v)
}
@ -306,12 +326,13 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
"cmd_timeout: 命令超时",
"cmd_active(true/false): 是否交互",
"cmd_daemon(true/false): 是否守护",
"cmd_dir: 工作目录",
"cmd_env key value: 环境变量",
"cmd_dir: 工作目录",
"cmd_log: 输出日志",
"cmd_temp arg...: 缓存结果",
"cmd_parse format|json|csv|cli|cut [count sep]: 解析结果",
"cmd_error: 输出错误",
"cmd_temp arg...: 缓存结果",
"cmd_parse format|json|csv|cli|cut [count sep headers]: 解析结果",
"cmd_headers",
}, Form: map[string]int{
"cmd_timeout": 1,
"cmd_active": 1,
@ -323,6 +344,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
"cmd_parse": 4,
"cmd_error": 0,
"cmd_select": -1,
"cmd_headers": 2,
"app_log": 1,
}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
// 管道参数
@ -865,7 +887,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
if len(arg) == 1 {
m.Cmdy("nfs.git", "sum", "-n", 20)
} else {
m.Cmdy("nfs.git", "sum", "-n", arg[1:])
m.Cmdy("nfs.git", "sum", "--reverse", "--since", arg[1:])
}
case "trends":
@ -920,7 +942,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
// 编译项目
if m.Cmdy("cli.compile", ""); m.Has("bin") {
target := path.Join(kit.Select(os.Getenv("GOBIN"), ""), m.Conf("compile", "name"))
target := path.Join(kit.Select(os.Getenv("GOBIN"), ""), m.Conf("runtime", "boot.ctx_app"))
os.Remove(target)
m.Append("bin", m.Cmdx("nfs.copy", target, m.Append("bin")))
os.Chmod(target, 0777)

View File

@ -7,5 +7,5 @@ var version = struct {
self int
}{
[]string{"2017-11-01 01:02:03", "2019-07-13 18:02:21"},
`2019-11-01 14:34:16`, `mac`, 657,
`2019-11-03 00:13:51`, `mac`, 659,
}

View File

@ -109,3 +109,8 @@ func ExecuteFile(m *Message, w io.Writer, p string) error {
tmpl.ParseGlob(p)
return tmpl.ExecuteTemplate(w, path.Base(p), m)
}
func ExecuteStr(m *Message, w io.Writer, p string) error {
tmpl := template.New("render").Funcs(CGI)
tmpl, _ = tmpl.Parse(p)
return tmpl.Execute(w, m)
}

View File

@ -250,8 +250,15 @@ func (m *Message) Push(str string, arg ...interface{}) *Message {
}
func (m *Message) Sort(key string, arg ...string) *Message {
cmp := "str"
if len(arg) > 0 {
if len(arg) > 0 && arg[0] != "" {
cmp = arg[0]
} else {
cmp = "int"
for _, v := range m.Meta[key] {
if _, e := strconv.Atoi(v); e != nil {
cmp = "str"
}
}
}
number := map[int]int{}
@ -274,7 +281,7 @@ func (m *Message) Sort(key string, arg ...string) *Message {
for j := i + 1; j < len(table); j++ {
result := false
switch cmp {
case "str":
case "", "str":
if table[i][key] > table[j][key] {
result = true
}
@ -306,6 +313,106 @@ func (m *Message) Sort(key string, arg ...string) *Message {
}
return m
}
func (m *Message) Limit(offset, limit int) *Message {
l := len(m.Meta[m.Meta["append"][0]])
if offset < 0 {
offset = 0
}
if offset > l {
offset = l
}
if offset+limit > l {
limit = l - offset
}
for _, k := range m.Meta["append"] {
m.Meta[k] = m.Meta[k][offset : offset+limit]
}
return m
}
func (m *Message) Filter(value string) *Message {
return m
}
func (m *Message) Group(method string, args ...string) *Message {
nrow := len(m.Meta[m.Meta["append"][0]])
keys := map[string]bool{}
for _, v := range args {
keys[v] = true
}
counts := []int{}
mis := map[int]bool{}
for i := 0; i < nrow; i++ {
counts = append(counts, 1)
if mis[i] {
continue
}
next:
for j := i + 1; j < nrow; j++ {
if mis[j] {
continue
}
for key := range keys {
if m.Meta[key][i] != m.Meta[key][j] {
continue next
}
}
for _, k := range m.Meta["append"] {
if !keys[k] {
switch method {
case "sum", "avg":
v1, e1 := strconv.Atoi(m.Meta[k][i])
v2, e2 := strconv.Atoi(m.Meta[k][j])
if e1 == nil && e2 == nil {
m.Meta[k][i] = fmt.Sprintf("%d", v1+v2)
}
}
}
}
mis[j] = true
counts[i]++
}
}
for i := 0; i < nrow; i++ {
for _, k := range m.Meta["append"] {
if !keys[k] {
switch method {
case "avg":
if v1, e1 := strconv.Atoi(m.Meta[k][i]); e1 == nil {
m.Meta[k][i] = strconv.Itoa(v1 / counts[i])
}
}
}
}
}
for i := 0; i < nrow; i++ {
m.Push("_counts", counts[i])
}
for i := 0; i < nrow; i++ {
if mis[i] {
for j := i + 1; j < nrow; j++ {
if !mis[j] {
for _, k := range m.Meta["append"] {
m.Meta[k][i] = m.Meta[k][j]
}
mis[i], mis[j] = false, true
break
}
}
}
if mis[i] {
for _, k := range m.Meta["append"] {
m.Meta[k] = m.Meta[k][0:i]
}
break
}
}
return m
}
func (m *Message) Table(cbs ...interface{}) *Message {
if len(m.Meta["append"]) == 0 {
return m

View File

@ -1135,7 +1135,9 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心",
}
args := arg[i : j+1]
if arg[i] == "feature" {
feature[arg[i+1]] = arg[i+2]
for k := 2; k < len(args); k++ {
feature[args[1]] = kit.Merge(feature[args[1]], args[k])
}
} else if arg[i] == "exports" {
for k := 1; k < len(args); k += 1 {
@ -1147,14 +1149,7 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心",
"value": kit.Select("", args, 1),
}
for k := 2; k < len(args)-1; k += 2 {
switch val := input[args[k]].(type) {
case nil:
input[args[k]] = args[k+1]
case string:
input[args[k]] = []interface{}{input[args[k]], args[k+1]}
case []interface{}:
input[args[k]] = append(val, args[k+1])
}
input[args[k]] = kit.Merge(input[args[k]], args[k+1])
}
inputs = append(inputs, input)
}
@ -1170,6 +1165,13 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心",
}
}
ctx := m.Cap("module")
if strings.Contains(cmd, ".") {
cs := strings.Split(cmd, ".")
ctx = strings.Join(cs[:len(cs)-1], ".")
cmd = cs[len(cs)-1]
}
m.Confv("_index", []interface{}{-2}, map[string]interface{}{
"name": kit.Select("", arg, 1),
"help": kit.Select("", arg, 2),
@ -1177,7 +1179,7 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心",
"init": init,
"type": right,
"ctx": m.Cap("module"),
"ctx": ctx,
"cmd": cmd,
"args": args,
"inputs": inputs,

View File

@ -3,29 +3,302 @@ package code
import (
"contexts/ctx"
"contexts/web"
"path"
"regexp"
"strings"
"time"
"toolkit"
)
var Index = &ctx.Context{Name: "code", Help: "代码中心",
Caches: map[string]*ctx.Cache{},
Configs: map[string]*ctx.Config{},
Caches: map[string]*ctx.Cache{},
Configs: map[string]*ctx.Config{
"docker": {Name: "docker", Help: "容器", Value: map[string]interface{}{
"shy": `
FROM {{options . "base"}}
WORKDIR /home/{{options . "user"}}/context
Env ctx_dev {{options . "host"}}
RUN wget -q -O - $ctx_dev/publish/boot.sh | sh -s install
CMD sh bin/boot.sh
`,
}},
},
Commands: map[string]*ctx.Command{
"zsh": &ctx.Command{Name: "zsh", Help: "终端", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
m.Echo("zsh")
"zsh": {Name: "zsh dir grep key [split reg fields] [filter reg fields] [order key method] [group keys method] [sort keys method]",
Form: map[string]int{"split": 2, "filter": 2, "order": 2, "group": 2, "sort": 2},
Help: "终端", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
p, arg := kit.Select(".", arg[0]), arg[1:]
switch arg[0] {
case "install":
m.Cmd("cli.system", "apk", "add", arg[1])
case "list":
m.Cmdy("nfs.dir", p, "time", "size", "path")
case "find":
m.Cmdy("cli.system", "find", p, "-name", arg[1])
case "grep":
if m.Options("split") {
re, _ := regexp.Compile(kit.Select("", m.Optionv("split"), 0))
fields := map[string]bool{}
for _, v := range strings.Split(kit.Select("", m.Optionv("split"), 1), " ") {
if v != "" {
fields[v] = true
}
}
m.Cmd("cli.system", "grep", "-rn", arg[1], p, "cmd_parse", "cut", ":", "3", "path line text").Table(func(index int, line map[string]string) {
if ls := re.FindAllStringSubmatch(line["text"], -1); len(ls) > 0 {
m.Push("path", line["path"])
m.Push("line", line["line"])
for _, v := range ls {
if len(fields) == 0 || fields[v[1]] {
m.Push(v[1], v[2])
}
}
}
})
m.Table()
} else {
m.Cmdy("cli.system", "grep", "-rn", arg[1], p, "cmd_parse", "cut", ":", "3", "path line text")
}
if m.Has("filter") {
m.Filter(m.Option("filter"))
}
if m.Has("order") {
m.Sort(kit.Select("", m.Optionv("order"), 0), kit.Select("", m.Optionv("order"), 1))
}
if m.Has("group") {
m.Group(kit.Select("sum", m.Optionv("group"), 1), strings.Split(kit.Select("", m.Option("group"), 0), " ")...)
}
if m.Has("sort") {
m.Sort(kit.Select("", m.Optionv("sort"), 0), kit.Select("", m.Optionv("sort"), 1))
}
case "tail":
m.Cmdy("cli.system", "tail", path.Join(p, arg[1]))
}
return
}},
"tmux": {Name: "tmux [session [window [pane cmd]]]", Help: "窗口", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
prefix := []string{"cli.system", "tmux"}
if len(arg) > 1 {
switch arg[1] {
case "modify":
switch arg[2] {
case "session":
m.Cmdy(prefix, "rename-session", "-t", arg[0], arg[3])
case "window":
m.Cmdy(prefix, "rename-window", "-t", arg[0], arg[3])
}
return
}
}
// 查看会话
if m.Cmdy(prefix, "list-session", "-F", "#{session_id},#{session_name},#{session_windows},#{session_height},#{session_width}",
"cmd_parse", "cut", ",", "5", "id session windows height width"); len(arg) == 0 {
return
}
// 创建会话
if arg[0] != "" && !kit.Contains(m.Meta["session"], arg[0]) {
m.Cmdy(prefix, "new-session", "-ds", arg[0])
}
m.Set("append").Set("result")
// 查看窗口
if m.Cmdy(prefix, "list-windows", "-t", arg[0], "-F", "#{window_id},#{window_name},#{window_panes},#{window_height},#{window_width}",
"cmd_parse", "cut", ",", "5", "id window panes height width"); len(arg) == 1 {
return
}
// 创建窗口
if arg[1] != "" && !kit.Contains(m.Meta["window"], arg[1]) {
m.Cmdy(prefix, "new-window", "-dt", arg[0], "-n", arg[1])
}
m.Set("append").Set("result")
// 查看面板
if len(arg) == 2 {
m.Cmdy(prefix, "list-panes", "-t", arg[0]+":"+arg[1], "-F", "#{pane_id},#{pane_index},#{pane_tty},#{pane_height},#{pane_width}",
"cmd_parse", "cut", ",", "5", "id pane tty height width")
return
}
// 执行命令
target := arg[0] + ":" + arg[1] + "." + arg[2]
if len(arg) > 3 {
if len(arg) > 5 {
switch arg[5] {
case "modify":
switch arg[6] {
case "text":
m.Cmdy(prefix, "set-buffer", "-b", arg[4], arg[7])
}
return
}
}
switch arg[3] {
case "buffer":
if len(arg) > 5 {
m.Cmdy(prefix, "set-buffer", "-b", arg[4], arg[5])
}
if len(arg) > 4 {
m.Cmdy(prefix, "show-buffer", "-b", arg[4])
return
}
m.Cmdy(prefix, "list-buffers", "cmd_parse", "cut", ": ", "3", "buffer size text")
for i, v := range m.Meta["text"] {
if i < 3 {
m.Meta["text"][i] = m.Cmdx(prefix, "show-buffer", "-b", m.Meta["buffer"][i])
} else {
m.Meta["text"][i] = v[2 : len(v)-1]
}
}
return
case "layout":
default:
m.Cmdy(prefix, "send-keys", "-t", target, strings.Join(arg[3:], " "), "Enter")
time.Sleep(1 * time.Second)
}
}
// 查看终端
m.Echo(strings.TrimSpace(m.Cmdx(prefix, "capture-pane", "-pt", target)))
return
}},
"tmux": &ctx.Command{Name: "tmux", Help: "窗口", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
"docker": {Name: "docker", Help: "容器", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
prefix := []string{"cli.system", "docker"}
switch arg[0] {
case "image":
prefix = append(prefix, "image")
pos := kit.Select("shy", arg, 1)
tag := kit.Select("2.1", arg, 2)
// 查看镜像
if m.Cmdy(prefix, "ls", "cmd_parse", "cut", "cmd_headers", "IMAGE ID", "IMAGE_ID"); len(arg) == 1 {
return
} else if i := kit.IndexOf(m.Meta["IMAGE_ID"], arg[1]); i > -1 {
arg, pos, tag = arg[2:], strings.TrimSpace(m.Meta["REPOSITORY"][i]), strings.TrimSpace(m.Meta["TAG"][i])
} else {
arg = arg[3:]
}
// 拉取镜像
if len(arg) == 0 {
m.Cmdy(prefix, "pull", pos+":"+tag)
return
}
switch arg[0] {
// 启动容器
case "运行":
m.Set("append").Set("result")
m.Cmdy("cli.system", "docker", "run", "-dt", pos+":"+tag)
return
// 清理镜像
case "清理":
m.Cmd(prefix, "prune", "-f")
// 删除镜像
case "delete":
m.Cmd(prefix, "rm", pos+":"+tag)
// 创建镜像
default:
m.Option("base", pos+":"+tag)
m.Option("name", arg[0]+":"+kit.Select("2.1", arg, 1))
m.Option("host", "http://"+m.Conf("runtime", "boot.hostname")+".local:9095")
m.Option("user", kit.Select("shy", arg, 2))
m.Option("file", "etc/Dockerfile")
if f, _, e := kit.Create(m.Option("file")); m.Assert(e) {
defer f.Close()
if m.Assert(ctx.ExecuteStr(m, f, m.Conf("docker", arg[0]))) {
m.Cmdy("cli.system", "docker", "image", "build", "-f", m.Option("file"), "-t", m.Option("name"), ".")
}
}
}
case "container":
prefix = append(prefix, "container")
if len(arg) > 1 {
switch arg[2] {
case "进入":
m.Cmdy("cli.system", "tmux", "new-window", "-dPF", "#{session_name}:#{window_name}.1", "docker exec -it "+arg[1]+" sh")
return
case "停止":
m.Cmd(prefix, "stop", arg[1])
case "启动":
m.Cmd(prefix, "start", arg[1])
case "重启":
m.Cmd(prefix, "restart", arg[1])
case "清理":
m.Cmd(prefix, "prune", "-f")
case "modify":
switch arg[3] {
case "NAMES":
m.Cmd(prefix, "rename", arg[1], arg[4:])
}
// 删除容器
case "delete":
m.Cmd(prefix, "rm", arg[1])
default:
if len(arg) > 2 {
m.Cmdy(prefix, "exec", arg[1], arg[2:])
} else {
m.Cmdy(prefix, "inspect", arg[1])
}
return
}
}
m.Cmdy(prefix, "ls", "-a", "cmd_parse", "cut", "cmd_headers", "CONTAINER ID", "CONTAINER_ID")
case "network":
if len(arg) == 1 {
m.Cmdy("cli.system", "docker", "network", "ls", "cmd_parse", "cut", "cmd_headers", "NETWORK ID", "NETWORK_ID")
break
}
kit.Map(kit.Chain(kit.UnMarshal(m.Cmdx("cli.system", "docker", "network", "inspect", arg[1])), "0.Containers"), "", func(key string, value map[string]interface{}) {
m.Push("CONTAINER_ID", key[:12])
m.Push("name", value["Name"])
m.Push("IPv4", value["IPv4Address"])
m.Push("IPv6", value["IPV4Address"])
m.Push("Mac", value["MacAddress"])
})
m.Table()
case "volume":
if len(arg) == 1 {
m.Cmdy("cli.system", "docker", "volume", "ls", "cmd_parse", "cut", "cmd_headers", "VOLUME NAME", "VOLUME_NAME")
break
}
default:
m.Cmdy("cli.system", "docker", arg)
}
return
}},
"git": {Name: "git", Help: "版本", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
m.Echo("git")
return
}},
"docker": &ctx.Command{Name: "docker", Help: "容器", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
m.Echo("docker")
return
}},
"git": &ctx.Command{Name: "git", Help: "版本", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
m.Echo("git")
return
}},
"vim": &ctx.Command{Name: "vim", Help: "编辑器", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
"vim": {Name: "vim", Help: "编辑器", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
m.Echo("vim")
return
}},

View File

@ -0,0 +1,3 @@
fieldset.item.docker div.output {
}

View File

@ -0,0 +1,36 @@
package main
import (
"contexts/cli"
"contexts/ctx"
"toolkit"
"fmt"
"os"
)
var Index = &ctx.Context{Name: `docker`, Help: `plugin`,
Caches: map[string]*ctx.Cache{},
Configs: map[string]*ctx.Config{
"_index": &ctx.Config{Name: "index", Value: []interface{}{
map[string]interface{}{"name": "demo", "help": "demo",
"tmpl": "componet", "view": "", "init": "",
"type": "public", "ctx": "demo", "cmd": "demo",
"args": []interface{}{}, "inputs": []interface{}{
map[string]interface{}{"type": "text", "name": "pod", "value": "hello world"},
map[string]interface{}{"type": "button", "value": "执行"},
},
},
}},
},
Commands: map[string]*ctx.Command{
"demo": {Name: "demo", Help: "demo", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
m.Echo(kit.Select("hello world", arg, 0))
return
}},
},
}
func main() {
fmt.Print(cli.Index.Plugin(Index, os.Args[1:]))
}

View File

@ -0,0 +1,3 @@
Script["docker/index.js"] = function(field, option, output) {return {
}}

View File

@ -0,0 +1,49 @@
kit shell "命令" private "web.code.zsh" \
text "" name dir imports plugin_path action auto \
select "" name cmd values list values find values grep values tail \
exports path path \
text "" name txt \
feature display editor \
button "搜索" \
button "返回" cb Last
kit clip "文本" private "web.code.tmux" "" "" "" "buffer" \
text "" name tag imports plugin_buffer action auto \
text "" name txt \
exports buffer buffer \
feature detail "复制" "下载" "修改" \
button "查看" action auto \
button "返回" cb Last
kit tmux "终端" private "web.code.tmux" \
text "context" name session imports plugin_session action auto \
text "" name window imports plugin_window action auto \
text "" name pane imports plugin_pane view char action auto \
text "" name cmd \
exports session session "" window window "" pane pane "" \
feature detail "复制" "下载" "修改" \
button "查看" action auto
kit image "镜像" private "web.code.docker" "image" \
text "" name pos imports plugin_REPOSITORY \
text "" name tag imports plugin_TAG \
exports IMAGE_ID IMAGE_ID "" REPOSITORY REPOSITORY "" TAG TAG "" \
feature detail "运行" "删除" "清理" \
button "查看" action auto
kit container "容器" private "web.code.docker" "container" \
text "" name arg imports plugin_CONTAINER_ID \
exports CONTAINER_ID CONTAINER_ID \
feature detail "进入" "停止" "启动" "重启" "修改" "删除" "清理" \
button "查看" action auto
kit network "网络" private "web.code.docker" "network" \
text "" name arg imports plugin_NETWORK_ID action auto \
exports NETWORK_ID NETWORK_ID \
button "查看" action auto
kit volume "存储" private "web.code.docker" "volume" \
text "" name arg imports plugin_CONTAINER_ID \
exports CONTAINER_ID CONTAINER_ID \
button "查看"

View File

@ -218,3 +218,43 @@ func List(arg interface{}, cb interface{}) {
}
}
}
func Merge(list interface{}, value string) interface{} {
switch val := list.(type) {
case nil:
return value
case string:
return []interface{}{val, value}
case []interface{}:
return append(val, value)
}
return list
}
func Contains(list interface{}, value string) bool {
switch val := list.(type) {
case nil:
case string:
case []string:
for _, v := range val {
if v == value {
return true
}
}
case []interface{}:
}
return false
}
func IndexOf(list interface{}, value string) int {
switch val := list.(type) {
case nil:
case string:
case []string:
for i, v := range val {
if strings.TrimSpace(v) == strings.TrimSpace(value) {
return i
}
}
case []interface{}:
}
return -1
}

View File

@ -1220,10 +1220,12 @@ function Plugin(page, pane, field, inits, runs) {
var meta = arguments.callee.meta
var list = arguments.callee.list
for (var i = 0; i < list.length; i += 3) {
(list[1] && line[list[1]] || list[i+1] && line[list[i+1]] || list[i+2]) &&
for (var i = 0; i < list.length; i += 3) {if (list[i+1] == name) {
for (var i = 0; i < list.length; i += 3) {
page.Sync("plugin_"+list[i]).set(meta[list[i+2]||""](list[i+1]? line[list[i+1]]: value, list[i+1]||name, line, list))
}
}
break
}}
}),
onchoice: shy("菜单列表", {
"返回": "Last",
@ -1232,7 +1234,7 @@ function Plugin(page, pane, field, inits, runs) {
"减参": "Remove",
"删除": "Delete",
}, ["返回", "复制", "加参", "减参", "删除"], function(event, value, meta) {
kit._call(plugin, plugin[meta[value]])
kit._call(plugin, plugin[meta[value]], [event])
return true
}),
onaction: shy("事件列表", {
@ -1290,7 +1292,7 @@ function Inputs(plugin, meta, item, target, option) {
onimport: shy("导入数据", {}, [item.imports], function() {
kit.List(arguments.callee.list, function(imports) {
page.Sync(imports).change(function(value) {
plugin.History(target.value, target), target.value = value
plugin.History(target.value, target), target.value = value.trim()
input.Event(event = document.createEvent("Event"))
item.action == "auto" && plugin.Runs(event)
})
@ -1372,10 +1374,10 @@ function Inputs(plugin, meta, item, target, option) {
return true
})
// Event入口 2.1
if (event.key == "Enter" && (event.ctrlKey || item.type == "text")) {
// Event入口 2.1
input.which.set(target.value) != undefined && plugin.History(target.value, target)
input.Event(event, {}) && plugin.Check(event, target)
input.Event(event, {}) && event.ctrlKey? plugin.Runs(event): plugin.Check(event, target)
}
},
onkeyup: function(event) {
@ -1409,11 +1411,27 @@ function Inputs(plugin, meta, item, target, option) {
return plugin.Inputs[item.name] = target, target.Input = input
}
function Output(plugin, type, msg, cb, target, option) {
var exports = plugin.target.Meta.exports
var name = plugin.target.Meta.name+"."+type
var feature = JSON.parse(plugin.target.Meta.feature||'{}')
var exports = JSON.parse(plugin.target.Meta.exports||'{}')
var output = Meta(plugin.Zone(type), target, {
_table: function() {plugin.onfigure("table")},
_canvas: function() {plugin.onfigure("canvas")},
clear: function() {target.innerHTML = ""},
Format: function() {
var ext = ".csv", txt = kit.Selector(target, "tr", function(tr) {
return kit.Selector(tr, "td,th", function(td) {
return td.innerText
}).join(",")
}).join("\n");
type == "editor" && msg.file && (ext = ".txt", txt = msg.result.join("\n"));
!txt && (ext = ".txt", txt = msg.result.join(""))
return [name, ext, txt]
},
Copy: function(event) {
kit.CopyText(output.Format()[2])
},
Jshy: function(event, args) {
// 内部命令
@ -1425,19 +1443,44 @@ function Output(plugin, type, msg, cb, target, option) {
},
Download: function() {
var type = ".csv", text = kit.Selector(target, "tr", function(tr) {
return kit.Selector(tr, "td,th", function(td) {
return td.innerText
}).join(",")
}).join("\n")
!text && (type = ".txt", text = plugin.msg.result.join(""))
var ps = output.Format()
plugin.ontoast({text:'<a href="'+URL.createObjectURL(new Blob([text]))+'" target="_blank" download="'+name+type+'">'+name+type+'</a>', title: "下载中...", width: 200})
plugin.ontoast({text:'<a href="'+URL.createObjectURL(new Blob([ps[2]]))+'" target="_blank" download="'+ps[0]+ps[1]+'">'+ps[0]+ps[1]+'</a>', title: "下载中...", width: 200})
kit.Selector(page.toast, "a", function(item) {item.click()})
},
onimport: shy("导入数据", {
_table: function(msg, list) {
return list && list.length > 0 && kit.OrderTable(kit.AppendTable(kit.AppendChild(target, "table"), msg.Table(), list), "", output.onexport)
return list && list.length > 0 && kit.OrderTable(kit.AppendTable(kit.AppendChild(target, "table"), msg.Table(), list), "", output.onexport, function(event, value, name, line, index) {
var td = event.target
plugin.oncarte(event, shy("菜单列表", {
"修改": "modify",
"删除": "delete",
"下载": "Download",
"复制": function(event, text) {kit.CopyText(text), plugin.ontoast(text, "Copy to ClipBoard!")},
}, feature.detail||["复制", "下载"], function(event, item, meta) {
var text = td.innerText.trim()
if (typeof meta[item] == "function") {meta[item](event, text); return}
item == "修改"? (text = kit.AppendChilds(td, [{type: "input", value: text, data: {onkeydown: function(event) {
if (event.key == "Enter") {
var id = ""
for (var i = 0; i < exports.length-1; i += 3) {
id = (id || line[exports[i+1]] || "").trim()
}
plugin.Run(event, [id, meta[item], name, event.target.value], function(msg) {
td.innerHTML = event.target.value
plugin.ontoast("修改成功")
}, true)
return
}
}}}]).input, text.focus(), text.setSelectionRange(0, -1)): output[meta[item]]? output[meta[item]](event): plugin.Run(event, [line[exports[1]].trim(), meta[item]||item], function(msg) {
console.log(msg)
})
return true
}),
)
})
},
_code: function(msg) {
return msg.result && msg.result.length > 0 && kit.OrderCode(kit.AppendChild(target, [{view: ["code", "div", msg.Results()]}]).first)
@ -1489,13 +1532,21 @@ function Output(plugin, type, msg, cb, target, option) {
page.output = target
meta[type](msg, cb)
}),
ondetail: shy("菜单列表", {
"删除": "_table",
"修改": "_canvas",
}, ["删除", "修改"], function(event, value, meta) {
kit._call(output, output[meta[value]], [event])
return true
}),
onchoice: shy("菜单列表", {
"表格": "_table",
"绘图": "_canvas",
"复制": "Copy",
"下载": "Download",
"返回": "Last",
"清空": "clear",
}, ["表格", "绘图", "下载", "返回", "清空"], function(event, value, meta) {
}, ["表格", "绘图", "复制", "下载", "返回", "清空"], function(event, value, meta) {
kit._call(output, output[meta[value]], [event])
return true
}),

View File

@ -303,7 +303,7 @@ kit = toolkit = (function() {var kit = {__proto__: document,
var td = kit.AppendChild(tr, "td", kit.Color(row[key]))
if (key == "when") {td.className = "when"}
if (row[key].startsWith("http")) {
if ((row[key]||"").startsWith("http")) {
td.innerHTML = "<a href='"+row[key]+"' target='_blank'>"+row[key]+"</a>"
}
@ -353,8 +353,8 @@ kit = toolkit = (function() {var kit = {__proto__: document,
tbody.appendChild(list[i])
}
},
OrderTable: function(table, field, cb) {if (!table) {return}
table.onclick = function(event) {var target = event.target
OrderTable: function(table, field, cb, cbs) {if (!table) {return}
table.oncontextmenu = table.onclick = function(event) {var target = event.target
target.parentElement.childNodes.forEach(function(item, i) {if (item != target) {return}
if (target.tagName == "TH") {var dataset = target.dataset
dataset["sort_asc"] = (dataset["sort_asc"] == "1") ? 0: 1
@ -362,7 +362,7 @@ kit = toolkit = (function() {var kit = {__proto__: document,
} else if (target.tagName == "TD") {var index = 0
kit.Selector(table, "tr", function(item, i) {item == target.parentElement && (index = i)})
var name = target.parentElement.parentElement.querySelector("tr").childNodes[i].innerText
name.startsWith(field) && kit._call(cb, [event, item.innerText, name, item.parentNode.Meta, index])
name.startsWith(field) && kit._call(event.type=="contextmenu"? cbs: cb, [event, item.innerText, name, item.parentNode.Meta, index])
}
})
kit.CopyText()
@ -439,7 +439,7 @@ kit = toolkit = (function() {var kit = {__proto__: document,
// HTML输入文本
CopyText: function(text) {
if (text) {
var input = kit.AppendChild(document.body, [{type: "input", value: text}]).input
var input = kit.AppendChild(document.body, [{type: "textarea", inner: text}]).last
input.focus(), input.setSelectionRange(0, text.length)
}
@ -544,6 +544,7 @@ kit = toolkit = (function() {var kit = {__proto__: document,
s = s.replace(/\033\[31m/g, "<span style='color:#f00'>")
s = s.replace(/\033\[0m/g, "</span>")
s = s.replace(/\033\[m/g, "</span>")
s = s.replace(/\n/g, "<br/>")
return s
},
Value: function() {