=============================================== 1999.10.4 発行 =========
         極私的 Emacs カスタマイズ紹介マガヂン
            Emacs をわたし色に染めて♪
------------------------------------------------------------------------
         第 13 回 メニューバーとλ、ホック
------------------------------------------------------------------------
※あなたのカスタマイズをぜひ教えてください。一般的なものから、他の人は
 絶対にしないような「外道」なものまで、何でも結構です。

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

	こんにちは。でるもんた・いいじまです。

	気が付いたら前回発行からもう 3 週間も空いてしまいました。
	たびたび遅れてしまって申し訳ありません。

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

☆今回のお題☆

	今回は予定を変更して、「メニューバーに項目を追加する」です。
	それに関連して、非常に重要な(と思う)「ラムダ関数」と、
	ラムダ関数が頻繁に使われる事例として「ホック」を紹介します。

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
☆メニューバーに追加する (1) 既存のメニューに追加する☆

	まずは簡単な例からいきましょう。

	メニューバーの Help の項目には、Emacs Tutorial(M-x help-with-
	tutorial;標準では C-h t;飯嶋式では M-h t)というものがあります。
	これは英語版のチュートリアルです。

	ところが、じつは日本語対応のものがあります。M-x help-with-tutorial-
	for-mule、C-h T(大文字の T;飯嶋式では M-h T)です。
	前回は Language: のところで Korean と入力しましたが、
	ここで Japanese と入力すれば、とうぜん日本語のものが出てきます。
	あるのなら常時使えるようにしておきたいものです。

	さて、この設定は簡単です。~/.emacs にひとこと書き加えるだけです。

		(define-key menu-bar-help-menu [tutorial-for-mule]
		    '("Tutorial for Mule" . help-with-tutorial-for-mule)
		)

	ご覧の通り、第 11 回で扱った「ファンクションキーの設定」と
	そっくりです。唯一の違いは、最後の引数が単なる「'コマンド名」の
	形ではなく「'("説明文" . コマンド名)」になっていることです。

	【補足】(1)大括弧の中の tutorial-for-mule という言葉は、かわりに
		   何を入れてもかまいません。ただし、すでにメニューで
		   使われている名前とは重ならないようにしてください。
		   重なったときの挙動は後述します。
		(2)括弧の中のふたつの項目の間には、ピリオドが入っています。
		   これを忘れないようにしてください。
		(3)コマンド名「help-with-tutorial-for-mule」の前には、
		   アポストロフィはつけません。これは、すでにその外側の
		   括弧の前につけてあるからです。どうしてもコマンド名の
		   直前にアポストロフィをつけたい場合は、
			(cons "説明文" 'コマンド名)
		   という書き方をしてください。また、「'コマンド名」の
		   かわりにキーマップ名を書く場合(後述)はアポストロフィ
		   をつけてはいけないので、この場合も
			(cons "説明文" キーマップ名)
		   とします。なお、cons を使う場合は、ふたつの項目の間
		   にはピリオドはいれません。

	なお、このように define-key を使った場合には、追加した項目が
	Help メニューの先頭に来てしまい、いささか格好が悪くなります。
	新しく追加する「Tutorial for Mule」が、既存の「Emacs Tutorial」の
	直後に来るようにすると格好が良くなります。このためには、define-
	key ではなく define-key-after を使います。

		(define-key-after menu-bar-help-menu [tutorial-for-mule]
		    '("Tutorial for Mule" . help-with-tutorial-for-mule)
		    'emacs-tutorial
		)

	こうすると、Emacs Tutorial の直後に Tutorial for Mule が追加され
	ます。

	【補足】この emacs-tutorial という名前は、メニューに Emacs Tutorial
		の項目が追加されるときに、[emacs-tutorial] という形で使われ
		ていたものです。

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
☆自分で新しいメニューを追加する☆

	上で説明したのは、既存のメニュー(Help や Tools など)に追加する
	場合でした。次は、メニューバーに新しいものを追加する場合です。

	いままでに、いくつかのマクロを紹介してきました。
	それを追加するためのメニューを作りましょう。
	さらに、それだけではなく、「便利なのに、メニューバーには
	入っていないコマンド」を入れてあげましょう。

	メニューの名前は、仮に Delmonta としておきましょう。

	さて、メニューを追加するのがキーを追加するのとほぼ同様だ、
	ということは、上のことでわかっていただけたと思います。
	ですから、新しく作る場合もキーの場合とほぼ同様の手順を踏みます。

◇キーマップ

	まずはキーマップを作ります。マップの名前は慣習に従って
	menu-bar-delmonta-menu としておきましょう。

		(setq menu-bar-delmonta-menu (make-sparse-keymap "Delmonta"))

	キーの場合は make-sparse-keymap には引数はありませんでしたが、
	メニューの場合には、引数としてメニューの表題を与えます。

◇バーに追加

	つぎに、メニューバーに追加します。

		(global-set-key [menu-bar delmonta]
			(cons "Delmonta" menu-bar-delmonta-menu))
		(setq menu-bar-final-items
			(cons 'delmonta menu-bar-final-items))

	これも、キーを追加する場合と大きくは変わりません。なお、define-key
	のあとの setq menu-bar-final-items は、単に global-set-key だけ
	ではメニューのいちばん左側(つまり、Buffers の左)に出てしまって
	格好が悪いからです。

	【後日補足】menu-bar-final-items は XEmacs では使えないようです。
	      私は XEmacs は使っていないのであまり調べていないのですが、
	      XEmacs でも使いたい場合はとりあえず、
	      	(if (boundp 'menu-bar-final-items)
	      		(setq menu-bar-final-items
	      			(cons 'delmonta menu-bar-final-items))
	      	)
	      としておけばいいでしょう。

◇項目を追加

	最後に、できたメニューバーに項目を足します。
	ここは既存のバーに追加する場合と同じです。

	ここでは、「後から追加したものが上に来る」というルールに従い、
	下から逆順に記述していくことにしましょう。

	(define-key menu-bar-delmonta-menu [tabwidth]
		'("Set Tab Width..." . delmonta-set-tab-width)
	)

	(define-key menu-bar-delmonta-menu [linemacro]
		'("Delmonta's Line Macro" . delmonta-line-macro)
	)

	(define-key menu-bar-delmonta-menu [separator1] '("--" . nil))
								;区切り線

	(define-key menu-bar-delmonta-menu [goto-line]
		'("Goto Line..." . goto-line)
	)

	(define-key menu-bar-delmonta-menu [toggle-read-only]
		'("Toggle Read-Only" . toggle-read-only)
	)

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
☆メニュー内容の削除とグレー化・差し換え☆

	さて、いままではメニューに追加してきたわけですが、
	ときにはメニューから消したいときもあります。

	たとえば、Tools メニューの Read Mail という項目には、rmail という
	コマンドが割りあてられていますが、このコマンドは仕様が古く、
	たとえば、日本語を扱うときに、文字化け(普通の文字化けと違って、
	極めて復旧困難です!)などの大きな問題を起こします。

	というわけで、特に素人さんに使わせる場合は、できればこの機能を
	使えないようにしたい、あるいは他のメーラーを使わせたい、と考える
	ことでしょう。そういう場合に、いくつかの方法があります。

◇下準備

	まず設定の前に、Read Mail という項目が、何という名前で登録されて
	いるのか調べておきましょう。

		% grep 'Read Mail' /usr/local/share/emacs/19.34/lisp/*.el

	そうすると、menu-bar.el に

		(define-key menu-bar-tools-menu [rmail] '("Read Mail" . rmail))

	という記述があることがわかります。以下、この [rmail] という
	名前を使って、いろいろな設定をしていきます。

	【補足】逆にいうと、新しく項目を追加する場合に、すでにあるものと
		同じ名前を使ってしまうと、すでにあるもののほうに悪影響が
		あるということになります。

◇メニューから消す

	まず簡単な方法としては、Read Mail の項目をメニューから削って
	しまう、ということが考えられます。これは簡単で、
		(define-key menu-bar-tools-menu [rmail] nil)
	とすれば OK です。

◇グレー化する

	あるいは、あえてそのまま残しておきながら、色をグレーにして、
	選択できないようにする方法もあります。

		(put 'rmail 'menu-enable '(not t))

	最初の引数は、Read Mail で呼び出される rmail というコマンド名です。
	ここではたまたま [] の中の rmail と一致していますが、一致して
	いない場合、たとえば元の定義が

		(define-key menu-bar-tools-menu [read-mail]
			'("Read Mail" . rmail)
		)

	だった場合は、read-mail ではなく rmail のほうを使います。

	次の引数はかならず 'menu-enable にします。

	最後の引数は「どのような条件のときに選択可能にするか」で、この
	場合は「常に選択不能」にしたいので (not t) すなわち nilにします。
	逆に、ある条件の時だけ選択可能にしたい場合は、この部分を、
		'(eq major-mode 'fundamental-mode)
	のように、式にアポストロフィをつけた形で書きます。

	【注意】この式には、単なる nil は書けないようです。
		仕方がないので、ここでは (not t) としています。

◇Read Mail を MH や Mew に差し換える

	rmail 以外にメーラーがある場合は、それに差し換えてしまうという
	方法もあります。たとえば、次のようにします。

		(define-key menu-bar-tools-menu [rmail]
			'("Read Mail with Mew" . mew)
		)

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
☆引数つきのコマンドを実行するために - ラムダ関数☆

	さて、今まで紹介してきたのは、「引数なしのコマンドを指定する場合」
	でした。では、引数ありのコマンドを指定する場合はどうすればいいの
	でしょうか。たとえば、第 9 回で紹介したカナ入力の場合、カナモード
	とローマ字モードを切り替えるには、its:select-mode という関数に、
	"roma-kana" または "kanainput" という引数を与える必要があります。

	一つの方策としては、そういうコマンドを定義してしまうという方法が
	あります。たとえば次のようにします。

		(defun roma-kana-mode ()
			(interactive)
			(its:select-mode "roma-kana")
		)
		(defun kanainput-mode ()
			(interacrtive)
			(its:select-mode "kanainput")
		)

		(define-key menu-bar-delmonta-menu [roma-kana]
				'("Roma-kana mode" . roma-kana-mode)
		)
		(define-key menu-bar-delmonta-menu [kanainput]
				'("Roma-kana mode" . kanainput-mode)
		)

	ところが実は、このように定義しなくてもよい方法があります。
	「ラムダ関数」という技法です。

	このケースでは、ラムダ関数を使って、つぎのように書けます。

		(define-key menu-bar-delmonta-menu [roma-kana]
			'("Roma-kana mode" .
				(lambda ()
					(interacrtive)
					(its:select-mode "roma-kana")
				)
			)
		)

	ラムダの使い方は、要約すると次のようになります。

		○まず、「関数を定義してから、関数名を指定する」という
		 オーソドックスな方法で書いてみる。
		○次に、「defun 関数名」の部分を lambda に変え、今まで
		 関数名を書いていた部分に (lambda () ...) を埋め込む。
		○アポストロフィの有無は最初のままに残す。

	さて、ラムダ関数は、関数名が書けるところならばだいたいどこにでも
	書けます。たとえば、メニューではなくキーの定義にも使うことが
	できます。簡単な例だと、

		(global-set-key [(shift up)] '(lambda ()
			(interactive)
			(previous-line 3)
		))

	といった使い方ができます。

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
☆おまけ - ホック☆

	さて、ラムダ関数が出てきましたので、おそらくラムダ関数をもっとも
	頻繁に使うであろう、ホックについて紹介しておきます。

	ホック(hook)というのは、「あるコマンドが呼び出されたときには、
	このコマンドを実行してください」という設定のことです。たとえば、

		(add-hook 'dired-mode-hook '(lambda()
		        (define-key dired-mode-map "\C-h" 'kill-buffer)
		))

	のようにすると、dired-mode に入ったときに、

		(define-key dired-mode-map "\C-h" 'kill-buffer)

	が自動的に実行されます。

	【補足】もちろん、add-hook の引数には、ラムダ関数だけではなく、
		名前のついた関数を指定することができます。たとえば、
			(add-hook 'dired-mode-hook 'display-time)
		とすれば、dired-mode になったときに (display-time) が
		自動的に実行されます。

	【注意】add-hook は、一つのホックに対して複数回実行することができ
		ます(それらのコマンドは所定の順序ですべて実行されます)。
		add-hook のかわりに setq を使うと、今までホックに入って
		いたものは消えてしまいますので注意してください。

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

☆次回予告☆

	次回は、「第 14 回 キー操作集大成〜コンソールからファンクション
	キーを使う〜」の予定です。第 11 回でやり残したカーソルキーと
	ファンクションキーの問題、また f10 キーをより ATOK 的にする方法、
	その他の変なキー操作などについてご紹介致します。

	それではまた♪

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

☆発行人☆

        でるもんた・いいじま <L94102@mail.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
これは「古文書」です。 古くなった情報も原則未修正で保存していますのでご注意ください。

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