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)。

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

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

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

[参考1] キー配列 Wikipedia

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

4.3 プロセスサイズ問題

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

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という選択肢が無いのであればともかく、選択可能であるのならばわざわざ 避ける理由は無いかなと思います。
  • 今(2019年時点)もメンテされている。テキストを編集するという用件自体は変わらない 訳ですから、エディタ本体のいじり所なんてそのうち無くなりそうにも思うのですが、 実際そういう訳では無さそうです。 CPUの性能が上がったり使えるメモリ量が増えたりして不可能だった事が可能に なってくると、それに合わせてできる事を増やしていけるものなのでしょう。
  • 色々な人が使っていて自分には普段用事が無いところにもノウハウが蓄積されている。 たまに「こういうのって無いのかな?」と探してみると思った以上に良い ものがあったりします。
  • 意外とシェル環境への応用が利く。例えばbashやtcshの行編集において、 Ctrl-a、Ctrl-e、Ctrl-f、Ctrl-b、Ctrl-k、Ctrl-y、TAB(Ctrl-i) あたりは Emacsのそれと同じ感じなので、Emacsで不自由の無い操作ができるのであれば、 shellのコマンドライン操作も不自由無いと思います。
  • 自分の都合の良いようにカスタマイズできる。やりすぎると 初期設定状態のときに困る事はありますが、そもそもユーザー管理のちゃんと している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-24.4(2014/10/20リリース)にはorg-mode安定版の8.2.10が含まれています。Emacs-24.4リリースを 境にorg-modeのリリース頻度は下がっていましたが、その後も活発に開発継続されているようです。

6.1.3 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 () ""
                                (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例)。 Makefile無しでもチェックできるようにする設定方法もあるようですが、少し大きなプロジェクトに なるとコンパイラにインクルードパスなどのオプションを指定する必要が出てくる為、結局Makefileを 使う方が手間がかかりませんでした。ご参考まで。

6.2.3 psvn

Subversionを操作するラッパー代わりに重宝しています。

6.2.4 magit

gitを操作するラッパー代わりに重宝しています。

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

その後、新しいmagitは拙作window-plusと組み合わせると 操作継続不能な状態に陥る現象があり、新しいmagitへの乗り換えをしばらく見送っていました。 ひとまず原因が判明した(参考)のですが、 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では改造してトラックしているファイルの一覧を出せるようにしていたのですが、 新しいmagitではmagit-status-sections-hookという変数のリストに magit-insert-tracked-files を入れればファイルの一覧を表示できます。

6.2.5 ediff

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

6.2.6 delete-trailing-whitespace

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

(require 'cl)
(defun toggle-delete-trailing-whitespace-setting ()
  (interactive)
  (cond ((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時点) して利用しています。ご参考まで。

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])とでは違いますが) 同じコードでイケてます。

; .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パッチによる日本語入力を行っていると、勝手に確定される 問題がありました。この為、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でコピーできる ようにしました。

(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での開発状況をチェックしてみるのが良いと思います。対応版が 出てる場合があります。ありがたい事です。

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)

2014年4月にCygwinのアップデートを行って以降(2015/4/19現在も)、低い頻度で seconds-to-timeという 関数の中で使用している round関数が「Arithmetic range error: "round", -0.0e+NaN」 でエラー する現象が見られるようになりました。run-with-timer関数によるタイマーイベントに 起因しているようですが原因不明です。Webで検索しても同様の現象に遭遇している例が ほぼ無いという状況です。本エラーが発生するとnyan-catのアニメーションが止まります。 一旦stopして再度startするとまた動きます。

Cygwin 2.3.0-1 にアップデート後、round関数のエラーは発生しなくなりました。恐らく Cygwinかnewlibのバグだったのではと推測されます。

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)か、 ターミナルで使う(いわゆる emacs -nw)しかありませんでした。

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

rzl24ozi氏の作成されたパッチ が IMEパッチのデファクトスタンダードとなっています。 ところが、24.4の時にTANEの環境下でCygwinで野良ビルドして使用していると、IME入力中に 何故かSegmentFaultで落ちる場合があった為、以降自前パッチを使用しています。 もしセカンドソースとしてお役に立つ事があれば幸いです。

