Development

UTF-8メモ

UTF-8 でマルチバイトになる場合について、実装するときいつも調べてる気がするので メモしておこうかなと。 バイト数 1 バイト目 2 バイト目 3 バイト目 4 バイト目 1 0xxxxxxx - - - 2 110xxxxx 10xxxxxx - - 3 1110xxxx 10xxxxxx 10xxxxxx - 4 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx Unicode のコードポイントは 1 バイト目から順番に x の部分を連結したものになる (一応順番的にはビッグエンディアン)。 規格上は 6 バイトまで考慮されてるらしいが、現状で存在するのは 4 バイトまでっぽい。 絵文字とかあからさまにコードポイント節約しに来てる感あるしな (知らんけど)。 文字数 UTF-8 で文字数と言ったときに僕の理解でも指す概念が 3 つくらいあって、 バイト数 コードポイントの数 見た目の文字数 (サロゲートペアとかを考慮した結果の) 下に行くほど判定が面倒臭くて、見た目の文字数を数えるには文字種を見て 連結する条件のテーブル引く必要がある。絵文字で J と P 並べたら日本の国旗になるとか。

OpenCL

GPU が乗ったマシンを買ったので、OpenCL で Device が取得できるのを見て 自己満足に浸るなどしていた (on Arch Linux)。 てか GPU って某 N 社が勝手に読んでる名前なんだっけ?忘れたけど。 インスコ: opencl-clhpp (OpenCL の C++ バインディング) opencl-mesa (乗ってる GPU に合わせたパッケージが必要な筈) ocl-icd (ローダー) あんまり関係ないけど compile_commands.json を生成してくれるのが便利なので 最近はどうでもいいコードでも CMake のプロジェクトを作っている。 で、コード: #include <iostream> #include <vector> #define CL_HPP_TARGET_OPENCL_VERSION 300 #include <CL/opencl.hpp> auto main() -> int { std::vector<cl::Platform> platforms; cl::Platform::get(&platforms); for (auto const &p: platforms) { std::vector<cl::Device> dev; p.getDevices(CL_DEVICE_TYPE_ALL, &dev); for (auto const &d: dev) { cl_device_type ty = d.getInfo<CL_DEVICE_TYPE>(); std::string type; switch (ty) { case CL_DEVICE_TYPE_CPU: type = "CPU"; break; case CL_DEVICE_TYPE_GPU: type = "GPU"; break; case CL_DEVICE_TYPE_ACCELERATOR: type = "Accelerator"; break; default: type = "unknown"; break; } std::cout << type << '\n'; std::cout << d.getInfo<CL_DEVICE_NAME>() << '\n'; std::cout << d.getInfo<CL_DEVICE_VENDOR>() << '\n'; std::cout << d.getInfo<CL_DEVICE_MAX_COMPUTE_UNITS>() << '\n'; } } } んで、その出力 GPU Radeon RX 5500 (NAVI14, DRM 3.40.0, 5.11.4-arch1-1, LLVM 11.1.0) AMD 22 今日はとりあえずコンパイル通って動いたので良し。後日いろいろ計算とかさせていきたいね。

プロンプトが壊れる件について

readlineのバグだったとか寝言言ってたけど違った。君のせいにしてごめんよ。 ソースコード読んでみて分かったんだけど、readline はエスケープシーケンスを考慮して文字数計算するみたいなことは もともとやってくれない。そのかわりに、文字数の計算で無視したい部分を ここ で定義してある RL_PROMPT_START_IGNORE (\001) と RL_PROMPT_END_IGNORE (\002) ではさむことによって プロンプトが崩れないようにする。 Bash のプロンプトを設定するときにはそれぞれ \[ と \] で挟むとこれらの文字に置き換えてくれるっぽい (これは挙動から推測しているだけで、正確には Bash のソースコードを読んでいないので分からない)。 これはちゃんと Bash の Manual page にも書いてある。 \[ begin a sequence of non-printing characters, which could be used to embed a terminal control sequence into the prompt \] end a sequence of non-printing characters man 読みましょうね。 …といっても readline は色付けのエスケープシーケンス無視する機能くらい持っててもいいと思うんだ……。

readlineのバグだった

注意: この記事の内容は間違っています。 こちらを参照してください。 この記事 で Bash のプロンプトが壊れるとか いろいろ言っていたが、いまさらながら調査した。 その結果、プロンプトにエスケープシーケンスが含まれていると、その文字数だけ履歴が残ったり 行の途中で折り返してしたりすることが分かった。 たぶんプロンプトから残りの文字数を計算する部分でエスケープシーケンスが処理されていない? 以下 PoC。 #include <stdio.h> #include <readline/readline.h> #include <readline/history.h> int main(void) { for (;;) { char *line = readline("\033[1mfoobar\033[0m"); if (line == NULL) { break; } add_history(line); } } これで 22222... の行まで入れたあとに 2 つ履歴を遡るとこれになる。 特に騒がれてないということはロケールとかフォント依存だったりするのかな……。 コード読んたりするのは明日以降に…。 というか今日プロンプトを2行にしてワークアラウンドしたんだけど、 2 行のプロンプト見にくくてあんまり好きじゃないのでなんとか解消したいんだよなぁ。 まあ太字にするのやめればいいんだけど。

Socket Activation

