shells

Table of Contents

WSL2

前回やった mingw64だけど、Disk上では、2.1Gも消費している。コンパイル等 のDiskアクセスはパフォーマンスが悪い(遅い)。 それに細かい事だけど、pacman -Syu した時にDiskの空き容量を調べる工程で、 CPUパワーを全部使い果している。どこかに無理がある設計だろうな。 実質、余り使い道は無い。

パフォーマンスが悪いと言えば、リリースされて直に入れたwsl1も悪かった。 最近のwsl2はどうなのだろう?

Linuxを手軽に動かしたい! Windows標準機能の「WSL2」がお薦め こんな記事で出会って、プチ試してみたい気がするぞ。

WSL を使用して Windows に Linux をインストールする方法(by MS)

Windows 10 HomeでWSL2 Ubuntuを使えるようにする

install ruby on FreeBSD

matzさんからの恒例のクリスマス・プレゼントruby 3.3.0を入れてみた。

まずはdebianだ。あろう事か、libyamlが入いってないぞエラー。例のいやが らせ、libyaml-dev まで入れて入った事になる、あれである。

次はFreeBSDだ。やはり同じ所で引っ掛る。今度は、/usr/localなんて、責任 範囲外だから、知らないよと言う、コンパイラーの根性に起因するエラーだ。

下記の様に環境変数を明示してあげたら、通った。

[sakae@fb /tmp/ruby-3.3.0]$ export LDFLAGS=-L/usr/local/lib
[sakae@fb /tmp/ruby-3.3.0]$ export CPPFLAGS=-I/usr/local/include
[sakae@fb /tmp/ruby-3.3.0]$ ./configure
[sakae@fb /tmp/ruby-3.3.0]$ time gmake

real    12m48.784s
user    11m56.259s
sys     0m38.196s

でも、残念ながら、JITは32Bit環境では、発動しないと言う罠が仕掛けられて いた。32Bit環境って、gdbによるグレート・ジャーニーには、うってつけ(ポ インター表示がすっきりしてるので)なんだけどな。

shells

突然だけどemacs上で使える、幾つかの端末と言うかshellを試してみる。 前回は、WezTermなんてのを見付けたし、Windows上でも、透けて見える端末と か色々あるからね。

そして、本物のemacs使いは、一度emacsを起動したら、OSを落とすまで、その 中から外に出る事が無いらしい。いわゆるemacs引きこもり症候群に罹患する らしい。でも、lsとかの良く使いコマンドはどうするの? diredで事足りるか。 じゃ、コンパイルは? そんなのMakefileを作っておいて、それでコンパイラー を起動できるよ。どうしてもって場合だけ、shellコマンドか。単発なら、 emacsからでもOKだな。

でも、長い事shellとの対話が必要なら、やっとその為のアプリの登場だ。

端末自慢をするのも良いけど、所詮OSとの通信窓口だ。通常はそこにshellが 顔を出す事になる。

トップバッターは、term

M-x term

Emacs での Shell Mode に関する基礎知識

[sakae@fb ~]$ pstree
-+= 00001 root /sbin/init
 :
 |-+= 01472 sakae emacs -nw --daemon (emacs-29.1)
 | |-+= 10515 sakae /bin/csh
 | | \--= 10519 sakae emacs test-hello.c (emacs-29.1)

emacs上のtermでcshを起動。そこからemacsを起動。

[sakae@deb ~]$ pstree
systemd─┬─avahi-autoipd───avahi-autoipd
        :
        ├─tmux: server─┬─bash───emacs───bash───emacs
        │              └─bash───pstree

同じ事をdebianでやった図。こちらの方が直感的だな。

termなshell上からemacsが起動するのは、お洒落であります。 そして頑固なんです。窓を掴んだまま離さない。他のemacsの窓にも移動でき ません(できるんだろうけど)。間違って起動しちゃったら、exitでshellを終 了しましょう。

M-x shell

上のtermと同じ事をやってみると、、、

[sakae@deb tmp]$ emacs hogefuga.txt
emacs: Terminal type "dumb" is not powerful enough to run Emacs.
It lacks the ability to position the cursor.
If that is not the actual type of terminal you have,
use the Bourne shell command 'TERM=...; export TERM' (C-shell:
'setenv TERM ...') to specify the correct type.  It may be necessary
to do 'unset TERMINFO' (C-shell: 'unsetenv TERMINFO') as well.

どこかで見たな。

M-x eshell

