=============================================== 1999.6.28 発行 =========
         極私的 Emacs カスタマイズ紹介マガヂン
            Emacs をわたし色に染めて♪
------------------------------------------------------------------------
    第 5 回 便利なマクロ (1) yank の「正常」化とタブ幅【前編】
------------------------------------------------------------------------
※あなたのカスタマイズをぜひ教えてください。一般的なものから、他の人は
 絶対にしないような「外道」なものまで、何でも結構です。

※解除の方法は、このメールの末尾をごらんください。
========================================================================

	こんにちは。でるもんた・いいじま です。
	先週はお休みをいただいて申し訳ありませんでした。

	で、今週は 1 週間ゆっくりとかけて、たまっている原稿(このマガジン
	や、学内むけの FAQ など)を片付ける予定だったのですが、なんと
	ゼミ発表の順番が予定より早く廻ってきたり、実験室で飼っている
	ラットが言うことをきかなかったりして、今週も忙しくなりそうです。

	そのせいで、今回の分量も少ないのですが、内容を薄くしたくは
	ないので、ペースを少し落としていこうと思います。

	というわけで、今回だけでやる予定だった「便利なマクロ(1)」は、
	今回と次回の 2 回に分けてお送りします。

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
☆目次☆

	◇本日のお題
	◇まずはキーマクロから
	◇.emacs に書く - 新しいコマンドをつくる
	◇便利なマクロ 1-1: yank の「正常」化

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

