Skip to content

Commit

Permalink
Feat(UI): 补齐所有 U+2500~U+259F 区段的表格线和方块
Browse files Browse the repository at this point in the history
基本策略如下:

* 只有宽度不明确的字符才需要倍增宽度。
* 策略1: 双写。对于某些字符来说,重复它自己就可以了。
* 策略2: 延长。对于某些字符来说,需要在它后面延长适当的字符,比如横线或方块,使之视觉上连续。
* 策略3: 空格。无法通过双写或者延长来扩展宽度的字符,只能增加空格。

另外还有两种候选策略,暂不予以支持:
* 替换字符。将宽度不明的字符,替换成外形和语义相似的另一个双倍宽度的字符。
  例如用/来代替╱, 但这种方法由于会破坏语义,在不同字体下难以保持一致,因此暂时不予考虑。
* 向前检视。结合下一个字符的形状,综合考虑如何扩展可以使图形更平滑。
  例如当█后面存在▁时,采用▄而不是█来扩展。实现相对比较复杂,暂时不予考虑。

另外,提供了一个 space 选项以强制采用策略3。

以及,增加了一个运行时调试开关以调试 ANSI codes。输入 /debug 可以开启或关闭。
  • Loading branch information
dzpao committed Jan 29, 2020
1 parent 9ac5c59 commit 8131c41
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 9 deletions.
68 changes: 61 additions & 7 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (
"github.com/dzpao/go-mud/mud"
"github.com/dzpao/go-mud/ui"
smartConfig "github.com/flw-cn/go-smartConfig"
"github.com/mattn/go-runewidth"
"github.com/rivo/tview"
"github.com/spf13/cobra"
"golang.org/x/text/width"
)
Expand Down Expand Up @@ -71,6 +73,15 @@ LOOP:
if ok {
showLine := beautify(rawLine)
plainLine := ansiRe.ReplaceAllString(rawLine, "")
if debug {
line := showLine
line = strings.Replace(line, "\x1b[", "<OSI>", -1)
line = strings.Replace(line, "\t", "<TAB>", -1)
c.ui.Println(line)
line = tview.TranslateANSI(showLine)
line = tview.Escape(line)
c.ui.Println(line)
}
c.ui.Println(showLine)
c.lua.OnReceive(rawLine, plainLine)
} else {
Expand All @@ -87,21 +98,34 @@ LOOP:
c.mud.Stop()
}

var debug bool

