viの.コマンドみたいなのを作りたい。

なぁと思ったので、試してみることに。2chで見た

 480_   名無しさん@お腹いっぱい。名無しさん@お腹いっぱい。    UXsv/QcH0   2006/11/27(月) 08:39:54
    vimで、
    ice coffee
    hot coffee
    ice tea
    hot tea
    ice milk
    hot milk
    を
    coffee
    tea
    milk
    にする最小の手順を書け
    なおカーソルはice coffeeのiの位置にある(ヒント:7手)

486_   名無しさん@お腹いっぱい。名無しさん@お腹いっぱい。    1mY8KcUE0   2006/11/27(月) 17:11:57
    正解は

    3dwj.j.

    の7手でした

と言うのがあって、面白いなぁと思ったので、xyzzyでもやってみようと。他のコマンドは殆ど置き換え可能だと思うけど「.」が優れている。のでパクろうかと。ちなみにxyzzyで3dwjに対応するのはM-3 M-d C-n。かな?よく分からない。現状では「.」らしきものはあえて書くならM-pかなぁとか思ったけど。ちょっとと言うか。大分違うような気もする。viの.は逆undo見たいな感じに見えた。
Omicron xyzzy/viモード
ここ見てパクろうと思ったけど、なかった。のでEmacsvipper-modeを調べてみることに。
/releases/ASAGAO-2.10/lisp/emulation/vip.el - Meadow - Trac
この辺かなぁと

	(defun vip-repeat (arg)
	  "(ARG)  Re-execute last destructive command.  vip-d-com has the form
	\(COM ARG CH REG), where COM is the command to be re-executed, ARG is the
	argument for COM, CH is a flag for repeat, and REG is optional and if exists
	is the name of the register for COM."
	  (interactive "P")
	  (if (eq last-command 'vip-undo)
	      ;; if the last command was vip-undo, then undo-more
	      (vip-undo-more)
	    ;; otherwise execute the command stored in vip-d-com.  if arg is non-nil
	    ;; its prefix value is used as new prefix value for the command.
	    (let ((m-com (car vip-d-com))
	          (val (vip-P-val arg))
	          (com (car (cdr (cdr vip-d-com))))
	          (reg (nth 3 vip-d-com)))
	      (if (null val) (setq val (car (cdr vip-d-com))))
	      (if (null m-com) (error "No previous command to repeat"))
	      (setq vip-use-register reg)
	      (funcall m-com (cons val com)))))

しかし、当然このままじゃxyzzyでは動かないし、何をやっているのかもよく分からないので、例によって一度適当に自分で試してみることに。

;取り合えず直前のコマンドを実行
(defun repeat-after-me ()
  (interactive)
  (unless (or (eq *last-command* *this-command*)
			  (eq *last-command* 'self-insert-command))
	(funcall *last-command*)
	(setq *this-command* *last-command*)))

 これだと引数を持たないのかも?少し微妙な感じ。キーボードマクロが折角あるので。其れを利用して、start-kbd-macro、end-kbd-macro、call-last-kbd-macro。この辺を適当なキーに割り当てれば言いかなぁと思ってみた。マクロ開始と終了は別のキーにする必要はないので。

(defvar *kbd-macro* nil)
(defun start-or-end-kbd-macro()
  (interactive)
  (if (eq *kbd-macro* nil)
	  (progn
		(start-kbd-macro)
		(setq *kbd-macro* t))
	(progn
	  (end-kbd-macro)
	  (setq *kbd-macro* nil))))

適当に一個にして見るとか。しかし、まだviの3dw.に適わないので、もう少し組み合わせれるようにしないと駄目な感じ。
しかし、改めて思ったけどEmacsは凄いね。sourceの管理とかが半端じゃない。何から何まで綺麗にまとめて情報が公開されまくり。