Closed19

Unicodeとの異体字バトルがはじまったぜ

hymkorhymkor

サポートしていない異体字セレクタコードだった。リストにコードを追加した。でも、いま異体字を表示できるターミナルはないので <U+xxxxxx>表記するしかない。あと、Ctrl-Yのペーストでは大丈夫だが、右クリックペーストでは異体字セレクタコード消えてしまう(受け取れない)

これは緊急性はないが

hymkorhymkor

Windows Terminal では、異体字よく見ると、ちゃんとフォント変わってるわ!「U+908A 」単品と「U+908A U+E0104」では「しんにょう」の点の数が違うわ。これはサポートしたいな

hymkorhymkor

WindowsTerminal で

fmt.Printf("[%c][%c%c]\n",0x908A,0x908A,0xE0104)

を実行すると

となる。これを コマンドプロンプトで行うと

になる。

いけると思ったが、よく見るとカーソル位置が違う。WindowsTerminal では3セル分文字幅を使っているように見えるが、実は4セル分カーソルが移動してしまっているという現象が発生する。これのせいで、

  • ReadLineで{0x908A,0xE0104} を3セルとみなすと、見かけは3セルにしか見えないが、実際のカーソル位置は4セル分動いているから、カーソル位置の整合性が狂う
  • ReadLineで{0x908A,0xE0104} を4セルとみなすと、カーソル位置は狂わないが、そのかわり再表示する時に文字が化ける

という現象が発生する。

SpiegelSpiegel

ちなみに Ubuntu 標準の Terminal で上のコードを実行すると以下の感じに。

異体字 in Ubuntu Terminal

標準フォントだと異体字の字形は持ってないのか。その代わり2セル分の幅になります。面倒なw

hymkorhymkor

どうおかしくなるかを確認できるコードを Go で書いた。

package main

import (
	"fmt"
)

func main() {
	fmt.Printf("[%c][%c%c]\n", 0x908A, 0x908A, 0xE0104)
	fmt.Printf("[%c][%c%c", 0x908A, 0x908A, 0xE0104)
	fmt.Printf("]\n")
}

1回で行われていた出力APIのコールを2回に分けると、カーソル位置のズレが表面化する。

ただし、Go言語は Windows の API コールを内部でそれなりにラッピングしているので、WindowsTerminal 開発陣に不具合だとアピールするには、切り分け根拠としてはちょっと弱い。C++ とかで書き直せればよいのだが

hymkorhymkor

他の issue だと node.js による検証が許されているようだ。
scoop install nodejs でインストール後、Windows Terminal を起動しなおしてから、node のコマンドラインで再試してみた。

> process.stdout.write("[\u908A\u{E0104}]\n")
[邊󠄄]
true
> process.stdout.write("[\u908A\u{E0104}") ; process.stdout.write("]\n")
[邊󠄄 ]
> process.stdout.write("[ABCD") ; process.stdout.write("]\n")
[ABCD]
true

true

hymkorhymkor

Windows Terminal のレポジトリに issue 立てた。すでに 1000も Open issue があるようなプロジェクトなので、速やかにいくはずがないが…。再現コードを node.js / golang 双方で書いたし、スクショもはったし、伝わることを祈る

(外国の巨大OSSプロジェクトに issue たてるのは初めてである。外国人相手でも個人プロジェクトなら、なんぼか経験あるんだが…)

hymkorhymkor

開発メンバーの人から I think this is covered in #3546. The Unicode support is not complete yet. という回答が来た。

まぁ、#3546 の存在は知ってはいたけれども、半年以上動きがないし、どうしたもんかなと思ってたんだよね。とりあえず、見た目玉アイコンで見たリアクションだけ入れておいた。まだトリアージされていないので、静観するしかないかな。やることはやった!

自分としては「そんな問題はない」とリジェクトされなかったのであれば、御の字である。問題さえ理解しておいて貰えれば、別にクローズされてもよいし。

hymkorhymkor

なお、go-readline-ny に付属している unicodetest というテストツールで、0x908A+0xE0104 を内部的に4桁扱いにして、C-y ×数回 + C-a + C-f ×数回を実行すると、こんな感じに盛大に化ける。文字の途中にカーソルが移動してしまうせいかな

hymkorhymkor

なお、このデモは nyagos 上で

go get github.com/zetamatta/go-readline-ny
cd ~/go/src/github.com/zetamatta/go-readline-ny
go build
cd unicodetest
echo %U+908A%%U+E0104% | clip
./unicodetest

で出来ます。ただし、現在はすでに回避コードが入っているので、文字化けまでは再現できなくなっています。

hymkorhymkor

0x908A+0xE0104 などの Variation Sequence を出力する際

fmt.Fprintf(w, " \x1B7\b\b\b\b%s\x1B8", string(s))

と出力することで、力技で回避したwww

( ESC 7 はカーソル位置記憶、ESC 8 が記憶したカーソル位置に復帰するエスケープシーケンス)

hymkorhymkor

ない、異体字セレクターの U+E0100 ~ U+E01EF ですが、Ctrl-Y ではペーストできるんですが、GUI操作のペースト(マウス右クリックからのペースト等)では通らないようです。これはどうしようもないです。

hymkorhymkor

WindowsTerminal 1.5 でも、まだ直ってない、ヨシ!?

このスクラップは2021/01/11にクローズされました