core of emacs

たまたま、ソファーの下から、足の裏ぐりぐり君を見つけた。突起のあるローラーを足裏で回して、つぼの刺激をしましょってやつ。

昔々、女房がバイトしてた時に、立ち仕事がずっと続いて足がむくんでしまったので、その解消の為に買ったと言ってた。30年ぶりぐらいの発掘品。今では、100均で売ってるとか。

使っていないので、オイラーが貰って、パソコンやる時に利用し始めた。 癖になりそう。違う刺激も欲しくなったので、100均を覗いてみるかな。

FreeBSD 12.0 Release

が、出たので記念に、32BitのDebian機に入れてみた。勿論仮想化のvbox(Ver. 5.2.22)上だけど。

もっさりしてる。portsnap autoして、世界のOSSのメニューを取り寄せた時、終了まで3時間もかかったぞ。通常の make updateも極めて遅い。前はそんな事無かったんだけどな。 VerUpと共に遅くなる運命にあるのか。

感覚で言っていてもしょうが無いので、超簡単なベンチをする。最初にFreeBSD 12.0の方

$ time tar zxf /usr/ports/distfiles/emacs-26.1.tar.xz
       37.81 real         6.88 user        28.36 sys

今度は、同じ環境にある、FreeBSD 11.2で試してみる。

$ time tar zxf /usr/ports/distfiles/emacs-26.1.tar.xz
       14.03 real         4.98 user         5.06 sys

こういうのを、統計的に有意な差と言うのでしょうか(って、それぞれ一回づつの試行じゃん)。sysに非常に時間がかかってるって事は、糞石対策をきっちりとやってますって事ですかね?

64Bitなvbox上では、5秒で展開してくれるから、3倍遅いのか。これじゃリナ系がi386を棄てるのも頷けるな。遅いと評判がたつのは、営業戦略上不利になりますから。いや違うな。ウブはトロイので、64bit機で動かさざるを得ないのよ。

ひょっとして、最近出た、vbox 6.0 にすれば、改善するのかな? ああ駄目だな。i386版はサポートしていない。5.2系は、2020年7月までは面倒 見てくれるそうだ。こうして、i386は徐々に見棄てられる運命にあるのね。

追跡

前回やった、(progn (prin1 "HOGE") "lv") の評価。HOGEが勝手に *Messages* に書き込まれてしまう問題。どういう風になってるの?

こういうのを調べるには、騒ぎを起こして犯人を炙り出すに限る。CERNの実験装置しかり、警視庁の捜査支援室しかり。マッチポンプ式だな。

でも、火付けは死罪ですぜ、って江戸時代かよ。暮はむしゃくしゃで、放火が増えるぞ。江戸に在住の方は、戸締り用心火の用心してくださいな。

メッセージバッファーを消してしまって置いて、どうなるか見る方法を思い付いた。バッファーを消すには、C-x k *Messages* しとけば良い。

実験してみた。emacsが怒って、バックトレース画面が出て来ると期待してたんだけど、何事も無かったように、勝手に *Messages* が作られて、そこに出力されてたよ。つまんねぇ奴だな。

ならば、バッファーが作成される瞬間を捉えてしまおう。サツ用語で言うと、現行犯逮捕。 新たなバッファーを作成するプリミティブ関数(Infoで調べたら2個有った)にBPを置く。それから、eshell上で評価。

(gdb) b Fget_buffer_create
Breakpoint 6 at 0x4aeae0: file buffer.c, line 512.
(gdb) b Fgenerate_new_buffer_name
Breakpoint 7 at 0x4ad490: file buffer.c, line 1076.
(gdb) c
Continuing.

