Emacsの雑記

目次

1. はじめに

Emacsは高機能でカスタマイズ性の高いテキストエディタです。 知らずに使っていたテキストエディタが実はEmacsのクローンだったという TANEなのですが、随分長い使用経歴を持つにもかかわらず、ちっとも底の見える 気のしないこのテキストエディタについて、役に立たないであろうどうでも良い事を だらだらと記してみたいと思います。

2. TANEのEmacs使用経歴

随分前にX68000を買ったとき、良いテキストエディタは無いかと教えてもらったのが MicroEMACSでした。使い始めた頃は歴史的な背景は全く知らず、実は非常に有名な テキストエディタと知ったのは随分後の話です😅

年代 '92 '93 '94 '00 '03 '06 '13 '14~
プライベート MicroEMACS(X68k) Meadow1 Meadow2 Meadow3 emacs-w32 emacs-w32
本物お仕事 Nemacs(UNIX) Mule(UNIX) Meadow1 Meadow2 Meadow3 Meadow3/emacs-w32 emacs-w32

「Ctrl-なんとか」や「ESC-なんとか」で操作するというのは、本物お仕事でEmacsを 使うようになって知った事でした。本物お仕事で知った操作をプライベートで活用したり、 プライベートで使いやすい操作を本物お仕事の方でもカスタマイズしてみたりと、 とにかく全てのテキスト編集をEmacsで行うような感じでした。

3. X68k Emacs図鑑

X68kには色々なEmacsが存在していました。 X68kはメモリ空間が広かった(12MBまでリニアにアクセスできた)ため、 メモリ使用量の多いEmacsでも沢山の移植が行われたのだと思われます。

そんな訳で、全部では無いかも知れませんがX68kの色々なEmacsのスクリーンショットを とってみました。丸文字になっているのはご愛嬌😅

3.1. MicroEMACS

マイクロという名とは裏腹にED.Xとかに比べるとちっともマイクロではなかった MicroEMACSですが、ファンクションキーやカーソルキーが普通に使用できるように なっていたのと、日本語ヘルプが表示できたのでなんとなく使えていました。 C言語を覚え始めた頃でもあった為、何気に予約語が強調表示されていたのが 具合が良かったと思います。

[MicroEMACS X68k]

3.2. Nemacsの移植版

UNDOも使えて良い感じでしたがMicroEMACSの表示や速度に慣れると乗り換えられませんでした。

[Nemacs X68k]

3.3. Muleの移植版

UNDOも使えて良い感じでしたが起動が遅くて乗り換えられませんでした。

[Mule X68k]

3.4. GNU Emacsの移植版

マウス対応していたりC-x 3で縦割りできたりと本家Emacsのまんまなのですが、 起動が遅くてやはり乗り換えられませんでした。

[GNU Emacs X68k]

3.5. SX-WINDOWで使えるNg(Nihongo micro Gnu emacs)

SX-WINDOWはあまり使っていなかったので 画面の感じだけ。 安定度があまり高くありませんでした。

[Ng SX-WINDOW]

3.6. Ko-Windowで使える MicroEMACSの移植版とMuleの移植版

マルチウインドウシステムなので起動時間は無視できて良い感じでした。 パソコン通信(注:インターネット接続の事では無い)している間の テキスト編集に使用してました。

[koem and komule Ko-Window]

4. Emacsの諸問題

高機能で歴史あるテキストエディタなのですが、オールOKという訳ではありません。 一般的に問題とされている点を挙げてみました。

4.1. 起動時間問題

一般的なEmacsへの指摘として「起動に時間がかかる」というものがあります。 Emacsは単純なテキスト編集に留まらず、EmacsLISPによってさまざまな 拡張を行う事ができます。これらのEmacsLISPを読み込むのに時間がかかります。 起動を早くする為の対応策がいくつか挙げられます。

  • EmacsLISPを予めバイトコンパイルしておく。
  • autoloadで用事のあるときにロードされるようにする。

しかし、これらの対策を行った所で瞬時に起動できる訳ではありません。結局、

  • 一度起動したら閉じない。

というのが事実上、最も有効な手段だと考えられます。

普通に使えるようになったマルチタスクOSでは、テキスト編集以外のことを したくなればサスペンドするとか、ウインドウを切り替えるなどしてEmacsを起動しっぱなしに する事は比較的容易な方法です。しかし、シングルタスクOSでメモリも少ないと 起動したままにするという対応はできません。この場合は起動時間を短縮する のが一番有効な手段と考えられます。 X68kのMicroEMACSでは各種EmacsLISPファイル(MicroEMACSのは見た目がLISPではありませんが) を読み込んだメモリ上のイメージを実行ファイル化する事で起動時間の短縮が図られていました。

テキスト編集だけを目的とする場合、立ち上げっぱなしにするというのは ピンと来ない方もいらっしゃるかも知れません。TANE自身は 本物お仕事で Emacs上で動作するメールソフトを使用していました。 常時ネット接続だと、メールを読むために起動、読み終わったら終了 なんてして いられません。あわせてテキスト編集も行うのでバッファ操作を覚える事になりました。 そして、バッファ操作を覚えてしまうとEmacsウインドウを一つ開いておけば十分になり、 その結果「一度起動したら閉じない」という感じに自然になっていました。

4.2. Emacs小指問題

Emacsの操作では「Ctrl-なんとか」が多用されます。 Ctrlキーは左手小指で押す必要がありますので、どの指よりも特にキーを押している 時間が長くなります。この為、左手小指を痛める人が居るようです。

X68kのキーボード も本物お仕事で使用していたワークステーションの キーボード(Sun Type4 keyboard)も、 「Ctrlキー」は「TABキーの下、左シフトキーの上」、「ESCキー」は「TABキーの上」に 配置されていました。しかし、現在主流となっている 「101/106キーボード 」では、 「Ctrlキー」は「左シフトキーの下」、「ESCキー」は「ファンクションキーF1の左側」 になっています。

「101/106キーボード」の「Ctrlキー」が「左シフトキーの下」という配置が、 左手小指(と左手首)にダメージを与えるようです。

回避策はいくつか考えられます。

  • カーソルはカーソルキーで移動する。
  • 右側Ctrlキーとの併用で負担分散する。
  • 101/106キーボードの場合、ソフト的に CapsLockキーとCtrlキーの論理位置を交換する(*1)。
  • ハードウェア的にCapsLockキーとCtrlキーのマッピングを交換可能なキーボードを使用する(東プレのREALFORCEシリーズなど)。

辺りが平和的な解決策だと考えられます。

因みに、「TABキーの下、左シフトキーの上」の位置にあるCtrlキー配置では それほど致命的な左手小指ダメージは無いと思われます。 ある時、数日間だけ106キーボード配列のままEmacsを使わなくてはならない時が あったのですが、そのときには確かに左手小指と左手首が痛くなりました😅 Ctrlキー配置をTABキーの下に戻せば痛みは再び無くなりました。 TANE自身(2024年現在)約30年間ほぼ毎日Emacsを使っていますが、 使うのを避けたくなるような致命的な小指ダメージは(前述数日間を除き)ありません。

(*1): 初めて触れたのが101/106キーボードという方には、 何故そのようなソフトウェアが存在するのか、何の為にキーレイアウトを変更するのか 理由が判らなかったかも知れません。この為です🙂

[参考1] キー配列 Wikipedia

[参考2] HHKBキーボードコレクション

4.3. プロセスサイズ問題

実行時プロセスサイズが大きいという点が挙げられる事がありました。 メモリが高価だった時代にはプロセスサイズが大きい事自体が悪とされて いたようにも思います。しかし、メモリの容量単価が安くなった現在(2024年時点)では それほど大きな問題では無くなっているようです。

X68kの頃もMicroEMACSとは言え、実行ファイルサイズが大きいアプリケーション に属していました。メモリサイズの問題もありましたが、1MBのフロッピーディスクでは そもそもMicroEMACSを入れただけで終わってしまう勢いだった為、 HDD無しで使うのは事実上不可能でした。

5. 色々思うこと

勝手に思う事を書いてみます。

5.1. なぜEmacsを選ぶのか?

Windows以前の日本のパソコンでは、フリーソフトでも様々なテキストエディタが 作られていたように思います。多くのものはカーソルはカーソルキーで移動し、 ファンクションキーに主だった操作がメニューとして割り当てられていました。 メニューを一通り見渡せばやりたい事は大体想像が付いて、実行してみればおおよそ 想像通りに動作する感じだったように思います。

