2011年7月3日日曜日

Emacsのコマンド2

1つのキーストロークに複数コマンドを割り当ててみる試みその2。

変数の真偽に応じて2種類のうちどちらかの動作をするコマンドを作成しました。

(require 'cl)
(defvar *toggle-command-flag* nil)

(defun toggle-command-flag ()
(interactive)
(setf *toggle-command-flag*
(not *toggle-command-flag*)))

(defun parse-body (body)
(let (fst scd rest)
(setf fst (car body)
scd (cadr body)
rest (cddr body))
(unless (stringp fst)
(when scd (push scd rest))
(setf scd fst)
(setf fst nil))
(unless (and (listp scd)
(eq (car scd) 'interactive))
(when scd (push scd rest))
(setf scd nil))
(list fst scd rest)))

(defun parse-toggle-command-form (form)
(when (or (<= (length form) 0)
(<= 3 (length form)))
(error "invalid toggle-command form"))
(list (first form) (second form)))

(defmacro define-toggle-command (name args &rest body)
(destructuring-bind (doc interactive form)
(parse-body body)
(destructuring-bind (then else)
(parse-toggle-command-form form)
`(defun ,name ,args
,@(when doc (list doc))
,@(when interactive (list interactive))
(if *toggle-command-flag*
,then
,else)))))

;; コマンド定義
(define-toggle-command toggle-ctrl-l-cmd ()
(interactive)
(call-interactively 'goto-line)
(call-interactively 'recenter-top-bottom))

(global-set-key (kbd "C-l") 'toggle-ctrl-l-cmd)

toggle-ctrl-l-cmdは、変数が偽の時はrecenter-top-bottomコマンドを、真の時は goto-lineコマンドを呼び出します。