diff --git a/base/lex/split.go b/base/lex/split.go
index bcd833fe..1b3ad89e 100644
--- a/base/lex/split.go
+++ b/base/lex/split.go
@@ -8,37 +8,34 @@ import (
kit "shylinux.com/x/toolkits"
)
-func _split_deep(text string) (deep int) {
+func _split_tab(text string) (tab int) {
for _, c := range text {
switch c {
case '\t':
- deep += 4
+ tab += 4
case ' ':
- deep++
+ tab++
default:
return
}
}
return
}
-func _split_deep2(stack []int, text string) ([]int, int) {
- deep := _split_deep(text)
+func _split_deep(stack []int, text string) ([]int, int) {
+ tab := _split_tab(text)
for i := len(stack) - 1; i >= 0; i-- {
- if deep <= stack[i] {
+ if tab <= stack[i] {
stack = stack[:len(stack)-1]
}
}
- stack = append(stack, deep)
+ stack = append(stack, tab)
return stack, len(stack)
}
-func _split_list(m *ice.Message, file string, arg ...string) {
+func _split_list(m *ice.Message, file string, arg ...string) map[string]interface{} {
const DEEP = "_deep"
- list := kit.List(kit.Data(DEEP, -1))
stack, deep := []int{}, 0
+ list := kit.List(kit.Data(DEEP, -1))
m.Cmd(nfs.CAT, file, func(text string) {
- // if text = kit.Split(text, "#", "#")[0]; strings.TrimSpace(text) == "" {
- // return
- // }
if strings.HasPrefix(strings.TrimSpace(text), "# ") {
return
}
@@ -46,11 +43,10 @@ func _split_list(m *ice.Message, file string, arg ...string) {
return
}
- // deep := _split_deep(text)
- stack, deep = _split_deep2(stack, text)
+ stack, deep = _split_deep(stack, text)
data := kit.Data(DEEP, deep)
- ls := kit.Split(text)
+ ls := kit.Split(text, m.Option(SPLIT_SPACE), m.Option(SPLIT_BLOCK), m.Option(SPLIT_QUOTE))
switch cb := m.OptionCB(SPLIT).(type) {
case func([]string, map[string]interface{}) []string:
ls = cb(ls, data)
@@ -77,9 +73,17 @@ func _split_list(m *ice.Message, file string, arg ...string) {
list = list[:len(list)-1]
}
})
- m.Echo(kit.Format(list[0]))
+ return list[0].(map[string]interface{})
+}
+func Split(m *ice.Message, arg ...string) map[string]interface{} {
+ return kit.Value(_split_list(m, arg[0], arg[1:]...), "list.0").(map[string]interface{})
}
+const (
+ SPLIT_SPACE = "split.space"
+ SPLIT_BLOCK = "split.block"
+ SPLIT_QUOTE = "split.quote"
+)
const SPLIT = "split"
func init() {
@@ -92,7 +96,7 @@ func init() {
return
}
- _split_list(m, arg[0], arg[1:]...)
+ m.Echo(kit.Format(_split_list(m, arg[0], arg[1:]...)))
m.ProcessDisplay("/plugin/local/wiki/json.js")
}},
}})
diff --git a/core/wiki/chart.go b/core/wiki/chart.go
index 56a8d813..f43046b7 100644
--- a/core/wiki/chart.go
+++ b/core/wiki/chart.go
@@ -1,21 +1,55 @@
package wiki
import (
+ "strings"
+
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/cli"
+ "shylinux.com/x/icebergs/base/lex"
+ "shylinux.com/x/icebergs/base/nfs"
kit "shylinux.com/x/toolkits"
-
- "strings"
)
+type item struct {
+ list []string
+ args []interface{}
+}
+
+func newItem(list []string, args ...interface{}) *item {
+ return &item{list, args}
+}
+func (item *item) echo(str string, arg ...interface{}) *item {
+ item.list = append(item.list, kit.Format(str, arg...))
+ return item
+}
+func (item *item) push(str string, arg interface{}) *item {
+ switch arg := arg.(type) {
+ case string:
+ if arg == "" {
+ return item
+ }
+ case int:
+ if arg == 0 {
+ return item
+ }
+ }
+ item.list, item.args = append(item.list, str), append(item.args, arg)
+ return item
+}
+func (item *item) dump(m *ice.Message) *item {
+ m.Echo(kit.Join(item.list, ice.SP), item.args...)
+ m.Echo(ice.NL)
+ return item
+}
+
// 图形接口
type Chart interface {
Init(*ice.Message, ...string) Chart
Data(*ice.Message, interface{}) Chart
Draw(*ice.Message, int, int) Chart
- GetWidth(...string) int
GetHeight(...string) int
+ GetWidth(...string) int
}
// 图形基类
@@ -25,31 +59,46 @@ type Block struct {
FontColor string
BackGround string
+ TextData string
+ RectData string
+
Padding int
MarginX int
MarginY int
- Width, Height int
-
- TextData string
- RectData string
-
- x, y int
+ Height int
+ Width int
+ x, y int
}
func (b *Block) Init(m *ice.Message, arg ...string) Chart {
- b.Text = kit.Select(b.Text, arg, 0)
- b.FontSize = kit.Int(kit.Select(m.Option(FONT_SIZE), kit.Select(kit.Format(b.FontSize), arg, 1)))
- b.FontColor = kit.Select(m.Option(STROKE), kit.Select(b.FontColor, arg, 2))
- b.BackGround = kit.Select(m.Option(FILL), kit.Select(b.BackGround, arg, 3))
- b.Padding = kit.Int(kit.Select(m.Option(PADDING), kit.Select(kit.Format(b.Padding), arg, 4)))
- b.MarginX = kit.Int(kit.Select(m.Option(MARGINX), kit.Select(kit.Format(b.MarginX), arg, 5)))
- b.MarginY = kit.Int(kit.Select(m.Option(MARGINY), kit.Select(kit.Format(b.MarginY), arg, 5)))
+ if len(arg) > 0 {
+ b.Text = arg[0]
+ }
+ if len(arg) > 1 {
+ b.FontSize = kit.Int(arg[1])
+ }
+ if len(arg) > 2 {
+ b.FontColor = arg[2]
+ }
+ if len(arg) > 3 {
+ b.BackGround = arg[3]
+ }
+ if len(arg) > 4 {
+ b.Padding = kit.Int(arg[4])
+ }
+ if len(arg) > 5 {
+ b.MarginX = kit.Int(arg[5])
+ b.MarginY = kit.Int(arg[5])
+ }
+ if len(arg) > 6 {
+ b.MarginY = kit.Int(arg[6])
+ }
return b
}
-func (b *Block) Data(m *ice.Message, root interface{}) Chart {
- b.Text = kit.Select(b.Text, kit.Value(root, kit.MDB_TEXT))
- kit.Fetch(root, func(key string, value string) {
+func (b *Block) Data(m *ice.Message, meta interface{}) Chart {
+ b.Text = kit.Select(b.Text, kit.Value(meta, kit.MDB_TEXT))
+ kit.Fetch(meta, func(key string, value string) {
switch key {
case FG:
b.TextData += kit.Format("%s='%s' ", FILL, value)
@@ -57,10 +106,10 @@ func (b *Block) Data(m *ice.Message, root interface{}) Chart {
b.RectData += kit.Format("%s='%s' ", FILL, value)
}
})
- kit.Fetch(kit.Value(root, "data"), func(key string, value string) {
+ kit.Fetch(kit.Value(meta, "data"), func(key string, value string) {
b.TextData += kit.Format("%s='%s' ", key, value)
})
- kit.Fetch(kit.Value(root, "rect"), func(key string, value string) {
+ kit.Fetch(kit.Value(meta, "rect"), func(key string, value string) {
b.RectData += kit.Format("%s='%s' ", key, value)
})
return b
@@ -70,15 +119,21 @@ func (b *Block) Draw(m *ice.Message, x, y int) Chart {
if strings.Contains(m.Option(ice.MSG_USERUA), "iPhone") {
float += 5
}
- m.Echo(``,
- x+b.MarginX/2, y+b.MarginY/2, b.GetWidth(), b.GetHeight(), b.BackGround, b.RectData)
- m.Echo(ice.NL)
- m.Echo(`%v`,
- x+b.GetWidths()/2, y+b.GetHeights()/2+float, b.FontColor, b.FontColor, b.TextData, b.Text)
- m.Echo("\n")
+ if m.Option(HIDE_BLOCK) != ice.TRUE {
+ item := newItem([]string{`").dump(m)
+ }
+ item := newItem([]string{`%v`, b.Text).dump(m)
return b
}
+func (b *Block) GetHeight(str ...string) int {
+ if b.Height != 0 {
+ return b.Height
+ }
+ return b.FontSize + b.Padding
+}
func (b *Block) GetWidth(str ...string) int {
if b.Width != 0 {
return b.Width
@@ -88,12 +143,6 @@ func (b *Block) GetWidth(str ...string) int {
en := len([]rune(s)) - cn
return cn*b.FontSize + en*b.FontSize*10/16 + b.Padding
}
-func (b *Block) GetHeight(str ...string) int {
- if b.Height != 0 {
- return b.Height
- }
- return b.FontSize + b.Padding
-}
func (b *Block) GetWidths(str ...string) int {
return b.GetWidth(str...) + b.MarginX
}
@@ -109,7 +158,6 @@ type Label struct {
}
func (b *Label) Init(m *ice.Message, arg ...string) Chart {
- b.Text = kit.Select(b.Text, arg, 0)
b.FontSize = kit.Int(m.Option(FONT_SIZE))
b.Padding = kit.Int(m.Option(PADDING))
b.MarginX = kit.Int(m.Option(MARGINX))
@@ -119,54 +167,35 @@ func (b *Label) Init(m *ice.Message, arg ...string) Chart {
b.max = map[int]int{}
for _, v := range strings.Split(arg[0], ice.NL) {
l := kit.Split(v, ice.SP, ice.SP)
+ b.data = append(b.data, l)
+
for i, v := range l {
switch data := kit.Parse(nil, "", kit.Split(v)...).(type) {
case map[string]interface{}:
v = kit.Select("", data[kit.MDB_TEXT])
}
-
if w := b.GetWidth(v); w > b.max[i] {
b.max[i] = w
}
}
- b.data = append(b.data, l)
}
// 计算尺寸
+ b.Height = len(b.data) * b.GetHeights()
for _, v := range b.max {
b.Width += v + b.MarginX
}
- b.Height = len(b.data) * b.GetHeights()
return b
}
func (b *Label) Draw(m *ice.Message, x, y int) Chart {
- order, _ := kit.Parse(nil, "", kit.Split(m.Option("order"))...).(map[string]interface{})
-
+ var item *Block
top := y
for _, line := range b.data {
left := x
for i, text := range line {
// 数据
- item := &Block{
- FontSize: b.FontSize,
- Padding: b.Padding,
- MarginX: b.MarginX,
- MarginY: b.MarginY,
- }
- if order != nil {
- if w := kit.Int(kit.Value(order, "index")); w != 0 && i%w == 0 {
- for k, v := range order {
- switch k {
- case FG:
- item.FontColor = kit.Format(v)
- case BG:
- item.BackGround = kit.Format(v)
- }
- }
- }
- }
-
+ item = &Block{FontSize: b.FontSize, Padding: b.Padding, MarginX: b.MarginX, MarginY: b.MarginY}
switch data := kit.Parse(nil, "", kit.Split(text)...).(type) {
case map[string]interface{}:
item.Init(m, kit.Select(text, data[kit.MDB_TEXT])).Data(m, data)
@@ -185,10 +214,9 @@ func (b *Label) Draw(m *ice.Message, x, y int) Chart {
}
item.Draw(m, left, top)
- left += item.GetWidth() + item.MarginX
- b.Height = item.GetHeight()
+ left += item.GetWidths()
}
- top += b.Height + b.MarginY
+ top += item.GetHeights()
}
return b
}
@@ -196,7 +224,7 @@ func (b *Label) Draw(m *ice.Message, x, y int) Chart {
// 链
type Chain struct {
data map[string]interface{}
- max map[int]int
+ ship []string
Block
}
@@ -207,161 +235,105 @@ func (b *Chain) Init(m *ice.Message, arg ...string) Chart {
b.MarginY = kit.Int(m.Option(MARGINY))
// 解析数据
- b.data = kit.Parse(nil, "", b.show(m, arg[0])...).(map[string]interface{})
+ m.Option(nfs.CAT_CONTENT, arg[0])
+ m.Option(lex.SPLIT_SPACE, "\t \n")
+ m.Option(lex.SPLIT_BLOCK, "\t \n")
+ b.data = lex.Split(m, "", kit.MDB_TEXT)
// 计算尺寸
- b.max = map[int]int{}
- b.Height = b.size(m, b.data, 0, b.max) * b.GetHeights()
- for _, v := range b.max {
- b.Width += v + b.MarginX
- }
+ b.Height = b.size(m, b.data) * b.GetHeights()
+ b.Draw(m, 0, 0)
+ b.Width += 200
+ m.Set(ice.MSG_RESULT)
return b
}
func (b *Chain) Draw(m *ice.Message, x, y int) Chart {
- b.draw(m, b.data, 0, b.max, x, y, &Block{})
+ b.draw(m, b.data, x, y, &b.Block)
+ m.Echo(``, m.Option(SHIP_STROKE), m.Option(SHIP_STROKE_WIDTH))
+ defer m.Echo(``)
+ for _, ship := range b.ship {
+ m.Echo(ship)
+ }
return b
}
-func (b *Chain) show(m *ice.Message, str string) (res []string) {
- miss := []int{}
- for _, line := range kit.Split(str, ice.NL, ice.NL) {
- // 计算缩进
- 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 := kit.Split(line, "\t ", "\t ")
- res = append(res, "{", kit.MDB_META, "{", "text")
- res = append(res, word...)
- res = append(res, "}", kit.MDB_LIST, "[")
- }
- return
-}
-func (b *Chain) size(m *ice.Message, root map[string]interface{}, depth int, width map[int]int) int {
- meta := root[kit.MDB_META].(map[string]interface{})
-
- // 最大宽度
- if w := b.GetWidths(kit.Format(meta[kit.MDB_TEXT])); w > width[depth] {
- width[depth] = w
- }
-
- // 计算高度
- height := 0
+func (b *Chain) size(m *ice.Message, root map[string]interface{}) (height int) {
+ meta := kit.GetMeta(root)
if list, ok := root[kit.MDB_LIST].([]interface{}); ok && len(list) > 0 {
kit.Fetch(root[kit.MDB_LIST], func(index int, value map[string]interface{}) {
- height += b.size(m, value, depth+1, width)
+ height += b.size(m, value)
})
} else {
height = 1
}
-
meta[HEIGHT] = height
return height
}
-func (b *Chain) draw(m *ice.Message, root map[string]interface{}, depth int, width map[int]int, x, y int, p *Block) int {
- meta := root[kit.MDB_META].(map[string]interface{})
- b.Width, b.Height = 0, 0
+func (b *Chain) draw(m *ice.Message, root map[string]interface{}, x, y int, p *Block) int {
+ meta := kit.GetMeta(root)
+ b.Height, b.Width = 0, 0
// 当前节点
item := &Block{
- BackGround: kit.Select(b.BackGround, kit.Select(p.BackGround, meta[BG])),
- FontColor: kit.Select(b.FontColor, kit.Select(p.FontColor, meta[FG])),
- FontSize: b.FontSize,
- Padding: b.Padding,
- MarginX: b.MarginX,
- MarginY: b.MarginY,
+ BackGround: kit.Select(p.BackGround, meta[BG]),
+ FontColor: kit.Select(p.FontColor, meta[FG]),
+ FontSize: p.FontSize,
+ Padding: p.Padding,
+ MarginX: p.MarginX,
+ MarginY: p.MarginY,
}
- if m.Option(COMPACT) != ice.TRUE {
- item.Width = b.max[depth]
- }
- item.x = x
- item.y = y + (kit.Int(meta[HEIGHT])-1)*b.GetHeights()/2
+ item.x, item.y = x, y+(kit.Int(meta[HEIGHT])-1)*b.GetHeights()/2
item.Init(m, kit.Format(meta[kit.MDB_TEXT])).Data(m, meta)
item.Draw(m, item.x, item.y)
+ // 画面尺寸
+ if item.y+item.GetHeight()+b.MarginY > b.Height {
+ b.Height = item.y + item.GetHeight() + b.MarginY
+ }
+ if item.x+item.GetWidth()+b.MarginX > b.Width {
+ b.Width = item.x + item.GetWidth() + b.MarginX
+ }
+
+ // 模块连线
if p != nil && p.y != 0 {
- x1 := p.x + p.GetWidths() - (p.MarginX+item.MarginX)/4
- y1 := p.y + p.GetHeights()/2
- x4 := item.x + (p.MarginX+item.MarginX)/4
- y4 := item.y + item.GetHeights()/2
- m.Echo(``,
- x1, y1, x1+(x4-x1)/4, y1, x1+(x4-x1)/2, y1+(y4-y1)/2, x4, y4)
+ x1, y1 := p.x+p.GetWidths()-(p.MarginX+item.MarginX)/4, p.y+p.GetHeights()/2
+ x4, y4 := item.x+(p.MarginX+item.MarginX)/4, item.y+item.GetHeights()/2
+ b.ship = append(b.ship, kit.Format(``,
+ x1, y1, x1+(x4-x1)/4, y1, x1+(x4-x1)/2, y1+(y4-y1)/2, x4, y4))
}
// 递归节点
- h := 0
- x += item.GetWidths()
- kit.Fetch(root[kit.MDB_LIST], func(index int, value map[string]interface{}) {
- h += b.draw(m, value, depth+1, width, x, y+h, item)
- })
- if h == 0 {
+ h, x := 0, x+item.GetWidths()
+ if kit.Fetch(root[kit.MDB_LIST], func(index int, value map[string]interface{}) {
+ h += b.draw(m, value, x, y+h, item)
+ }); h == 0 {
return item.GetHeights()
}
return h
}
-func _chart_show(m *ice.Message, kind, text string, arg ...string) {
- var chart Chart
- switch kind {
- case LABEL: // 标签
- chart = &Label{}
- case CHAIN: // 链接
- chart = &Chain{}
- }
+var chart_list = map[string]func(m *ice.Message) Chart{}
- // 扩展参数
- m.Option(FONT_SIZE, "24")
+func _chart_show(m *ice.Message, kind, text string, arg ...string) {
+ // 画笔参数
+ m.Option(STROKE_WIDTH, "2")
m.Option(STROKE, cli.BLUE)
m.Option(FILL, cli.YELLOW)
- // 扩展参数
- m.Option(STYLE, "")
- m.Option(STROKE_WIDTH, "2")
+ m.Option(FONT_SIZE, "24")
m.Option(FONT_FAMILY, "monospace")
- // 扩展参数
- m.Option(COMPACT, ice.FALSE)
+
+ // 几何参数
m.Option(PADDING, "10")
m.Option(MARGINX, "10")
m.Option(MARGINY, "10")
- // m.Option("font-family", kit.Select("", "monospace", len(text) == len([]rune(text))))
+ chart := chart_list[kind](m)
+
+ // 解析参数
for i := 0; i < len(arg)-1; i++ {
m.Option(arg[i], arg[i+1])
}
- if m.Option(BG) != "" {
- m.Option(FILL, m.Option(BG))
- }
- if m.Option(FG) != "" {
- m.Option(STROKE, m.Option(FG))
- }
+ m.Option(FILL, kit.Select(m.Option(FILL), m.Option(BG)))
+ m.Option(STROKE, kit.Select(m.Option(STROKE), m.Option(FG)))
// 计算尺寸
chart.Init(m, text)
@@ -370,30 +342,36 @@ func _chart_show(m *ice.Message, kind, text string, arg ...string) {
// 渲染引擎
_wiki_template(m, CHART, "", text)
- defer m.Echo(``)
+ defer m.Echo("")
chart.Draw(m, 0, 0)
+ m.RenderResult()
+}
+func AddChart(name string, hand func(m *ice.Message) Chart) {
+ chart_list[name] = hand
}
const (
- FG = "fg"
- BG = "bg"
- FILL = "fill"
- STROKE = "stroke"
+ FG = "fg"
+ BG = "bg"
+
+ STROKE_WIDTH = "stroke-width"
+ STROKE = "stroke"
+ FILL = "fill"
+ FONT_SIZE = "font-size"
+ FONT_FAMILY = "font-family"
- STYLE = "style"
- WIDTH = "width"
- HEIGHT = "height"
PADDING = "padding"
MARGINX = "marginx"
MARGINY = "marginy"
+ HEIGHT = "height"
+ WIDTH = "width"
- FONT_SIZE = "font-size"
- FONT_FAMILY = "font-family"
-
- STROKE_WIDTH = "stroke-width"
-
- COMPACT = "compact"
-
+ COMPACT = "compact"
+ HIDE_BLOCK = "hide-block"
+ SHIP_STROKE = "ship-stroke"
+ SHIP_STROKE_WIDTH = "ship-stroke-width"
+)
+const (
LABEL = "label"
CHAIN = "chain"
)
@@ -401,17 +379,35 @@ const CHART = "chart"
func init() {
Index.Merge(&ice.Context{Commands: map[string]*ice.Command{
- CHART: {Name: "chart label|chain text", Help: "图表", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
- _chart_show(m, arg[0], strings.TrimSpace(arg[1]), arg[2:]...)
+ CHART: {Name: "chart type=label,chain auto text", Help: "图表", Action: map[string]*ice.Action{
+ ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
+ AddChart(LABEL, func(m *ice.Message) Chart {
+ return &Label{}
+ })
+ AddChart(CHAIN, func(m *ice.Message) Chart {
+ m.Option(STROKE_WIDTH, "1")
+ m.Option(FILL, cli.BLUE)
+ m.Option(MARGINX, "40")
+ m.Option(MARGINY, "0")
+
+ m.Option(COMPACT, ice.TRUE)
+ m.Option(HIDE_BLOCK, ice.TRUE)
+ m.Option(SHIP_STROKE, cli.CYAN)
+ m.Option(SHIP_STROKE_WIDTH, "1")
+ return &Chain{}
+ })
+ }},
+ }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
+ if len(arg) > 1 {
+ _chart_show(m, arg[0], strings.TrimSpace(arg[1]), arg[2:]...)
+ }
}},
}, Configs: map[string]*ice.Config{
CHART: {Name: CHART, Help: "图表", Value: kit.Data(
kit.MDB_TEMPLATE, `