From 89024c6f309dcabf4f6f8a003dbe21e88791c9c6 Mon Sep 17 00:00:00 2001 From: shaoying Date: Fri, 6 Dec 2019 11:10:20 +0800 Subject: [PATCH] add chart.go --- src/examples/wiki/chart.go | 271 +++++++++++++++++++++++++++++++++++++ src/examples/wiki/wiki.go | 21 ++- src/plugin/story/index.shy | 6 +- src/toolkit/core.go | 4 +- usr/local/wiki/miss.md | 31 ++++- 5 files changed, 326 insertions(+), 7 deletions(-) create mode 100644 src/examples/wiki/chart.go diff --git a/src/examples/wiki/chart.go b/src/examples/wiki/chart.go new file mode 100644 index 00000000..61f579e2 --- /dev/null +++ b/src/examples/wiki/chart.go @@ -0,0 +1,271 @@ +package wiki + +import ( + "contexts/ctx" + mis "github.com/shylinux/toolkits" + "strings" + "toolkit" +) + +// 图形接口 +type Chart interface { + Init(*ctx.Message, ...string) Chart + Draw(*ctx.Message, int, int) Chart + + GetWidth(...string) int + GetHeight(...string) int +} + +// 图形基类 +type Block struct { + Text string + FontColor string + BackGround string + + FontSize int + LineSize int + Padding int + Margin int + + Width, Height int + + TextData string + RectData string +} + +func (b *Block) GetWidth(str ...string) int { + if b.Width != 0 { + return b.Width + } + return len(kit.Select(b.Text, str, 0))*b.FontSize/2 + b.Padding +} +func (b *Block) GetHeight(str ...string) int { + if b.Height != 0 { + return b.Height + } + return b.FontSize*b.LineSize/10 + b.Padding +} +func (b *Block) GetWidths(str ...string) int { + return b.GetWidth(str...) + b.Margin +} +func (b *Block) GetHeights(str ...string) int { + return b.GetHeight() + b.Margin +} +func (b *Block) Init(m *ctx.Message, arg ...string) Chart { + b.Text = kit.Select(b.Text, arg, 0) + b.FontColor = kit.Select("white", kit.Select(b.FontColor, arg, 1)) + b.BackGround = kit.Select("red", kit.Select(b.BackGround, arg, 2)) + b.FontSize = kit.Int(kit.Select("24", kit.Select(kit.Format(b.FontSize), arg, 3))) + b.LineSize = kit.Int(kit.Select("12", kit.Select(kit.Format(b.LineSize), arg, 4))) + return b +} +func (b *Block) Draw(m *ctx.Message, x, y int) Chart { + m.Echo(``, + x+b.Margin/2, y+b.Margin/2, b.GetWidth(), b.GetHeight(), b.BackGround, b.RectData) + m.Echo(`%v`, + x+b.GetWidths()/2, y+b.GetHeights()/2, b.FontSize, b.FontColor, b.TextData, b.Text) + return b +} +func (b *Block) Data(root interface{}) { + mis.Table(mis.Value(root, "data"), 0, 100, func(key string, value string) { + b.TextData += key + "='" + value + "' " + }) + mis.Table(mis.Value(root, "rect"), 0, 100, func(key string, value string) { + b.RectData += key + "='" + value + "' " + }) + b.FontColor = kit.Select(b.FontColor, mis.Value(root, "fg")) + b.BackGround = kit.Select(b.BackGround, mis.Value(root, "bg")) +} + +type Chain struct { + data map[string]interface{} + max map[int]int + Block +} + +func (b *Chain) Init(m *ctx.Message, arg ...string) Chart { + // 解析数据 + b.data = mis.Parse(nil, "", b.show(m, arg[0])...).(map[string]interface{}) + b.FontColor = kit.Select("white", arg, 1) + b.BackGround = kit.Select("red", arg, 2) + b.FontSize = kit.Int(kit.Select("24", arg, 3)) + b.LineSize = kit.Int(kit.Select("12", arg, 4)) + b.Padding = kit.Int(kit.Select("8", arg, 5)) + b.Margin = kit.Int(kit.Select("8", arg, 6)) + + // 计算尺寸 + b.max = map[int]int{} + b.Height = b.size(m, b.data, 0, b.max) * b.GetHeights() + width := 0 + for _, v := range b.max { + width += b.GetWidths(strings.Repeat(" ", v)) + } + b.Width = width + m.Log("info", "data %v", kit.Formats(b.data)) + return b +} +func (b *Chain) show(m *ctx.Message, str string) (res []string) { + miss := []int{} + list := mis.Split(str, "\n") + for _, line := range list { + // 计算缩进 + dep := 0 + loop: + for _, v := range []rune(line) { + switch v { + case ' ': + dep++ + case '\t': + dep += 4 + default: + break loop + } + } + + // 计算层次 + if len(miss) > 0 { + if miss[len(miss)-1] > dep { + for i := len(miss) - 1; i >= 0; i-- { + if miss[i] < dep { + break + } + res = append(res, "]", "}") + miss = miss[:i] + } + miss = append(miss, dep) + } else if miss[len(miss)-1] < dep { + miss = append(miss, dep) + } else { + res = append(res, "]", "}") + } + } else { + miss = append(miss, dep) + } + + // 输出节点 + word := mis.Split(line) + res = append(res, "{", "meta", "{", "text") + res = append(res, word...) + res = append(res, "}", "list", "[") + } + return +} +func (b *Chain) size(m *ctx.Message, root map[string]interface{}, depth int, width map[int]int) int { + meta := root["meta"].(map[string]interface{}) + + // 最大宽度 + text := kit.Format(meta["text"]) + if len(text) > width[depth] { + width[depth] = len(text) + } + + // 计算高度 + height := 0 + if list, ok := root["list"].([]interface{}); ok && len(list) > 0 { + kit.Map(root["list"], "", func(index int, value map[string]interface{}) { + height += b.size(m, value, depth+1, width) + }) + } else { + height = 1 + } + + meta["height"] = height + return height +} +func (b *Chain) draw(m *ctx.Message, root map[string]interface{}, depth int, width map[int]int, x int, y int) Chart { + meta := root["meta"].(map[string]interface{}) + b.Width, b.Height = 0, 0 + + // 当前节点 + block := &Block{ + BackGround: kit.Select(b.BackGround, meta["bg"]), + FontColor: kit.Select(b.FontColor, meta["fg"]), + FontSize: b.FontSize, + LineSize: b.LineSize, + Padding: b.Padding, + Margin: b.Margin, + Width: b.GetWidth(strings.Repeat(" ", width[depth])), + } + + block.Data(root["meta"]) + block.Init(m, kit.Format(meta["text"])).Draw(m, x, y+(kit.Int(meta["height"])-1)*b.GetHeights()/2) + + // 递归节点 + kit.Map(root["list"], "", func(index int, value map[string]interface{}) { + b.draw(m, value, depth+1, width, x+b.GetWidths(strings.Repeat(" ", width[depth])), y) + y += kit.Int(kit.Chain(value, "meta.height")) * b.GetHeights() + }) + return b +} +func (b *Chain) Draw(m *ctx.Message, x, y int) Chart { + return b.draw(m, b.data, 0, b.max, x, y) +} + +type Table struct { + data [][]string + max map[int]int + Block +} + +func (b *Table) Init(m *ctx.Message, arg ...string) Chart { + // 解析数据 + b.max = map[int]int{} + for _, v := range mis.Split(arg[0], "\n") { + l := mis.Split(v) + for i, v := range l { + switch data := mis.Parse(nil, "", mis.Split(v)...).(type) { + case map[string]interface{}: + v = kit.Select("", data["text"]) + } + if len(v) > b.max[i] { + b.max[i] = len(v) + } + } + b.data = append(b.data, l) + } + b.FontColor = kit.Select("white", arg, 1) + b.BackGround = kit.Select("red", arg, 2) + b.FontSize = kit.Int(kit.Select("24", arg, 3)) + b.LineSize = kit.Int(kit.Select("12", arg, 4)) + b.Padding = kit.Int(kit.Select("8", arg, 5)) + b.Margin = kit.Int(kit.Select("8", arg, 6)) + + // 计算尺寸 + width := 0 + for _, v := range b.max { + width += b.GetWidths(strings.Repeat(" ", v)) + } + b.Width = width + b.Height = len(b.data) * b.GetHeights() + + m.Log("info", "data %v", kit.Formats(b.data)) + return b +} +func (b *Table) Draw(m *ctx.Message, x, y int) Chart { + b.Width, b.Height = 0, 0 + for n, line := range b.data { + for i, text := range line { + l := 0 + for j := 0; j < i; j++ { + l += b.GetWidths(strings.Repeat(" ", b.max[i])) + } + block := &Block{ + BackGround: kit.Select(b.BackGround), + FontColor: kit.Select(b.FontColor), + FontSize: b.FontSize, + LineSize: b.LineSize, + Padding: b.Padding, + Margin: b.Margin, + Width: b.GetWidth(strings.Repeat(" ", b.max[i])), + } + + switch data := mis.Parse(nil, "", mis.Split(text)...).(type) { + case map[string]interface{}: + text = kit.Select(text, data["text"]) + block.Data(data) + } + block.Init(m, text).Draw(m, x+l, y+n*b.GetHeights()) + } + } + return b +} diff --git a/src/examples/wiki/wiki.go b/src/examples/wiki/wiki.go index f577bfe6..d96e6dba 100644 --- a/src/examples/wiki/wiki.go +++ b/src/examples/wiki/wiki.go @@ -386,6 +386,26 @@ var Index = &ctx.Context{Name: "wiki", Help: "文档中心", m.Cmdy("cli.system", "cmd_dir", arg[0], "bash", "-c", strings.Join(arg[1:], " ")) return }}, + "chart": {Name: "chart type text", Help: "绘图", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + m.Option("render", "raw") + var chart Chart + switch arg[0] { + case "block": + chart = &Block{} + case "chain": + chart = &Chain{} + case "table": + chart = &Table{} + } + arg[1] = strings.TrimSpace(arg[1]) + + chart.Init(m, arg[1:]...) + m.Echo(``, + chart.GetWidth(), chart.GetHeight()) + chart.Draw(m, 0, 0) + m.Echo(``) + return + }}, "title": {Name: "title text", Help: "一级标题", Hand: func(m *ctx.Message, c *ctx.Context, cmd string, arg ...string) (e error) { ns := strings.Split(m.Conf("runtime", "node.name"), "-") @@ -450,7 +470,6 @@ var Index = &ctx.Context{Name: "wiki", Help: "文档中心", } if len(arg) > 3 { data = mis.Parse(nil, "", show(m, arg[3])...).(map[string]interface{}) - m.Log("what", "%v", mis.Formats(data)) } max := map[int]int{} diff --git a/src/plugin/story/index.shy b/src/plugin/story/index.shy index 800231a6..5615b860 100644 --- a/src/plugin/story/index.shy +++ b/src/plugin/story/index.shy @@ -41,11 +41,11 @@ kit xls "表格" "index.js" "index.css" private "web.wiki.xls" \ feature style "mind" \ exports xls_id id -kit svg "" public "web.wiki.svg" \ - select "" name type values "16 30 48 60" action auto \ +kit chart "图表" public "web.wiki.chart" \ + select "" name type values "chain block" action auto \ + textarea "" name happy half 4 height "200px" \ select "" name type values "white red yellow green blue black" action auto \ select "" name type values "black blue green yellow red white" action auto \ - textarea "" name happy half 4 height "200px" \ feature display svg \ button "查看" diff --git a/src/toolkit/core.go b/src/toolkit/core.go index f797bf11..e4f5099b 100644 --- a/src/toolkit/core.go +++ b/src/toolkit/core.go @@ -79,13 +79,13 @@ func Select(value string, args ...interface{}) string { if len(args) > 1 { switch b := args[1].(type) { case bool: - if b && arg != "" { + if b && Right(arg) { return arg } return value } } - if arg != "" { + if Right(arg) { return arg } case []interface{}: diff --git a/usr/local/wiki/miss.md b/usr/local/wiki/miss.md index 4f582172..f636cc56 100644 --- a/usr/local/wiki/miss.md +++ b/usr/local/wiki/miss.md @@ -1,6 +1,35 @@ # {{title "Hello World"}} -{{runs "help"}} +{{chart "block" `hello 慕尼黑 world` "white" "red" "32"}} +{{chart "block" `hello world` "red" "green"}} + +{{chart "chain" ` +chat + ocean + river + dream fg red bg white + zsh + auto.sh + tmux + docker + git + vim data { hi hello } rect { nice world } + auto.vim + storm + steam +`}} + +{{chart "table" ` +'{ text 宇宙 fg white bg green }' '{ text 天文 fg red bg white }' 气象 地质 +'{ text 物理 fg white bg blue' 物质 '{ text 能量 fg red bg white }' 信息 +'{ text 数学 fg white bg green }' '{ text 代数 fg red bg white }' 函数 几何 +'{ text 生命 fg white bg blue' 基因 '{ text 组织 fg red bg white }' 系统 +`}} + +{{chart "table" ` +'{ text 编程 fg white bg green }' '{ text 语言 fg red bg white }' 框架 平台 +'{ text 设计 fg white bg blue' 功能 '{ text 性能 fg red bg white }' 智能 +`}} 命令 参数 选项 配置