blog.syfm

徒然なるままに考えていることなどを書いていくブログ

一年を振り返り… (2022)

執筆をサボっていたのでこの振り返りは大晦日の電車の中でスマホで書いています 😇

仕事

今年もメルペイのコード決済チームにいた。今年からチームの TechLead となり、それと同時に一番長くチームに在籍しているメンバーとなった。

仕事内容に関しては大きな案件はあまりなく、どちらかといえばマイクロサービス統廃合や、お客さま体験の改善を中心に進めていた。加えて、TL としてチーム全体のエンジニアリングスキルの底上げを図ったり、インターン生のサポートといったソフトスキルが求められるシーンも多かったと思う。 また、期間限定で他の案件にも多少関わっており、特にメルカードの案件では普段と異なることができたので楽しかった。 メルカードでは負荷試験の担当もしており、ローンチ日が不安だったが無事に捌き切れたので一安心だった。

技術

仕事の技術スタックは去年と特に変わらず。 チームで開発しているマイクロサービスの分散トランザクションを管理するための仕組みを移行させており、そのあたりの知識がより深まったように思う。 また、to B のシステムだけでなく to C のシステム設計にも多少関わったのでそのあたりの設計の違いを久々に感じることができた。

プライベートでは趣味のプログラミングでフロントエンドをつくる機会があり、TypeScript や React、Next.js、GraphQL あたりをよく触っていた。特に React 18 の Concurrent Rendering や React Server Components の仕組みが面白かった。また、Next.js の app ディレクトリによるコロケーションや、GraphQL の fragment コロケーションのような思想は Go における API ドキュメントやテストファイルの仕組みと類似しており、そういった共通点が見られるのも興味深かった。

ときどき設計方針で悩む時があるが、他のプロジェクトや OSS、公式のベストプラクティスを見ながら試行錯誤している。

OSS

引き続き Evans と go-fuzzyfinder のメンテナンスを中心に行っている。とはいえ、最近は Evans の開発が停滞しがちになってきており、より活発に開発したい人がいたらメンテナへ迎えても良いかもなぁと感じている。そのあたりはゆっくり考えたい。

go-fuzzyfinder では go-ansisgr というライブラリをつくったことにより、ANSI Escape Sequence の Select Rendition Graphic をサポートした。去年からやりたいと思ってできていなかった機能なのでようやくという感じ。

GitHub Sponsors では 2022/12 現在で 8 名の方から、計 1000 円/月程度の支援をいただいた。本当にありがとうございます。

読んだ本

技術書

ビジネス書

  • 教養としての決済

漫画

  • かぐや様は告らせたい 25~28
  • ブルーピリオド 12~13
  • 正直不動産 14~15
  • 九条の大罪 5~6
  • チェンソーマン 4~12
  • さよなら絵梨
  • フツーに聞いてくれ
  • タコピーの原罪
  • HUNTER×HUNTER 1~37
  • 百木田家の古書暮らし 1~2
  • 好きな子がメガネを忘れた

ずっと読んでいたかぐや様が終わってしまい悲しい気持ちがあるが、今年読み始めた HUNTER×HUNTER は当分終わらなそうなので安心できる (?)

旅行

今年もいくつか旅行に行っていた。

湯本

自分の地元だが、パートナーが初めてこちらへ来たので近くの温泉旅館に泊まった。翌日には適当に小名浜に海を見に行ったりしていた。 湯本の旅館に泊まるのはなんだかんだ初めてで新鮮な気持ちだったが、温泉自体はハワイアンズやさはこの湯で何度も入っていたので懐かしさがあった。

伊東

親戚との旅行で行った。 久々にあった人も多く、(話は聞いていたが) いつの間にかはとこが誕生していてびっくりした。 伊東は鎌倉殿の 13 人でも舞台となるので聖地巡礼をしたかったけど、団体行動は難しく、断念せざるを得なかった 😇

軽井沢

ひさびさの ISUCON 兼旅行で行ったところ。 東京とくらべて気温が 7~8 度くらい低く、めちゃめちゃ涼しく快適だったので避暑地と言われる所以を体感できた。 人もそこまで多くなく、美味しいごはんも食べられるのであと数日くらい滞在していたかった。 また、ちょっと電車で移動するとあの夏で待ってるの聖地があり、このアニメにハマっていた自分からするとその点でも最高だった。