func (c *Client) DoCmd(cmd string) {
if cmd == "exit" || cmd == "quit" {
c.quit <- true
return
} else if cmd == "lua.reload" {
} else if cmd == "/reload-lua" {
c.lua.Reload()
return
} else if cmd == "/debug" {
debug = !debug
return
} else if cmd == "/lines" {
for i := 0; i < 100000; i++ {
c.ui.Printf("%d %s\n", i, time.Now())
}
c.ui.Println("测试内容填充完毕")
return
} else if strings.HasPrefix(cmd, `'`) {
// 北侠默认支持单引号自动变成 say 命令效果
cmd = "say " + cmd[1:]
} else if strings.HasPrefix(cmd, `"`) {
cmd = "chat " + cmd[1:]
} else if strings.HasPrefix(cmd, `*`) {
cmd = "chat* " + cmd[1:]
} else if strings.HasPrefix(cmd, `;`) {
cmd = "rumor " + cmd[1:]
} else if cmd == "debug" {
debug = !debug
}

c.ui.Println(cmd)
Expand All @@ -115,12 +139,25 @@ func ambiWidthAdjuster(option string) func(string) string {
singleAmbiguousWidth := func(str string) string {
return str
}
spaceAmbiguousWidth := func(str string) string {
newStr := ""
for _, c := range str {
newStr += string(c)
p := width.LookupRune(c)
if p.Kind() == width.EastAsianAmbiguous {
newStr += " "
}
}
return newStr
}
option = strings.ToLower(option)
switch option {
case "double":
return doubleAmbiguousWidth
case "single":
return singleAmbiguousWidth
case "space":
return spaceAmbiguousWidth
case "auto":
if runtime.GOOS == "windows" {
return singleAmbiguousWidth
Expand All @@ -137,18 +174,35 @@ func doubleAmbiguousWidth(str string) string {
for _, c := range str {
newStr += string(c)
switch c {
case '┌', '┬', '├', '┼', '└', '┴', '─',
'╓', '╥', '╟', '╫', '╙', '╨',
'╭', '╰':
case '┌', '┎', '└', '┖', '─',
'┬', '┭', '┰', '┱', '├', '┞', '┟', '┠', '┴', '┵', '┸', '┹',
'┼', '╁', '╀', '╂', '┽', '╃', '╅', '╉',
'╓', '╙', '╥', '╟', '╨', '╫', '╭', '╰':
newStr += "─"
case '┏', '┍', '┗', '┕', '━',
'┳', '┲', '┯', '┮', '┣', '┢', '┡', '┝', '┻', '┺', '┷', '┶',
'╋', '╇', '╈', '┿', '╊', '╆', '╄', '┾':
newStr += "━"
case '╔', '╦', '╠', '╬', '╚', '╩', '═',
'╒', '╤', '╞', '╪', '╘', '╧':
newStr += "═"
case '█', '▇', '▆', '▅', '▄', '▃', '▂', '▁', '▀':
// 上述三类字符的共同点就是右侧有水平线线头,因此以相应的线条来延伸它们。
case '█', '▇', '▆', '▅', '▄', '▃', '▂', '▁', '▀',
'▔', '┄', '┅', '┈', '┉':
// 这几个字符从语义上讲宽度是含糊的,
// 且实际显示效果占一个拉丁字母宽度,并且充斥了整个宽度,因此双写以延伸它们
newStr += string(c)
case '▕', '▒', '▓':
// 这几个字符虽然从语义上讲宽度是含糊的,
// 但在某些字体中显示效果已经是两个拉丁字母宽度了,
// 因此仅用空格来调整宽度,不再重复,以免重叠
newStr += " "
case '╌', '╍', '╶', '╺', '╾', '╼', '░', '▗', '▙', '▚', '▜', '▟', '▝', '▛', '▞', '▐':
// 这些字符的 East_Assia_Width 属性都是 single,语义上就只占一个拉丁字母的宽度,因此什么也不做
default:
// U+2500 ~ U+259F 区间除了本函数列出来的字符之外,其余字符从外观上看只能是通过空格来扩展
p := width.LookupRune(c)
if p.Kind() == width.EastAsianAmbiguous {
if p.Kind() == width.EastAsianAmbiguous && runewidth.RuneWidth(c) == 1 {
newStr += " "
}
}
Expand Down
7 changes: 5 additions & 2 deletions mud/mud.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func (mud *MudServer) Run() {
return
}

mud.Println("连接成功。")
mud.screen.Println("连接成功。")

netWriter := encoder.NewWriter(mud.conn)
mud.server.SetOutput(netWriter)
Expand Down Expand Up @@ -126,7 +126,10 @@ func (mud *MudServer) telnetNegotiate(m IACMessage) {
} else if m.Command == DO {
mud.conn.Write([]byte{IAC, WONT, m.Args[0]})
} else if m.Command == GA {
mud.input <- "IAC GA"
// FIXME: 接收到 GA 后,应当强制完成当前的不完整的行。
// TODO: 更进一步地,应当在 GA 收到前,阻止用户发送命令。
// 为了不影响用户体验,可以允许输入,但不允许回车发送,等到收到 GA 后再发送。
// TODO: 此功能应当仅当 GA 可用时打开,且允许用户通过配置文件关闭。
}
// TODO: IAC 不继续传递给 UI
if mud.config.IACDebug {
Expand Down

0 comments on commit 8131c41

Please sign in to comment.