Emacs-26.3をベースにしています。過去バージョン向けには Emacs-24.5はこちらを、 Emacs-25.xはこちらを、 Emacs-26.1はこちらを、 Emacs-26.2はこちらを参照してみてください。

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

    xz -dc ~/Downloads/emacs-26.3.tar.xz | tar xf -
    cd emacs-26.3
    xz -dc ~/Downloads/emacs-w32_26.3_20190907.patch.xz | patch -p1
    ./configure --prefix=/usr --with-w32 --without-imagemagick
    make
    
  4. /usr/bin/emacs-w32.exe をビルドしたsrc/emacs.exe で置き換える。 元の実行ファイルは別名で退避しておくのが良いでしょう。
  5. lisp/international/w32-ime.el と lisp/international/w32-ime.elc を/usr/share/emacs/26.3/lisp/international/. にコピーする。
  6. 以下の設定を.emacs(オールドスタイルですみません)に追加する。

    ;;
    ;; IME setup
    ;;
    (set-language-environment "Japanese")
    (if (eq 'w32 (window-system))
        (progn
          (load "international/w32-ime")
          (setq w32-ime-buffer-switch-p nil) ; 全バッファでIME状態同期
          (kill-local-variable 'w32-ime-mode-line-state-indicator)
          (setq default-input-method "W32-IME")
          (setq-default w32-ime-mode-line-state-indicator "[-]")
          (setq w32-ime-mode-line-state-indicator-list '("[-]" "[あ]" "[-]"))
          (w32-ime-initialize)))
    

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

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

  • 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を使用した感じになってます。25.1向けには24.5向けのパッチを元にしています。 また、rzl24ozi氏作成のパッチも一部参考にさせていただいてます。
  • IMEは全バッファで状態同期するモードで使用しています。termモード でバッファ再描画を非同期に行った際、IME制御の構造上の問題で勝手に入力確定される場合が あった為です(参考)。ただ、単純に w32-ime-buffer-switch-pをnilにしただけではインジケータの再描画がうまく対応できていなかった為、 lisp/international/w32-ime.elに少し手を入れています。
  • オリジナルではJPEG画像表示の時に減色されてしまうのですがフルカラー表示に強制しています (参考)。
  • imagemagickパッケージはconfigure実行時に意図的に外しています。 含めてもビルドは完了すると思いますが24.3の時には動作不安定な実行ファイルが できあがりました(参考)。 24.4,24.5,25.x,26.[123] ではpdf-tools との相性が悪かった為 (参考)、 引き続き意図的に外してビルドしています。
  • Cygwinでのビルドしか考えてませんのでconfigure.batはメンテしていません。
  • termモードのターミナルエミュレーション表示が遅い点を改造しています (参考)。
  • 25.1でnyan-modeのような run-with-timer関数を使用したアプリで、time-add関数が 「Specified time is not representable」のメッセージでエラーする場合に対して ワークアラウンドを入れました (参考)。副作用としてtime-add関数の引数に非数(NaN)を 与えた場合(例えば (time-add (/ 0.0 0.0) 1.0) とか)でもエラーにならずに非数を0に変換して 値を返します。
  • C-x C-f のファイル読み込みなどで「*.c」のような正規表現で複数のファイルを読み込もうとしたとき 64個以上のファイルを開こうとするとSegfaultになるのをワークアラウンドしています (参考)。ただし、1024個を超えるとダメかも知れません。 FD_SETSIZEに依存しないような根本的な直し方が必要と思われます。

既知のバグ

  • emacs-w32で起動後、ウインドウをマウスで操作する事無くIMEの切り換えを行ってもIME入力が有効にならない。 マウスでウインドウを移動もしくはリサイズする事でIME切り換え可能になります。 他のアプリにウインドウフォーカスを移した後、再びemacs-w32にウインドウフォーカスを移すだけでは IME入力が有効にはならないようです。

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ベースに変更。微修正。

TOP PREV

著者: TANE

Emacs 26.3 (Org mode 9.1.14)