diff --git a/base/nfs/nfs.go b/base/nfs/nfs.go index 3f55dca7..d0e5b165 100644 --- a/base/nfs/nfs.go +++ b/base/nfs/nfs.go @@ -232,6 +232,17 @@ const ( FILE = "file" ) +const ( + DIR_ROOT = "dir_root" + DIR_TYPE = "dir_type" + DIR_DEEP = "dir_deep" + DIR_REG = "dir_reg" +) +const ( + TYPE_ALL = "all" + TYPE_DIR = "dir" + TYPE_FILE = "file" +) var Index = &ice.Context{Name: "nfs", Help: "存储模块", Configs: map[string]*ice.Config{ diff --git a/base/ssh/ssh.go b/base/ssh/ssh.go index 35fd6814..2a79078a 100644 --- a/base/ssh/ssh.go +++ b/base/ssh/ssh.go @@ -277,7 +277,7 @@ func (f *Frame) Start(m *ice.Message, arg ...string) bool { defer s.Close() buf := bytes.NewBuffer(make([]byte, 0, 4096)) - defer m.Echo(buf.String()) + defer func() { m.Echo(buf.String()) }() // 脚本解析 f.source = arg[0] @@ -380,4 +380,4 @@ var Index = &ice.Context{Name: "ssh", Help: "终端模块", }, } -func init() { ice.Index.Register(Index, &Frame{}) } +func init() { ice.Index.Register(Index, &Frame{}, SOURCE, QRCODE) } diff --git a/base/web/favor.go b/base/web/favor.go index 43a0f7cd..75fbba8d 100644 --- a/base/web/favor.go +++ b/base/web/favor.go @@ -264,11 +264,10 @@ const ( ) const FAVOR = "favor" -const ( // TYPE - TYPE_SPIDE = "spide" - TYPE_SPACE = "space" - TYPE_STORY = "story" +const PLUGIN = "plugin" + +const ( // TYPE TYPE_RIVER = "river" TYPE_STORM = "storm" TYPE_ACTION = "action" @@ -303,6 +302,7 @@ func init() { _favor_create(m, arg[0]) }}, mdb.INSERT: {Name: "insert zone type name text", Help: "插入", Hand: func(m *ice.Message, arg ...string) { + _favor_create(m, arg[0]) _favor_insert(m, arg[0], arg[1], arg[2], kit.Select("", arg, 3)) }}, mdb.MODIFY: {Name: "modify key value old", Help: "编辑", Hand: func(m *ice.Message, arg ...string) { diff --git a/base/web/render.go b/base/web/render.go index 27b049e7..1ea5c37f 100644 --- a/base/web/render.go +++ b/base/web/render.go @@ -9,6 +9,7 @@ import ( "fmt" "net/http" + "os" "path" "time" ) @@ -56,6 +57,9 @@ func Render(msg *ice.Message, cmd string, args ...interface{}) { case ice.RENDER_DOWNLOAD: msg.W.Header().Set("Content-Disposition", fmt.Sprintf("filename=%s", kit.Select(path.Base(arg[0]), arg, 2))) msg.W.Header().Set("Content-Type", kit.Select("text/html", arg, 1)) + if _, e := os.Stat(arg[0]); e != nil { + arg[0] = "/" + arg[0] + } http.ServeFile(msg.W, msg.R, arg[0]) case ice.RENDER_RESULT: diff --git a/base/web/share.go b/base/web/share.go index 0bedc550..dc85c8fc 100644 --- a/base/web/share.go +++ b/base/web/share.go @@ -260,7 +260,7 @@ func init() { } switch value[kit.MDB_TYPE] { - case TYPE_STORY: + case STORY: value = _share_story(m, value, arg...) } diff --git a/base/web/space.go b/base/web/space.go index 35c71a38..d266d659 100644 --- a/base/web/space.go +++ b/base/web/space.go @@ -223,7 +223,7 @@ func init() { _space_send(m, arg[0], arg[1:]...) }}, - "/space/": {Name: "/space/", Help: "空间站", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + "/space/": {Name: "/space/ type name", Help: "空间站", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { if s, e := websocket.Upgrade(m.W, m.R, nil, m.Confi(SPACE, "meta.buffer.r"), m.Confi(SPACE, "meta.buffer.w")); m.Assert(e) { name := m.Option(kit.MDB_NAME, strings.Replace(kit.Select(m.Option(ice.MSG_USERADDR), m.Option(kit.MDB_NAME)), ".", "_", -1)) kind := kit.Select(WORKER, m.Option(kit.MDB_TYPE)) diff --git a/base/web/spide.go b/base/web/spide.go index eef0cde1..99589baa 100644 --- a/base/web/spide.go +++ b/base/web/spide.go @@ -47,7 +47,7 @@ func _spide_login(m *ice.Message, name string) { } if msg.Result() != "" { kit.Value(value, "client.login", msg.Result()) - kit.Value(value, "client.share", m.Cmdx(SHARE, TYPE_SPIDE, name, + kit.Value(value, "client.share", m.Cmdx(SHARE, SPIDE, name, kit.Format("%s?sessid=%s", kit.Value(value, "client.url"), kit.Value(value, "cookie.sessid")))) } m.Render(ice.RENDER_QRCODE, kit.Dict( @@ -70,7 +70,7 @@ func _spide_create(m *ice.Message, name, address string, arg ...string) { dir, file := path.Split(uri.EscapedPath()) m.Rich(SPIDE, nil, kit.Dict( "cookie", kit.Dict(), "header", kit.Dict(), "client", kit.Dict( - "share", ShareCreate(m.Spawn(), TYPE_SPIDE, name, address), + "share", ShareCreate(m.Spawn(), SPIDE, name, address), "name", name, "url", address, "method", "POST", "protocol", uri.Scheme, "hostname", uri.Host, "path", dir, "file", file, "query", uri.RawQuery, diff --git a/core/chat/action.go b/core/chat/action.go index e4dfd989..4dff0016 100644 --- a/core/chat/action.go +++ b/core/chat/action.go @@ -123,7 +123,7 @@ func _action_show(m *ice.Message, river, storm, index string, arg ...string) { } func _action_proxy(m *ice.Message) (proxy []string) { if m.Option(POD) != "" { - proxy = append(proxy, web.PROXY, m.Option(POD)) + proxy = append(proxy, web.SPACE, m.Option(POD)) m.Option(POD, "") } return proxy diff --git a/core/chat/search.go b/core/chat/search.go index 58e69a47..0626efdf 100644 --- a/core/chat/search.go +++ b/core/chat/search.go @@ -10,10 +10,10 @@ func init() { Commands: map[string]*ice.Command{ "/" + mdb.SEARCH: {Name: "/search", Help: "搜索引擎", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { if len(arg) > 2 { - m.Cmdy(mdb.RENDER, arg) + m.Cmdy(m.Space(m.Option("pod")), mdb.RENDER, arg) return } - m.Cmdy(mdb.SEARCH, arg) + m.Cmdy(m.Space(m.Option("pod")), mdb.SEARCH, arg) }}, }, }, nil) diff --git a/core/code/pprof.go b/core/code/pprof.go index 8f0b0f9f..a44bee5b 100644 --- a/core/code/pprof.go +++ b/core/code/pprof.go @@ -82,7 +82,7 @@ func _pprof_show(m *ice.Message, zone string, id string) { m.Cmd(cli.DAEMON, m.Confv(PPROF, "meta.pprof"), "-http="+p, val[BINNARY], msg.Append(kit.MDB_TEXT)) url := "http://" + p + "/ui/top" - m.Cmd(web.FAVOR, favor, web.TYPE_SPIDE, url, msg.Append(kit.MDB_TEXT)) + m.Cmd(web.FAVOR, favor, web.SPIDE, url, msg.Append(kit.MDB_TEXT)) m.Set(ice.MSG_RESULT).Echo(url).Echo(" \n").Echo("\n") m.Echo(strings.Join(list, "\n")).Echo("\n") diff --git a/core/wiki/data.go b/core/wiki/data.go new file mode 100644 index 00000000..5454dee6 --- /dev/null +++ b/core/wiki/data.go @@ -0,0 +1,39 @@ +package wiki + +import ( + "github.com/shylinux/icebergs" + "github.com/shylinux/icebergs/base/mdb" + "github.com/shylinux/icebergs/base/nfs" + "github.com/shylinux/toolkits" +) + +func _data_show(m *ice.Message, name string, arg ...string) { + m.Cmdy(nfs.CAT, name) + m.CSV(m.Result()) +} + +const DATA = "data" +const ( + DataPlugin = "/plugin/local/wiki/data.js" +) + +func init() { + Index.Merge(&ice.Context{Name: "data", Help: "数据表格", + Configs: map[string]*ice.Config{ + DATA: {Name: "data", Help: "数据表格", Value: kit.Data( + kit.MDB_SHORT, "name", "path", "", "regs", ".*\\.csv", + )}, + }, + Commands: map[string]*ice.Command{ + DATA: {Name: "data path=auto auto", Help: "数据表格", Meta: kit.Dict(mdb.PLUGIN, DataPlugin), Action: map[string]*ice.Action{ + nfs.SAVE: {Name: "save path text", Help: "保存", Hand: func(m *ice.Message, arg ...string) { + _wiki_save(m, DATA, arg[0], arg[1]) + }}, + }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + if !_wiki_list(m, DATA, kit.Select("./", arg, 0)) { + _data_show(m, arg[0]) + } + }}, + }, + }, nil) +} diff --git a/core/wiki/draw.go b/core/wiki/draw.go index 9b4ccb71..2bb4a079 100644 --- a/core/wiki/draw.go +++ b/core/wiki/draw.go @@ -2,13 +2,9 @@ package wiki import ( "github.com/shylinux/icebergs" + "github.com/shylinux/icebergs/base/mdb" + "github.com/shylinux/icebergs/base/nfs" "github.com/shylinux/toolkits" - - "path" -) - -const ( - DRAW = "draw" ) func _draw_show(m *ice.Message, zone, kind, name, text string, arg ...string) { @@ -23,48 +19,34 @@ func _draw_plugin(m *ice.Message, arg ...string) { }) } +const DRAW = "draw" +const ( + DrawPlugin = "/plugin/local/wiki/draw.js" +) + func init() { - sub := &ice.Context{Name: "draw", Help: "思维导图", + Index.Register(&ice.Context{Name: "draw", Help: "思维导图", Configs: map[string]*ice.Config{ DRAW: {Name: "draw", Help: "思维导图", Value: kit.Data(kit.MDB_SHORT, "name", "path", "", "regs", ".*\\.svg", "prefix", ``, "suffix", ``, )}, }, Commands: map[string]*ice.Command{ - DRAW: {Name: "draw path=自然/编程/hi.svg auto", Help: "思维导图", Meta: kit.Dict( - "display", "/plugin/local/wiki/draw.js", - ), Action: map[string]*ice.Action{ - "save": {Name: "save path text", Help: "保存", Hand: func(m *ice.Message, arg ...string) { - m.Cmd("nfs.save", path.Join(m.Conf(DRAW, "meta.path"), kit.Select("hi.svg", arg, 0)), kit.Select(m.Option("content"), arg, 1)) + DRAW: {Name: "draw path=自然/编程/hi.svg auto", Help: "思维导图", Meta: kit.Dict(mdb.PLUGIN, DrawPlugin), Action: map[string]*ice.Action{ + nfs.SAVE: {Name: "save path text", Help: "保存", Hand: func(m *ice.Message, arg ...string) { + _wiki_save(m, DATA, arg[0], arg[1]) }}, "run": {Name: "show path text", Help: "运行", Hand: func(m *ice.Message, arg ...string) { _draw_show(m, arg[0], arg[1], arg[2], arg[3], arg[4:]...) }}, - "plugin": {Name: "plugin", Help: "插件", Hand: func(m *ice.Message, arg ...string) { + mdb.PLUGIN: {Name: "plugin", Help: "插件", Hand: func(m *ice.Message, arg ...string) { _draw_plugin(m, arg...) }}, }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - reply(m, cmd, arg...) - }}, - }, - } - - sub.Register(&ice.Context{Name: "创业", Help: "创业", - Commands: map[string]*ice.Command{ - "项目开发": {Name: "项目开发", Help: "项目开发", Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { - m.Echo("hello world") - }}, - "项目测试": {Name: "项目测试", Help: "项目测试", Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { - - }}, - "改变世界": {Name: "改变世界", Help: "改变世界", Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { - m.Echo("hello world") - }}, - "认识世界": {Name: "认识世界", Help: "认识世界", Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { - m.Echo("hello world") + if !_wiki_list(m, DRAW, kit.Select("./", arg, 0)) { + _wiki_show(m, DRAW, arg[0]) + } }}, }, }, nil) - - Index.Register(sub, nil) } diff --git a/core/wiki/feel.go b/core/wiki/feel.go new file mode 100644 index 00000000..cf425bab --- /dev/null +++ b/core/wiki/feel.go @@ -0,0 +1,55 @@ +package wiki + +import ( + "github.com/shylinux/icebergs" + "github.com/shylinux/icebergs/base/mdb" + "github.com/shylinux/icebergs/base/web" + "github.com/shylinux/toolkits" + + "os" + "path" +) + +func _feel_show(m *ice.Message, name string, arg ...string) { + m.Echo(path.Join(m.Conf(FEEL, "meta.path"), name)) +} + +const FEEL = "feel" +const FeelPlugin = "/plugin/local/wiki/feel.js" + +func init() { + Index.Merge(&ice.Context{Name: "feel", Help: "影音媒体", + Configs: map[string]*ice.Config{ + FEEL: {Name: "feel", Help: "影音媒体", Value: kit.Data( + kit.MDB_SHORT, "name", "path", "", "regs", ".*.(qrc|png|jpg|JPG|MOV|m4v)", + "height", "600", "page.limit", "3", + )}, + }, + Commands: map[string]*ice.Command{ + FEEL: {Name: "feel path=auto auto", Help: "影音媒体", Meta: kit.Dict( + web.PLUGIN, FeelPlugin, "detail", []string{"标签", "删除"}, + ), Action: map[string]*ice.Action{ + mdb.CREATE: {Name: "create", Help: "创建", Hand: func(m *ice.Message, arg ...string) { + m.Conf(FEEL, kit.Keys(path.Base(arg[2]), "-2"), arg[3]) + p := path.Join(m.Conf(FEEL, "meta.path"), arg[2]) + q := path.Join(m.Conf(FEEL, "meta.path"), arg[3]) + os.MkdirAll(q, 0777) + m.Assert(os.Link(p, path.Join(q, path.Base(arg[2])))) + }}, + mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) { + m.Assert(os.Remove(path.Join(m.Conf(FEEL, "meta.path"), m.Option("path")))) + }}, + web.UPLOAD: {Name: "upload", Help: "上传", Hand: func(m *ice.Message, arg ...string) { + _wiki_upload(m, FEEL) + }}, + }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + m.Option("prefix", m.Conf(FEEL, "meta.path")) + m.Option("height", m.Conf(FEEL, "meta.height")) + m.Option("limit", m.Conf(FEEL, "meta.page.limit")) + if !_wiki_list(m, FEEL, kit.Select("./", arg, 0)) { + _feel_show(m, arg[0]) + } + }}, + }, + }, nil) +} diff --git a/core/wiki/image.go b/core/wiki/image.go deleted file mode 100644 index f4b94386..00000000 --- a/core/wiki/image.go +++ /dev/null @@ -1,22 +0,0 @@ -package wiki - -import ( - ice "github.com/shylinux/icebergs" -) - -func init() { - - Index.Register(&ice.Context{Name: "jpg", Help: "图片", - Configs: map[string]*ice.Config{}, - Commands: map[string]*ice.Command{ - "list": {Name: "list name", Help: "列表", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Echo(arg[0]) - }}, - "save": {Name: "save name text", Help: "保存", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - }}, - "show": {Name: "show name", Help: "渲染", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - }}, - }, - }, nil) - -} diff --git a/core/wiki/template.go b/core/wiki/template.go index f42046ec..9de5e39f 100644 --- a/core/wiki/template.go +++ b/core/wiki/template.go @@ -7,14 +7,13 @@ data-type="{{.Option "type"}}" data-name="{{.Option "name"}}" data-text="{{.Opti {{range $index, $value := .Optionv "list"}}
  • {{index $value 0}}: {{index $value 1}}
  • {{end}}` var spark = `

    {{.Option "text"}}

    ` -var local = `
    -{{range $index, $value := .Optionv "input"}}{{$value}}{{end}}
    ` - -var shell = `$ {{.Option "input"}} # {{.Option "name"}} -{{.Option "output"}} -` - +var chart = `` var field = `
    {{.Option "name"}}
    @@ -23,40 +22,13 @@ var field = `
    ` -var field0 = `
    -{{.Option "name"}} {{$meta := .Optionv "meta"}} -
    - {{if $meta}} - {{range $index, $value := index $meta "inputs"}} - {{$type := index $value "_input"}} -
    - -
    - {{end}} - {{end}} - -
    -
    -
    - {{if .Result}} -
    {{.Result}}
    - {{else if .Appendv "append"}} - {{$msg := .}} - {{range $index, $value := .Appendv "append"}}{{end}} - {{range $index, $_ := .Appendv "_index"}}{{range $_, $key := $msg.Appendv "append"}}{{$line := $msg.Appendv $key}} - - {{end}}{{end}} -
    {{$value}}
    {{index $line $index}}
    - {{end}} -
    - +var shell = `$ {{.Option "input"}} # {{.Option "name"}} +{{.Option "output"}} ` +var local = `
    +{{range $index, $value := .Optionv "input"}}{{$value}}{{end}}
    ` + var order = `` @@ -72,14 +44,6 @@ data-type="{{.Option "type"}}" data-name="{{.Option "name"}}" data-text="{{.Opti var stack = `
    ` -var prefix = `` - var premenu = `` var endmenu = `
    ") - }}, - - "data": {Name: "data path auto", Help: "数据表格", Meta: kit.Dict("display", "local/wiki/data"), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - if len(arg) > 0 && arg[0] == "action" { - switch arg[1] { - case "保存": - m.Cmd("nfs.save", path.Join(m.Conf(cmd, "meta.path"), arg[2]), arg[3]) - } - return - } - - if reply(m, cmd, arg...) { - // 目录列表 - return - } - // 解析数据 - m.CSV(m.Result()) - }}, - "feel": {Name: "feel path auto 上传:button=@upload", Help: "影音媒体", Meta: kit.Dict( - "display", "local/wiki/feel", "detail", []string{"标签", "删除"}, - ), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - if m.Option("_action") == "上传" { - m.Cmd(web.CACHE, "watch", m.Option("_data"), path.Join(m.Option("name"), m.Option("_name"))) - return - } - - if len(arg) > 0 && arg[0] == "action" { - switch arg[1] { - case "删除": - m.Assert(os.Remove(path.Join(m.Conf(cmd, "meta.path"), m.Option("path")))) - case "保存": - m.Cmd("nfs.save", path.Join(m.Conf(cmd, "meta.path"), arg[2]), arg[3]) - case "标签": - m.Conf(cmd, kit.Keys(path.Base(arg[2]), "-2"), arg[3]) - p := path.Join(m.Conf(cmd, "meta.path"), arg[2]) - q := path.Join(m.Conf(cmd, "meta.path"), arg[3]) - os.MkdirAll(q, 0777) - m.Assert(os.Link(p, path.Join(q, path.Base(arg[2])))) - } - return - } - - if len(arg) == 0 || strings.HasSuffix(arg[0], "/") { - // 文件列表 - m.Option("dir_root", m.Conf(cmd, "meta.path")) - m.Option("dir_reg", m.Conf(cmd, "meta.regs")) - m.Cmdy("nfs.dir", kit.Select("./", arg, 0), "time size path").Table(func(index int, value map[string]string, head []string) { - m.Push("label", m.Conf(cmd, path.Base(value["path"]))) - }) - - // 目录列表 - m.Option("dir_reg", "") - m.Option("dir_type", "dir") - m.Cmdy("nfs.dir", kit.Select("./", arg, 0)) - - if len(arg) > 0 { - m.Sort("time", "time_r") - } else { - m.Sort("line", "int_r") - } - return - } - // 下载文件 - m.Echo(path.Join(m.Conf(cmd, "meta.path"), arg[0])) - }}, "walk": {Name: "walk path=@province auto", Help: "走遍世界", Meta: kit.Dict("display", "local/wiki/walk"), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { if len(arg) > 0 && arg[0] == "action" { switch arg[1] { diff --git a/core/wiki/word.go b/core/wiki/word.go index 38ae60d8..b6200960 100644 --- a/core/wiki/word.go +++ b/core/wiki/word.go @@ -12,18 +12,257 @@ import ( "strings" ) +func _title_show(m *ice.Message, kind, text string, arg ...string) { + title, _ := m.Optionv(TITLE).(map[string]int) + switch kind { + case ENDMENU: + // 后置目录 + m.Render(ice.RENDER_TEMPLATE, endmenu) + return + case PREMENU: + // 前置目录 + m.Render(ice.RENDER_TEMPLATE, premenu) + return + case SECTION: + // 分节标题 + title[SECTION]++ + m.Option("level", "h3") + m.Option("prefix", fmt.Sprintf("%d.%d", title[CHAPTER], title[SECTION])) + case CHAPTER: + // 章节标题 + title[CHAPTER]++ + title[SECTION] = 0 + m.Option("level", "h2") + m.Option("prefix", fmt.Sprintf("%d", title[CHAPTER])) + default: + // 文章标题 + m.Option("level", "h1") + m.Option("prefix", "") + } + + // 基本参数 + m.Option(kit.MDB_TYPE, TITLE) + m.Option(kit.MDB_NAME, text) + m.Option(kit.MDB_TEXT, text) + + // 添加目录 + menu, _ := m.Optionv("menu").(map[string]interface{}) + menu["list"] = append(menu["list"].([]interface{}), map[string]interface{}{ + "content": m.Option("content", text), + "prefix": m.Option("prefix"), + "level": m.Option("level"), + }) + + // 渲染引擎 + m.Render(ice.RENDER_TEMPLATE, m.Conf(TITLE, "meta.template")) +} +func _brief_show(m *ice.Message, name, text string, arg ...string) { + m.Option(kit.MDB_TYPE, BRIEF) + m.Option(kit.MDB_NAME, name) + m.Option(kit.MDB_TEXT, text) + + // 渲染引擎 + m.Render(ice.RENDER_TEMPLATE, m.Conf(BRIEF, "meta.template")) +} +func _refer_show(m *ice.Message, name, text string, arg ...string) { + m.Option(kit.MDB_TYPE, REFER) + m.Option(kit.MDB_NAME, name) + m.Option(kit.MDB_TEXT, text) + + list := [][]string{} + for _, v := range kit.Split(strings.TrimSpace(text), "\n") { + list = append(list, kit.Split(v, " ")) + } + m.Optionv("list", list) + m.Render(ice.RENDER_TEMPLATE, m.Conf(REFER, "meta.template")) +} +func _spark_show(m *ice.Message, name, text string, arg ...string) { + m.Option(kit.MDB_TYPE, SPARK) + m.Option(kit.MDB_NAME, name) + m.Option(kit.MDB_TEXT, text) + + m.Optionv("list", kit.Split(text, "\n")) + m.Render(ice.RENDER_TEMPLATE, m.Conf(SPARK, "meta.template")) +} + +func _chart_show(m *ice.Message, kind, name, text string, arg ...string) { + var chart Chart + switch kind { + case LABEL: + // 标签 + chart = &Label{} + case CHAIN: + // 链接 + chart = &Chain{} + } + name = strings.TrimSpace(name) + text = strings.TrimSpace(text) + + // 基本参数 + m.Option(kit.MDB_TYPE, kind) + m.Option(kit.MDB_NAME, name) + m.Option(kit.MDB_TEXT, text) + + // 扩展参数 + m.Option("font-size", "24") + m.Option("stroke", "blue") + m.Option("fill", "yellow") + // 扩展参数 + m.Option("style", "") + m.Option("compact", "false") + m.Option("stroke-width", "2") + m.Option("padding", "10") + m.Option("margin", "10") + // m.Option("font-family", kit.Select("", "monospace", len(text) == len([]rune(text)))) + m.Option("font-family", "monospace") + for i := 0; i < len(arg)-1; i++ { + m.Option(arg[i], arg[i+1]) + } + + // 计算尺寸 + chart.Init(m, text) + m.Option("width", chart.GetWidth()) + m.Option("height", chart.GetHeight()) + + // 渲染引擎 + m.Render(ice.RENDER_TEMPLATE, m.Conf(CHART, "meta.template")) + chart.Draw(m, 0, 0) + m.Render(ice.RENDER_TEMPLATE, m.Conf(CHART, "meta.suffix")) +} +func _field_show(m *ice.Message, name, text string, arg ...string) { + // 基本参数 + m.Option(kit.MDB_TYPE, FIELD) + m.Option(kit.MDB_NAME, name) + m.Option(kit.MDB_TEXT, text) + + // 命令参数 + data := kit.Dict(kit.MDB_NAME, name) + cmds := kit.Split(text) + m.Search(cmds[0], func(p *ice.Context, s *ice.Context, key string, cmd *ice.Command) { + if ls := strings.Split(cmds[0], "."); len(ls) > 1 { + m.Cmd(ctx.COMMAND, strings.Join(ls[:len(ls)-1], "."), key) + } else { + m.Cmd(ctx.COMMAND, key) + } + if data["feature"], data["inputs"] = cmd.Meta, cmd.List; len(cmd.List) == 0 { + data["inputs"] = m.Confv("field", "meta.some.simple.inputs") + } + }) + + // 扩展参数 + for i := 0; i < len(arg)-1; i += 2 { + if data := m.Confv("field", kit.Keys("meta.some", arg[i+1], arg[i])); data != nil { + m.Option(arg[i], data) + } else { + m.Parse("option", arg[i], arg[i+1]) + } + data[arg[i]] = m.Optionv(arg[i]) + } + + // 渲染引擎 + m.Option("meta", data) + m.Render(ice.RENDER_TEMPLATE, m.Conf(FIELD, "meta.template")) +} +func _shell_show(m *ice.Message, name, text string, arg ...string) { + m.Option(kit.MDB_TYPE, SHELL) + m.Option(kit.MDB_NAME, name) + m.Option(kit.MDB_TEXT, text) + + // 渲染引擎 + m.Option("output", m.Cmdx(cli.SYSTEM, "sh", "-c", m.Option("input", text))) + m.Render(ice.RENDER_TEMPLATE, m.Conf(SHELL, "meta.template")) +} +func _local_show(m *ice.Message, name, text string, arg ...string) { + m.Option(kit.MDB_TYPE, LOCAL) + m.Option(kit.MDB_NAME, name) + m.Option(kit.MDB_TEXT, text) + + m.Option("input", m.Cmdx("nfs.cat", text)) + m.Render(ice.RENDER_TEMPLATE, m.Conf(LOCAL, "meta.template")) +} + +func _order_show(m *ice.Message, name, text string, arg ...string) { + m.Option(kit.MDB_TYPE, ORDER) + m.Option(kit.MDB_NAME, name) + m.Option(kit.MDB_TEXT, text) + + m.Optionv("list", kit.Split(strings.TrimSpace(text), "\n")) + m.Render(ice.RENDER_TEMPLATE, m.Conf(ORDER, "meta.template")) +} +func _table_show(m *ice.Message, name, text string, arg ...string) { + m.Option(kit.MDB_TYPE, TABLE) + m.Option(kit.MDB_NAME, name) + m.Option(kit.MDB_TEXT, text) + + head, list := []string{}, [][]string{} + for i, v := range kit.Split(strings.TrimSpace(text), "\n") { + if i == 0 { + head = kit.Split(v) + } else { + line := kit.Split(v) + for i, v := range line { + if ls := kit.Split(v); len(ls) > 1 { + style := []string{} + for i := 1; i < len(ls)-1; i += 2 { + switch ls[i] { + case "bg": + ls[i] = "background-color" + case "fg": + ls[i] = "color" + } + style = append(style, ls[i]+":"+ls[i+1]) + } + line[i] = kit.Format(`%s`, strings.Join(style, ";"), ls[0]) + } + } + list = append(list, line) + } + } + m.Optionv("head", head) + m.Optionv("list", list) + m.Render(ice.RENDER_TEMPLATE, m.Conf(TABLE, "meta.template")) +} +func _stack_show(m *ice.Message, name, text string, arg ...string) { + m.Option(kit.MDB_TYPE, STACK) + m.Option(kit.MDB_NAME, name) + m.Option(kit.MDB_TEXT, text) + + chain := &Chain{} + m.Render(ice.RENDER_TEMPLATE, m.Conf(STACK, "meta.template")) + Stack(m, STACK, 0, kit.Parse(nil, "", chain.show(m, text)...)) + m.Echo("") +} + +func _word_show(m *ice.Message, name string, arg ...string) { + m.Set(ice.MSG_RESULT) + m.Option("render", "raw") + m.Optionv(TITLE, map[string]int{}) + m.Optionv("menu", map[string]interface{}{"list": []interface{}{}}) + m.Optionv(ice.MSG_ALIAS, m.Confv(WORD, "meta.alias")) + m.Cmdy(ssh.SOURCE, path.Join(m.Conf(WORD, "meta.path"), name)) +} + const ( WORD = "word" TITLE = "title" + BRIEF = "brief" + REFER = "refer" + SPARK = "spark" + CHART = "chart" FIELD = "field" SHELL = "shell" + LOCAL = "local" + + ORDER = "order" + TABLE = "table" + STACK = "stack" CHAPTER = "chapter" SECTION = "section" - PREMENU = "premenu" ENDMENU = "endmenu" + PREMENU = "premenu" LABEL = "label" CHAIN = "chain" @@ -33,17 +272,18 @@ func init() { Index.Merge(&ice.Context{ Configs: map[string]*ice.Config{ TITLE: {Name: "title", Help: "标题", Value: kit.Data("template", title)}, - CHART: {Name: "chart", Help: "图表", Value: kit.Data("template", prefix, "suffix", ``)}, - FIELD: {Name: "field", Help: "插件", Value: kit.Data("template", field, - "some", kit.Dict("simple", kit.Dict( - "inputs", kit.List( - kit.MDB_INPUT, "text", "name", "name", - kit.MDB_INPUT, "button", "value", "查看", "action", "auto", - kit.MDB_INPUT, "button", "value", "返回", "cb", "Last", - ), - )), - )}, + BRIEF: {Name: "brief", Help: "摘要", Value: kit.Data("template", brief)}, + REFER: {Name: "refer", Help: "参考", Value: kit.Data("template", refer)}, + SPARK: {Name: "spark", Help: "段落", Value: kit.Data("template", spark)}, + + CHART: {Name: "chart", Help: "图表", Value: kit.Data("template", chart, "suffix", ``)}, + FIELD: {Name: "field", Help: "插件", Value: kit.Data("template", field)}, SHELL: {Name: "shell", Help: "命令", Value: kit.Data("template", shell)}, + LOCAL: {Name: "local", Help: "文件", Value: kit.Data("template", local)}, + + ORDER: {Name: "order", Help: "列表", Value: kit.Data("template", order)}, + TABLE: {Name: "table", Help: "表格", Value: kit.Data("template", table)}, + STACK: {Name: "stack", Help: "结构", Value: kit.Data("template", stack)}, WORD: {Name: "word", Help: "语言文字", Value: kit.Data(kit.MDB_SHORT, "name", "path", "", "regs", ".*\\.shy", "alias", map[string]interface{}{ @@ -59,144 +299,64 @@ func init() { }, Commands: map[string]*ice.Command{ TITLE: {Name: "title [chapter|section|endmenu|premenu] text", Help: "标题", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - title, _ := m.Optionv(TITLE).(map[string]int) - switch arg[0] { - case ENDMENU: - // 后置目录 - m.Render(ice.RENDER_TEMPLATE, endmenu) - return - case PREMENU: - // 前置目录 - m.Render(ice.RENDER_TEMPLATE, premenu) - return - case SECTION: - // 分节标题 - arg = arg[1:] - title[SECTION]++ - m.Option("level", "h3") - m.Option("prefix", fmt.Sprintf("%d.%d", title[CHAPTER], title[SECTION])) - case CHAPTER: - // 章节标题 - arg = arg[1:] - title[CHAPTER]++ - title[SECTION] = 0 - m.Option("level", "h2") - m.Option("prefix", fmt.Sprintf("%d", title[CHAPTER])) - default: - // 文章标题 - m.Option("level", "h1") - m.Option("prefix", "") + if len(arg) == 0 { + ns := strings.Split(cli.NodeName, "-") + arg = append(arg, kit.Select(ns[len(ns)-1], "")) } - - // 基本参数 - m.Option(kit.MDB_TYPE, TITLE) - m.Option(kit.MDB_NAME, arg[0]) - m.Option(kit.MDB_TEXT, arg[0]) - - // 添加目录 - ns := strings.Split(m.Conf("runtime", "node.name"), "-") - menu, _ := m.Optionv("menu").(map[string]interface{}) - menu["list"] = append(menu["list"].([]interface{}), map[string]interface{}{ - "content": m.Option("content", kit.Select(ns[len(ns)-1], arg, 0)), - "prefix": m.Option("prefix"), - "level": m.Option("level"), - }) - - // 渲染引擎 - m.Render(ice.RENDER_TEMPLATE, m.Conf(TITLE, "meta.template")) + if len(arg) == 1 { + arg = append(arg, arg[0]) + } + _title_show(m, arg[0], arg[1], arg[2:]...) }}, - CHART: {Name: "chart label|chain name text", Help: "图表", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - var chart Chart - switch arg[0] { - case LABEL: - // 标签 - chart = &Label{} - case CHAIN: - // 链接 - chart = &Chain{} + BRIEF: {Name: "brief name text", Help: "摘要", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + if len(arg) == 0 { + m.Echo(`
    `) + return } - arg[1] = strings.TrimSpace(arg[1]) - arg[2] = strings.TrimSpace(arg[2]) - - // 基本参数 - m.Option(kit.MDB_TYPE, arg[0]) - m.Option(kit.MDB_NAME, arg[1]) - m.Option(kit.MDB_TEXT, arg[2]) - - // 扩展参数 - m.Option("font-size", "24") - m.Option("stroke", "blue") - m.Option("fill", "yellow") - // 扩展参数 - m.Option("style", "") - m.Option("compact", "false") - m.Option("stroke-width", "2") - m.Option("padding", "10") - m.Option("margin", "10") - // m.Option("font-family", kit.Select("", "monospace", len(arg[2]) == len([]rune(arg[2])))) - m.Option("font-family", "monospace") - for i := 3; i < len(arg)-1; i++ { - m.Option(arg[i], arg[i+1]) + if len(arg) == 1 { + arg = []string{"", arg[0]} } - - // 计算尺寸 - chart.Init(m, arg[2]) - m.Option("width", chart.GetWidth()) - m.Option("height", chart.GetHeight()) - - // 渲染引擎 - m.Render(ice.RENDER_TEMPLATE, m.Conf(CHART, "meta.template")) - chart.Draw(m, 0, 0) - m.Render(ice.RENDER_TEMPLATE, m.Conf(CHART, "meta.suffix")) + _brief_show(m, arg[0], arg[1], arg[2:]...) }}, - FIELD: {Name: "field name text", Help: "插件", Action: map[string]*ice.Action{ + REFER: {Name: "refer name `[name url]...`", Help: "参考", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + _refer_show(m, arg[0], arg[1], arg[2:]...) + }}, + SPARK: {Name: "spark name text", Help: "感悟", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + if len(arg) == 0 { + m.Echo(`
    `) + return + } + if len(arg) == 1 { + arg = []string{"", arg[0]} + } + _spark_show(m, arg[0], arg[1], arg[2:]...) + }}, + + CHART: {Name: "chart label|chain name text arg...", Help: "图表", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + _chart_show(m, arg[0], arg[1], arg[2], arg[3:]...) + }}, + FIELD: {Name: "field name cmd", Help: "插件", Action: map[string]*ice.Action{ "run": {Name: "run", Help: "运行", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(arg[1:]) }}, }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - // 基本参数 - m.Option(kit.MDB_TYPE, FIELD) - m.Option(kit.MDB_NAME, arg[0]) - m.Option(kit.MDB_TEXT, arg[1]) - - // 命令参数 - data := kit.Dict(kit.MDB_NAME, arg[0]) - cmds := kit.Split(arg[1]) - m.Search(cmds[0], func(p *ice.Context, s *ice.Context, key string, cmd *ice.Command) { - if ls := strings.Split(cmds[0], "."); len(ls) > 1 { - m.Cmd(ctx.COMMAND, strings.Join(ls[:len(ls)-1], "."), key) - } else { - m.Cmd(ctx.COMMAND, key) - } - if data["feature"], data["inputs"] = cmd.Meta, cmd.List; len(cmd.List) == 0 { - data["inputs"] = m.Confv("field", "meta.some.simple.inputs") - } - }) - - // 扩展参数 - for i := 2; i < len(arg)-1; i += 2 { - if data := m.Confv("field", kit.Keys("meta.some", arg[i+1], arg[i])); data != nil { - m.Option(arg[i], data) - } else { - m.Parse("option", arg[i], arg[i+1]) - } - data[arg[i]] = m.Optionv(arg[i]) - } - - // 渲染引擎 - m.Option("meta", data) - m.Render(ice.RENDER_TEMPLATE, m.Conf(cmd, "meta.template")) + _field_show(m, arg[0], arg[1], arg[2:]...) + }}, + SHELL: {Name: "shell name cmd", Help: "命令", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + _shell_show(m, arg[0], arg[1]) + }}, + LOCAL: {Name: "local name text", Help: "文件", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + _local_show(m, arg[0], arg[1]) }}, - SHELL: {Name: "shell name text", Help: "命令", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - // 基本参数 - m.Option(kit.MDB_TYPE, SHELL) - m.Option(kit.MDB_NAME, arg[0]) - m.Option(kit.MDB_TEXT, arg[1]) - // 渲染引擎 - m.Option("input", strings.Join(arg[1:], " ")) - m.Option("output", m.Cmdx(cli.SYSTEM, "sh", "-c", m.Option("input"))) - m.Render(ice.RENDER_TEMPLATE, m.Conf(SHELL, "meta.template")) + ORDER: {Name: "order name text", Help: "列表", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + _order_show(m, arg[0], arg[1], arg[2:]...) + }}, + TABLE: {Name: "table name text", Help: "表格", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + _table_show(m, arg[0], arg[1], arg[2:]...) + }}, + STACK: {Name: "stack name text", Help: "结构", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + _stack_show(m, arg[0], arg[1], arg[2:]...) }}, WORD: {Name: "word path=自然/编程/hi.shy auto", Help: "语言文字", Meta: kit.Dict( @@ -210,13 +370,7 @@ func init() { // 目录列表 return } - - // 解析脚本 - m.Option("render", "raw") - m.Optionv(TITLE, map[string]int{}) - m.Optionv("menu", map[string]interface{}{"list": []interface{}{}}) - m.Optionv(ice.MSG_ALIAS, m.Confv(WORD, "meta.alias")) - m.Set(ice.MSG_RESULT).Cmdy(ssh.SOURCE, path.Join(m.Conf(WORD, "meta.path"), arg[0])) + _word_show(m, arg[0]) }}, }, }, nil) diff --git a/init.go b/init.go index ff8866c4..d951142e 100644 --- a/init.go +++ b/init.go @@ -106,6 +106,18 @@ var Index = &Context{Name: "ice", Help: "冰山模块", "help": {Name: "help", Help: "帮助", Hand: func(m *Message, c *Context, cmd string, arg ...string) { m.Echo(strings.Join(kit.Simple(m.Confv("help", "index")), "\n")) }}, + "name": {Name: "name", Help: "命名", Hand: func(m *Message, c *Context, cmd string, arg ...string) { + for k, v := range names { + m.Push("key", k) + switch v := v.(type) { + case *Context: + m.Push("value", v.Name) + default: + m.Push("value", "") + } + } + m.Sort("key") + }}, "exit": {Name: "exit", Help: "结束", Hand: func(m *Message, c *Context, cmd string, arg ...string) { m.root.target.server.(*Frame).code = kit.Int(kit.Select("0", arg, 0)) m.Cmd("ssh.source", "etc/exit.shy", "exit.shy", "退出配置") diff --git a/misc/chrome/chrome.go b/misc/chrome/chrome.go index 21a49a28..aa0e336a 100644 --- a/misc/chrome/chrome.go +++ b/misc/chrome/chrome.go @@ -2,19 +2,36 @@ package crx import ( "github.com/shylinux/icebergs" + "github.com/shylinux/icebergs/base/mdb" "github.com/shylinux/icebergs/base/web" "github.com/shylinux/icebergs/core/code" "github.com/shylinux/toolkits" ) +const CHROME = "chrome" + var Index = &ice.Context{Name: "chrome", Help: "浏览器", - Caches: map[string]*ice.Cache{}, Configs: map[string]*ice.Config{ - "chrome": {Name: "chrome", Help: "chrome", Value: kit.Data(kit.MDB_SHORT, "name", "history", "url.history")}, + CHROME: {Name: "chrome", Help: "浏览器", Value: kit.Data( + kit.MDB_SHORT, "name", web.FAVOR, "url.history", + )}, }, Commands: map[string]*ice.Command{ + "/crx": {Name: "/crx", Help: "/crx", Action: map[string]*ice.Action{ + "history": {Name: "history", Help: "历史记录", Hand: func(m *ice.Message, arg ...string) { + m.Cmdy(web.SPIDE, "dev", "/code/chrome/favor", "cmds", "insert", "name", arg[1], "note", arg[2], + "tab", m.Conf(CHROME, "meta.favor"), "sid", m.Option("sid")) + }}, + }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + }}, + "/favor": {Name: "/favor", Help: "收藏", Action: map[string]*ice.Action{ + mdb.INSERT: {Name: "insert", Help: "插入", Hand: func(m *ice.Message, arg ...string) { + m.Cmdy(web.FAVOR, mdb.INSERT, m.Option("tab"), web.SPIDE, m.Option("name"), m.Option("note")) + }}, + }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + }}, - "chrome": {Name: "chrome", Help: "浏览器", List: kit.List( + CHROME: {Name: "chrome", Help: "浏览器", List: kit.List( kit.MDB_INPUT, "text", "name", "name", "action", "auto", kit.MDB_INPUT, "text", "name", "wid", "action", "auto", kit.MDB_INPUT, "text", "name", "url", @@ -76,48 +93,6 @@ var Index = &ice.Context{Name: "chrome", Help: "浏览器", // 下发命令 m.Cmdy(web.SPACE, arg[0], "bookmark", arg[1:]) }}, - - web.LOGIN: {Name: "_login", Help: "_login", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Option("you", "") - m.Richs("login", nil, m.Option("sid"), func(key string, value map[string]interface{}) { - // 查找空间 - m.Option("you", value["you"]) - }) - - m.Info("%s %s cmd: %v sub: %v", m.Option("you"), m.Option(ice.MSG_USERURL), m.Optionv("cmds"), m.Optionv("sub")) - }}, - "/help": {Name: "/help", Help: "帮助", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Cmdy("help") - }}, - "/login": {Name: "/login", Help: "登录", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Cmdy("login", "init", c.Name) - }}, - "/logout": {Name: "/logout", Help: "登出", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Cmdy("login", "exit") - }}, - - "/favor": {Name: "/favor", Help: "收藏", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - if len(arg) > 0 { - // 添加收藏 - web.FavorInsert(m, m.Option("tab"), web.TYPE_SPIDE, m.Option("note"), arg[0]) - return - } - }}, - - "/crx": {Name: "/crx", Help: "/crx", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - switch arg[0] { - case "login": - m.Cmdy(web.SPIDE, "dev", "msg", "/code/chrome/login", "sid", m.Option("sid")) - - case "bookmark": - m.Cmdy(web.SPIDE, "dev", "/code/chrome/favor", "cmds", arg[2], "note", arg[3], - "tab", kit.Select(m.Conf("chrome", "meta.history"), arg, 4), "sid", m.Option("sid"), "type", "spide") - - case "history": - m.Cmdy(web.SPIDE, "dev", "/code/chrome/favor", "cmds", arg[2], "note", arg[3], - "tab", m.Conf("chrome", "meta.history"), "sid", m.Option("sid")) - } - }}, }, } diff --git a/misc/git/git.go b/misc/git/git.go index 5cc234a0..594f95e7 100644 --- a/misc/git/git.go +++ b/misc/git/git.go @@ -3,8 +3,10 @@ package git import ( ice "github.com/shylinux/icebergs" "github.com/shylinux/icebergs/base/cli" + "github.com/shylinux/icebergs/base/mdb" "github.com/shylinux/icebergs/base/web" "github.com/shylinux/icebergs/core/code" + "github.com/shylinux/icebergs/core/wiki" kit "github.com/shylinux/toolkits" "os" @@ -78,7 +80,7 @@ var Index = &ice.Context{Name: "git", Help: "代码库", // 应用项目 m.Cmd("nfs.dir", m.Conf(web.DREAM, "meta.path"), "name path").Table(func(index int, value map[string]string, head []string) { - add(m, value["name"], value["path"]) + // add(m, value["name"], value["path"]) }) }}, "auto": {Name: "auto", Help: "自动化", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { @@ -110,7 +112,9 @@ var Index = &ice.Context{Name: "git", Help: "代码库", }) m.Sort("name") }}, - "total": {Name: "total name=auto auto", Help: "提交统计", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + "total": {Name: "total name=auto auto", Help: "提交统计", Meta: kit.Dict( + mdb.PLUGIN, wiki.DataPlugin, + ), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { if len(arg) > 0 { // 提交详情 m.Richs("repos", nil, arg[0], func(key string, value map[string]interface{}) { @@ -145,7 +149,7 @@ var Index = &ice.Context{Name: "git", Help: "代码库", }) wg.Wait() m.Push("name", "total") - m.Push("days", days) + m.Push("days", kit.Int(days)+1) m.Push("commit", commit) m.Push("adds", adds) m.Push("dels", dels) @@ -208,7 +212,7 @@ var Index = &ice.Context{Name: "git", Help: "代码库", } args := []string{} - args = append(args, "log", "--shortstat", "--pretty=commit: %ad %n%s", "--date=iso", "--reverse") + args = append(args, "log", kit.Format("--author=%s\\|shylinux", m.Option(ice.MSG_USERNAME)), "--shortstat", "--pretty=commit: %ad %n%s", "--date=iso", "--reverse") if len(arg) > 0 { args = append(args, kit.Select("-n", "--since", strings.Contains(arg[0], "-"))) if strings.Contains(arg[0], "-") && !strings.Contains(arg[0], ":") {