結構時間があいてしまってあれなのですが、以前 Nimlang の関数を Emacs から呼び出す(途中までしかできてない) という記事を書いてそのまま放置だったけれど、Nim のバージョンが上がってから試したらすんなり動いたというのと、el-get に登録したので紹介します。(Nim の lambda_lifting に関するバグがなおったあと良くなったとおもいますが、詳しいバージョンや Issue 番号など忘れてしまいました)
おさらい
Emacs25 から追加される dynamic module という機能で C の関数を呼び出すという機能を利用して、C にコンパイル可能な Nim で Emacs 用の拡張を作るという試みです。
- 作者?の Aptel さんによる説明 (作者といういいかたでいいのかな?)
その他日本語記事:
確認している Emacs と Nim
以下のバージョンで確認しています。
- emacs-version(master branch): 25.1.50.1
- Nim version(devel branch): 0.14.02
インストール
el-get に登録したので`el-get-list-package` とかでインストールできます。dynamic module を利用した拡張は(MELPA などで簡単にインストールして使える形で提供しているのは)まだないので、他の Dynamic Module の拡張のやり方を真似しようかな思っているので MELPA にはまだ登録していません。なので、位置づけとしては、Nim で Emacs の拡張を書くお遊びパッケージという感じです。
使い方
インストールが終わったら、
(el-get 'sync 'nim-emacs-module)
でロードパスの登録と autoload を使えるようにして、M-x `nim-emacs-module-init`で~/.emacs.d/に nim-emacs-module ディレクトリを作ります。(確認してないけど、別に手動でも OK です)
あとは作りたいパッケージ名の名前でファイルを作ります。例えば sample-xxx 関数を持つなら、sample.nim というファイル名になります。ここでつけるファイル名が Nim では(Nim でいう)モジュール名になり、なおかつ Emacs 用の関数の prefix 名となります。(便宜上そうなるように設計してるだけで Emacs 側にそれを強制するルールはありませんが)
あとは開いたファイルで, M-x nim-emacs-module-insert-template で必要な設定がファイルに挿入されます。
現在の nim-emacs-module では以下のようなコードが挿入されます。 (挿入されるものは将来的に変更されるかもしれないので、こんなニュアンスなんだという理解のほうがいいかもです。)
# `plugin_is_GPL_compatible` indicates that its code is # released under the GPL or compatible license; Emacs will refuse to # load modules that don't export such a symbol. {.emit:\"int plugin_is_GPL_compatible;\".} import emacs_module # Primitive wrapper for emacs_module.h import emextra # Helper library init(emacs) # Example(Create a file named `mod_test.nim`): emacs.defun(return_t, 1): env.intern(env, \"t\".cstring) # Provide functions registered by above from here. emacs.provide() # How to test the example's code: # # $ emacs -Q -L . # # and then in *scratch* buffer, evaluate those lines: # # The file name ‘ mod-test ‘ is added as prefix name of each functions and # its package name. # (require 'mod-test) # (mod-test-return-t)
Nim では#がコメントなので実質数行のコードですが、なんとなく Emacs で拡張作ってる方には Nim を知らなくてもわかるのではと思います。
この例では、ファイル名が mod-test.nim で関数名が return_t、引数の数が1つの Emacs の関数`mod-test-return-t`が作られます。
コンパイルの方法は nim-mode で C-c C-c でコンパイルできるようにしていますが、M-x nim-emacs-module-compile でもコンパイルできるはずです。
コンパイル後は上記コメントのように mod-test パッケージを require して、関数を試すという感じです。
今後
Emacs の dynamic module 機能がまだ始まったばかりなので今後どうなるかわかりませんが、多言語で複数パッケージを管理するスキームができたら真似してみたいなぁとおもいます。あと C、Nim とも初心者なので、まだ Nim<->Emacs Module 間でのメモリの扱いがどうなるのかわからなくてプリミティブなテストしか作ってないので時間があればもうちょっとなんとかしたいなぁという感じです。(Pull Requests 大歓迎です)