Breakpoint 6, Fget_buffer_create (buffer_or_name=8241948) at buffer.c:512
512     {
(gdb) p buffer_or_name
$34 = 8241948
(gdb) xpr
Lisp_String
$35 = (struct Lisp_String *) 0x7dc318 <pure+81240>
"*Messages*"

トラップと言うか、罠に落ちてくれた。

Lisp Backtrace:
"prin1" (0xabcc5710)
"progn" (0xabcc57d8)
"eval" (0xabcc58e8)
"eshell-exec-lisp" (0xabcc5ab0)
"eshell-lisp-command" (0xabcc5c50)
"eval" (0xabcc5e28)
"eshell-do-eval" (0xabcc61c0)
  :

その時の、バックトレース。どうやらprin1に先立って、*Messages*を用意してるように見える。バッファーを作っている所は、buffer.c 内だ。一般のelispユーザーには見えない所で、コソコソやってる。

(gdb) bt
#0  Fget_buffer_create (buffer_or_name=8241948) at buffer.c:512
#1  0x00000000004221d9 in message_dolog (m=m@entry=0x7fffabcc5420 "\";\370\002", nbytes=nbytes@entry=1, nlflag=nlflag@entry=false, multibyte=multibyte@entry=true) at xdisp.c:10266
#2  0x000000000051a741 in printchar (ch=ch@entry=34, fun=fun@entry=43296) at print.c:311
#3  0x000000000051cd7a in print_object (obj=<optimized out>, obj@entry=49822740, printcharfun=43296, escapeflag=<optimized out>) at print.c:1835
#4  0x000000000051e5d6 in print (obj=obj@entry=49822740, printcharfun=<optimized out>, escapeflag=<optimized out>) at print.c:1131
#5  0x000000000051e71f in Fprin1 (object=49822740, printcharfun=<optimized out>) at print.c:629
#6  0x0000000000503093 in eval_sub (form=<optimized out>) at eval.c:2237
#7  0x0000000000503490 in Fprogn (body=<optimized out>) at eval.c:455
 :   ;; depth is 92  too deep!

でも、C語のbtを見れば、これはもう、ストリートカメラにばっちりと証拠が撮影されてますなあ。動かぬ証拠で有罪確定。まてまて、カメラに写っているからって、無条件で信用していいのか? 頑張ればねつ造出来るぞ。裁判になったら、それが真正な物が証明しろと、難癖付けてみような。

ああ、どうも雑音が多すぎるな。反省々。

つたない考察では、 *Messages* を、特別扱いしてるな。そう、Unixあたりで言うsyslogみたいにね。

ob6$ fgrep *Messages* *.c
buffer.c:        " prin1", "*scratch*", " *Minibuf-0*", "*Messages*", and
editfns.c:The message also goes into the `*Messages*' buffer, if `message-log-max'
gnutls.c:Set this larger than 0 to get debug output in the *Messages* buffer.
lread.c:   *Messages*.  */
print.c:   *Messages*.  */
xdisp.c:/* The name of the *Messages* buffer, a string.  */
xdisp.c:   to *Messages*.  */
xdisp.c:/* Output a newline in the *Messages* buffer if "needs" one.  */
xdisp.c:             in the *Messages* buffer now, delete the oldest ones.
xdisp.c:         incrementing windows_or_buffers_changed even if *Messages* is
xdisp.c:     shorter.  This can be caused by log truncation in *Messages*.  */
xdisp.c:They are still logged to the *Messages* buffer.  */);
xdisp.c:  Vmessages_buffer_name = build_pure_c_string ("*Messages*");
xfaces.c:       load color" messages in the *Messages* buffer.  */

C語のemacsエリアでも、決め打ちしてる節がある。

ob6$ fgrep *Messages* *.el
  :
