メニューをカスタマイズする関数には、次のようなものがあります。
create-menu | 新たに作成した空のメニューを返します。 |
create-popup-menu | 新たに作成したポップアップメニューを返します。 |
define-menu | 固定的なメニューを定義します。 |
define-popup-menu | 固定的なポップアップメニューを定義します。 |
delete-menu | メニューから項目等を削除します。 |
add-menu-item | 新たに作成したメニュー項目をメニューの末尾に追加します。 |
add-menu-separator | セパレータをメニューの末尾に追加します。 |
add-popup-menu | ポップアップメニューをメニューの末尾に追加します。 |
insert-menu-item | メニュー項目を作成しメニューの所定の位置に挿入します。 |
insert-menu-separator | セパレータをメニューの所定の位置に挿入します。 |
insert-popup-menu | ポップアップメニューをメニューの所定の位置に挿入します。 |
set-menu | 指定されたメニューをデフォルトのメニューにします。 |
use-local-menu | カレントバッファにローカルなメニューを設定します。 |
get-menu | 指定されたメニューから、タグ名または位置で検索したメニューを取得します。 |
get-menu-position | メニューの中からタグの位置を検索して返します。 |
track-popup-menu | フローティングポップアップメニューを表示します。 |
詳細は、リンク先のリファレンスを参照下さい。
xyzzy の標準で提供されているメニューには、次のようなものがあります。 (app-menu.l より。)
*app-menu* | 標準ツールバーに表示されるメニュー |
*app-popup-menu* | マウスの右クリックメニュー |
*app-rectangle-popup-menu* | 矩形処理用メニュー |
*dictionary-popup-menu* | 辞書引き用メニュー |
*paste-rectangle-popup-menu* | 矩形貼り付け用メニュー |
カスタマイズして使用しそうなのは、*app-menu*, *app-popup-menu* あたりと思います。
xyzzy 標準のメニューをカスタマイズする場合は、 *init-app-menus-hook* を使って処理を実行します。以下例では、 *app-popup-menu* に「文字変換」を追加します。
(add-hook '*init-app-menus-hook* #'(lambda() (insert-popup-menu *app-popup-menu* 0 (define-popup-menu (:item nil "小文字に変換(&D)" 'downcase-selection :modify-any-selection) (:item nil "大文字に変換(&U)" 'upcase-selection :modify-any-selection)) "文字変換(&M)")))
あるメニューをそのメニュー単体で呼び出したり、他のメニューに追加したりと、 複数の箇所で使用することがある場合は、変数にメニュー定義を格納しておくと便利です。
例えば、次のようなメニューを定義した場合、
(setq *my-menu* (define-popup-menu (:item nil "apropos(&A)" 'apropos) (:item nil "describe-key(&D)" 'describe-key) :sep (:item nil "list-function(&L)" 'list-function) ))
以下のような設定により、C-x F1 でフローティングポップアップメニューを表示させることができます。
(global-set-key '(#\C-x #\F1) #'(lambda () (interactive) (track-popup-menu *my-menu*)))
また、以下のような設定により、標準メニューの「ツール(T)」の先頭部分にメニューを追加することができます。
(add-hook '*init-app-menus-hook* #'(lambda () (let ((tools (get-menu *app-menu* 'ed::tools))) (insert-popup-menu tools 0 *my-menu* "自家用(&I)") (insert-menu-separator tools 1) )))
動的にメニューを作成する関数などでは、その関数の中でメニューを作成したほうが良いかもしれません。 以下の例では、全てのバッファをポップアップリストで表示します。 現在選択されているバッファには、チェックが入ります。
(defun popup-buffer-list () (interactive) (let ((menu (create-popup-menu nil))) (dolist (buffer (buffer-list)) (let ((item (buffer-name buffer))) (add-menu-item menu nil item #'(lambda () (interactive) (switch-to-buffer item)) #'(lambda () (when (string= item (buffer-name (selected-buffer))) :check))))) (track-popup-menu menu)))
「ウィンドウ(W)」の前に「私の(M)」メニューを追加する。
(add-hook '*init-app-menus-hook* #'(lambda () (insert-popup-menu *app-menu* (get-menu-position *app-menu* 'ed::window) (define-popup-menu (:item nil "名前1(&A)..." '実行する関数1) :sep (:popup nil "グループ1(&B)" (:item nil "名前2(&C)" '実行する関数2) )) "私の(&M)")))
これは、私の使っているメニュー「亀入(K)」の一部です。
→ my-kamenu
ファイル名 my-kamenu.l で、site-lisp フォルダに保存し、
初期化ファイルからロードして使っています。山本 泰三さんの
favorite.l を参考にさせて頂きました。
(require "my-kamenu")
こんな感じ。
(add-hook '*init-app-menus-hook* #'(lambda () (let ((menu *buffer-bar-context-menu*)) (add-menu-separator menu nil) (add-menu-item menu nil "名前1(&A)" '実行する関数1) (add-menu-item menu nil "名前2(&B)" '実行する関数2) )))
これは、私の使っているメニューです。*buffer-bar-context-menu* を書き換えてしまっています。
→ my-buffer-bar-context-menu
ここでは、以下の事をしてます。
ファイル名 my-buffer-bar-context-menu.l で、site-lisp フォルダに保存し、 初期化ファイルからロードして使ってます。
(require "my-buffer-bar-context-menu")
favorite.l のメニューを C-x F2 でポップアップで表示します。
(global-set-key '(#\C-x #\F2) #'(lambda () (interactive) (track-popup-menu (get-menu *app-menu* (1- (get-menu-position *app-menu* *favorites-menu-position*)) t))))
M-x toggle-app-menu で、標準ツールバーをトグルします。 [xyzzy:02412](亀井さん)より。 (こんな使い方でいいのかな?)
(add-hook '*init-app-menus-hook* #'(lambda () (let ((toggle-app-menu *app-menu*)) (defun toggle-app-menu () (interactive) (set-menu (setq toggle-app-menu (unless toggle-app-menu *app-menu*)))))))
標準メニューを消す場合は、こんなことをしておくといいかも。 M-Apps で標準メニューをポップアップ表示します。
(defun popup-app-menu () (interactive) (let ((menu (copy-menu-items *app-menu* (create-popup-menu)))) (track-popup-menu menu))) (global-set-key #\M-Apps 'popup-app-menu)