オフ会

旅行ではないけど、中学生くらいから付き合いのある友人らと 3 年ぶりくらいにオフ会をした。 久々だったにも関わらず、みんな全然変わっておらず安心した。 また、初めて会うメンバーもいたのでドキドキだったがすぐ思い出話で盛り上がった。 ゆるく続いているこの関係が今後も続いていけば良いなと思う。

観たアニメ

この中だとかぐや様が一番良かった。3期目なので安心感があったし、自分が一番見たかった回 (ラップ回) が見れたので良かった。この調子で YouTuber 白銀父もやってほしい。

やったゲーム

ひたすら龍が如くをやっていた。やはり 0 がストーリー的にもシステム的にも一番完成度が高くて面白かった。 また、アルセウスはダイパやプラチナ世代だったのでそのあたりをやっていると分かる演出が多々あってとても面白かった。 バイオレットも特に中盤から終盤にかけて結構アツくて良かった。

植物

家の日当たりが格段に良くなったので、基本的に屋外で育てている。枯らさない限り植物の数が減ることはないので今年は買う数を減らしていたものの、興味が出ていたアガベ ブラック&ブルーをふるさと納税で手に入れた。とてもかっこいい。 パキポディウムとかも面白いけど結構お高いのと管理が難しそうでまだしばらくは買わないかも。

今年から猫を 2 匹飼い始めた。どちらも同じ施設の保護猫で、引き取ったときは生後 3 ヶ月くらいの子猫だった。 家の中を走り回っていて大変なときもあるものの、とても可愛いのでなるべく長く幸せに生きてほしい。 今はもう 8 ヶ月くらいになり、すっかり大きくなった。特にキジトラのほうの猫 (まめ) の体重増加が著しい。

Catlog Board を一台導入しているが、それだけだとトイレをカバーしきれていないので追加導入したり、Pendant もいずれ使いたい。

なにか猫に関連するサービスなり仕組みを作れたらいいなーと思いつつ特に思いついていない…。

人生

今年の頭にノリでマンションのモデルルームをいくつか見に行ったら気に入ってしまい、気づいたら購入していた。ローンを組むのも当然初めてで、人生の中でもっとも高い買い物になった。 住んで早半年以上経つが、困るようなことは全くなく、むしろ賃貸のときよりすべての設備が大幅にグレードアップしているので快適に過ごすことができている。前の家が 2LDK+Nで、今の家は 3LDK+WIC+N なので部屋も広くなった。 月々の支払いに関しても、前の賃貸より多少上がった程度で、最悪自分一人でも支払えるくらいの額となっている。

また、10 月には結婚をした。もともとお互い事実婚で良いというスタンスだったが、家が資産となったことでその相続に関する問題が出てきたり、病院での面会をはじめとする諸問題など、事実婚はあらゆるところで考慮しなければいけないことがあり、最終的には両家の両親とも相談し、最大公約数を取るような選択として入籍した。選択的夫婦別姓があれば即その決断をしていたので今後の人々のためにも早く導入してほしい。 とはいえ、結婚により家族、親族、友人をはじめとするたくさんの方々からお祝いをいただいたのでそれは素直に嬉しかった。

終わりに

この振り返りを書く前は今年もなんもしなかったな…と思っていたけど実際はめちゃめちゃいろいろなことをしていた…。なんとなく始めたこの振り返りによってちゃんと一年を思い出せているのでこれからも引き続き書いていければなと思う。

今年は大きな事件・事故などなく本当に穏やかな一年であったように思う。来年も同じように穏やかに過ごせますように。

go-fuzzyfinder で色をつけられるようになった

個人的にほそぼそと開発をしていた ktr0731/go-fuzzyfinder を使うと fzf のような UI を持つ CLI ツールを非常に簡単につくることができます。go-fuzzyfinder では、Preview Window という、現在選択しているアイテムの詳細情報を知らせるための表示領域を持っています。これは非常に便利な機能ですが、一方で未実装の機能が一つありました。

それが Preview Window 内の文字列にスタイルをつけて表示する機能です。fzf の --preview フラグでは同様に Preview Window を表示できますが、こちらでは色をつけた表示も可能であるため、go-fuzzyfinder もこの機能を導入したいと考えていました。

