『初心者がやってみました』な記事です。
背景、欲しかったもの
たとえば、以下のようなファイルがあるとします:
assets/
├── map
│ ├── tilesets
│ ├── tmx
│ │ └── map-data-1.tmx
│ └── tsx
└── scripts
└── script1.lisp
script1.lisp
から map-data-1.tmx
を参照したいとします。相対パスを使ってみます:
(load-map "../map/tmx/map-data-1.tmx")
これは汚い。そこで scheme 付きのパスを考えます:
(load-map "tmx:map-data-1.tmx")
tmx
という scheme (alias) は、 assets/schemes.txt
で定義されるものとします:
tmx: map/tmx
tsx: map/tsx
tileset: map/tileset
これで tmx:map-data-1.tmx
は assets/map/tmx/map-data-1.tmx
を指すものとします。 Emacs では、 find-file-at-point
コマンドに、このスキーム付きパスを理解してもらいたいです。
作り方
それではパッケージを作って行きます。今回は advice-add
で find-file-at-point
を上書きしました。『正しいやり方』を全く直感できないのの、動けば良いということにします。
ちなみに helpful で関数定義つきのヘルプが見られます。地味なコツが非常に効いてきますよね。
1. schemes.txt
の特定
Boilerplate
まずパッケージの書き方を調べます。以下ページを参考にしました:
- パッケージフォーマット | Emacs JP
- 41.2 Simple Packages
- 41.1 Packaging Basics
- A Simple Guide to Writing & Publishing Emacs Packages
また、たまたま流れてきた短いパッケージ (tomoya/consult-ghq) も参考にしました。
Dominating file の特定
現層から上階層に遡り、 schemes.txt
を探します。これは一発です:
(locate-dominating-file default-directory "schemes.txt")
A Simple Guide to Writing & Publishing Emacs Packages に載っていました。
2. <scheme>:<path>
の展開
まずは toy-scheme-resolve
でスキーム付きパスを絶対パスに変換可能にします。
schemes.txt
は以下の形式で書かれています:
my_scheme: path/to/a/directory
文字列操作
やりたいのはこの手の操作です:
cat schemes.txt | grep "^$scheme" | awk -F':' '{print $2}' | awk -f ' ' '$1'
多くの文字列操作は、 s-
シリーズにありました。 (Emacs用文字列操作ライブラリ s.el の使い方 - Qiita)
分からないのは grep
相当の部分です。 ELisp ではどう書けば良いのでしょうか?
このような場合、 emacs-jp で聞けば 1 発 です。 re-search-forward
と string-match
を教えていただきました。今回も助かりました。
正直、 emacs-jp が無ければ、僕は Emacs を使っていないかもしれません。
ポイント (カーソル) 位置のファイル名を取得する
Emacs で言う『ポイント』は、他エディタで言う『カーソル』のことです。ポイント位置のファイル名を返すコマンドは以下です:
(thing-at-point 'filename)
これの返値をスキーム付きパスとして解決して使用します。これで toy-scheme-ffap
を実装できました。
3. パッケージの提供
advice-add
このコマンドで find-file-at-point
を toy-scheme-ffap
で上書きしました。
Minor mode の提供
toy-scheme-mode
が ON のときのみ toy-scheme-ffap
を使いたいと思います。 How to Make an Emacs Minor Mode を参考に、 minor mode を作りました。調べれば一発で分かるっていうのは最高です。
それと、 global な minor mode も用意しました。
完成!
まとめ
ファイル間のリンクを強化する UI を作成しました。今後は、スクリプトファイルと翻訳テーブルを関連付けたり、マップ座標とスクリプトをリンクできたらと思います。