emacs and mg
Table of Contents
切っ掛けは etags
この所Debianでapt updateがさっぱりやってこないんで、i386のサポートは終了しちゃったかと思っていた。そしたら噂をすれば影ってやつで、emacs一式に新しいのが降ってきた。よかったねと思っていたら、丁度やってたetagsがご機嫌斜めになっちゃった。
GNU Emacs 27.1 (build 1, i686-pc-linux-gnu, GTK+ Version 3.24.24, cairo version 1.16.0) of 2023-01-06, modified by Debian sakae@deb:/tmp/t$ etags etags.c Segmentation fault
いきなりのセグフォ。こういう時は、検死だな。
Core was generated by `etags etags.c'. Program terminated with signal SIGSEGV, Segmentation fault. #0 0x0041f83b in ?? () (gdb) bt #0 0x0041f83b in ?? () #1 0x00418f8a in ?? () #2 0x00415611 in ?? () #3 0x00414967 in ?? () #4 0xb7adce46 in __libc_start_main (main=0x414940, argc=2, argv=0xbfb912b4, init=0x4afa20, fini=0x4afa80, rtld_fini=0xb7f03230 <_dl_fini>, stack_end=0xbfb912ac) at ../csu/libc-start.c:308 #5 0x004149b1 in ?? ()
死因不明社会。
new emacs
これはもう、自分でemacs-worldを作りあげろって言う、神の思し召しかな。ならばやってやろうじゃん。どうせ新しくするなら、JIT版がいいかな。
ネイティブコンパイルEmacsの登場 を参考に libgccgit-10-dev なんてのを入れてから、新しい仕様でレシピを作成。
sakae@deb:/tmp/emacs$ ./configure --with-native-compilation --with-x-toolkit=lucid
待つ事、およそ45分。ELNてのがネイティブ用らしいから、順調みたい。
make[3]: Entering directory '/tmp/emacs/lisp' ELC+ELN emacs-lisp/comp.elc ELC+ELN emacs-lisp/comp-cstr.elc
そして、出来上がったのがこれ。ヘッドは随分先のバージョン番号になってるな。
GNU Emacs 30.0.50 (build 1, i686-pc-linux-gnu, X toolkit, cairo version 1.16.0, Xaw scroll bars) of 2023-01-14
久し振りなんで、どんなアプリがインストールされたか、確認してみる。
-rwxr-xr-x 1 root root 791440 Jan 14 07:46 etags* -rwxr-xr-x 1 root root 800660 Jan 14 07:46 ctags* -rwxr-xr-x 1 root root 221456 Jan 14 07:46 emacsclient* -rwxr-xr-x 1 root root 208196 Jan 14 07:46 ebrowse* -rwxr-xr-x 1 root root 29090580 Jan 14 07:46 emacs-30.0.50* lrwxrwxrwx 1 root root 13 Jan 14 07:46 emacs -> emacs-30.0.50*
ネイティブにコンパイルされた物は、今迄と違う場所に入った。
sakae@deb:/usr/local/lib/emacs/30.0.50/native-lisp/30.0.50-dcdd4d6e$ ls bytecomp-12882072-18e0ca75.eln ja-dic-283bfd77-a5e4a1e7.eln byte-opt-9c5f25f5-e9c39fdd.eln loaddefs-gen-e8a3ad9c-00161efc.eln charscript-600dca1a-50cd3215.eln preloaded/ comp-7672a6ed-d7431afe.eln radix-tree-669a468d-a0a70c74.eln comp-cstr-ef162ef7-34596d4c.eln titdic-cnv-765ac3be-dff341f9.eln emoji-zwj-4f682c68-8845604c.eln
ユーザー固有の物は ~/.emacs.d/eln-cache/30.0.50-dcdd4d6e こんな所に鎮座するんだな。ユーザーパッケージをアクセスすると、jitで変換されてキャッシュが増加してく。重いと評判のorgも、初回のアクセス時はコンパイルの影響で黙りこんでしまうけど、次回からはスイスイと動く。これがjitの威力なんだな。実感出来てよかったな。
そして、付属品のコンパイル。詳細を省略しちゃうのは、いかがなものかと思うぞ。もっと生々しいログが欲しいんだけどな。
sakae@deb:/tmp/emacs/lib-src$ make make -C ../lib all make[1]: Entering directory '/tmp/emacs/lib' GEN alloca.h GEN dirent.h : CC fingerprint.o CC mktime.o : CC save-cwd.o AR libgnu.a make[1]: Leaving directory '/tmp/emacs/lib' CCLD etags CCLD ctags CCLD emacsclient CCLD ebrowse CCLD hexl CCLD make-docfile CCLD make-fingerprint
これでもCのソースです。本当にctagsとetagsは兄弟と言うか双子だな。育ちはちょいと違うけど。これぞ、デジタル・ツインです。
sakae@deb:/tmp/emacs/lib-src$ cat ctags.c #define CTAGS 1 #include "etags.c"
それはそうと、configure時に指定したやつ –with-x-toolkit=lucid は何?
--with-x-toolkit=KIT use an X toolkit (KIT one of: yes or gtk, gtk2, gtk3, lucid or athena, motif, no)
という説明。Xの一番初期のやつがathenaでその次がmotifでその次ぐらいがlucidとかになるのかな。後はひたすら重いgtkシリーズか。さすがにqt5とかは無いな。だってGNUですものか。
--with-native-compilation[=TYPE] compile with Emacs Lisp native compiler support. The TYPE 'yes' (or empty) means to enable it and compile natively preloaded Lisp files; 'no' means to disable it; 'aot' will make the build process compile all the Lisp files in the tree natively ahead of time. (This will usually be quite slow.)
libgccjitが有る環境(なんて言う説明は無いけど)で、このオプションを指定すると、ターボチャージャーが働くようになるんだな。GNU特有な環境が必要ですって、ことさら断らないのは、虚偽広告ではなかろうか?
sakae@deb:~$ ldd /usr/local/bin/emacs-30.0.50 | grep jit libgccjit.so.0 => /lib/i386-linux-gnu/libgccjit.so.0 (0xb4960000)
config結果を見ると、こんな所に目がいった。
What compiler should emacs be built with? gcc -g3 -O2 Does Emacs support sound? yes Does Emacs use -lsqlite3? yes
巨大になってfirefoxとかを、追い越したいんだな。オイラーの希望はPDFを閲覧出来るようにな、お願いしますよ。
ああ、 『らじる★らじる』の聴き逃しサービス(1) を読むと、ブラウザーの拡張は、何でもjavascriptにお任せって風。そのスクリプトも、その都度DLするってんだから、ネットワーク資源の無駄使いも甚しい。こんな事でいいのか。 で、この記事で知ったのだけど、NHK+ が一週間と切っているのは、あの権利団体のせいか。成程ね。
連鎖反応
折角ヘッドを取ってきたので、エクスプローラーしてたら、leimにSKKな辞書が有った。昔から同梱されてたのかなあ? そう言えば、思い出したぞ。 DDSKK のインストール
;; for SKK ------------------------------- (global-set-key (kbd "C-x j") 'skk-auto-fill-mode) (setq skk-egg-like-newline t) (setq skk-sticky-key ";") (setq skk-user-directory "~/.ddskk") (setq skk-inhibit-ja-dic-search t) ;; disable ja-dic.el (setq skk-large-jisyo "/usr/local/share/skk/SKK-JISYO.L") (setq skk-extra-jisyo-file-list (list "/usr/local/share/skk/SKK-JISYO.JIS2" "/usr/local/share/skk/SKK-JISYO.notes" : "/usr/local/share/skk/SKK-JISYO.office.zipcode"))
こんなコードを書いてみる。SKKは変換のタイミングを大文字で指定する事になっている。シフトキーを多用する事になるんで、小指の負担が大きい。上のsticyを設定しておくと、へんかんってのを、Henkan と指定(Hのためにシフトキーが必要)するのを避けて、;henkan と入力出来る。
辞書は、skk-getすれば、一式取寄せられるんだけど、そのままでは有効にならない。少なくともlarge-jisyoだけは設定しておくべし。これが有効になってるかどうかは、大丈夫 が変換出来れば、大丈夫である。
それから、Windowsに入っているemacsも新しいのにした。
GNU Emacs 28.2 (build 2, x86_64-w64-mingw32) of 2022-09-14
ものの説明によればjitがサポートされているようだけど、それを有効にするには、かなり色々な物を取り込まなければいけないようなので、諦めた。
emacs 28.2になったおかげでorg-modeで、<e した時に、ブロックの用意が出来無かった。
(require 'org-tempo)
を追加した。微妙に変化してるのね。
msys2
Windowsに入れたemacsは、どうやら MSYS2 な環境で構築されてるっぽい。pacmanでパッケージを入れるって、ArchLinuxみたいな通の人達だな。
そういえば、ArchLinuxのemacsはjitが有効になってないな。jitって、まだ市民権を得ていない、アーリーなものか。
mg
前回からの続きでmgのデータ構造を追跡。だって本物のemacsじゃ規模が大き過ぎて大変だもの。なに、大きくても小くても、そんなに大差は無いだろう。
funmap_add
最初に目が行ったのは、mg語の関数銘とC言の関数名の対比を登録する手続。ご多分に洩れず、リスト構造になってる。呼出関係は下記のようだ。モード毎に登録されてくんだな。
(gdb) bt #0 funmap_add (fun=0x149949e0 <dired>, fname=0x149624c0 "dired", fparams=1) at funmap.c:258 #1 0x149946fb in dired_init () at dired.c:208 #2 0x14980e46 in main (argc=0, argv=0xcf7ca998) at main.c:138
結果のリストをトラバースって、Lispで言う、 cadrじゃないですか。それじゃaddしてく方は、これまたLisp用語に直せばconsだな。
(gdb) p *funs $2 = { fn_funct = 0x15eb38e0 <yank>, fn_name = 0x15e82d9e "yank", fn_nparams = 1, fn_next = 0x35e80028 <functnames+2800> } (gdb) p *$.fn_next $3 = { fn_funct = 0x15e9b300 <filewrite>, fn_name = 0x15e83df2 "write-file", fn_nparams = 1, fn_next = 0x35e80018 <functnames+2784> } : $24 = { fn_funct = 0x15eb0f10 <splitwind>, fn_name = 0x15e81786 "split-window-vertically", fn_nparams = 0, fn_next = 0x35e7fec8 <functnames+2448> } : $57 = { fn_funct = 0x15ea64b0 <re_queryrepl>, fn_name = 0x15e82f22 "query-replace-regexp", fn_nparams = -1, fn_next = 0x35e7fcb8 <functnames+1920> } : $178 = { fn_funct = 0x15e9f0e0 <apropos_command>, fn_name = 0x15e82808 "apropos", fn_nparams = 1, fn_next = 0x0 }
引数の数も一緒に登録してる。不定個の引数は、-1 って表現してるけど、これもLispでは定番の構造だな。まあ、Lispが陽に表れていないけど、内部はあれだな。全体が180個ぐらいの関数で、出来上がっている。ミニと言うかマイクロを名乗る資格が十分に有るよ。
complete_function_list
complete_function_list
なんて言う楽しそうな関数を見付たので、試してみる。
M-x tag TAB したら、引掛ってきた。
(gdb) bt #0 complete_function_list (fname=0xcf7fc8c0 "tag") at funmap.c:307 #1 0x19b1e40c in complt (flags=9, c=9, buf=0xcf7fc8c0 "tag", nbuf=64, cpos=3, \ nx=0xcf7fc83c) at echo.c:556 #2 0x19b1c8e6 in veread (fp=0x19b0ad50 "M-x ", buf=0xcf7fc8c0 "tag", nbuf=64, \ flag=9, ap=0xcf7fc8a4 "3") at echo.c:240 #3 0x19b1c5b0 in eread (fmt=0x19b0ad50 "M-x ", buf=0xcf7fc8c0 "tag", nbuf=64, \ flag=9) at echo.c:181 #4 0x19b1f8dc in extend (f=0, n=1) at extend.c:536 #5 0x19b27b5b in mgwrap (funct=0x19b1f880 <extend>, f=0, n=1) at kbd.c:461 #6 0x19b27a61 in doin () at kbd.c:167 #7 0x19b2b380 in main (argc=0, argv=0xcf7fca18) at main.c:244