2026年2~3月の活動 (css-completion, eslint設定など)
- 前回 (2026-02-01) https://vain0x.github.io/blog/2026-02-01/diary/
css-completion
- https://github.com/vain0x/HTML-CSS-Class-Completion
textDocument/referencesを追加しようとしてた- だいたい動いてるけど、ぎこちない部分は残ってて (一貫性がないとか)、まだリリースしてない(ことをいま思い出した)
- ちょっとした追加のつもりだったが意外とそうでもなかった
- 既存の実装は completion (
className=""の中でトリガー) がメインだから className 属性の位置を発見 → CSSを読むという順番 - references は CSS/JSX の一方でトリガーして両方を読みにいくという順番
- JSXのファイル全体をみて className を探すというのが要追加だった (同様にHTMLも)
- (本題から逸れるが) 必要条件で絞り込み の手法
- 課題から考えると、次のような実装方法に飛びつきそうになる
- JSXファイル全体を監視して className 属性に記載されているクラス名を全列挙し、インデックスを作っておく
- トリガー時にクラス名でインデックスを引いて、使用箇所を列挙する
- これでもいい
- リクエスト時に、検索対象のクラス名で文字列検索して、それぞれの出現箇所でそれが「CSSクラス名としての出現か」を確認して絞り込む
- 文字列検索の時点ではコメント内などの無関係な出現も含んでいる
- リクエスト時に、検索対象のクラス名で文字列検索して、それぞれの出現箇所でそれが「CSSクラス名としての出現か」を確認して絞り込む
- 若干遅いが使ってるかぎり許容範囲
- 課題から考えると、次のような実装方法に飛びつきそうになる
- CSSクラス名にマッチする正規表現
- completion のトリガー位置が class 属性の一部かを確認するために、トリガー位置の直前の文字列が
class="<classname>*$のようなパターンにマッチするか確認する、という実装だったclass=と$の間は「クラス名とスペースのみ」にマッチするという意味合いで、「クラス名に含まれうる文字種」をパターンに含めていた (/[-_0-9A-Za-z.,:#()[\]]+/みたいな)
- パターンに含まれない記号があるとうまく動かないので、足りない記号をときどき追加していた
- 特に tailwind 併用だと
hover:bg-[#FFFFFF]のような記号が含まれるクラス名がよくある
- 特に tailwind 併用だと
- CSSやHTMLの仕様をあらためて確認したら、そもそもアプローチがよくなかったことに気づいた
class属性の値は単に空白区切り
- もっとはやく仕様を参照すればよかった
- completion のトリガー位置が class 属性の一部かを確認するために、トリガー位置の直前の文字列が
- テストコードの生成に claude code を使ってみた
- もりもり生成されるので助かった
stok
- stok: Environment variable injector を作った
- APIトークンを平文で持つが、リポジトリ内ではなくユーザーディレクトリに置きたい、という妙なユースケースへのソリューション
- リポジトリ内にはっきり書かなかったが、agent によるリポジトリ内のファイル読み取りを承認不要にしつつ、トークンは読まれづらくする
- ほんとうに意味あるかは不明
- リポジトリ内にはっきり書かなかったが、agent によるリポジトリ内のファイル読み取りを承認不要にしつつ、トークンは読まれづらくする
- これは仕様と設計だけ書いて、実装を claude code で生成した
- ほぼワンショットでほぼ修正なく動いたから agentic かというとあやしい
- もっと複雑な課題を設定しないと練習にならないか
- ほぼワンショットでほぼ修正なく動いたから agentic かというとあやしい
- 実装は Rust
- 「シェルスクリプトで書ける程度のコマンドをわざわざシステム言語で実装するな」みたいな言説はよくあったが、手間の差が小さいので “わざわざ” でもなくなった
.envの内容をプロセスの環境変数にすると、コマンドによっては扱いが変わるかもしれない.env変更時のリロードと干渉するとか
querypack
-
SQLファイルごとに、そのクエリーを呼ぶラッパー関数を生成するというもの
- ついでにSQLファイルのコンテンツをコードに埋め込む (実行時のファイルアクセスを不要にする)、ローダーとして役割もある
- (ローダー:
import Query from "path/to/query.sql"をできるようにするということ)
- (ローダー:
- ついでにSQLファイルのコンテンツをコードに埋め込む (実行時のファイルアクセスを不要にする)、ローダーとして役割もある
-
TypeScript 型定義を生成する機能もあるが、型情報はクエリ内に手書きで埋め込む というもの
- 型検査とかはない
-
生成されるコードを手書きすればよくないか?
- ミニマルを指向して機能を削りすぎ?
-
プラグマ構文は sqlc や TypeScript との一貫性を考慮して次のようにした。コロンの位置がよく分からないことに
-- name: queryName :one -- param paramName: paramType -- field fieldName: fieldType -
実装は TypeScript で手書き (楽しいから)
-
コードジェネレータは watch 機能があったほうがよさそうにみえるが、ない
- これを利用するプロジェクト側に watch して何かする仕組みが何かしらあるだろうと想定し、そこに乗せればいいかと思う
- コンパイラとかと違ってインクリメンタル化の恩恵もない
-
構想は以前からあったが Rust で SQL Compiler を作ってる を読んで思い出したので書いた
- (migrate と formatter は何に使うんだろう)
読んだ記事
- Against Query Based Compilers を読んだ
- コンパイラ (おそらくアナライザも含む) をクエリーベースにしてインクリメンタル計算すると高性能化 (レイテンシ低下) できる
- しかしそれ以前に、もっとシンプルに効率化可能になるように、言語仕様を設計しておくこともできるという話
- 例えば構文解析がファイルごとに独立であれば並列化できる
その他
- 「知ってるつもり 無知の科学」を読んだ