上記の2者共、本物のshellを起動している。対して、eshellは、なるべくlisp で機能を実現しましょって方針。こうしておけば、どこでも同じ挙動が実現で きる。どうしてもって場合だけ、サブ・シェルを起動する。この方針って、普 段使いで許容できる事?

debianで叩いたコマンドが2000個記録に残っているんで、ベスト10を出してみ た。オイラー特有の使用履歴かも知れないけど、参考にはなるだろう。

[sakae@deb ~]$ cut -f1 -d' ' < .bash_history | sort | uniq -c | sort -nr | head
    404 ls
    275 cd
    129 sudo
    109 mg
     68 sync
     59 wd
     53 cat
     45 grep
     40 pwd
     37 cc
[sakae@deb ~]$ cut -f1 -d' ' < .bash_history | sort | uniq -c | sort -nr | wc
    115     230    1594

2000個中1219個がベスト10に入っている。コマンドの種類は115種だった。頻 度のグラフを書いてみるまでもなく、ロング・テールな様相だね。それにして も、100種ものコマンドを繰り出すオイラーは、偉いな(と、自画自賛)。

新ためでコマンドを見ると、mgなんてのが有る。mgってOpenBSDで動作する emacsのクローンさ。all C言語での提供。カスタマイズは出来ないけど、めっ ぽう小さくて高速起動する。それに肖ってemacsclientって長ったらしいコマ ンドのエイリアスにしてるんだ。また、wdは、cd /tmp のエイリアスさ。作業 場は、清掃不要なRAM-Diskなんだわ。

mgとペアになると言うか、emacsをダエモン・モードで起動するエイリアスも 用意してる。Linux用にsystemdでemacsをサーバー化しちゃう機能も用意され てるけど、それはチトやりすぎ。世の中Linuxだけじゃ無いんだよと叫びつつ、 エイリアスに、してるのさ。

こうしてベスト10を観察すると、外部コマンドは、コンパイラーだけだね。後 は曲がり形にeshellが面倒を見てくれそう。

どんなコマンドをサポートしてるかとかは、 Eshell manual を参照。

コンパイル作業とかをしてて、しまったログを取るのを忘れたなんて場合、窓 をセーブしてしまえばOK。ただ、困った事がある。

less hogeとかしてて、ファイルの最後に辿りついた時、q すると

Process /usr/bin/less finished

と言われて、eshellが終了しちゃうんだ。 カスタマブルな Emacs Lisp 製シェル「eshell」 まだ詳しく読んでいないけ ど、解決策が有るのかな?

die emacs

ネットをうろうろしてると、 Emacsは死んだ なんてのに出会った。そうだよねぇ。閉じてしまったら終わり ですよ。 そして、こんな喧喧諤諤な意見も出てきた。 Emacsって今だに使われていますか?というより、使う必要がありますか?

ダイナミックモジュール

上で危惧されてた事が実現されてしてしまった。まあ、そのおかげで、前回やった IMEが簡単に実現できるんだけどね。

#define DLL_EXPORT

#include <emacs-module.h>
#include <string.h>

DLL_EXPORT int plugin_is_GPL_compatible;

emacs_value
my_hello (emacs_env *env, ptrdiff_t nargs, emacs_value *args, void *data) {
  emacs_value str;

  if (nargs == 0) {
    const char *phello = "Hello World";
    str = env->make_string (env, phello, strlen (phello));
  } else if (nargs > 0) {
    str = args[0];
  }

  emacs_value func_symb = env->intern (env, "message");
  emacs_value func_args[] = {str};
  env->funcall (env, func_symb, 1, func_args);
  return env->intern (env, "t");
}

DLL_EXPORT int emacs_module_init (struct emacs_runtime *ert) {
  if (ert->size < sizeof (*ert))
    return 1;
  emacs_env *env = ert->get_environment (ert);
  if (env->size < sizeof (*env))
    return 2;

  { emacs_value func = env->make_function (env, 0, 1, my_hello,
                                           "My Hello function.", NULL);
    emacs_value symbol = env->intern (env, "my-hello");
    emacs_value args[] = {symbol, func};
    env->funcall (env, env->intern (env, "defalias"), 2, args);
  }
  { emacs_value symbol = env->intern (env, "test-hello");
    emacs_value args[] = {symbol};
    env->funcall (env, env->intern (env, "provide"), 1, args);
  }
  return 0;
}

コンパイルして、pathの通った所に配置。