simple.el:  "Return the \"*Messages*\" buffer.
simple.el:  (or (get-buffer "*Messages*")
simple.el:      (with-current-buffer (get-buffer-create "*Messages*")
startup.el:      (with-current-buffer "*Messages*"
startup.el:        ;; Give *Messages* the same default-directory as *scratch*,
startup.el:     ;; buffers (probably *scratch*, *Messages*, *Minibuf-0*).

勿論、elispユーザーエリアも同様だ。

play/morse.el.gz

プリミティブもいいんだけど、底無し沼っぽいんで、軽めに行くぞ。そうemacsを動かしているelispの集積地の探訪。幾つかのdirが或るけど、面白そうな所をば。

モールスに反応。コードを見るも、音はしないっぽい。つまらないじゃないかと言う輩用に、NATO軍御用達の冗長コードが乗ってた。聞き間違い防止用。

朝日のあ、いろはのい、上野のう、、、ってのの英語版。言葉が訛っていてもただしく伝わるように、、文字通り死活問題ですからね。明治維新を経て、徴兵制度が引かれた時、方言が軍隊内で大問題になった。薩摩弁と津軽弁じゃ意思疎通は無理。それで標準語ですよ。 更に大事な所は、朝日のあ とかやったのね。

(defvar nato-alphabet '(("a" . "Alfa")
                        ("b" . "Bravo")
                          :
                        ("(" . "Open")
                        (")" . "Close")
                        ("@" . "At"))
  "NATO phonetic alphabet.
See "International Code of Signals" (INTERCO), United States
Edition, 1969 Edition (Revised 2003) available from National
Geospatial-Intelligence Agency at URL `http://www.nga.mil/'")

括弧は、カッコ、コッカ とは、言わないのね。このテーブルを参照して、文字をフォネティクスコードに変換する関数と、逆変換する関数が定義されてる。

使いかたは、関数付属のdocを参照。

(defun nato-region (beg end)
  "Convert all text in a given region to NATO phonetic alphabet."

helloを変換してみた。

hello
;; select hello then M-x nato-region
Hotel-Echo-Lima-Lima-Oscar

で、どんな動きをするかと思って最初からedebugにかけてみると、

        (cond ((looking-at "\\s-+")
               (goto-char (match-end 0))
               (setq sep ""))
=>            ((setq nato (assoc str★nato-alphabet))
               (delete-char 1)

カーソルが★の所で、下記の様なエラー。

Symbol's value as variable is void: nato-alphabet

テーブルの名前がわからんとな。そうか、関数が一度も使われないと、テーブ ルがロードされない訳ね。edebugするなら、一度走らせてからにしろ、って事 なのね。了解しました。

leim

emacsで日本語ってのを以前やったけど、デフォで日本語出来るのね。C-\ すると、ステータス行が、Aあ に変化して日本語が入力できる様になる。入力中に大文字のKをたたくと、カナになる。

文節を縮めるには、C-i 延すには、C-o。次の文節へは、C-f 。次の候補グループへは、l 前のグループへは、L。キャンセルは、C-c。

ローマ字入力がちょっと特殊だけど、何も準備してない時に使うには、うってつけかな。

(define-key global-map (kbd "C-x j") 'toggle-input-method)

C-\ での切替で、手が釣りそうなので、上記の設定をしたよ。

こんな素敵な入力メソッドは、muleの遺産である。インターナショナルなDirに収納されてるぞ。後で謹んで拝んでおけ。

SKK

入力メソッドと言えば、もう一つ有名なものがあったぞ。

SKKの導入

SKK+AZIKで快適・効率的な日本語入力を!

ようこそ、SKK Openlab へ(本家)

C-xj すると、SKKモードになって、モードラインに かな って出て来る。

C-x j runs the command skk-auto-fill-mode (found in global-map), which
is an interactive autoloaded compiled Lisp function in ‘skk.el’.

It is bound to C-x j.

(skk-auto-fill-mode &optional ARG)

日本語入力モード。自動折り返し機能付き。
マイナーモードの一種で、オリジナルのモードには影響を与えない。
正の引数を与えると、強制的に ‘auto-fill-mode’ 及び SKK モードに入る。
負の引数を与えると ‘auto-fill-mode’ 及び SKK モードから抜ける。

おお、初めて日本語のdocを見たぞ。

SKKはshift keyを多用する。その負担を軽くする為、 windows 10 での SandS と言うのが有るそうな。

etc

来年にやりたい事が列挙されてるかなあ?

Qiita Advent Calendar

RMS's gdb Debugger Tutorial

各種言語の対比