【Go】幅広い入力を𝙈𝙮 𝙣𝙚𝙬 𝙜𝙚𝙖𝙧...にするtransform.Transformer実装
先日、こちらの記事を拝見して「おもしろい!」と感じました。
Twitterなんかで「𝙈𝙮 𝙣𝙚𝙬 𝙜𝙚𝙖𝙧...」という文字を見かけるたびに、これみんなどうやってタイプしてるんだろう?と気になっていたので、なるほど、こうしたツールやWebサイトを利用するのね、と得心しました。
上記記事ではCLIをリリースして下さっています。もっと幅広く使えるツールも作ってみたいな、ということで目をつけたのがGoのtransform.Transformer
の実装です。以下ではその詳細を述べていきます。
transform.Transformer?
Goの持ち味の1つが、io.Reader
/io.Writer
による入出力の抽象化&ストリーム化です。それらのインタフェースを活用することで、幅広い入出力に効率良く処理をかませることができます。
その活用例の一つとして、ShiftJISでエンコーディングされたファイルの読み込みなどがあります。下記の記事でも解説されていますが、GoはUTF-8で文字列を扱うため、ShiftJISでエンコーディングされたコードを読み込むには、transform.NewReader(io.Reader, japanese.ShiftJIS.NewDecoder())
によってio.Reader
を作成し、これを所望のストリーム処理に繋げます。
transform.NewReader
の第2引数はtransform.Transformer
インタフェースであり、次のメソッドを持つ構造体であればオリジナルの変換処理を実装することができます。
type Transformer interface {
Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error)
Reset()
}
Transform
関数が肝で、src
から読み取ったバイト列に所望の変換を行い、dst
に書き込みます。入力のsrc
が何度かに分けられる場合を想定しマルチバイト文字の際は文字途中での分割に対する配慮が必要ですし、書き込みたいバイト列に対しdst
の長さが不足する際は余剰分を留保しておく必要があるなど、なかなか実装が面倒な子ではあります。しかしこれを実装することで様々な入出力の間に文字列の変換を入れることができるのは、大きな魅力ではないでしょうか。
ということで、Unicodeで表現できる範囲内で書体を変えるようなtransform.Transformer
の実装を作ってみます。
今回の実装
作成したパッケージは下記です。
a-z
, A-Z
, 0-9
の文字を所望の書体に変換します。これらの文字は1バイト文字なので、その分だけtransform.Transformer
の実装は簡単でした。
現状は次の書体に対応しています。
- Bold
- Italic
- BoldItalic
- Script
- BoldScript
- Fraktur
- BoldFraktur
- DoubleStruck
- SansSerif
- SansSerifBold
- SansSerifItalic
- SansSerifBoldItalic
- Monospce
例えば文字列を変換して標準出力に出す場合は次のように使います。
package main
import (
"io"
"os"
"strings"
"github.com/tenkoh/go-textstyle"
"golang.org/x/text/transform"
)
func main() {
s := "Hello, Gophers"
r := transform.NewReader(strings.NewReader(s), textstyle.Bold())
io.Copy(os.Stdout, r)
//Output: 𝐇𝐞𝐥𝐥𝐨, 𝐆𝐨𝐩𝐡𝐞𝐫𝐬
}
ここで使用している以外にも様々な入出力を選択できます。例えば出力先をhttp.RequestなんかにしつつTwitter APIを噛ませれば、所望の書体に変換した上でTwitterに投稿するようなアプリケーションが簡単に構築できますね。
上記コード中では基本的にコードポイントのオフセットを与えるだけで変換する簡単な処理を採用しています。いろいろな書体のオフセット量を算出してコードに書き写すのが手間だったので、go generate
によるコード生成も試しています。いろいろな経験ができて勉強になりました。
おわりに
みんなで楽しく𝙈𝙮 𝙣𝙚𝙬 𝙜𝙚𝙖𝙧...しましょう!愉快な活用事例があればぜひコメントで教えてください。大変喜びます。
Discussion