そして最近になってようやくこの機能を入れることができました。この記事では、この機能をどのように使うことができるのか、そしてどのような設計・実装になっているのかを紹介します。

使い方

API に変更はありません。go-fuzzyfinder を v0.7.0 にアップデートするだけでこの機能を使えるようになります。 PreviewWindow に表示される文字列に ANSI エスケープシーケンス が含まれている場合、go-fuzzyfinder はそれを解釈し、パラメータに応じてスタイルが適用されます。

たとえば、ターミナルで以下のようなコマンドを実行してみます。Hello, の部分はボールドされており、World! の部分は赤色になっています。

$ echo '\x1b[1mHello, \x1b[0;31mWorld!'

go-fuzzyfinder の PreviewWindow でも同じ文字列を表示してみます。

ターミナルで表示したときとまったく同じような表示となりました。

同様に、ファイルを bat で開き、その出力を go-fuzzyfinder の PreviewWindow で表示してみた例です。bat は cat のような振る舞いをしますが、シンタックスハイライト付きのリッチな表示をします。PreviewWindow でも同様にカラフルな表示となりました。

このように、go-fuzzyfinder がエスケープシーケンスを解釈できるようになり、PreviewWindow の表示をよりリッチにできるようになりました。

Select Graphic Rendition

Terminal で色を付けるための機能は Select Graphic Rendition (SGR) と言います。これはANSI エスケープシーケンスの仕様の一つで、色だけでなくボールドやイタリックといった表現もできます。

たとえば先ほどの例では以下のような文字列でした。

$ echo '\x1b[1mHello, \x1b[0;31mWorld!'