systemd の Unit ファイルっぽいものにはいろいろ種類があって、 一番よく見かける .service のやつの他にも .socket とか .mount とかいろいろある。 その中で、ソケット関連を systemd がよしなにやってくれる socket activation というやつが 便利そうだったので適当に触ってみた。 service と socket について socket の方を enable しておくと、systemd が指定したソケットを見ておいて、 必要なときに対応する service の方を起動してくれる。 んで仮に service を止めたとしても、socket の方が残ってればまた 接続があったときによしなに service を起動してくれる。 完璧に Unix ドメインソケットの話してるけど、ソケットのファイルの管理は 地味にめんどい (ファイル残ってると次回起動するときに面倒くさいので消したいとか パーミッションをいろいろやりたいとか) のでそのへんを自動でやってくれるのは便利だなと思いました。

CMakeのedit_cacheが使えるという話

CMake で Makefile とか生成したときにできる edit_cache ターゲットが実は便利なやつだったと 気づいた。 edit_cache すると、すでにビルドディレクトリとして CMake を走らせたディレクトリの オプションをいろいろ編集できる。 これまでは適当に CMakeCache.txt を直接編集してたけど、このツールだともっと楽で安全に編集できるっぽい。 make edit_cache とかで起動する。 するとデフォルトだと CMAKE_INSTALL_PREFIX と CMAKE_BUILD_TYPE が出るっぽい。 まあ現実的に変えたそうなやつだし妥当だと思う。 なぜか Boost を find_package のした結果設定された変数が出てるけどなんでなんでしょうね (にっこり)。 あと CMakeLists.txt の中で option(...) コマンドを使ってると、これで設定してる変数も出る。便利。 でカーソルキーとか J/K とかで項目選んで Enter 押すと編集。bool だと ON と OFF が切り替わる。 PATH とかだとそこが編集可能になるんだけどカーソル一番後ろにしといて欲しかった。

CMake on Windows (ライブラリの解決関係)

zlib とか libpng とかをビルドして、適当に C:\usr とかに配置してたら CMake が認識してくれなかった。 -DCMAKE_PREFIX_PATH で C:\usr を指定してやれば解決。 > cmake -DCMAKE_PREFIX_PATH=C:\usr .. このパスが複数ある場合 (例えばライブラリごとにインストールされているパスが違う場合) は CMake のリスト (セミコロン ; で区切る) で渡せばよい。 参考 CMAKE_PREFIX_PATH — CMake 3.20.0-rc1 Documentation

シェルのプロンプトが壊れる

端末が完全に壊れるので困ってる。 数ヶ月この状態が続いていて、僕が .bashrc の中で変なハックをしてるのが悪いのかなとか いろいろ考えていじくり回してたんだけどどうしようもない。 というかこれが vte のバグか readline のバグか分かってなかったんだけど、 termtosvg で録画してもこれになるということは readline のバグである可能性が高いということか。 master ブランチとかを取ってきてビルドすれば直ったりするかな・・・? 追記 この件はこの記事の方法で解決しました。

カジュアルにブラウザ拡張を作ってWebサイトを快適にする

この記事は「ョョョねこ Advent Calendar 2020」 12日目の記事です。 「ョョョねこ Advent Calendar」なのにねこも VRChat も関係ない記事でいいのかなと 思いつつ、説明見た感じだと記事のテーマは割となんでもいいっぽかったので (言い訳) 12日目を 担当することにしました。 とか言ってたら 3 日も過ぎてました。すみません……。 突然ですが、いつも使っていた Web サイトに突然いらない機能が追加されて「あー、この表示消したいなー」 とか思うことありますよね。(え?ない?) そういうときに適当にブラウザ拡張を作って Web ページを勝手にカスタマイズしてしまおうというのがこの 記事の趣旨です。 多少の JavaScript の知識を前提として書きますが、JavaScript が分からなくても この記事の中のサンプルコードを少し編集するだけでも簡単なブラウザ拡張が作れるように書いたつもりです。

DBusのEmacs Lispバインディング

Emacs の scratch バッファで DBus のメソッドを叩いたりできるので便利。たぶん。 DBus 便利じゃんね。(分かってない) 準備 require する。M-x describe-function すると勝手に内部で require するようなので 忘れていたが、当然といえば当然。 (require 'dbus) Introspection プロパティとかインターフェースを眺めるやつ。 GNOME Shell のスクリーンショットのインターフェースを眺めてみる。 XML でなくて S 式で表示される。 (dbus-introspect-xml :session "org.gnome.Shell" "/org/gnome/Shell/Screenshot") メソッドを叩く 適当に introspection で見えた通りに引数を詰め込んでウィンドウのスクリーンショットを撮ってみる。 コマンドラインの dbus-send だと型の指定が面倒だが(まあ 1 と "1" の区別つかないのでそれはそう) Emacs だと Lisp での型が適当に DBus の型にマッピングされていて割と楽。 あと引数が一致しなかったりしたら Emacs Lisp の例外が上がる。 (dbus-call-method :session "org.gnome.Shell" "/org/gnome/Shell/Screenshot" "org.gnome.Shell.Screenshot" "ScreenshotWindow" t t nil "/tmp/foo.png") elisp の型とのマッピングだとうまくいかない場合やマッピングされていない型を使っているメソッドを叩く場合、キーワードパラメータで手動で指定できる。