一方、UNIX(系OS)で使用できるテキストエディタはviかEmacsの二択しかありませんでした。 どちらも起動したは良いが そもそも編集方法が判らない(特にvi)、セーブの仕方が判らない、 終了の仕方が判らない..... などなど、どうデザインすればこんな謎めいた ユーザーインターフェースになるんだ?と首を傾げる人も多いのではないかと思います。 もちろんTANEもその一人です😅

なぜUNIX(系OS)では Emacsとviの二択しかなかったのかは定かではありませんが、 Emacsについて使われ続けている理由を少し考えてみました。

  • 1980年代末にはフリーソフトウェアとして実績のあるテキストエディタとなっていた。
  • 日本語化されたEmacsの派生品(NemacsやMule)が作られた。

特に日本では日本語文字が入力できる点が重要となる訳ですが、viではそれを満たす事が 簡単ではなかったと考えられます。また、

  • 知らないと設定/操作方法が意味不明。
  • UNIX(系OS)ユーザ独特の「判らない事をいちいち聞くのは悪」とされる文化。

も要因として挙げられるかもしれません。これらの要素を合わせると、

  1. 日本語が編集できるのはEmacs(の派生品)しか無い。
  2. でも設定や使い方がほぼ呪文。それにも関わらず 聞くと何故か怒られる。
  3. 良くわからないまま うまく使えている人の設定をパクってきたり、操作方法を どうにか覚えて取り合えず使えるようになってしまう。

変に敷居が高いものですから、一度覚えてしまうとそのスキルを簡単には捨てられ なくなってしまうのだと考えます。スキルを捨てられないという点はviにも 共通して言えるかも知れません。

TANEの場合は、たまたま具合の良かったのがEmacsだったので、敷居が高いのをどうにか 覚えた感覚はありませんが、習得したスキルを簡単に捨てられないというのは 当てはまっているかも😅

5.2. なぜEmacsを使い続けるのか?

使い続ける要因は色々ありますが、次のようなものが挙げられるように思います。

  • 習得したスキルを捨てられない。環境適応能力が低いと言われればそれまでですが、 Emacsという選択肢が無いのであればともかく、選択可能であるのならばわざわざ 避ける理由は無いかなと思います。
  • 今(2024年時点)もメンテされている。テキストを編集するという用件自体は変わらない 訳ですから、テキストエディタ本体のいじり所なんてそのうち無くなりそうにも思うのですが、 実際そういう訳では無さそうです。 CPUの性能が上がったり使えるメモリ量が増えたりして不可能だった事が可能に なってくると、それに合わせてできる事を増やしていけるものなのでしょう。
  • 色々な人が使っていて自分には普段用事が無いところにもノウハウが蓄積されている。 たまに「こういうのって無いのかな?」と探してみると思った以上に良い ものがあったりします。
  • 意外とCUIシェル環境への応用が利く。例えばbashやtcshの行編集において、 Ctrl-a、Ctrl-e、Ctrl-f、Ctrl-b、Ctrl-k、Ctrl-y、TAB(Ctrl-i) あたりは Emacsのそれと同じ感じなので、Emacsで不自由の無い操作ができるのであれば、 コマンドライン操作も不自由無いと思います。
  • 自分の都合の良いようにカスタマイズできる。やりすぎると 初期設定状態のときに困る事はありますが、そもそもユーザー管理のちゃんと しているOSであれば、他人の設定を使って何かするなんて事はありません。 どこに行っても自分の設定を持ち回る事ができるならば、本気で困る事は 無いと思います。

結局、一番の理由は 「そこにEmacsがあったから」 かも知れません🙂

6. 個人的によく使うモードの御紹介

色々ある素晴らしいモードや拡張の極々一部にしか過ぎないですが、 個人的によく使うモードや機能を挙げてみたいと思います。

6.1. 一般的な文書編集に利用しているモード

主に文書編集に利用しているモードを挙げてみます。

6.1.1. 文字コードの自動判定

shift_jis(cp932)もeuc-jpもutf-8もいけるので重宝しています。

そういえば、htmlファイルを手書きする際に、metaタグのcharsetをbuffer-file-coding-systemに使用 するモードになっていて、japanese-cp932にセットして欲しいにも関わらず、何故かjapanese-shift-jis に強制されていました。japanese-shift-jisだと例えば「~」文字を含めてセーブできません。 以下の一文を.emacs(オールドスタイルですみません)に加えてmetaタグを見ないようにしています。

(setq auto-coding-functions nil) ; HTMLモードでmetaタグのcharsetをbuffer-file-coding-systemに使用しない

6.1.2. org-mode

まとめ文書を書くのに利用しています(本文書もorg-modeを使用しています)。 wikiの表記ルールを取り入れている所もあり、良い感じにHTMLに整形してくれるので便利に利用しています。 Emacs-29.2(2024/01/18リリース)にはorg-mode安定版の9.6.15が含まれています。 活発に開発継続されています。

6.1.3. color-moccur(moccur-grep/moccur-grep-find)

EmacsLISPで書かれた grep風のコマンドです。grepするファイルに対して 文字コード依存が無いので、M-x grep でハマりがちな文字コードはどれか一つ しか選べなくてションボリという事がありませんでした。

6.1.4. keisen-mule

Emacsで表や図の一部を書こうと思うとこれ無しでは無理です。Emacsのバージョンが 上がる度にエラーする文が出る事がありますが、修正可能な感じなので Emacs 24.3以降においても便利に使っています。 (keisen-muleの参考サイト(リンク切れ)) (keisen-mule.el.xz:26.1,2,3以降で使っている野良パッチバージョン)

以下のような設定/バインドで使用しています。

(load "keisen-mule")
(setq keisen-key-flag t)
(setq keisen-mode-view-status-flag nil)
(setq keisen-auto-line-feed-flag t)
(setq keisen-auto-enlarge-vertically-flag t)
(setq keisen-auto-enlarge-horizontally-flag nil)