☆本日のお題☆

	今回は、いよいよ「マクロ」です。

	Emacs のマクロの強さには定評があり、ファイラー(dired モード)
	やメールリーダーなども Emacs のマクロで実現されています。
		#もっとも、こういった高度なことは外部のプログラムの
		#力を借りなければなかなか実現できないのですが。

	ということで、この便利なマクロ機能を利用しよう、というのが
	今回の狙いです。

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
☆まずはキーマクロから☆

	まず簡単なのが、キー操作を記録して、それを簡単なキーで再現する
	「キーボードマクロ」でしょう。

	たとえば、各行の行頭に「> 」の 2 文字を挿入したいとします。
	このときは、
		○カーソルを行頭に持ってくる
		○「> 」の 2 文字を入力する
		○カーソルを次の行に送る
	という作業を繰り返すことになります。

	これをいちいち入力するのは面倒なので、この操作を覚えさせて、
	簡単なキーで一気に処理できるようにしたいものです。

	【補足】もちろん、これは置換機能を使って「"^J" を "^J> " に
		置換する」(^J は C-j のことで、キー入力する場合は、
		Emacs 標準なら C-q C-j、飯嶋式 VZ 化なら C-p C-j と
		します)あるいは、正規表現の置換機能を使って「"^" を
		"> " に置換する」でもできます。また、マウスが使える
		環境ならば、ひたすら中クリックという方法もあります。

				☆

	そこで、次のように操作してみてください。

		Emacs 標準キー操作の場合
			C-x (       C-a    > SPC   C-n   C-x )
		飯嶋式の場合
			M-o C-x (   C-a    > SPC   C-x   M-o C-x )

	この、
		「C-x (」が「これからキー操作記録開始」
		「C-x )」が「キー操作記録終了」
	の意味です。飯嶋式の場合はいずれの前にも M-o がついていますが、
	これは第 4 回で説明した理由の通りです。

	そうしてから C-x e(飯嶋式の場合は M-o も忘れずに)としてみると、
	さっき入力した内容が再現されているということがわかると思います。
	これで何度でも入力ができます。

	もっとも、M-o C-x e という 3 ストロークが簡単かどうかは疑問です
	が(^^;)、この対策は次回にまわすことにします。

	次回には、
		○C-x ( と C-x ) を両方とも C-_ に割り当てる
		○C-x e を C-\ か何かに割り当てる
	ということをしたいと思います。

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
☆.emacs に書く - 新しいコマンドをつくる☆

	さて、ではそれを何度も使うので、.emacs に保存しておきましょう…
	ということになると、ちょっと話が複雑になります。

	この場合は、キーマクロとはちょっと違ったアプローチをとることに
	なります。すなわち、「新しいコマンドをつくってしまう」のです。

	新しいコマンドをつくるには、.emacs に
		(defun コマンド名 ()
			(interactive)
			ここに、実行したい操作を
			(コマンド名) の形で並べて書く
		)
	と書きます。コマンド名のあとの () (interactive) については、
	ちょっと複雑になるので次回にまわします。

	この場合は、新しくつくるコマンド名を仮に insert-quotation と
	しましょう。

	カーソル移動の部分については、M-x beginning-of-line などとして
	みればカーソルが動くことがわかりますし、第 4 回で
		(global-set-key "\C-x" 'next-line)
	のようにしましたから、.emacs ではコマンド名を括弧でくくって
	(beginning-of-line)、(next-line) とすればいいことがわかります。

	問題は文字入力の場合です。これはさすがに (>) や ( ) のように
	書くわけにはいきません(いずれも別の意味になります)ので、
		(insert "> ")
	という書き方にする必要があります。

	というわけで、できあがりは次のようになります。

		(defun insert-quotation ()
			(interactive)
			(beginning-of-line)
			(insert "> ")
			(next-line)
		)
	と書くことになります。

	こうしてやると、M-x insert-quotation RET で、「行頭に "> " を
	挿入」をしてくれます。必要ならば、global-set-key を使って
	これを別のキーに割り当ててやるといいでしょう。

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
☆便利なマクロ 1-1: yank の「正常」化☆

	さて、今回ご紹介するのは、yank の「正常」化です。

	第 4 回で VZ 化した人は、C-j の挙動が何か変だ、とお気づきに
	なったと思います。つまり、C-j は本来ならば
		○削除したものをペーストする
		○次に C-j を押したら、その前に削除したものが出てくる
	という仕様になっているべきですが、C-k c と同じく、なんど押しても
	最後に削除したものだけが出てきます。

	ということで、次のようなマクロを組んでみました。

		(defun my-yank ()
			"kill-ring から要素を取りだしてペーストし、
			次のペーストではその前のものが出るようにします。"
			(interactive)
			(yank)
			(rotate-yank-pointer 1)
		)

		(global-set-key "\C-j" 'my-yank)

	このように、() と (interactive) の間には、"" でくくってコマンドの
	説明を入れておくことができます。この説明は、apropos(第 4 回の
	ワンポイント参照)などで見ることができます。

	さて、プログラムの中では、まず (yank) で、ペーストをして
	います。これについては説明は要らないと思います。

	ついで、rotate-yank-pointer という関数を使っています。
	これを理解するには、Emacs で「削除」をしたときにそのデータが
	どのように保存されているのかを理解する必要があります。

	じつはこれについては私もよく分かっていない(^^;)ので、
	おおざっぱな概念だけを説明したいと思います。

				☆

	Emacs では、文章を「削除(kill)」したときには、kill-ring
	という場所に一時的に保存されます。たとえば、3 つの文章を
	削除したときの kill-ring の内容は次のようになります。

		+----- kill-ring -----+
		|3 度目に削除した内容 |←yank pointer
		|2 度目に削除した内容 |
		|1 度目に削除した内容 |
		+---------------------+

	ここで重要なのが yank pointer というもので、yank コマンドで
	ペーストしたときには、yank pointer が指している位置のものが
	ペーストされます。ところが、(yank) しても、kill-ring の内容も
	変化しなければ yank pointer も動かないので、次の (yank) では
	同じものが出てくることになります。そこで、自分の手で yank
	pointer を動かしてやります。これが rotate-yank-pointer です。

	rotate-yank-pointer すると、kill-ring の内容は次のようになります。

		+----- kill-ring -----+
		|3 度目に削除した内容 |
		|2 度目に削除した内容 |←yank pointer
		|1 度目に削除した内容 |
		+---------------------+
	そこで、もういちど (yank) すると、「2 度目に削除した内容」が
	ペーストされることになります。

				☆

	なお、どうやら、yank pointer を動かしたあとで kill すると、

		+----- kill-ring -----+
		|5 度目に削除した内容 |←yank pointer
		|4 度目に削除した内容 |
		|3 度目に削除した内容 |
		|2 度目に削除した内容 |
		|1 度目に削除した内容 |
		+---------------------+

	といった具合になってしまいます。つまり、kill すると yank pointer は
	先頭に戻ってしまいます。したがって、この状態から my-yank を 2 回
	行えば、望み通り「4/5 度目に削除した内容」がペーストされますが、
	さらにもういちど my-yank すると、余計な「3 度目に削除した内容」が
	出てきてしまいます。

	私は、これについては実害がないので放置してあります。実害がない
	というより、今日この原稿を書くまで、そういう仕様だということに
	気づかなかったのです(^^;)

	【解説】Emacs の「文字削除」には、kill と delete の 2 種類があり
		ます。kill した場合は kill-ring に保存され、yank コマンド
		でペーストできるのに対し、delete すると、どこにも保存
		されずに消えてしまいます。たとえば、delete-char で
		削除した文字は、undo で戻すことはできますが、それ以外、
		たとえば C-y などで戻すことはできません。
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
☆後日注 - 完全解決☆

	上記のような問題点は完全に解決しました。

		(defun my-yank ()
		        "kill-ring から要素を取りだしてペーストし、
			次のペーストではその前のものが出るようにします。"
		        (interactive)
		        (save-excursion (insert (car kill-ring)))
		        (setq kill-ring (cdr kill-ring))
		)

	としてください。解説は後日。

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
☆今週のワンポイント☆

	今週のワンポイントは、eval-??? コマンドです。

	(defun ...) などを .emacs に書くと、通常は Emacs を再起動しな
	ければその結果は有効になりません。ところが、デバッグをしている
	ときには、わざわざそんなことをしていては面倒です。

	そこで、(defun ...) の部分を範囲指定して、
		M-x eval-region RET
	とすると、その部分(範囲指定された部分)がその時点で評価されます。
	デバッグの場合、あるいは、M-x ではできない設定を一時的にしたい
	場合には、この方法は非常に便利です。

	なお、この eval-region の他に、バッファ全体を評価する eval-buffer、
	その場でコマンドを入力する eval-expression があります。

	【補足】eval-expression は初期状態では「使用禁止」になっている
		ので、実行すると「使用禁止を解除するか?」と訊かれます。
		よく使うようならば、.emacs に
			(put 'eval-expression 'disabled nil)
		と書いておくといいでしょう。

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
☆次回予告☆

	次回は、「便利なマクロ(1)」の後編です。主として
		○引数をとるマクロ
		○if、while などの構造を使ったマクロ
		○M-x では呼び出せない下請けサブルーチン
	などの話題を取りあげたいと思います。そのほかに、実例として、
		○C-x ( と C-x ) を両方とも C-_ に割り当てる
		○タブ幅を設定する
	というマクロを紹介します。

	それでは、また来週…だといいですね♪

========================================================================
極私的 Emacs カスタマイズ紹介マガジン Emacs をわたし色に染めて♪

☆発行人☆

        でるもんた・いいじま <L94102@komaba.ecc.u-tokyo.ac.jp>
			http://user.ecc.u-tokyo.ac.jp/~l94102/emacs/

                ※このメールマガジンで取り上げてほしいテーマ、ご意見など
                 ありましたら、上のメールアドレスまでお気軽にどうぞ。

☆配信☆
        このメールマガジンは、「インターネットの本屋さん・まぐまぐ」を
        利用して配信しています。
                http://www.mag2.com     (マガジン ID=0000013484)

☆バックナンバー・登録解除・メールアドレス変更は☆

	上記のホームページまでどうぞ。
	なお、手動での登録解除は行っておりませんのでご了承下さい。
=========================================================================

Copyright © IIJIMA Hiromitsu aka Delmonta, 2016/03/10 15:09 JST
これは「古文書」です。 古くなった情報も原則未修正で保存していますのでご注意ください。

古文書本館トップ | 電脳外道学会