キーボードマクロ

概要

Keyboard macros are a powerful Emacs feature. キーボードマクロは Emacs の力強い特徴です。キーボードマクロ は単にキーシーケンスを 記録する だけのものです。キーシーケンス とは、打鍵したキーの並びと、Emacs のコマンドに結びついたマウスでの操作、メニューの操作のことです。なので、キーボードマクロは Emacs のコマンドを実行する ユーザ操作のシーケンス(並び・連なり) ということになります。

“キーボード” マクロがほとんどのユーザ操作を記録できるということが分かっていただけたでしょうか。 — 単に キーボード の操作 だけではない ということが。よろしいですね。

注意:キーボードマクロについての説明を Lisp マクロとは混同しないでください。Lisp マクロは Lisp 関数に似ていて(それほどではないですが)、defmacro を用いて定義されます。

これがキーボードマクロを 定義 するやり方です:

そして定義したキーボードマクロを 実行する やり方は:

これがマクロを 37 回実行する方法です (37 を与えるために ‘C-u’ を使います):

例:

ファイルの中の すべて の行の最後に “--- foobar 参上” とテキストを追加したいとしましょう。

  1. 1 行目のはじめに テキストカーソル / TextCursor を移動します。
  2. C-x (’ で、キーボードマクロの記録を開始します。
  3. C-e’ (あるいは ‘M-x end-of-line’) で 1 行目の最後にカーソルを移動します。
  4. --- foobar 参上”と入力します。
  5. C-a’ (あるいは ‘M-x beginning-of-line’) で、1 行目の初めにカーソルを移動します。
  6. C-n’ (あるいは ‘M-x next-line’) で、2 行目の初めにカーソルを移動します。
  7. C-x )’ で、キーボードマクロの記録を止めます。
  8. C-u 0 C-x e’ で、ファイルの終わりに達するまで、マクロを無限回数実行します。 (無限回数については、無限引数 / InfiniteArgument を参照のこと)。

ここで重要なのは、スタートしたのと似た位置まで、マクロを定義するということです。 — そうすれば、そのマクロを実行した後、もう一度実行できる場所にいることになります。これはキーボードマクロを定義する際に従うべき一般的なルールです。マクロを連続で N 回実行できるように作ってみましょう。

この一般的なルールに慣れたほうがいいのですが、実は、リージョンの各々の行に対して、直前のキーボードマクロを適用するショートカットが存在します。

あるいはもっと正確を期すなら (コマンドのドキュメントを引用すると):

  ポイントとマークの間の行について、行の最初に戻って、直前のキーボードマクロを走らせます。

最後に定義したキーボードマクロに名前を付けることができ、そうすれば名前で実行することができます:

なぜそうするのでしょう。1 つの理由は、同じ時に 1 つ以上のマクロを定義できるようにするためです。この直前のマクロに my-macro のように名前を付けたなら、また別のことをするマクロを定義します。そのようにすれば、2 番目のマクロを ‘C-x e’ で実行することができ、まるで Emacs コマンドのように my-macro を ‘M-x my-macro’ で実行することができます。もし 2 番目のマクロにも名前を付けたなら、今度は 3 番目を定義することができます…。

キーボードマクロは、今の Emacs セッション にしか定義されません。次以降のセッションで再利用できるようにしたければ、それを自分の初期化ファイル (.emacs_emacs) に保存してください。そのファイルを開いたら、次のコマンドで、マクロ定義を挿入するのです。