(global-set-key [f12] 'keisen-draw-right)
(global-set-key [f9]  'keisen-draw-left)
(global-set-key [f10] 'keisen-draw-down)
(global-set-key [f11] 'keisen-draw-up)
(global-set-key [f8]  'keisen-toggle-width)

(global-set-key [M-right] 'keisen-draw-right)
(global-set-key [M-left]  'keisen-draw-left)
(global-set-key [M-down]  'keisen-draw-down)
(global-set-key [M-up]    'keisen-draw-up)

TEXT-MODEにおいて、自動インデントにTAB文字が使われる場合、左方向に線を引くときにいちいち つっかかる場合があります。 M-x make-variable-buffer-local で indent-tabs-mode をローカルバッファ向けにコピーし、 M-x set-variable で indent-tabs-mode を nil にセットすると、インデントにTAB文字が 使用されなくなります。これで左方向に線を引くのも問題無しです。 毎回入力するのは面倒臭いので以下のような感じのバインドを使用しています。

(global-set-key "\C-t\C-x"   #'(lambda () "toggle-indent-tabs-mode(buffer local)"
                                (interactive)
                                (make-variable-buffer-local 'indent-tabs-mode)
                                (setq indent-tabs-mode (not indent-tabs-mode))
                                (message (format "indent-tabs-mode %s" (if (eq indent-tabs-mode t) "enabled" "disabled")))))

6.2. プログラム作成に利用しているモード

主にプログラムの作成に利用しているモードを挙げてみます。

6.2.1. 各種プログラム言語モード

X68kのMicroEMACSでキーワードが強調表示されるのが実に良い感じでしたが、 現在のEmacsは更に良い感じに色づけしてくれたりします。 Typoを見つけたりするのに非常に便利に使っています。

6.2.2. flymake

編集しながらプログラムソースの文法をリアルタイムにチェックしてくれる素晴らしいモードです。 Makefileの知識が必要なので少し導入の敷居は高いですが使い始めると手放せません。

TANEが使用している例です (.emacs設定, Makefile例1, Makefile例2(Emacs27.1))。 Makefile無しでもチェックできるようにする設定方法もあるようですが、少し大きなプロジェクトに なるとコンパイラにインクルードパスなどのオプションを指定する必要が出てくる為、結局Makefileを 使う方が手間がかかりませんでした。ご参考まで。

因みに、emacs-27.0.50からソースディレクトリのMakefileがflymakeに対応しています (参考)。 ただし「-fsyntax-only」オプションが付いていない為、CPUを爆食いしたりカレントディレクトリに 不要な一時ファイルを生成しっぱなしになるようです。 Emacsの本体コードをいじる場合は手動でMakefileを変更しています(参考)。

6.2.3. psvn

Subversionを操作するフロントエンドとして重宝していましたが、gitに移行してから出番が無くなってしまいました...
Emacs-29.1では 24.3以降非奨励となっていた toggle-read-only という関数が削除執行されたため動かなくなってました。 toggle-read-only を read-only-mode に置き換えて直してみました。御参考まで。

6.2.4. magit

gitを操作するフロントエンドとして重宝しています。

2022年6月16日にMagit3.3.0に移行してみました。2.7系以前は色々パッチを当てていたのですが、 Emacs-28.1,28.2との組み合わせでは特に問題になるような事は起こっていませんでした。 Emacs-29.1では transient.elが更新されたのとload-pathの検索順番が変わった為か magitのバージョンが合わないとうまく動かないようです (参考1, 参考2)。

以下は2.7系までの記録の為に残した文書になります。御参考まで。


2013年11月時点、psvnのようにtrackされているファイルの一覧を表示できないのが少し不便だったので、 一覧を出せるように改造して使ってみていました。大きなプロジェクトでの使い勝手はイマイチに なるかも知れませんがご参考まで (旧patch, magit-20131215.1444ベースパッチ magit-20141228.1413ベースパッチ)。 本家はGitHub で開発されています。 masterブランチはとても更新頻度が高いので、magit 2.7系より前のには前述パッチは当たらなくなって いますががよしなに。

その後、magit 2.7系では拙作window-plusと組み合わせると 操作継続不能な状態に陥る現象があり、magit 2.7系への乗り換えをしばらく見送っていました。 ひとまず原因が判明した(参考)のですが、 window-plus側ではどうしようも無かった為、magitが依存しているtransientというパッケージ の方にパッチを当てて使用しています。御参考まで。

--- transient.el.orig   2019-04-19 20:47:04.112000700 +0900
+++ transient.el        2019-07-07 21:07:37.434244400 +0900
@@ -2336,7 +2336,10 @@
   (transient--timer-cancel)
   (setq transient--showp t)
   (let ((transient--source-buffer (current-buffer))
-        (buf (get-buffer-create " *transient*")))
+        (buf (get-buffer-create " *transient*"))
+        (dbf-bkup display-buffer-function)
+        )
+    (setq display-buffer-function nil)
     (unless (window-live-p transient--window)
       (setq transient--window
             (display-buffer buf transient-display-buffer-action)))
@@ -2364,7 +2367,9 @@
       (let ((window-resize-pixelwise t)
             (window-size-fixed nil))
         (fit-window-to-buffer nil nil 1))
-      (goto-char (point-min)))))
+      (goto-char (point-min)))
+    (setq display-buffer-function dbf-bkup)
+    ))

 (defun transient--insert-groups ()
   (let ((groups (cl-mapcan (lambda (group)

因みにmagit 2.7系より前では改造してトラックしているファイルの一覧を出せるようにしていたのですが、 magit 2.7系ではmagit-status-sections-hookという変数のリストに magit-insert-tracked-files を入れればファイルの一覧を表示できます。


6.2.5. ediff

二つのバッファやファイルの差分を表示します。縦分割表示したり差分を マージする作業などに利用しています。

6.2.6. delete-trailing-whitespace

不要な空白を削除してくれます。gitは不要な空白が赤く表示されて目障りなので本機能を 利用するようになりました。たまに削られると困る場合もありますので、 こちら で知った トグルを可能にする設定と併せて、以下のように.emacsに設定しています。

(require 'cl-lib)
(defun toggle-delete-trailing-whitespace-setting ()
  (interactive)
  (cond ((cl-find 'delete-trailing-whitespace before-save-hook)
         (progn
           (remove-hook 'before-save-hook 'delete-trailing-whitespace)
           (message "Disabled delete-trailing-whitespace")
           ))
        ((progn
          (add-hook 'before-save-hook 'delete-trailing-whitespace)
          (message "Enabled delete-trailing-whitespace")
          ))
        ))
(add-hook 'before-save-hook 'delete-trailing-whitespace)

6.2.7. whitespace-mode

空白を可視化してくれるモードです。ただ、デフォルト表示はとてもうるさい表示になる為、 以下のような設定で、全角空白文字、TAB文字、不要な空白 を表示するようにしています。

(add-hook 'find-file-hook (lambda () (whitespace-mode t))) ; ファイルを開いた時にwhitespace-modeを設定する

(require 'whitespace)
(setq whitespace-style '(tabs space-mark tab-mark face spaces trailing))
(setq whitespace-display-mappings
      '(
        (space-mark   ?\xA0  [?\u00A4]     [?_]) ; hard space - currency
        (space-mark   ?\x8A0 [?\x8A4]      [?_]) ; hard space - currency
        (space-mark   ?\x920 [?\x924]      [?_]) ; hard space - currency
        (space-mark   ?\xE20 [?\xE24]      [?_]) ; hard space - currency
        (space-mark   ?\xF20 [?\xF24]      [?_]) ; hard space - currency
        (space-mark ?\u3000 [?\u25a1] [?_ ?_]) ; full-width-space - square
        (tab-mark     ?\t    [?\u00BB ?\t] [?\\ ?\t]) ; tab - left quote mark
        ))
; whitespace-spaceの定義を全角スペースにし、色をつけて目立たせる
(setq whitespace-space-regexp "\\(\u3000+\\)")
(set-face-foreground 'whitespace-space "cyan")
(set-face-background 'whitespace-space nil)
;; whitespace-trailingを色つきアンダーラインで目立たせる
(set-face-underline  'whitespace-trailing t)
(set-face-foreground 'whitespace-trailing "cyan")
(set-face-background 'whitespace-trailing nil)
;; whitespace-tab を色つきアンダーラインで目立たせる
(set-face-underline  'whitespace-tab t)
(set-face-foreground 'whitespace-tab "gray85")
(set-face-background 'whitespace-tab nil)

global-whitespace-mode を設定していないのは、term+やscratchバッファなど にも効いてしまうのと、disableにした時に全てのバッファが連動してしまうのが 所望の動きではなかった為です。

6.3. その他ファイル操作やアクセサリなど

テキスト編集以外に便利に利用しているモードを挙げてみます。

6.3.1. dired/diredx

ファイル操作も行えますが、それ以上に 圧縮されたファイルを展開せずに中身を閲覧したり、 画像を表示できたりする点を便利に利用しています。

.emacsなどに以下を設定しておくと、

(setq dired-dwim-target t)

ディレクトリ間でファイルコピーを行う際、例えば AとBの二つのdiredバッファを ウインドウ分割で開いておくと、 Aのdiredバッファで'C'を実行した時、コピー先として Bのdiredバッファのディレクトリパスが使用されます。 ただ、油断すると同ディレクトリでリネームしたいだけの時にうっかり別ディレクトリに 移動してしまう事があるのに注意が必要です😅

6.3.2. zlc-mode

MiniBufferでファイルやコマンドを補完する際、zshライクに候補バッファ表示から 選択できるようになります。こちら(リンク切れ) のサイトで知りました(GitHub はこちら)。

少しバグっていたのを直したり(2013/11時点)、 使い勝手を直したり (2013/11時点, 2015/04時点, 2016/08時点, 2021/12時点) して利用しています。ご参考まで。

6.3.3. TRAMP

ネットワーク越しのファイルをあたかもローカルファイルのように編集できます。 おかげで、リモートのLinuxマシンに乗り込んでEmacsを起動して......てな事を やらなくても済みます。

Meadowでは plink や pscpを使用する必要がありましたが、Cygwinの emacs-w32 やLinuxなどでの Emacsでは ssh や scp を使えば良いです。

以下はかつて不具合に遭遇した時の対処として行なっていました。記録の為に残した文書です。


TRAMPでリモートマシンに繋いだままの 状態でホストマシンをスリープなどで停止→リジューム すると、 スリープ前まで出来ていたリモートファイルへのアクセスが 何故かできなくなる 事がありました。 解決策は「~/.emacs.d/tramp」というファイルを消してEmacsを再起動すると いう残念な方法しか無いようです(2015/02/07時点)。

その後(2015/11/01時点)、どうせ消すんだったら 「~/.emacs.d/tramp」にそもそも書き込まなければ いいんじゃね?と思い、tramp-dump-connection-propertiesという関数を .emacsで 再定義してみました。一応、~/.emacs.d/trampを消す必要もなくなり、 Emacs上で開いていた場合はkill-bufferでtrampアクセスしたバッファおよびtramp関連バッファを 一旦削除すればEmacsを再起動すること無く復帰できるようです。 24.5向けのコードですが、25.x,26.[123]でも、ひとまず(ファイル書き込み部が24.5と(25.x or 26.[123])とでは違いますが) 同じコードでイケてます。

さらにその後(2022/04/7時点)、28.1ではリモートファイル読み込みでエラーが発生する ようになったため、以下の再定義は行わない方が良いです。

; .emacs.d/trampファイルを書くのを抑止する
(load-library "net/tramp-cache.elc")
(defun tramp-dump-connection-properties ()
  "Write persistent connection properties into file `tramp-persistency-file-name'."
  ;; We shouldn't fail, otherwise (X)Emacs might not be able to be closed.
  (ignore-errors
    (when (and (hash-table-p tramp-cache-data)
               (not (zerop (hash-table-count tramp-cache-data)))
               tramp-cache-data-changed
               (stringp tramp-persistency-file-name))
      (let ((cache (copy-hash-table tramp-cache-data))
            print-length print-level)
        ;; Remove temporary data.  If there is the key "login-as", we
        ;; don't save either, because all other properties might
        ;; depend on the login name, and we want to give the
        ;; possibility to use another login name later on.
        (maphash
         (lambda (key value)
           (if (and (vectorp key)
                    (not (tramp-file-name-localname key))
                    (not (gethash "login-as" value)))
               (progn
                 (remhash "process-name" value)
                 (remhash "process-buffer" value)
                 (remhash "first-password-request" value))
             (remhash key cache)))
         cache)
        ;; Dump it.
        (with-temp-buffer
          (insert
           ";; -*- emacs-lisp -*-"
           ;; `time-stamp-string' might not exist in all (X)Emacs flavors.
           (condition-case nil
               (progn
                 (format
                  " <%s %s>\n"
                  (time-stamp-string "%02y/%02m/%02d %02H:%02M:%02S")
                  tramp-persistency-file-name))
             (error "\n"))
           ";; Tramp connection history.  Don't change this file.\n"
           ";; You can delete it, forcing Tramp to reapply the checks.\n\n"
           (with-output-to-string
             (pp (read (format "(%s)" (tramp-cache-print cache))))))
;          (write-region
;           (point-min) (point-max) tramp-persistency-file-name)
          )))))

6.3.4. term+

不自由な感じのあったtermモードが一気に使いやすくなりました。 こちら のサイトで知りました。 テキスト編集はEmacs上で行っても、ファイル操作やコマンド実行はターミナルソフト を使用するという方は少なく無いと思いますが、term+を使用すると本当にEmacsの中だけで 事が足りるようになるかと思います。

2013年11月以降、Cygwinの emacs-w32 を使用しているのですが、 Emacs本体のターミナルエミュレーションがあまりにも遅かったので改造したものを 使用しています。 ご参考まで

termモードで定期的な画面書き換えを行う(例えばtopコマンドを使用するなど)ウインドウと並べて、 別ウインドウのバッファでIMEパッチによる日本語入力を行っていると、勝手に確定される 問題がありました。 その後、27.2で対応してみたのですが、TANEの普段使いが IMEは全バッファで状態同期するモードで 使用している為、何かしら副作用があるかも知れません (7. emacs-w32 on Cygwinについても参照)。 Anthyでは問題無いようです。

デフォルトのバインドではC-yは Emacs上のkill-ringの内容をterm+のコマンド入力行にyankしますが、 bashやtcshのコマンドライン上で C-yによるyankを普通に使うTANEには、全然関係無い別バッファで コピーした長大なkill-ringの内容を いきなり shellのコマンドラインにぶちまけられてしまって 困る場合がありました。そこで、.emacsに以下を追加して一部バインドを変更して使用しています。 ついでに編集モードのコピーが説明通りに動いている気がしなかったので、 term+input-readonly-mapのESCキー割り当てを外して、普通に M-wでコピーできる ようにしました。

(when (version<= "28.0" emacs-version )
  (setq Buffer-menu-name-width 19) ;workaround for Emacs28
  )

(setq term+char-map
  (let ((map (make-sparse-keymap)))
    ;; unbind
    (define-key map (kbd "C-x") nil)
    (define-key map (kbd "M-x") nil)
    (define-key map (kbd "M-:") nil)
    ;; bind
    (define-key map (kbd "C-M-j") #'term+edit-as-expected)
    (define-key map (kbd "M-RET") #'term+edit-as-expected)
    (define-key map (kbd "C-q") #'term+pass-through)
    (define-key map (kbd "C-c C-e") #'term+send-esc)
    (define-key map (kbd "C-c C-c") #'term-interrupt-subjob)
    (define-key map (kbd "C-c h") #'term+hardcopy)
    (define-key map (kbd "C-c l") #'term+toggle-buffer-log)
    (define-key map (kbd "C-c r") #'term+toggle-record)
    (define-key map (kbd "M-y") #'term+yank)  ;;変更
    map))

(setq term+input-readonly-map
  (let ((map (make-sparse-keymap)))
    (define-key map " " #'term+mark-or-copy)
    (define-key map (kbd "RET") #'term-char-mode)
;    (define-key map (kbd "ESC") #'term-char-mode) ;削除
    map))

本当はdefine-key関数で部分変更できるハズなのですが、うまく定義できなかったので term+char-mapおよびterm+input-readonly-mapを上書きしています。 具体的には、「C-y」を無効にしたいのですが、以下のように書いてもうまくいきませんでした。

(define-key term+char-map (kbd "C-y") nil)

6.3.5. text-translator

kill-ringに入れたテキストを直接翻訳サイトに流し込んで翻訳結果を得られます。 英語のマニュアルとかをどうにか読むのに重宝していました。 いつの日からかサイトに接続できなくなったので使わなくなってます。 こちら のサイトで知りました。

Google翻訳では改行がピリオド扱いになってしまうので、

(setq text-translator-do-fill-region t)

を .emacsに追加して使用していました。

6.3.6. google-translate

text-translatorが一時的に使えなかった事があり、代替品として知ったのが使うきっかけ でした。text-translatorと違ってGoogle翻訳へのアクセス専用です。 GitHubで開発されています(こちら)。

時々、Google翻訳は訳が変な場合があった(参考)ので、 text-translatorはGoogle以外の翻訳サイトにアクセスするようにして使い分けていました。

オリジナルではターゲット(翻訳先)が固定されています。text-translatorに慣れると面倒臭く 感じるようになったので、以下のような自動判定コードを.emacsに追加しています。

(defun google-translate-uiex (&optional begpos endpos)
  "region文字列をGoogleで翻訳"
  (interactive "r")
  (let* ((str  (replace-regexp-in-string "\n" " " (if (= begpos endpos)
                                                      (read-from-minibuffer "sentence: ")
                                                    (substring-no-properties (buffer-substring-no-properties begpos endpos))))))
    (if (> (* (/ (float (length (replace-regexp-in-string "[^A-Za-z _0-9\'\"\,\.\!\?\-]+" "" str)))
                 (length str))
              100)
           95)
        (google-translate-translate "en" "ja" str)
      (google-translate-translate "ja" "en" str))))
(global-set-key "\C-ct" 'google-translate-uiex)

判定コードはtext-translatorのを拝借しています。また、改行コードは空白に置き換えて ピリオド扱いにならないようにしています。

あと、たまに「JSON readtable error」というメッセージが出て翻訳できなくなる 事があります。Google側がちょいちょい変更を加えてくる影響を受けている為です。 その時はGitHubでの開発状況をチェックしてみるのが良いと思います。対応版が 出てる場合があります。ありがたい事です。

その後、翻訳結果を別ウインドウを開くのが面倒臭くなってしまい ggltr-mode ってのを作ってみました (参考1, 参考2, 参考3)。 翻訳先の言語は一つの代わりに翻訳元言語はautoになっているのと、翻訳元領域を選択するだけなので infoやmanなどを読んだり、ewwで何語か判らないページを読むのが楽になったような気がします😅

6.3.7. japanese-holidays

calendarでカレンダー表示した際に日本の休日を表示できます。 本物お仕事では必ずこれで祝日確認をしてました。 2016年10月現在、こちら でメンテナンスが 継続されているようです。

カレンダー表示だけだと、2016年頃からは拙作のmcalendarを 使用するようになりました。

6.3.8. Nyan Mode

Nyan Cat」という世界的にブームに なっていたらしいYouTube動画に出ているネコのアクセサリ表示です。 以前はホームページがあったのですが、2015年4月時点で GitHub での公開のみになっているようです。

バッファ内のカーソル位置をモードラインにビジュアル化するのが本来の機能なのですが、 アニメーションが止まったのをもって、Emacsが固まっているか否かを判断するのに使用 してます。 そういえば、Webで公開されているEmacs画面画像を見ていると、意外とnyan-wavy-trailや nyan-start-animation を設定している人は少ないように思います。

(require 'nyan-mode)
(nyan-mode)
(setq-default nyan-wavy-trail t)
(setq nyan-bar-length 12)
(nyan-start-animation)

Emacs-29.1では C-M-<wheel-up> や C-M-<wheel-down> でフレームやウインドウのサイズは そのままにフレームのフォントを大きくしたり小さくしたりする事ができるようになったのですが、 nyan-modeの表示はサイズが変更されませんでした。そこで以下のようなパッチをあてて使ってみています。 アニメーションの度に create-image する感じになっていてイマイチかも知れない点は 御承知おき頂ければと思います。

--- nyan-mode.el.orig   2022-04-09 08:34:28.000000000 +0900
+++ nyan-mode.el        2023-06-27 23:46:02.249915500 +0900
@@ -166,8 +166,7 @@

 (defvar nyan-animation-frames (if (image-type-available-p 'xpm)
                                   (mapcar (lambda (id)
-                                            (create-image (concat nyan-directory (format "img/nyan-frame-%d.xpm" id))
-                                                          'xpm nil :ascent 95))
+                                            (concat nyan-directory (format "img/nyan-frame-%d.xpm" id)))
                                           '(1 2 3 4 5 6))))
 (defvar nyan-current-frame 0)

@@ -194,8 +193,12 @@

 (defun nyan-get-anim-frame ()
   (if (nyan--is-animating-p)
-      (nth nyan-current-frame nyan-animation-frames)
-    nyan-cat-image))
+      (create-image
+       (nth nyan-current-frame nyan-animation-frames)
+       'xpm nil :ascent 95)
+    (create-image nyan-cat-image
+                  'xpm nil :ascent 'center)
+    ))

 (defun nyan-wavy-rainbow-ascent (number)
   (if (nyan--is-animating-p)

6.3.9. desktop-save-mode

開いているファイル名を保存しておき、Emacsを終了→再起動したとき、前回 開いていた複数のファイルを再度開き直す事ができます。例えばちょっとしたメモとか 編集はしないけど参照する為に開き始めると、すぐに数十以上の単位でファイルを 開いている場合があります。それらを再び全て開きなおすのは 結構な手間なのですが、 Windowsは月に1回の頻度でアップデートによる再起動が要求されるので、不本意ながら Emacsも再起動せざるを得ない状況があります。この場合に大変重宝しています。 因みに、かなり前から存在していたようですが、知ったのは2017年です😅

定期的に保存するモードもあるようですが、TANEは 適当な作業の区切りや終了する前に手動でセーブ(desktop-save)、 再起動時に手動でロード(desktop-read)しています。

7. emacs-w32 on Cygwinについて

TANEが2013年頃からメインに使用しているのはCygwinのemacs-w32です。 Cygwin上で動作しながらもウインドウ描画などはWindowsネイティブ で動作するという組み合わせです。因みに、2013年より前はX-windowを使う(2013年以降で言うemacs-X11、2022年以降で言うemacs-gtk)か、 ターミナルで使う(いわゆる emacs -nw)しかありませんでした。

Cygwin上で動作するのでDLL依存がありますが、外部プロセス実行で発生するもろもろの問題が 解決される(解決が容易になる)利点があります。 ただ、Cygwinでパッケージインストールしたemacs-w32では、MeadowやNTEmacsのようにMS-IMEを使用する ことはできませんでした。そこで、NTEmacsからIME制御部分(いわゆるIMEパッチ)をemacs-w32とマージして 使用しています。

rzl24ozi氏の作成されたパッチ が IMEパッチのデファクトスタンダードでした。 時は流れて2020年末に 細田さんによるプロジェクト 「Emulator of GNU Emacs IME patch for Windows (tr-ime)」 で、ダイナミックモジュール機構を利用して IMEパッチの無いバイナリでもIMEパッチ相当の動作で MS-IMEによる日本語入力を行えるようになっています。 何よりもMELPAのパッケージに登録されているので、 IMEパッチよりもずっと手軽にIMEを利用できるようになっています。

という訳で2024年2月現在「IMEパッチって要るの?」って感じなのですが、 自分好みに大分自由にいじってしまってます😅 IME以外の部分についても具合の悪いと 思った点を実験的に弄っている部分がありますので、もしお役に立つような事がありましたら幸いです。

Emacs-29.2をベースにしています。 過去バージョン向けには

参照してみてください。

ビルドとインストール方法は以下の通りです。

  1. 予めCygwinパッケージのemacs-w32(29.2)をインストールしておきます。
  2. Cygwinでビルドします。emacs-29.2のtar-ballは適当な所から拾ってください。 ビルドに必要なツールやライブラリが揃ってなければ揃えてください(29.2ではC++コンパイラ(g++など)も必要になっています)。
    パッチは emacs-w32_29.2_20240203.patch.xzをダウンロード してください。
  3. 任意のディレクトリで 以下の手順でビルドします。2.でダウンロードしたファイルは ~/Downloads ディレクトリ下に置いてあるものとしています。

    xz -dc ~/Downloads/emacs-29.2.tar.xz | tar xf -
    cd emacs-29.2
    xz -dc ~/Downloads/emacs-w32_29.2_20240203.patch.xz | patch -p1
    ./configure --prefix=/usr --with-w32 --with-imagemagick --with-native-image-api
    make -j $(nproc)
    

    「--with-imagemagick」や「--with-native-image-api」はお好みでどうぞ。

  4. /usr/bin/emacs-w32.exe (と、もしあれば /usr/bin/emacs-w32.pdmp も; emacs-29.2-1では.pdmpは無いようです)を それぞれビルドした src/emacs.exe と src/emacs.pdmp で置き換える。 元の実行ファイルは別名で退避しておくのが良いでしょう。
  5. lisp/international/w32-ime.el と lisp/international/w32-ime.elc を/usr/share/emacs/29.2/lisp/international/. にコピーする。
  6. 以下の設定を.emacs(オールドスタイルですみません)に追加する。

    ;;
    ;; IME setup
    ;;
    (set-language-environment "Japanese")
    (load "international/w32-ime" t) ;international/w32-imeが無くてもエラーしないload設定
    (when (eq 'w32 (window-system))
    
      ;; tr-imeと同居する場合は以下の2行を有効にする
    ;  (require 'tr-ime)
    ;  (tr-ime-advanced-install)
    
      (when (featurep 'w32-ime)
        (setq w32-ime-buffer-switch-p nil) ; 全バッファでW32-IME状態同期
        (setq default-input-method "W32-IME")
    ;    (setq-default w32-ime-mode-line-state-indicator "[-]")
    ;    (setq w32-ime-mode-line-state-indicator-list '("[-]" "[あ]" "[-]"))
        (setq w32-ime-mode-line-state-indicator-list '("[-]" (format "[%s]" current-input-method-title) "[-]"))
        (setq w32-ime-input-method-title "あ")
        (setq-default mode-line-mule-info
                      `(""
                        ,(propertize
                          "%z"
                          'help-echo 'mode-line-mule-info-help-echo
                          'mouse-face 'mode-line-highlight
                          'local-map mode-line-coding-system-map)
                        (:eval (mode-line-eol-desc)))
                      )
        (w32-ime-initialize)
    
        (defun w32-isearch-update ()
          (interactive)
          (isearch-update))
        (define-key isearch-mode-map [compend] 'w32-isearch-update)
        (define-key isearch-mode-map [kanji] 'isearch-toggle-input-method)
        (define-key isearch-mode-map "\C-o"  'isearch-toggle-input-method)
    
        (add-hook 'isearch-mode-hook
                  (lambda () (setq w32-ime-composition-window (minibuffer-window))))
        (add-hook 'isearch-mode-end-hook
                  (lambda () (setq w32-ime-composition-window nil)))
        )
      )
    

以上で使えるんじゃないかと思いますが、エラーなど出た時はうまく対応してください😅

ネイティブコンパイルについて

  • 28.1からELISPのネイティブコンパイル機能が利用可能になりました。 Cygwin64では 29.2-1 はネイティブコンパイル無し、29.2-2 はネイティブコンパイル有効でテスト版としてリリースされています (Subject: emacs 29.2-1emacs 29.2-2 (TEST)) Cygwin64の場合はconfigureオプションに「--with-native-compilation」を追加することで有効になります。 実際に使うと色々(特にrebaseに関連して)ハマりどころがありそうです。もし有効にして事件に遭遇した場合は がんばって対応するしかないようです😅
    拙作のパッチ適用は自前でビルドする事を前提としていますので、ネイティブコンパイルの有無はお好きな方を選んでいただければ良いかと思います。
  • Cygwin32では未サポートという扱いですが、特別なconfigureオプション「--with-cygwin32-native-compilation」で ビルドを行う事はできるようです。ただ起動してみると「child_info_fork::abort」メッセージが出てまともに使える感じではありませんでした。 Cygwin 3.4以降、Cygwin32はサポートされなくなりました。

パッチのざっくりした内容や注意事項は以下です。

  • IMEに関係するパッチについて
    • IMEパッチ自体は24.4,24.5向けに emacs-24.2-ime-2012-09-02.patch.tar.gz(リンク切れ)と emacs-24.3-ime-2013-05-03.patch.tar.gz(リンク切れ)を 元にしていました。2013-05-03ではMinGW特化されてしまってそのままではCygwinビルドできなかった為、 ダメだった所は2012-09-02を使用した感じになってます。また、rzl24ozi氏作成のパッチも一部参考にさせていただいてます。
    • 変数w32-ime-buffer-switch-pをnilに設定(全バッファでW32-IME状態同期)したとき 「M-x set-input-method」 でW32-IME以外のIMを選択してもアクティブにできないバグを 修正しました(参考)。
      ※補足: W32-IMEは他のIMと違ってEmacsの外部で制御されるイメージです。この為、W32-IMEのバッファと他IMのバッファとを other-window(C-x o)などで行き来する際、「W32-IMEとその他のIMが同時にONになりそうな場合は衝突回避の為に一旦両方OFFにする」 という動きになります。テスト版の時のメモも参照いただければと思います(参考)。
    • インジケーター設定変数 w32-ime-mode-line-state-indicator-list に 指定するリストの要素にリストを指定出来るようにしました。 また、w32-ime-mode-line-state-indicator は不要になりました(あっても参照していません)。 リストを指定場合eval した結果文字列がインジケーターとして表示されます。 これによりW32-IME以外の IMの場合でも current-input-method-title の文字列を表示できるようになりました。
    • mode-lineに表示されたインジケーターのマウスオーバーに対応しました。 マウスカーソルをかざすとToolTipが表示されます (参考)。
    • isearch(C-s)の文字列入力時にinput-methodの表示に対応できるように lisp/international/w32-ime.elに手を加えました(参考)。 ただし、w32-imeで対応しているmode-lineに表示 されるインジケーターと二重表示になるので .emacsに対応した記述が必要となります。 設定例では、lisp/bindings.elで定義されている変数 mode-line-mule-info をカレントインプットメソッド 表示を行わないように再定義しています。
    • IMEパッチの当たっていないCygwinパッケージインストールした emacs-w32 と.emacsを共通化できる ようにlisp/international/w32-ime.elに手を加えました。もしIMEパッチ無しの emacs-w32 で international/w32-ime をロードした場合、(featurep 'w32-ime)の結果がnilとなります。 また、international/w32-imeをロードする際の missing-ok フラグを t にする事で、 IMEパッチがそもそも無いEmacs(例えばLinuxのEmacsなど)とも.emacsを共通化できると思います。
    • w32-ime.elを読み込んだ時、(window-system)の戻り値が'w32ではないとき W32-IMEをレジストしないようにしました。 例えば「emacs-w32 -nw」で起動した時は「M-x set-input-method」の選択候補にW32-IMEは含まれなくなります。
    • IMEは全バッファで状態同期するモードで使用しています。 w32-ime-buffer-switch-pをnilにしただけではインジケータの再描画がうまく対応できていなかった為、 lisp/international/w32-ime.elに手を入れています。 また「w32-ime-buffer-switch-p を t にした場合(バッファ毎にIMEの状態を保持するモード)」 でのtermとIMEの相性問題を対応したつもりですが、 副作用があるかも知れません。
    • W32-IMEの機能である単語登録関数 w32-ime-toroku-region が 機能していないようだったのを対応してみました。 しかし、Windows10の20H2では(22H2時点でも)単語登録ダイアログが開けなくなってしまった為、結局機能しません😓 (参考: 単語登録を行うWin32APIである ImmConfigureIME の実験)
      もう機能する事は無さそうです(2023年8月時点)。
    • 「C-x 5 2」(make-frame-command)で新規フレームを生成する際、IMEがONのままだと Segfaultするバグを修正しました(参考)。
    • Windows10で emacs-w32で起動後、ウインドウをマウスで操作する事無くIMEの切り換えを行ってもIME入力が 有効にならないバグをワークアラウンドしてみました(参考)。 何故これで上手くいくのか謎な対応方法なのでやっぱりダメな場合はあるかも知れません。 もしやっぱりダメそうな場合は「ウインドウを一回動かす」か 「他のアプリにウインドウフォーカスを移した後、再びウインドウフォーカスを戻す」で対応してみてください。
    • フォント設定を行っていない場合(例えば -Qオプションで起動した時など)、「MS Gothic-10」が最優先となるようにしました。 もし、他のフォントが良いとかサイズを変えたい場合などは各自でソースコードを弄っていただければと思います。
      ※補足:IMEパッチと連動したのは「MSゴシック」が日本語版Windowsに標準搭載される和文フォントという位置づけのため、 日本語文字を入力する為のIMEパッチと連動させるのが良い(逆にIMEパッチが無いのであれば和文フォントをデフォルトにする 必要は無い)と考えたからです。
    • USE_W32_IMEをdefineしない場合(即ちW32_IMEパッチを含まないビルドを行う場合)に コンパイルエラーするのを修正しました。 configure実行後、src/config.hの 「#define USE_W32_IME 1」となっている箇所を削除すれば IMEパッチに関係する機能を 含まないビルドが可能になっていると思います。 すみませんがconfigureオプションでは指定できるようになってません....
    • Cygwin64でビルドした際にワーニングになるコードがあったのを修正しました。 SetWindowLong()とGetWindowLong()を使うコードは32bitと64bitで共通コードにできないのか...?🤔
    • Emacs 28系でイベントの発生状況が変わった事から、IMEのステータス表示の更新に ELISP機能の run-with-timerを 使用するようにlisp/international/w32-ime.elを更新しました(参考)。
    • emacs-w32_29.1_20230909.patch.xzから バッファのテキストスケール変更 (C-x C-+, C-x C--, C-x C-0, C-mouse wheel)で変更されたフォントサイズに IMEで変換中のインライン表示の フォントサイズが連動するように対応してみました(参考)。
      伝統的に、Emacsバッファ表示と変換中インライン表示のフォントのサイズがズレるという問題に対処する為に

      (modify-all-frames-parameters '((ime-font . "MeiryoKe_Console-9"))) ;インライン表示フォントのズレに対応する伝統的な方法
      

      のように フレームパラメータの ime-font にEmacsバッファ表示と合うようにフォントファミリ名を指定するという方法がありますが、 本パッチでは「環境変数LANGがja_JP.UTF-8のようにシフトJIS系ではない設定の場合に ...」で直したフォント関連対応が 作用している為、ime-fontを指定しなくても Emacsバッファ表示と 変換中インライン表示のフォントファミリは連動するように なっていました(サイズが対応できていなかったので今回はそれを対応した)。本対応では以下のような振舞いになります。

      • ime-fontを指定しない(もしくは「(ime-font . nil)」の)場合、変換中インライン表示は Emacsバッファ表示に応じてフォントファミリとサイズが自動的に連動します。 ただし、フォントによっては微妙にサイズがズレる場合があります。そういうものだと思ってやってください💦 emacs-w32_29.2_20240203.patch.xzで追加されたフォントサイズ補正を抑止するとサイズがズレる 事はなくなります。各自の要件に合わせて設定いただければと思います。
      • (ime-font . "MeiryoKe_Console")」のように ime-fontにフォントファミリ名(のみ)を指定した場合、 変換中インライン表示の フォントファミリは ime-fontで指定したものを、サイズはEmacsバッファ表示に連動します。 これもフォントによってサイズがズレる場合があります💦 emacs-w32_29.2_20240203.patch.xzで追加されたフォントサイズ補正を抑止するとサイズがズレる 事はなくなります。各自の要件に合わせて設定いただければと思います。
      • (ime-font . "MeiryoKe_Console-10.5")」のように ime-fontにフォントファミリ名とサイズを指定した場合、 変換中インライン表示は Emacsバッファ表示によらず常に ime-fontで指定したフォントファミリとサイズで表示されます。

      変数w32-ime-enable-font-scalingを nilにすると emacs-w32_29.1_20230805.patch.xz 以前の動作に戻ります。 デフォルトは tになっています。

  • IME以外のEmacs本体に関するパッチについて
    • オリジナルではJPEG画像表示の時に減色されてしまうのですがフルカラー表示に強制しています (参考)。
    • imagemagickパッケージについて 26.3までのビルド例では--without-imagemagickとしていましたが、27.1以降--with-imagemagickとしました。 もし動きが怪しいようならば--without-imagemagickで様子を見てみるという手はあるかも知れません。 因みに、--with-imagemagickでは24.3の時は不安定な実行ファイルができあがりました(参考)。 24.[45], 25.x, 26.[12]ではpdf-tools との相性が悪かった のですが(参考)、26.3では 2019年12月時点でのGitHubのpdf-toolsにパッチを当てる事で相性問題を解消できました (参考)。 27.1以降でも相性問題の対応は必要です。 28.2+パッチ20221209版以降 Emacs本体でimagemagick-render-typeを無視するようにしました (2022年12月時点の新しいpdf-toolsでも設定されていてバージョンアップ等の理由でパッケージインストールすると ハマる可能性があったので(参考))。
    • termモードのターミナルエミュレーション表示が遅い点を改造しています (参考)。
    • C-x C-f のファイル読み込みなどで「*.c」のような正規表現で複数のファイルを読み込もうとしたとき 64個以上のファイルを開こうとするとSegfaultになっていたのをワークアラウンドしていました (参考)。2019年2月時点ではFD_SETSIZEは64で定義されていましたが、 2023年6月時点ではCygwinの場合は1024に変更されているようです。 ワークアラウンドの効果は相殺されていますが EmacsのコードでFD_SETSIZEを再定義するワークアラウンドは残したままとしています。 29.1では正規表現指定で1024個を超えるファイルを読み込んでも大丈夫になっているようです。
    • 27.1以降で画像を180°回転させたときに(加えて29.1では上下反転/左右反転したときも)表示が化けるバグを修正しています(参考)。
    • 環境変数LANGがja_JP.UTF-8のようにシフトJIS系ではない設定の場合に、 日本語文字フォント名(フォントファミリ)の フォントを設定できなかったり、 describe-fontコマンドでフォント名が化ける場合があった(参考) のを対応してみました。内部的にUTF-16を扱うWin32APIを使用するようにしたので LANGの影響は受けないようになっています。
    • フォントによって幅や高さが異常に大きくなる場合があるのに対応してみました (参考)。 ポイント値からDPIとスケーリングが考慮されたピクセルサイズの高さが、 1.16倍を 超えるようなサイズになった場合は、ピクセルサイズを元にアセント値とディセント値を 再計算しています。 対処方法としては正しくないかも知れません。
      今更ですが emacs-w32_29.2_20240203.patch.xzから本機能を抑止する設定を追加しました。 w32-enable-tweak-font-metricsを nilにするとフォントサイズ補正を行ないません。デフォルトは tになっています。 また、フォントキャッシュが機能している為、フォントを表示した後に設定を変更しても即反映されない場合があります。 .emacsに設定値を記す事を推奨します。
    • harfbuzzが有効な時、Cygwinでは cygharfbuzz-0.dll を読み込むようにしました (参考)。 「👨‍👩‍👧‍👦」のような合字の絵文字などが表示できるようになります。また、モノクロ絵文字フォントの 「Noto Emoji」を使用するにはこの対応が必要なようです (参考)。
    • emacs-gtk(旧emcas-X11)において、読み込んだフォントによってSegfaultで落ちる場合があったのをワークアラウンドしました(参考)。 29.1で修正されています。
    • イタリック体のフェイスを持たないフォントに対して斜体表示する機能を追加してみました(参考)。 以下の設定を.emacsに追加する事で有効になります。

      (setq w32-enable-synthesized-fonts t)
      (set-face-attribute 'italic      nil :weight 'normal :slant 'italic :underline nil)
      

      イタリックの字形を持たないフォント(例えば "MS Gothic")ではイタリック体で表示する事はできません (参考)。 Emacs22の頃に w32-enable-synthesized-fonts という変数を tに設定すると任意のフォントでも 斜体表示する事ができたようですが (Emacs22をベースとするMeadow3では特に設定はしなくても有効でした)、Emacs23で機能自体が削除されたようです。 今回、機能の有効/無効を切り替える為に 変数 w32-enable-synthesized-fonts を再利用する形を 取っています。 ただ、表示の仕方が完璧では無い為、例えば斜体表示されている文字列の上を左から右にカーソル移動すると表示が欠けます。 表示が乱れた場合は redraw-displayで再描画する必要があるかと思います。 29.1で追加されたダブルバッファリング機構により 少しタイムラグはありますが自動的に再描画されるようになっています。

    • image-diredでサムネイルを生成する際、(恐らくCygwinの問題で)ハング状態に陥った後Segfaultで落ちる場合があったのをEmacsでワークアラウンドしました (参考)。 ただし、なぜこれでうまくいくのか判らない対応方法なので避けきれていない可能性があります (参考)。
    • src/w32image.cがCygwinでのビルドに対応していなかったのを対応してみました (参考)。Cygwinでもconfigureオプション「--with-native-image-api」 を指定できます。
    • メニューの「Option→Set Default Font ...」で開くフォント選択ダイアログで選択出来なかったフォントも選べるように 対応してみました(参考)。 w32apiの ChooseFont()関数 のFlags変数に CF_INACTIVEFONTS フラグを立てる事で対応しています。 ただし、本フラグが機能するのはWindows7以降のようなので、WindowsVista以前のWindowsでは機能しないかも知れません(未確認)。
    • emacs-w32_28.2_20221209.patch.xzと同じ方法で29.xでもカラー絵文字表示に対応しています(参考)。 DirectWriteを扱うコードがC++となっている為、追加で g++などのコンパイラをインストールしておく必要があります。 configureオプションによる切り替えはありませんのでカラー絵文字表示は常に有効でビルドされます。
      カラー絵文字フォントのフォーマットには いくつか種類がありますが Windowsの「Segoe UI Emoji」で使用されているCOLR/CPALテーブルという方式のカラー絵文字フォントのみの対応となります。 EmojiOne Colorや Twitter Color EmojiのようなSVGのOpenTypeフォントや、 Noto Color Emoji(Windowsではフォントファイルが認識できないみたいですが)は 対象外となります。 表示するには.emacs等にフォントの設定を行う必要があります。 パッチ無しemacs-w32でSegoe UI Emojiを モノクロ表示で使用できていれば そのままで問題ありません。 もし設定されていない場合、最小限の設定としてひとまず

      (set-fontset-font "fontset-default" 'emoji
                       '("Segoe UI Emoji" . "iso10646-1") nil 'prepend)
      

      を.emacsに足せば良いかと思います。各自環境都合もあるかと思いますのでうまく設定していただければと思います。
      変数 w32-enable-color-emoji-render をnilにするとモノクロ表示になります(redraw-displayコマンドでの再描画が必要です)。

    • SVG描画に対応しています(Cygwinパケージのemacs-w32は対応していません)。 emacs-w32でのRSVG表示対応は24.3で実験していた頃 (参考1,参考2)から 行なっていたのですが記してませんでした😅
    • 組み込みImageMagickを使用した image-mode画像表示の 上下反転/左右反転に対応しました (参考)。
    • 「--with-native-image-api」で アニメーションGIFファイルを表示した際、アニメーションしない為ワークアラウンドとして GIFファイルは native-image-apiでの表示対象から外しました (参考)。
    • src/w32font.c および src/w32uniscribe.c 内のフォントファミリ一覧を生成するコードにおいて、 重複削除を行なっているようなのですがうまく動いていないようだったのを修正しました。 フォントフォールバックを検査する際に、重複していた分の処理が無くなるのでフォールバックに かかる時間が若干短くなります(参考)。
    • emacs-w32_29.2_20240203.patch.xzでフォントフォールバック時にフォントを探すのに時間が かかる原因箇所を調べる手段を組み込んでみました (参考)。次のように使う想定です。

      1. Emacs起動後、scratchバッファなどで以下のようなロギング設定を行なう。

        (progn
          (setq font-log nil)
          (setq debug-font-find-time-limit 900) ;今回追加した設定変数. 900msより時間がかかるとログに記録する.
          ) ; and press C-j
        
      2. 例えば「M-x view-hello-file」を実行します。
      3. 終わったら「M-x font-show-log」で開いたログの中に 以下のような文字列で記録されます。

        font_find_for_lface: exec time 6892.0ms > 900.0ms char=0x1787 (#<font-entity harfbuzz outline Leelawadee UI sans iso10646-1 regular normal normal 0 nil 0 nil ((:format . opentype) (:script symbol buginese khmer lao thai latin))>)
        

        この例では、char=0x1787というユニコード文字を表示しようとして 6892ms時間がかかり、 「Leelawadee UI」が選ばれたという事を示しています。 文字0x1787は scratchバッファなどで 「C-x 8 RET」で16進文字コードで文字入力した後、 「M-x describe-char」で文字を調べて 「script: khmer」である事が分かります。 他にもあれば同じ要領で探すのに時間のかかったフォントを特定してください。

      4. .emacsに

        (set-fontset-font t 'khmer "Leelawadee UI")
        

        を追加して明示的にフォントを指定します。フォントフォールバックの発生を防げるので フォントを探す時間の短縮になります。

      我が家ではview-hello-fileが表示されるまでに1分近くかかっていたものが1秒に短縮されるケースがありました (参考)。

  • IME以外のEmacsLISPに関するパッチについて
    • image-diredでリモートファイルのサムネイルを生成する際(拙作スクリプト wrapped_convertが必要です)、 TRAMPが複数の非同期プロセスに対応していないのが原因でハング状態に陥るのをワークアラウンドしました (参考1,参考2)。 29.1以降でも同じように対応していますが、ファイル数が多いとimage-diredバッファウインドウが表示されるまで 時間がかかるようです(参考3)。 ※lisp/image/image-dired-external.el
    • system-typeが cygwinの場合は org-plantuml-jar-path で指定されるCygwin形式のファイルパスを、 内部でWindows形式のファイルパスに変換するように変更しました。 (参考)。 ※lisp/org/ob-plantuml.el
    • --with-imagemagickでビルドしたEmacsで 且つ、org-modeで変数org-image-actual-widthを nilに 設定した上で、#+ATTR_HTML: や #+ATTR_ORG: の :width で画像表示幅の指定を省略した場合に 画像フォーマットによって インライン画像が表示されない場合があったのをワークアラウンドしてみました (参考)。 ※lisp/org/org.el
    • 29.1以降のewwで背景色の塗りつぶしができていない場合があったのを 修正しました(参考)。 ※lisp/net/shr.el
    • 28.1以降のewwでバイナリファイルへのリンクを開こうとするとハング状態に陥るのをワークアラウンドしてみました (参考1,参考2)。 29.1以降でも同じように対応しています。 ※lisp/net/eww.el
    • image-dired でサムネイルを選択して画像を表示する際 29.1では image-mode を 使用するようになったのですが、バッファの再利用を行なわない方式になった為、 同じウインドウに表示されない場合があったりしたのを改善してみました (参考)。 ※lisp/image/image-dired.el
    • 29.1で機能追加された image-crop に色々と不具合 (参考)があったのを修正してみました。 ※lisp/image/image-crop.el
    • info 表示でセクションタイトルのフォントフェイスが適用されない場合があるのを ワークアラウンドしました(参考)。 ※lisp/info.el

その他

  • Emacs-27.1以降、--with-imagemagickでビルドした場合に JPEG2000画像フォーマットのファイルを表示させた際、 SegfaultでEmacsが落ちる事がありました(参考)。 パッケージのImageMagickが壊れているのが原因でした。 ImageMagickを自前でビルドして(その際に--with-gslibというconfigureオプションを外してビルドする) DLL(cygMagickCore-7.Q16HDRI-7.dllとcygMagickWand-7.Q16HDRI-7.dll)を Cygwinパッケージのものと入れ替える事で対応する必要がありました (参考)。
    ImageMagickのCygwinパッケージが 7.0.10.27 から 7.0.10.61 にアップデートされた時に直ったようです (参考)。
  • ImageMagickの不具合をいくつか対応してみました (ImageMagick-7.0.10-61_20230620a.patch.xz)。

    • HEICフォーマットの画像ファイルを表示すると色が化けるのを対応 (参考1, 参考2)。
    • TGAフォーマットで 透明度付きのグレースケールタイプの場合に表示が化けるのを対応(参考)。

    ビルドや置き換え (ビルドしたDLL(cygMagickCore-7.Q16HDRI-*.dllcygMagickWand-7.Q16HDRI-*.dll)をパッケージ版と置き換える)は 面倒臭いですが もしCygwinパッケージで困った場合に試してみていただければと思います。

  • ImageMagickの convertコマンドを外部起動して画像を表示するようなケース (例えば --without-imagemagickでビルドしたり image-diredを使用する場合など)で遭遇した不具合に対応するための perlスクリプトを作成しました(wrapped_convert_211205a.tar.xz)。 素のconvertをラップして機能追加する感じなので素のconvertコマンド自体は必要ですが、 Emacsでconvertコマンドを指定しているものをwrapped_convertに切り替える事で不具合対応します。 詳細はスクリプトの先頭部分に記してあります(utf-8の日本語です😓)。

8. 終わりに

使っても使っても極めた気のしないEmacsというテキストエディタですが、極められるものでは 無いのかもと思い始めています。しかしながら、使い続けていると新たな発見があるのは面白い所 だと思います。むしろそういう所に魅力があるのかも知れません。

本文書では針の先ほどもEmacsの魅力を伝えられていないと思いますが、 「なにやら長い間使っている奴が居るらしい Emacsってどうよ?」と興味を持って いただけたなら幸いです。

9. 履歴

  2013/03/31 : 初版。
  2013/04/13 : 個人的によく使うモードの御紹介に「ediff」と「moccur-grep/moccur-grep-find」を追加した。
               他、ちょっとだけ文書修正。
  2013/04/14 : 誤記修正。
  2013/04/28 : 細かい言い回しなどを修正。
  2013/05/18 : 誤記修正。
  2013/09/12 : 文言を少し見直し。
  2014/01/01 : 個人的によく使うモードの御紹介を更新。
  2014/01/13 : 「Emacs-W32 on Cygwinについて」を追加。追記や誤記修正。
  2014/05/04 : 微修正。
  2015/04/19 : Emacs-24.5ベースに変更。
  2015/05/11 : 微修正。
  2015/05/30 : 微改善。
  2015/09/20 : keisen-mule,google-translateに追記。
  2015/11/01 : term+, TRAMP, nyan-modeに情報追加。google-translateの自動判定コードを更新。
  2015/11/03 : 「Emacs-W32 on Cygwinについて」に追記。
  2015/11/22 : term+, nyan-modeに情報追加。google-translateの自動判定コードを更新。その他誤記修正/改善。
  2016/01/16 : 誤記修正。
  2016/07/03 : 誤記修正。ちょっとだけ更新。
  2016/08/06 : ちょっとだけ更新。
  2016/10/15 : Emacs-25.1ベースに変更。色々更新。
  2016/12/02 : term+のキーバインド変更コードを更新。
  2016/12/18 : term+のキーバインド変更コードがやっぱりうまくいってなくて元に戻しました。
  2017/01/15 : org-mode 9.0.2対応。内容に変更はありません。
  2018/06/05 : Emacs-26.1ベースに変更。微修正。
  2018/06/10 : 既知のバグとしてIMEが有効にならない場合がある点を追記した。
  2018/06/23 : リンク切れ修正、その他更新。
  2019/04/24 : Emacs-26.2ベースに変更。微修正。
  2019/09/08 : Emacs-26.3ベースに変更。微修正。
  2019/12/08 : Emacs-26.3向けパッチの修正(emacs-w32_26.3_20191207.patch.xz版)。
  2019/12/16 : 文章微改版。
  2020/04/25 : Emacs-26.3向けパッチの更新(emacs-w32_26.3_20200425.patch.xz)。その他微改版。
  2020/04/29 : Emacs-26.3向けパッチの更新(emacs-w32_26.3_20200429.patch.xz)。追記。
  2020/04/30 : 文章微改版。
  2020/07/26 : 文章微改版。
  2020/08/15 : Emacs-27.1ベースに変更。その他、微更新。
  2020/09/01 : Emacs-27.1向けパッチの更新(emacs-w32_27.1_20200901.patch.xz)。
  2020/09/20 : 文章微改版。
  2020/10/25 : リンク修正。
  2021/03/28 : Emacs-27.2ベースに変更。その他更新。
  2021/04/02 : 文章微修正。
  2021/10/03 : Emacs-27.2向けパッチの更新(emacs-w32_27.2_20211003.patch.xz)。
  2021/11/06 : 文章修正。delete-trailing-whitespaceのトグル設定で使用するfind関数をcl-find関数に修正しました。
  2022/04/17 : Emacs-28.1ベースに変更。その他更新。
  2022/09/17 : Emacs-28.2ベースに変更。その他更新。
  2022/09/29 : 微改版(リンクURLの変更)。
  2022/12/09 : Emacs-28.2向けパッチの更新(emacs-w32_28.2_20221209.patch.xz)。
  2022/12/24 : 文章微改版
  2023/08/05 : Emacs-29.1ベースに変更。その他更新。
  2023/09/09 : Emacs-29.1向けパッチの更新(emacs-w32_29.1_20230909.patch.xz)。
  2023/10/06 : 文章微改版
  2024/02/03 : Emacs-29.2ベースに変更。その他更新。

TOP PREV

著者: TANE

Emacs 29.2 (Org mode 9.7-pre)