\x1b[CSI (Control Sequence Introducer) と呼ばれるもので、これにより ANSI エスケープシーケンスの開始を示しています。あとに続くセミコロンで区切られた数値はパラメータで、このパラメータによりどのような表示にするかを指定できます。最後に m が付き、これによりパラメータの終了を示します。 今回の例では、先頭にさっそく CSI が現れており、パラメータとして 1 が指定されています。これはボールドを示しており、表示を見ると Hello, が太字になっているのが分かると思います。また、後続の CSI では 0 および 31 が指定されています。0 は既存のスタイルをすべてリセットし、31 は文字列を赤色にします。

色の指定にはいくつかの種類があり、それぞれ指定方法が異なっています。 もっとも基本的なものは 16 色のみの指定ができ、単一の値を取ります。

\x1b[31m

次に 256 色の指定方法があります。パラメータは文字色は 38;5、背景色は 48;5 から始まり、n の値によりどの色を選択するかを指定します。

\x1b[38;5;<n>m
\x1b[48;5;<n>m

次に RGB の指定方法があります。これは True Color とも呼ばれています。パラメータは文字色は 38;2、背景色は 48;2 から始まり、<r><g><b> の値によって色を指定します。 RGB で 16 色および 256 色のそれぞれの色も表現できますが、これらは区別できなければいけません。ターミナルにカスタムテーマが適用されている場合、RGB による指定ではこの設定が無視されます。

\x1b[38;2;<r>;<g>;<b>m
\x1b[48;2;<r>;<g>;<b>m

SGR と gdamore/tcell

go-fuzzyfinder はその描画に gdamore/tcell を利用しています。tcell でもスタイルを適用できますが、SGR をそのまま解釈できるわけではありません。そのため、入力となる文字列をなんらかの形でパースし、tcell の API に適合できるように落とし込んで上げる必要があります。 SGR のシーケンスを含んだ文字列をパースできるライブラリはいくつか存在していました。ただ、一部の機能が不十分だったり、go-fuzzyfinder の既存実装にうまく馴染むものがありませんでした。

そこで、1 からライブラリを実装することにしました。それが ktr0731/go-ansisgr です。

ktr0731/go-ansisgr

go-ansisgr では、NewIterator という関数があり、これが唯一のエントリポイントとなっています。この関数はイテレータを返し、このイテレータエスケープシーケンスを除いた文字と、その文字に適用されているスタイルを返します。

実際の例を見てみましょう。

in := "\x1b[1mHello, \x1b[0;31mWorld!"
iter := ansisgr.NewIterator(in)

for {
        r, style, ok := iter.Next()
        if !ok {
                break
        }

        // do nothing.
}

iter.Next() による 3 つの戻り値があります。

okイテレータの終端を表します。 r は次の文字を表す rune 型の値です。この例ではループごとに Hello …のようになります。

style はその文字に適用されているスタイルです。こちらは少し複雑になっています。ForegroundBackground というメソッドがあり、それぞれ文字色と文字の背景色を表しています。このメソッドの戻り値により、それぞれに色が設定されているかどうかがわかります。

color, ok := style.Foreground()

oktrue だった場合、色が設定されています。color を見ることでどんな色が設定されているかがわかります。 color.Mode() は、その色が 16 色、256 色、RGB のどの形式で指定されているかを表しています。また、color.Value() はその形式におけるパラメータの値です。たとえば \x1m[31m では 31、\x1m[38;5;120m では 120、\x1m[38;2;10;20;30m では 660510 (0x0a141e) となります。 RGB の場合、color.RGB() により R、G、B それぞれの値を取得することもできます。

また、style には Bold()Italic() のような bool を返すメソッドがあり、この値によってどのスタイルが適用されているかを表します。

API の一覧について、より詳しくは ドキュメント を参照してください。

go-fuzzyfinder への組み込み

こうしてできた go-ansisgr を go-fuzzyfinder へ組み込みました。gdamore/tcell は一文字ずつ描画していくため、go-ansisgr のイテレータのようなインターフェースとの組み合わせが良く、go-fuzzyfinder へ組み込んだときも大きなコードの変更なしに導入できました。*1

実際の diff は こちら から見ることができます。既存の描画のためのループ内で iter.Next() を呼び、描画対象文字とそのスタイルを順番に取得しています。

まとめ

go-fuzzyfinder で SGR がサポートされ、スタイルを適用した文字列を PreviewWindow で表示できるようになりました。 この機能の大部分は go-ansisgr によって実装・提供されており、このライブラリは入力となる SGR を含んだ文字列をイテレータ形式で扱うことができ、特に gdamore/tcell のような一文字ずつ描画していくようなライブラリとの相性が良いです。

go-fuzzyfinder も go-ansisgr もぜひお試しください!

*1:そうなるように API を設計したので当たり前といえば当たり前ですが…

ローカルで pkg.go.dev 形式のドキュメントを閲覧する

Go を書くとき公開されている API や、そのコメントに不足や余分がないかチェックするために GoDoc を使っていた。特にプライベートパッケージはインターネットからドキュメントを参照できないため、GoDoc をローカルで起動し、チェックしていた。

syfm.hatenablog.com

ただ、Go modules が登場し、GoDoc から pkg.go.dev へ移行したため、pkg.go.dev と GoDoc のどちらも使っているような状況になっていた。 また、GoDoc には Go modules 関連機能がなかったり、pkg.go.dev にはどんどん新機能が入るのに対し GoDoc には実装されなかったりと違いが大きくなってきた。

そこで godoc コマンドのようにローカルで pkg.go.dev 形式のドキュメントを見ることができないかを調べた結果、golang.org/x/pkgsite に含まれているコマンドで実現できるようだった。

pkg.go.dev

golang.org/x/pkgsiteOSS となったのは 2020 年 6 月頃で、2021 年 2 月頃に pkgsite コマンドが追加されており、簡単にローカルでドキュメントを見ることができるようになっていた。

インストールは go install でできるが、Go のバージョンによっては特定の commit をチェックアウトしてインストールする必要がある。

$ cd pkgsite

# Go 1.18
$ git checkout 9ffe8b928e4fbd3ff7dcf984254629a47f8b6e63

# Go 1.17
$ git checkout 4d836c6a652cde92f433967680dfd6171a91ec12

$ go install ./cmd/pkgsite

使い方は非常にシンプルで、ドキュメントを表示したいモジュールのディレクトリへ移動し、以下のコマンドを実行するだけで良い。 デフォルトで localhost:8080 で起動するが、このあたりの挙動はコマンドライン引数で変更できる。 なお、pkg.go.dev と違い、検索といった一部の機能は利用できない。

$ pkgsite

これで GoDoc と同じように pkg.go.dev 形式でドキュメントを閲覧できるようになり、便利になった 👏