forked from x/ContextOS
vps add web/wiki
This commit is contained in:
parent
54904b5c7a
commit
07165a1957
1
Makefile
1
Makefile
@ -5,6 +5,7 @@ install:
|
|||||||
@go get github.com/go-sql-driver/mysql
|
@go get github.com/go-sql-driver/mysql
|
||||||
@go get github.com/nsf/termbox-go
|
@go get github.com/nsf/termbox-go
|
||||||
@go get github.com/skip2/go-qrcode
|
@go get github.com/skip2/go-qrcode
|
||||||
|
@go get github.com/gomarkdown/markdown
|
||||||
@cp etc/go.snippets ~/.vim/snippets/
|
@cp etc/go.snippets ~/.vim/snippets/
|
||||||
@cp etc/shy.vim ~/.vim/syntax/
|
@cp etc/shy.vim ~/.vim/syntax/
|
||||||
@touch etc/local.shy
|
@touch etc/local.shy
|
||||||
|
@ -169,7 +169,7 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心",
|
|||||||
Help: "用户登录, sessid: 会话ID, username: 用户名, password: 密码, load: 加载用户信息, save: 保存用户信息, filename: 文件名",
|
Help: "用户登录, sessid: 会话ID, username: 用户名, password: 密码, load: 加载用户信息, save: 保存用户信息, filename: 文件名",
|
||||||
Form: map[string]int{"cert": 1, "pub": 1, "key": 1, "ip": 1},
|
Form: map[string]int{"cert": 1, "pub": 1, "key": 1, "ip": 1},
|
||||||
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) { // {{{
|
if aaa, ok := c.Server.(*AAA); m.Assert(ok) { // {{{
|
||||||
stream := ""
|
stream := ""
|
||||||
if m.Has("ip") {
|
if m.Has("ip") {
|
||||||
stream = m.Option("ip")
|
stream = m.Option("ip")
|
||||||
|
@ -168,7 +168,7 @@ func (cli *CLI) Start(m *ctx.Message, arg ...string) bool { // {{{
|
|||||||
}
|
}
|
||||||
m.Optionv("ps_target", cli.target)
|
m.Optionv("ps_target", cli.target)
|
||||||
return nil
|
return nil
|
||||||
}, "parse", arg[1]).Target().Name)
|
}, "scan", arg[1]).Target().Name)
|
||||||
|
|
||||||
if m.Options("init.shy") {
|
if m.Options("init.shy") {
|
||||||
msg := m.Spawn().Cmd("source", m.Conf("init.shy"))
|
msg := m.Spawn().Cmd("source", m.Conf("init.shy"))
|
||||||
|
@ -544,7 +544,7 @@ func (m *Message) Copy(msg *Message, meta string, arg ...string) *Message { // {
|
|||||||
|
|
||||||
func (m *Message) Log(action string, str string, arg ...interface{}) *Message { // {{{
|
func (m *Message) Log(action string, str string, arg ...interface{}) *Message { // {{{
|
||||||
l := m.Sess("log", !m.Confs("compact_log"))
|
l := m.Sess("log", !m.Confs("compact_log"))
|
||||||
if l == nil || m.Detail(0) == "log" || m.Detail(0) == "write" {
|
if l == nil || m.Detail(0) == "log" || m.Detail(0) == "write" || m.Options("silent") {
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -973,7 +973,10 @@ func (m *Message) Gets(key string) bool { // {{{
|
|||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
func (m *Message) Echo(str string, arg ...interface{}) *Message { // {{{
|
func (m *Message) Echo(str string, arg ...interface{}) *Message { // {{{
|
||||||
return m.Add("result", fmt.Sprintf(str, arg...))
|
if len(arg) > 0 {
|
||||||
|
return m.Add("result", fmt.Sprintf(str, arg...))
|
||||||
|
}
|
||||||
|
return m.Add("result", str)
|
||||||
}
|
}
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
@ -2232,8 +2235,8 @@ var CGI = template.FuncMap{
|
|||||||
}
|
}
|
||||||
|
|
||||||
list := make([]int, n)
|
list := make([]int, n)
|
||||||
for i := 0; i < n; i++ {
|
for i := 1; i <= n; i++ {
|
||||||
list[i] = i
|
list[i-1] = i
|
||||||
}
|
}
|
||||||
return list
|
return list
|
||||||
}, // }}}
|
}, // }}}
|
||||||
|
@ -1209,8 +1209,9 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
|
|||||||
key := m.Meta["append"][i]
|
key := m.Meta["append"][i]
|
||||||
switch key {
|
switch key {
|
||||||
case "filename":
|
case "filename":
|
||||||
if trip > 0 {
|
if line > -1 && trip > 0 && trip <= len(v) {
|
||||||
v = v[trip:]
|
v = v[trip:]
|
||||||
|
m.Meta["filename"][line] = v
|
||||||
}
|
}
|
||||||
case "dir":
|
case "dir":
|
||||||
continue
|
continue
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
package web // {{{
|
package web // {{{
|
||||||
// }}}
|
// }}}
|
||||||
import ( // {{{
|
import ( // {{{
|
||||||
|
"bufio"
|
||||||
"contexts"
|
"contexts"
|
||||||
|
"github.com/gomarkdown/markdown"
|
||||||
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
@ -13,7 +16,6 @@ import ( // {{{
|
|||||||
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@ -101,7 +103,7 @@ func (web *WEB) Trans(m *ctx.Message, key string, hand func(*ctx.Message, *ctx.C
|
|||||||
|
|
||||||
msg.Log("cmd", "%s [] %v", key, msg.Meta["option"])
|
msg.Log("cmd", "%s [] %v", key, msg.Meta["option"])
|
||||||
msg.Put("option", "request", r).Put("option", "response", w)
|
msg.Put("option", "request", r).Put("option", "response", w)
|
||||||
hand(msg, msg.Target(), key)
|
hand(msg, msg.Target(), msg.Option("path"))
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case msg.Has("redirect"):
|
case msg.Has("redirect"):
|
||||||
@ -243,6 +245,17 @@ func (web *WEB) Start(m *ctx.Message, arg ...string) bool { // {{{
|
|||||||
web.Configs["logheaders"] = &ctx.Config{Name: "日志输出报文头(yes/no)", Value: "no", Help: "日志输出报文头"}
|
web.Configs["logheaders"] = &ctx.Config{Name: "日志输出报文头(yes/no)", Value: "no", Help: "日志输出报文头"}
|
||||||
m.Capi("nserve", 1)
|
m.Capi("nserve", 1)
|
||||||
|
|
||||||
|
yac := m.Sess("tags", m.Sess("yac").Cmd("scan"))
|
||||||
|
yac.Cmd("train", "void", "void", "[\t ]+")
|
||||||
|
yac.Cmd("train", "other", "other", "[^\n]+")
|
||||||
|
yac.Cmd("train", "key", "key", "[A-Za-z_][A-Za-z_0-9]*")
|
||||||
|
yac.Cmd("train", "code", "struct", "struct", "key", "\\{")
|
||||||
|
yac.Cmd("train", "code", "struct", "\\}", "key", ";")
|
||||||
|
yac.Cmd("train", "code", "struct", "typedef", "struct", "key", "key", ";")
|
||||||
|
yac.Cmd("train", "code", "function", "key", "\\*", "key", "(", "other")
|
||||||
|
yac.Cmd("train", "code", "function", "key", "key", "(", "other")
|
||||||
|
yac.Cmd("train", "code", "define", "#define", "key", "other")
|
||||||
|
|
||||||
if m.Cap("protocol") == "https" {
|
if m.Cap("protocol") == "https" {
|
||||||
web.Caches["cert"] = &ctx.Cache{Name: "服务证书", Value: m.Conf("cert"), Help: "服务证书"}
|
web.Caches["cert"] = &ctx.Cache{Name: "服务证书", Value: m.Conf("cert"), Help: "服务证书"}
|
||||||
web.Caches["key"] = &ctx.Cache{Name: "服务密钥", Value: m.Conf("key"), Help: "服务密钥"}
|
web.Caches["key"] = &ctx.Cache{Name: "服务密钥", Value: m.Conf("key"), Help: "服务密钥"}
|
||||||
@ -277,9 +290,25 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
|
|||||||
"cmd": &ctx.Config{Name: "cmd", Value: "tmux", Help: "路由数量"},
|
"cmd": &ctx.Config{Name: "cmd", Value: "tmux", Help: "路由数量"},
|
||||||
"cert": &ctx.Config{Name: "cert", Value: "etc/cert.pem", Help: "路由数量"},
|
"cert": &ctx.Config{Name: "cert", Value: "etc/cert.pem", Help: "路由数量"},
|
||||||
"key": &ctx.Config{Name: "key", Value: "etc/key.pem", Help: "路由数量"},
|
"key": &ctx.Config{Name: "key", Value: "etc/key.pem", Help: "路由数量"},
|
||||||
|
"wiki_dir": &ctx.Config{Name: "wiki_dir", Value: "usr/wiki", Help: "路由数量"},
|
||||||
|
"which": &ctx.Config{Name: "which", Value: "redis.note", Help: "路由数量"},
|
||||||
"root_index": &ctx.Config{Name: "root_index(true/false)", Value: "true", Help: "路由数量"},
|
"root_index": &ctx.Config{Name: "root_index(true/false)", Value: "true", Help: "路由数量"},
|
||||||
"auto_create": &ctx.Config{Name: "auto_create(true/false)", Value: "true", Help: "路由数量"},
|
"auto_create": &ctx.Config{Name: "auto_create(true/false)", Value: "true", Help: "路由数量"},
|
||||||
"refresh_time": &ctx.Config{Name: "refresh_time(ms)", Value: "1000", Help: "路由数量"},
|
"refresh_time": &ctx.Config{Name: "refresh_time(ms)", Value: "1000", Help: "路由数量"},
|
||||||
|
"define": &ctx.Config{Name: "define", Value: map[string]interface{}{
|
||||||
|
"ngx_command_t": map[string]interface{}{
|
||||||
|
"position": map[string]interface{}{
|
||||||
|
"file": "nginx-1.15.2/src/core/ngx_core.h",
|
||||||
|
"line": "22",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"ngx_command_s": map[string]interface{}{
|
||||||
|
"position": map[string]interface{}{
|
||||||
|
"file": "nginx-1.15.2/src/core/ngx_conf_file.h",
|
||||||
|
"line": "77",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, Help: "路由数量"},
|
||||||
"check": &ctx.Config{Name: "check", Value: map[string]interface{}{
|
"check": &ctx.Config{Name: "check", Value: map[string]interface{}{
|
||||||
"login": []interface{}{
|
"login": []interface{}{
|
||||||
map[string]interface{}{
|
map[string]interface{}{
|
||||||
@ -438,9 +467,11 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
|
|||||||
"template": "wiki_menu", "title": "wiki_menu",
|
"template": "wiki_menu", "title": "wiki_menu",
|
||||||
},
|
},
|
||||||
map[string]interface{}{
|
map[string]interface{}{
|
||||||
|
"module": "web", "command": "/wiki_list",
|
||||||
"template": "wiki_list", "title": "wiki_list",
|
"template": "wiki_list", "title": "wiki_list",
|
||||||
},
|
},
|
||||||
map[string]interface{}{
|
map[string]interface{}{
|
||||||
|
"module": "web", "command": "/wiki_body",
|
||||||
"template": "wiki_body", "title": "wiki_body",
|
"template": "wiki_body", "title": "wiki_body",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -875,11 +906,11 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
|
|||||||
// }}}
|
// }}}
|
||||||
}},
|
}},
|
||||||
"/create": &ctx.Command{Name: "/create", Help: "创建目录或文件", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"/create": &ctx.Command{Name: "/create", Help: "创建目录或文件", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
// if check := m.Spawn().Cmd("/share", "/upload", "dir", m.Option("dir")); !check.Results(0) { // {{{
|
if check := m.Spawn().Cmd("/share", "/upload", "dir", m.Option("dir")); !check.Results(0) { // {{{
|
||||||
// m.Copy(check, "append")
|
m.Copy(check, "append")
|
||||||
// return
|
return
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
r := m.Optionv("request").(*http.Request)
|
r := m.Optionv("request").(*http.Request)
|
||||||
if m.Option("method") == "POST" {
|
if m.Option("method") == "POST" {
|
||||||
if m.Options("filename") { //添加文件或目录
|
if m.Options("filename") { //添加文件或目录
|
||||||
@ -1076,7 +1107,6 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
val := v.(map[string]interface{})
|
val := v.(map[string]interface{})
|
||||||
m.Log("fuck", "why %v", val)
|
|
||||||
//命令模板
|
//命令模板
|
||||||
if detail, ok := val["detail"].([]interface{}); ok {
|
if detail, ok := val["detail"].([]interface{}); ok {
|
||||||
msg := m.Spawn().Add("detail", detail[0].(string), detail[1:])
|
msg := m.Spawn().Add("detail", detail[0].(string), detail[1:])
|
||||||
@ -1148,7 +1178,150 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
|
|||||||
|
|
||||||
m.Echo("blog service")
|
m.Echo("blog service")
|
||||||
}},
|
}},
|
||||||
"/wiki": &ctx.Command{Name: "/wiki", Help: "维基", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"/wiki_tags": &ctx.Command{Name: "/wiki_tags ", Help: "博客", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
|
if len(arg) > 0 {
|
||||||
|
m.Option("dir", arg[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
yac := m.Find("yac.parse4", true)
|
||||||
|
|
||||||
|
msg := m.Sess("nfs").Cmd("dir", path.Join(m.Conf("wiki_dir"), m.Option("dir")), "dir_name", "path")
|
||||||
|
for i, v := range msg.Meta["filename"] {
|
||||||
|
name := strings.TrimSpace(v)
|
||||||
|
es := strings.Split(name, ".")
|
||||||
|
switch es[len(es)-1] {
|
||||||
|
case "pyc", "o", "gz", "tar":
|
||||||
|
continue
|
||||||
|
case "c":
|
||||||
|
m.Log("fuck", "parse %s", name)
|
||||||
|
case "h":
|
||||||
|
default:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
f, e := os.Open(name)
|
||||||
|
m.Assert(e)
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
m.Log("fuck", "parse %d/%d %s", i, len(msg.Meta["filename"]), name)
|
||||||
|
|
||||||
|
bio := bufio.NewScanner(f)
|
||||||
|
for line := 1; bio.Scan(); line++ {
|
||||||
|
yac.Options("silent", true)
|
||||||
|
l := yac.Cmd("parse", "code", "void", bio.Text())
|
||||||
|
|
||||||
|
key := ""
|
||||||
|
switch l.Result(1) {
|
||||||
|
case "struct":
|
||||||
|
switch l.Result(2) {
|
||||||
|
case "struct", "}":
|
||||||
|
key = l.Result(3)
|
||||||
|
case "typedef":
|
||||||
|
if l.Result(3) == "struct" {
|
||||||
|
key = l.Result(5)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "function":
|
||||||
|
switch l.Result(3) {
|
||||||
|
case "*":
|
||||||
|
key = l.Result(4)
|
||||||
|
default:
|
||||||
|
key = l.Result(3)
|
||||||
|
}
|
||||||
|
case "define":
|
||||||
|
key = l.Result(3)
|
||||||
|
}
|
||||||
|
if key != "" {
|
||||||
|
m.Confv("define", strings.Join([]string{key, "position"}, "."), map[string]interface{}{
|
||||||
|
"file": strings.TrimPrefix(name, m.Confx("wiki_dir")),
|
||||||
|
"line": line,
|
||||||
|
"type": l.Result(1),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
yac.Meta = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m.Log("fuck", "parse %s", time.Now().Format("2006-01-02 15:04:05"))
|
||||||
|
}},
|
||||||
|
"/wiki_body": &ctx.Command{Name: "/wiki_body", Help: "维基", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
|
if ls, e := ioutil.ReadFile(path.Join(m.Conf("wiki_dir"), m.Confx("which"))); e == nil {
|
||||||
|
pre := false
|
||||||
|
es := strings.Split(m.Confx("which"), ".")
|
||||||
|
if len(es) > 0 {
|
||||||
|
switch es[len(es)-1] {
|
||||||
|
case "md":
|
||||||
|
ls = markdown.ToHTML(ls, nil, nil)
|
||||||
|
default:
|
||||||
|
pre = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if pre {
|
||||||
|
m.Option("nline", bytes.Count(ls, []byte("\n")))
|
||||||
|
m.Option("nbyte", len(ls))
|
||||||
|
m.Add("append", "code", string(ls))
|
||||||
|
m.Add("append", "body", "")
|
||||||
|
} else {
|
||||||
|
m.Add("append", "body", string(ls))
|
||||||
|
m.Add("append", "code", "")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.Options("query") {
|
||||||
|
if v, ok := m.Confv("define", m.Option("query")).(map[string]interface{}); ok {
|
||||||
|
if val, ok := v["position"].(map[string]interface{}); ok {
|
||||||
|
m.Add("append", "name", fmt.Sprintf("%v#hash_%v", val["file"], val["line"]))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
msg := m.Sess("nfs").Cmd("dir", path.Join(m.Conf("wiki_dir"), m.Option("dir")), "dir_name", "path")
|
||||||
|
for _, v := range msg.Meta["filename"] {
|
||||||
|
name := strings.TrimPrefix(strings.TrimSpace(v), m.Conf("wiki_dir"))
|
||||||
|
es := strings.Split(name, ".")
|
||||||
|
switch es[len(es)-1] {
|
||||||
|
case "pyc", "o", "gz", "tar":
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if strings.Contains(name, m.Option("query")) {
|
||||||
|
m.Add("append", "name", name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := m.Spawn().Cmd("/wiki_list")
|
||||||
|
m.Copy(msg, "append").Copy(msg, "option")
|
||||||
|
}},
|
||||||
|
"/wiki_list": &ctx.Command{Name: "/wiki_list", Help: "维基", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
|
ls, e := ioutil.ReadDir(path.Join(m.Conf("wiki_dir"), m.Option("which")))
|
||||||
|
m.Option("dir", m.Option("which"))
|
||||||
|
if e != nil {
|
||||||
|
dir, _ := path.Split(m.Option("which"))
|
||||||
|
m.Option("dir", dir)
|
||||||
|
ls, e = ioutil.ReadDir(path.Join(m.Conf("wiki_dir"), dir))
|
||||||
|
}
|
||||||
|
|
||||||
|
parent, _ := path.Split(strings.TrimSuffix(m.Option("dir"), "/"))
|
||||||
|
m.Option("parent", parent)
|
||||||
|
for _, l := range ls {
|
||||||
|
if l.Name()[0] == '.' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
es := strings.Split(l.Name(), ".")
|
||||||
|
if len(es) > 0 {
|
||||||
|
switch es[len(es)-1] {
|
||||||
|
case "pyc", "o", "gz", "tar":
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m.Add("append", "name", l.Name())
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
"/wiki/": &ctx.Command{Name: "/wiki", Help: "维基", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
|
m.Option("which", strings.TrimPrefix(key, "/wiki/"))
|
||||||
m.Append("template", "wiki")
|
m.Append("template", "wiki")
|
||||||
}},
|
}},
|
||||||
"temp": &ctx.Command{Name: "temp", Help: "应用示例", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"temp": &ctx.Command{Name: "temp", Help: "应用示例", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
|
@ -185,7 +185,7 @@ func (yac *YAC) train(m *ctx.Message, page, hash int, word []string) (int, []*Po
|
|||||||
}
|
}
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
func (yac *YAC) parse(m *ctx.Message, out *ctx.Message, page int, void int, line string, level int) (string, []string) { // {{{
|
func (yac *YAC) parse(m *ctx.Message, out *ctx.Message, page int, void int, line string, level int) (string, []string, int) { // {{{
|
||||||
if m.Confs("debug") {
|
if m.Confs("debug") {
|
||||||
m.Log("debug", "%s\\%d %s(%d): %s", m.Conf("label")[0:level], level, yac.name(page), page, line)
|
m.Log("debug", "%s\\%d %s(%d): %s", m.Conf("label")[0:level], level, yac.name(page), page, line)
|
||||||
}
|
}
|
||||||
@ -224,7 +224,7 @@ func (yac *YAC) parse(m *ctx.Message, out *ctx.Message, page int, void int, line
|
|||||||
if state == nil { //嵌套语法递归解析
|
if state == nil { //嵌套语法递归解析
|
||||||
for i := 0; i < m.Capi("ncell"); i++ {
|
for i := 0; i < m.Capi("ncell"); i++ {
|
||||||
if x := yac.mat[s][byte(i)]; i < m.Capi("nlang") && x != nil {
|
if x := yac.mat[s][byte(i)]; i < m.Capi("nlang") && x != nil {
|
||||||
if l, w := yac.parse(m, out, i, void, line, level+1); l != line {
|
if l, w, _ := yac.parse(m, out, i, void, line, level+1); l != line {
|
||||||
line, word = l, append(word, w...)
|
line, word = l, append(word, w...)
|
||||||
state = x
|
state = x
|
||||||
break
|
break
|
||||||
@ -245,7 +245,7 @@ func (yac *YAC) parse(m *ctx.Message, out *ctx.Message, page int, void int, line
|
|||||||
|
|
||||||
if hash == 0 {
|
if hash == 0 {
|
||||||
word = word[:0]
|
word = word[:0]
|
||||||
} else { //执行命令
|
} else if out != nil { //执行命令
|
||||||
msg := out.Spawn(m.Source()).Add("detail", yac.hand[hash], word)
|
msg := out.Spawn(m.Source()).Add("detail", yac.hand[hash], word)
|
||||||
if m.Back(msg); msg.Hand { //命令替换
|
if m.Back(msg); msg.Hand { //命令替换
|
||||||
m.Assert(!msg.Has("return"))
|
m.Assert(!msg.Has("return"))
|
||||||
@ -257,7 +257,7 @@ func (yac *YAC) parse(m *ctx.Message, out *ctx.Message, page int, void int, line
|
|||||||
m.Log("debug", "%s/%d %s(%d): %v", m.Conf("label")[0:level], level, yac.name(page), page, word)
|
m.Log("debug", "%s/%d %s(%d): %v", m.Conf("label")[0:level], level, yac.name(page), page, word)
|
||||||
}
|
}
|
||||||
|
|
||||||
return line, word
|
return line, word, hash
|
||||||
}
|
}
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
@ -266,7 +266,7 @@ func (yac *YAC) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server
|
|||||||
c.Caches = map[string]*ctx.Cache{}
|
c.Caches = map[string]*ctx.Cache{}
|
||||||
c.Configs = map[string]*ctx.Config{}
|
c.Configs = map[string]*ctx.Config{}
|
||||||
|
|
||||||
if len(arg) > 0 && arg[0] == "parse" {
|
if len(arg) > 0 && arg[0] == "scan" {
|
||||||
return yac
|
return yac
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -277,7 +277,7 @@ func (yac *YAC) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server
|
|||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
func (yac *YAC) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{
|
func (yac *YAC) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{
|
||||||
if len(arg) > 0 && arg[0] == "parse" {
|
if len(arg) > 0 && arg[0] == "scan" {
|
||||||
return yac
|
return yac
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,7 +304,7 @@ func (yac *YAC) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{
|
|||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
func (yac *YAC) Start(m *ctx.Message, arg ...string) (close bool) { // {{{
|
func (yac *YAC) Start(m *ctx.Message, arg ...string) (close bool) { // {{{
|
||||||
if len(arg) > 0 && arg[0] == "parse" {
|
if len(arg) > 0 && arg[0] == "scan" {
|
||||||
lex := m.Sess("lex")
|
lex := m.Sess("lex")
|
||||||
if lex.Cap("status") != "start" {
|
if lex.Cap("status") != "start" {
|
||||||
lex.Target().Start(lex)
|
lex.Target().Start(lex)
|
||||||
@ -338,7 +338,7 @@ func (yac *YAC) Start(m *ctx.Message, arg ...string) (close bool) { // {{{
|
|||||||
if len(line) == 0 {
|
if len(line) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
_, word := yac.parse(m, out, m.Optioni("page"), m.Optioni("void"), line, 1)
|
_, word, _ := yac.parse(m, out, m.Optioni("page"), m.Optioni("void"), line, 1)
|
||||||
|
|
||||||
if len(word) > 0 {
|
if len(word) > 0 {
|
||||||
word = word[:len(word)-1]
|
word = word[:len(word)-1]
|
||||||
@ -469,14 +469,28 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心",
|
|||||||
}
|
}
|
||||||
// }}}
|
// }}}
|
||||||
}},
|
}},
|
||||||
"parse": &ctx.Command{
|
"parse": &ctx.Command{Name: "parse page hash word...", Help: "添加语法规则, page: 语法集合, hash: 语句类型, word: 语法模板", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
Name: "parse filename [yac_name [help]] [line line] [void void]",
|
if yac, ok := m.Target().Server.(*YAC); m.Assert(ok) { // {{{
|
||||||
|
m.Optioni("page", yac.page[arg[0]])
|
||||||
|
m.Optioni("void", yac.page[arg[1]])
|
||||||
|
|
||||||
|
str, word, hash := yac.parse(m, nil, m.Optioni("page"), m.Optioni("void"), arg[2], 1)
|
||||||
|
m.Result(str, yac.hand[hash], word)
|
||||||
|
}
|
||||||
|
// }}}
|
||||||
|
}},
|
||||||
|
"scan": &ctx.Command{
|
||||||
|
Name: "scan filename [yac_name [help]] [line line] [void void]",
|
||||||
Help: "解析文件, filename: yac_name:模块名, yac_help:模块帮助, 文件名, line: 默认语法, void: 默认空白",
|
Help: "解析文件, filename: yac_name:模块名, yac_help:模块帮助, 文件名, line: 默认语法, void: 默认空白",
|
||||||
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if yac, ok := m.Target().Server.(*YAC); m.Assert(ok) { // {{{
|
if yac, ok := m.Target().Server.(*YAC); m.Assert(ok) { // {{{
|
||||||
m.Optioni("page", yac.page["line"])
|
m.Optioni("page", yac.page["line"])
|
||||||
m.Optioni("void", yac.page["void"])
|
m.Optioni("void", yac.page["void"])
|
||||||
m.Start(m.Confx("yac_name", arg, 1), m.Confx("yac_help", arg, 2), key, arg[0])
|
if len(arg) > 0 {
|
||||||
|
m.Start(m.Confx("yac_name", arg, 1), m.Confx("yac_help", arg, 2), key, arg[0])
|
||||||
|
} else {
|
||||||
|
m.Start(m.Confx("yac_name", arg, 1), m.Confx("yac_help", arg, 2))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// }}}
|
// }}}
|
||||||
}},
|
}},
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>{{option .Meta "page_title"}}</title>
|
<title>{{option .Meta "page_title"}}</title>
|
||||||
<style>
|
<style>
|
||||||
fieldset {
|
fieldset {
|
||||||
@ -20,6 +21,12 @@
|
|||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
padding-right: 20px;
|
padding-right: 20px;
|
||||||
}
|
}
|
||||||
|
pre {
|
||||||
|
border:solid 1px green;
|
||||||
|
padding:5px;
|
||||||
|
border-left:solid 5px green;
|
||||||
|
overflow:scroll;
|
||||||
|
}
|
||||||
code {
|
code {
|
||||||
font-size:14px;
|
font-size:14px;
|
||||||
}
|
}
|
||||||
@ -27,6 +34,11 @@
|
|||||||
font-size:14px;
|
font-size:14px;
|
||||||
font-family:monospace;
|
font-family:monospace;
|
||||||
}
|
}
|
||||||
|
html, body {
|
||||||
|
height:100%;
|
||||||
|
width:100%;
|
||||||
|
margin:0px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
<script src="/library/context.js"></script>
|
<script src="/library/context.js"></script>
|
||||||
<script>
|
<script>
|
||||||
|
@ -1,12 +1,227 @@
|
|||||||
{{define "wiki_head"}}
|
{{define "wiki_head"}}
|
||||||
<div>hello wiki_head world!</div>
|
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{define "wiki_menu"}}
|
{{define "wiki_menu"}}
|
||||||
<div>hello wiki_menu world!</div>
|
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{define "wiki_list"}}
|
{{define "wiki_list"}}
|
||||||
<div>hello wiki_list world!</div>
|
<script>
|
||||||
|
function jumpto(url) {
|
||||||
|
if (url == "..") {
|
||||||
|
var ps = locaiton.href.split();
|
||||||
|
}
|
||||||
|
location.href=url;
|
||||||
|
}
|
||||||
|
function keyup(event) {
|
||||||
|
console.log(event);
|
||||||
|
if (event.key == "z") {
|
||||||
|
var input = document.getElementsByClassName("query_input")[0];
|
||||||
|
if (!window.query_show) {
|
||||||
|
window.query_show = true;
|
||||||
|
var query = document.getElementsByClassName("query_menu")[0];
|
||||||
|
var input = query.getElementsByTagName("input")[0];
|
||||||
|
input.style.visibility = "visible";
|
||||||
|
input.style.width = "80px";
|
||||||
|
input.focus();
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
document.onkeyup = keyup;
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
.container {
|
||||||
|
height:100%;
|
||||||
|
min-width:300px;
|
||||||
|
}
|
||||||
|
.head {
|
||||||
|
color:white;
|
||||||
|
font-size:20px;
|
||||||
|
font-weight:bold;
|
||||||
|
background-color:#222;
|
||||||
|
text-align:center;
|
||||||
|
vertical-align:middle;
|
||||||
|
padding:10px;
|
||||||
|
width:100%;
|
||||||
|
height:27px;
|
||||||
|
}
|
||||||
|
.title {
|
||||||
|
font-style:italic;
|
||||||
|
}
|
||||||
|
.toggle_menu {
|
||||||
|
cursor:pointer;
|
||||||
|
float:left;
|
||||||
|
}
|
||||||
|
.query_menu {
|
||||||
|
cursor:pointer;
|
||||||
|
margin-right:20px;
|
||||||
|
float:right;
|
||||||
|
}
|
||||||
|
.query_button {
|
||||||
|
cursor:pointer;
|
||||||
|
float:right;
|
||||||
|
margin-left:10px;
|
||||||
|
}
|
||||||
|
.query_input {
|
||||||
|
visibility:hidden;
|
||||||
|
width:0px;
|
||||||
|
position:absolute;
|
||||||
|
right:40px;
|
||||||
|
top:12px;
|
||||||
|
}
|
||||||
|
.list {
|
||||||
|
width:15%;
|
||||||
|
min-width:140px;
|
||||||
|
float:left;
|
||||||
|
max-height:1000px;
|
||||||
|
overflow:scroll;
|
||||||
|
}
|
||||||
|
.list_item {
|
||||||
|
padding-top:10px;
|
||||||
|
padding-left:30px;
|
||||||
|
min-height:30px;
|
||||||
|
margin-left:-30px;
|
||||||
|
}
|
||||||
|
.list_item:hover, .list_item:active {
|
||||||
|
background-color:green;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div class="container">
|
||||||
|
<div class="head">
|
||||||
|
<div class="toggle_menu" onclick="toggle()">三</div>
|
||||||
|
<div class="query_menu">
|
||||||
|
<input class="query_input" type="text" onkeyup="return query(event)">
|
||||||
|
<div class="query_button" onclick="return query()"> Q</div>
|
||||||
|
</div>
|
||||||
|
<div class="title" onclick="return jumpto('/wiki/')">shylinux</div>
|
||||||
|
</div>
|
||||||
|
<div class="list">
|
||||||
|
{{$msg := .}}
|
||||||
|
{{$ncol := append . |len}}
|
||||||
|
{{$nrow := append . 0|append .|len}}
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<div class="list_item" onclick="return jumpto('/wiki/{{option $msg "parent"|meta}}')">返回上一层</div>
|
||||||
|
</li>
|
||||||
|
{{range $row, $val := append . 0|append .}}
|
||||||
|
<li>
|
||||||
|
<div class="list_item" onclick="return jumpto('/wiki/{{option $msg "dir"|meta}}/{{append $msg "name" $row}}')">
|
||||||
|
{{append $msg "name" $row}}
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
{{end}}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{define "wiki_body"}}
|
{{define "wiki_body"}}
|
||||||
<div>hello wiki world!</div>
|
<script>
|
||||||
|
function toggle() {
|
||||||
|
window.list_hide = !window.list_hide;
|
||||||
|
var list = document.getElementsByClassName("list")[0];
|
||||||
|
var content = document.getElementsByClassName("content")[0];
|
||||||
|
if (list_hide) {
|
||||||
|
list.style.visibility = "hidden";
|
||||||
|
list.style.width="0px";
|
||||||
|
list.style.height="0px";
|
||||||
|
list.style["min-width"]="0px";
|
||||||
|
content.style.width="100%";
|
||||||
|
} else {
|
||||||
|
list.style.visibility = "visible";
|
||||||
|
list.style.width="15%";
|
||||||
|
list.style.height="100%";
|
||||||
|
list.style["min-width"]="180px";
|
||||||
|
content.style.width="85%";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function query(event) {
|
||||||
|
if (event) {
|
||||||
|
if (event.code == "Enter") {
|
||||||
|
jumpto("/wiki/?query="+encodeURIComponent(event.target.value));
|
||||||
|
}
|
||||||
|
console.log("what")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
window.query_show = !window.query_show;
|
||||||
|
var query = document.getElementsByClassName("query_menu")[0];
|
||||||
|
var input = query.getElementsByTagName("input")[0];
|
||||||
|
if (window.query_show) {
|
||||||
|
input.style.visibility = "visible";
|
||||||
|
input.style.width = "80px";
|
||||||
|
|
||||||
|
} else {
|
||||||
|
input.style.visibility = "hidden";
|
||||||
|
input.style.width = "0px";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var tags_list = {
|
||||||
|
{{range $key, $val := conf . "define"}}
|
||||||
|
"{{$key}}": true,
|
||||||
|
{{end}}
|
||||||
|
};
|
||||||
|
function tags(event) {
|
||||||
|
var tag = document.getSelection().toString();
|
||||||
|
console.log(tag);
|
||||||
|
if (tag && tag.length > 0 && tags_list[tag]) {
|
||||||
|
jumpto("/wiki/?query="+encodeURIComponent(tag));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
toggle();
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
.content {
|
||||||
|
width:85%;
|
||||||
|
height:100%;
|
||||||
|
float:left;
|
||||||
|
min-width:400px;
|
||||||
|
}
|
||||||
|
.toggle {
|
||||||
|
background-color:green;
|
||||||
|
width:2%;
|
||||||
|
height:100%;
|
||||||
|
float:left;
|
||||||
|
}
|
||||||
|
.text {
|
||||||
|
width:96%;
|
||||||
|
float:left;
|
||||||
|
margin-left:2%;
|
||||||
|
}
|
||||||
|
.link {
|
||||||
|
font-size:18px;
|
||||||
|
}
|
||||||
|
.number {
|
||||||
|
font-size:12px;
|
||||||
|
float:left;
|
||||||
|
position:relative;
|
||||||
|
left:-6px;
|
||||||
|
top:22px;
|
||||||
|
text-align:right;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div class="content">
|
||||||
|
<div class="toggle" title="点击,显示或隐藏目录" onclick="toggle()"></div>
|
||||||
|
<div class="text">
|
||||||
|
<div class="number">
|
||||||
|
{{range option . "nline"|meta|list}}
|
||||||
|
<div id="hash_{{.}}"><code>{{.}}</code></div>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
{{$msg := .}}
|
||||||
|
{{if append . "name"}}
|
||||||
|
<ul>
|
||||||
|
{{range append . "name"}}
|
||||||
|
<li class="link">
|
||||||
|
<div><a href="/wiki/{{option $msg "dir"|meta}}/{{.}}">{{.}}</a></div>
|
||||||
|
</li>
|
||||||
|
{{end}}
|
||||||
|
<ul>
|
||||||
|
{{else}}
|
||||||
|
<p>{{append . "body"|meta|unscaped}}</p>
|
||||||
|
<p><pre><code onmouseup="return tags(event)">{{append . "code"|meta}}</code></pre><p>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user