[sakae@arch tmp]$ cc --shared -fPIC -o test-hello.so test-hello.c
[sakae@arch tmp]$ mv test-hello.so ~/.emacs.d/lisp/

いざ、実行。結果は、メッセージ・バッファーに蓄積されてる。

(require 'test-hello)
(my-hello)
(my-hello "foo bar baz")

M-x gdb

前回やった、emacsからgdbを起動すると、端末がdumbになってしまう問題を追 求する。dumbをlisp/で、検索すると、色々な場所に出現してて、始末におえ ない。

そこで、論理思考を発動。曰く、前回のサブ・プロセスを起動してるソースに 注目。requireで取り込んでいる奴ね。怪しいファイルが発見された。 lisp/progmodes/gud.el.gz

(require 'comint)

詳細を確認する。 lisp/comint.el.gz

(defcustom comint-terminfo-terminal "dumb"
  "Value to use for TERM when the system uses terminfo."

(defun comint-term-environment ()
  "Return an environment variable list for terminal configuration."
  ;; If using termcap, we specify `emacs' as the terminal type
  ;; because that lets us specify a width.
  ;; If using terminfo, we default to `dumb' because that is
  ;; a defined terminal type.  `emacs' is not a defined terminal type
  ;; and there is no way for us to define it here.
  ;; Some programs that use terminfo get very confused
  ;; if TERM is not a valid terminal type.
  (with-connection-local-variables
   (if system-uses-terminfo
       (list (format "TERM=%s" comint-terminfo-terminal)
             "TERMCAP="
             (format "COLUMNS=%d" (window-width)))
     (list "TERM=emacs"
           (format "TERMCAP=emacs:co#%d:tc=unknown:" (window-width))))))

ピッタりな所に行きついた。dumbをscreenとかに変更して実行(comint.elcは 削除しておく)。

そしたら、教育的な指導もなく、ターゲットのemacsが起動してきた。但し、 画面制御が正常に行なわれないので、実際には使えないけど。。。 まあ、emacsOSが起動するまでの軌跡ぐらいは、十分に確認できる。

昔、同じような事を、qemu上に構築したOpenBSDでやった。それに比べると、 遥かに作業は楽だ。

inside emacs

中がどうなってるか、探検したい。周り道かも知れないけれど、、、

compile log

とりあえず、コンパイルログを採取してみた。何事も成り立ちからって事です。

make[3]: Leaving directory '/tmp/emacs-29.1/lisp'
cp -f temacs bootstrap-emacs
rm -f bootstrap-emacs.pdmp
./temacs --batch  -l loadup --temacs=pbootstrap \
        --bin-dest /opt/bin/ --eln-dest /opt/lib/emacs/29.1/
Loading loadup.el (source)...
Dump mode: pbootstrap

Dumping under the name bootstrap-emacs.pdmp
Dumping fingerprint: b7c7e345e75bb28f3d5898825aad47729948a2d89f71048848bd5ab650a
01f4d
Dump complete
Byte counts: header=100 hot=4203180 discardable=72640 cold=3900468
Reloc counts: hot=461661 discardable=4837
  :
rm -f emacs && cp -f temacs emacs
LC_ALL=C ./temacs -batch  -l loadup --temacs=pdump \
        --bin-dest /opt/bin/ --eln-dest /opt/lib/emacs/29.1/
Loading loadup.el (source)...
Dump mode: pdump
  :
Pure-hashed: 17370 strings, 5449 vectors, 48562 conses, 4937 bytecodes, 323 othe
rs
Dumping under the name emacs.pdmp
Dumping fingerprint: b7c7e345e75bb28f3d5898825aad47729948a2d89f71048848bd5ab650a
01f4d
Dump complete
Byte counts: header=100 hot=3914300 discardable=72640 cold=3639080
Reloc counts: hot=438601 discardable=4837

make –dry-run

最近のツール・チェインはコンパイル過程をなるべく隠すみたいで、つまらな い。曰く、CC eval.c とか compiling compile.c みたいにね。 生々しいやつが欲しいのよ。

やり方は、3つ程あるみたい。

make VERBOSE=1
gcc -### -o output_file source_file.c  ;; gcc only ?
make --dry-run

このうちの、ドライランが、時間もかからず、お勧め。

気になる、temacsの作成手順を白昼の元に晒してみる。

  CCLD     temacs
gcc -o temacs.tmp \
  -Demacs  -I. -I. -I../lib -I../lib         -I/usr/include/libxml2            \
     -MMD -MF deps/.d -MP     -I/usr/include/p11-kit-1        -O0 -g3     \
    dispnew.o frame.o scroll.o xdisp.o menu.o  window.o charset.o coding.o cate\gory.o ccl.o character.o chartab.o bidi.o cm.o term.o terminal.o xfaces.o    em\
acs.o keyboard.o macros.o keymap.o sysdep.o bignum.o buffer.o filelock.o insdel\
.o marker.o minibuf.o fileio.o dired.o cmds.o casetab.o casefiddle.o indent.o s\
earch.o regex-emacs.o undo.o alloc.o pdumper.o data.o doc.o editfns.o callint.o\
 eval[…]
../lib-src/make-fingerprint temacs.tmp
mv temacs.tmp temacs

詳しい事は、elisp manualのAppendix E GNU Emacsの内部にあるぞ。これを一 読してからかな。それとも、 lisp.h lispsym あたりを徘徊してからかな。自習材料一杯!!

それから、どうでもいい事だけど、make –dry-run の最後に、こんなのが出 てた。一応作成されたemacsで、lispらしいハロワを実行してるんですねぇ。 でも、関数型じゃないから、そこんとこ宜しくと断りをいれてる。

v=$(src/emacs --batch --eval '(progn (defun f (n) (if (= 0 n) 1 (* n (f (- n 1)\
)))) (princ (f 10)))' 2> /dev/null); \
[ "X$v" = "X3628800" ] && exit 0; \
echo >&2 '***'; \
echo >&2 '*** '"\"make all\" succeeded, but Emacs is not functional."; \
echo >&2 '***'; \
 :

これを見ると、emacsもshell属の一員ですってのが、良くわかる。

speed down by ielm

前回スピードくらべをした時、ielm環境では、めっぽう遅かった。その原因が メモリー割付にあるかと思って比較してみた。 ielm

((conses 8 507007 56324) (symbols 24 29032 18) (strings 16 151494 5376)
 (string-bytes 1 4145785) (vectors 8 53032)
 (vector-slots 4 1020450 61978) (floats 8 369 382)
 (intervals 28 4858 813) (buffers 560 17))

normal

((conses 8 504313 55645) (symbols 24 28952 2) (strings 16 151170 5700)
 (string-bytes 1 4132879) (vectors 8 53068)
 (vector-slots 4 1024947 50880) (floats 8 370 381)
 (intervals 28 4765 906) (buffers 560 15))

目立つ差は無いな。でも、一度ielmを起動しちゃうと、普通の環境にも影響が 出てしまう事が判明した。

(4.357396313 2 0.293296019)
(4.329022473 2 0.292284805)
(4.32166502 2 0.29148105499999977)

ielmの起動履歴が無い場合のスピード。

(14.452575794 50 7.3472316650000025)
(14.464804613 50 7.3487036399999965)

そして、こちらは、ielmの起動と実行経験が有る環境(もちろん、ielmは削除した状 態)。地球温暖化みたいに、一度スイッチが入いってしまうと、もう元の環境 には戻れないぞって言う闇からの警告です。クワバラ・クワバラは、雷様にし か御利益がありません。

ひょっとして、ielmを起動しちゃうと、gc-cons-threshold とか gc-cons-percentage が変更されてしまうかと調べてみたけど、そうでもない みたい。でも、面白いコマンド (memory-report) を発見。

Estimated Emacs Memory Usage

   9.2 MiB  Overall Object Memory Usage
   5.6 MiB  Memory Used By Global Variables
   1.4 MiB  Memory Used By Symbol Plists
   235 KiB  Reserved (But Unused) Object Memory
    39 KiB  Total Buffer Memory Usage
       0 B  Total Image Cache Size

Object Storage

   4.4 MiB  Strings
   2.4 MiB  Conses
   1.9 MiB  Vectors
   462 KiB  Symbols
   6.1 KiB  Buffer-Objects
   2.1 KiB  Intervals
     888 B  Floats

Largest Buffers

    12 KiB  test.el
     8 KiB  *scratch*
     :
     
Largest Variables

   3.7 MiB  package-archive-contents
   256 KiB  load-history
   160 KiB  package--compatibility-table
   118 KiB  obarray
     :

これはCommonLispの(room)相当だな。

tips org-mode

org-modeでファイルを開いた時にすべてのヘッディングを畳んだ状態にするに は

(setq org-startup-folded 'content)

を、init.elに記述しておくとな。


This year's Index

Home