いまや、次以降のセッションでも、名前付きキーボードマクロが、まるで標準の Emacs コマンドのように、 ‘M-x’ で実行できるようになりました。それをキーに割り付けたければ、初期化ファイルに次のようなコードを加えることです。

    (global-set-key (kbd "C-c a") 'my-macro)

これにより、キーの並び ‘C-c a’ がマクロ my-macro に割り付けられます。

次の資料も役立ちます:

Isearch 問題 

Isearch はマクロを記録する際に、重要な要素となります。バッファの中のある場所を検索し、コマンドを実行するといったことを、マクロは正確に繰り返すことができます。不運にも Isearch を使用し、次々にサーチを実行して場所を移動するマクロは、次に検索にヒットした文字列をスキップしてしまうという振舞いをし、そして ‘isearch-mode’ に留まるのではなしに、モードから出てしまいます。これはバグとして、[1] に報告されているのですが、不運にもバグではないとのことです[2]

訳注:リンク先でのやりとりを要約すると、Emacs21 以上のバージョンで (global-set-key [?\C-.] “\C-s\C-w”) を評価した後、’C-s C-w’(現在カーソルのある単語を検索する) の振舞いと ‘C-.’ の振舞いが違うということが、バグではないかと報告されました。Emacs20ではこの違いは見られなかったというのがその根拠となっています。バグではないという答えの主旨は、マクロの中では isearch が終わったら、isearch を出るような仕様に Emacs21 では変更された、とのことです。代替案も掲載されていrます。

Emacs Lisp からキーボードマクロを呼ぶ

name-last-kbd-macro を使うとき、キーボードマクロを定義する文字列は、あなたが与えたそのマクロ名での関数定義となります。 そういったマクロを Emacs lisp の中では、関数のように名前で呼び出すことはできません。 例えば、キーボードマクロを “foo” と名付けたなら、Lisp のなかでそのマクロを実行するために、ただ (foo) と書くわけには行かないのです。その代わりに、このように execute-kbd-macro を使わなければなりません。

    (execute-kbd-macro (symbol-function 'foo))

(symbol-function 関数はそのシンボル引数の関数定義を返します。この場合、foo キーボードマクロを定義した文字列を返します。)

キーボードマクロ実行中にユーザに問い合わせること

キーボードマクロ実行中のある時点で Emacs を一時停止し、ユーザに問い合わせをするために、’C-x q’ (kbd-macro-query コマンド) があります。

C-x q は kbd-macro-query コマンドを実行します。

  それは 'macros.el' の中にあり、自動ロードされる対話型の Lisp 関数です。
[引数リストは関数定義がロードされるまでは無効です。]

キーボードマクロの実行中にユーザに問い合わせを行ないます。
  前置引数により、再帰的編集に入り、キーボードマクロの中であってもキーボードコマンドを読むことができます。ユーザーはマクロの実行のたびに違うコマンドを与えることもできます。
  前置引数がなければ、マクロの実行を続けるかどうかを尋ねることができます。
オプションは:
Y       今回の繰り返しを通常通り終了し、次の繰り返しへと続ける。
N       今回の繰り返しの残りをスキップし、次の繰り返しを始める。
RET     マクロを完全に今止める。
C-l     画面を再描画し、再度、尋ねる。
C-r     再帰的編集に入り、そこから出たときに再度尋ねる。

キーボードマクロ実行中にプロンプトを表示する

マクロ実行のたびに入力プロンプトを ミニバッファ / MiniBuffer に表示するために、次のコードを使用できます。

(次の関数定義を評価した上で、)キーボードマクロ定義の途中で ‘C-x Q’ を押すと、ミニバッファにプロンプトが出ます (再帰的編集を使用しています)。何かテキストを入力して、RET を押すと再帰的編集が終わり、マクロの定義がミニバッファで続けられます。再度、RET を押すと入力したテキストがそのポイントに挿入されます。もしそのテキストをすぐに挿入したくなければ、入力をキルする(’C-a C-k RET’)ことができます。そしてそれはマクロ定義の後のほうで使うことができます。

    (defun my-macro-query (arg)
      "Prompt for input using minibuffer during kbd macro execution.
    With prefix argument, allows you to select what prompt string to use.
    If the input is non-empty, it is inserted at point."
      (interactive "P")
      (let* ((query (lambda () (kbd-macro-query t)))
             (prompt (if arg (read-from-minibuffer "PROMPT: ") "Input: "))
             (input (unwind-protect
                        (progn
                          (add-hook 'minibuffer-setup-hook query)
                          (read-from-minibuffer prompt))
                      (remove-hook 'minibuffer-setup-hook query))))
        (unless (string= "" input) (insert input))))
    (global-set-key "\C-xQ" 'my-macro-query)

Emacs 22 では、より短い定義ができます:

      (let* ((prompt (if arg (read-from-minibuffer "PROMPT: ") "Input: "))
             (input (minibuffer-with-setup-hook (lambda () (kbd-macro-query t))
                      (read-from-minibuffer prompt))))
        (unless (string= "" input) (insert input)))

ワンキー・マクロ

コードをファンクションキーに割り付けたくなるかも知れません。このように:

    (global-set-key '[(f1)]          'call-last-kbd-macro)
    (global-set-key '[(shift f1)]    'toggle-kbd-macro-recording-on)

元々のキー割付けを使用するより、ずっと速いです。

トグルする関数:

    (defun toggle-kbd-macro-recording-on ()
      "One-key keyboard macros: turn recording on."
      (interactive)
      (define-key
        global-map
        (events-to-keys (this-command-keys) t)
        'toggle-kbd-macro-recording-off)
      (start-kbd-macro nil))
    (defun toggle-kbd-macro-recording-off ()
      "One-key keyboard macros: turn recording off."
      (interactive)
      (define-key
        global-map
        (events-to-keys (this-command-keys) t)
        'toggle-kbd-macro-recording-on)
      (end-kbd-macro))

GnuEmacs の一部

;;; kmacro.el — 拡張したキーボードマクロ
;;; edmacro.el — キーボードマクロ・エディタ

外部パッケージ

kmacro パッケージが、使用中の Emacs セッションで定義され、名前付けされたキーボードマクロを扱うために、素晴らしいサポート機能を用意していますが、保存したり、組織化したり、再ロードしたりといった面は少し弱点として残っています。こういった仕事に当たっては、 Emacros パッケージが便利です。

キーボードマクロ・タイマー

キーボードマクロ・タイマー / KeyboardMacroTimer を参照してください。


カテゴリ・キー カテゴリ・用語集